Files
source/Editor/selectwin.cpp
T
2024-12-25 22:03:03 +02:00

1698 lines
54 KiB
C++

// WANNE: EDITOR: todo
#include "builddefines.h"
#ifdef JA2EDITOR
#include "tiledef.h"
#include "vsurface.h"
#include "worlddat.h"
#include "random.h"
#include "sysutil.h"
#include "Font Control.h"
#include "selectwin.h"
#include "EditorDefines.h"
#include "Editor Taskbar Utils.h"
#include "vobject_blitters.h"
#include "Text.h"
extern BOOLEAN gfOverheadMapDirty;
//extern void SetClippingRect(SGPRect *clip);
//extern void GetClippingRect(SGPRect *clip);
extern INT32 iEditorToolbar;
extern BOOLEAN fDontUseRandom;
extern UINT16 GenericButtonFillColors[40];
struct SelectionWindow
{
SGPRect window;
SGPPoint displayAreaStart; // Area where selectable items are drawn
SGPPoint displayAreaEnd;
SGPPoint spacing; // For displayed items
};
SelectionWindow gSelection;
BOOLEAN gfRenderSquareArea = FALSE;
INT16 iStartClickX,iStartClickY;
INT16 iEndClickX,iEndClickY;
INT32 iButtonIcons[4];
INT32 iSelectWin,iCancelWin,iScrollUp,iScrollDown,iOkWin;
BOOLEAN fAllDone=FALSE;
BOOLEAN fButtonsPresent=FALSE;
//These definitions help define the start and end of the various wall indices.
//This needs to be maintained if the walls change.
#define WALL_LAST_WALL_OFFSET 30
#define WALL_FIRST_AFRAME_OFFSET 31
#define WALL_LAST_AFRAME_OFFSET 34
#define WALL_FIRST_WINDOW_OFFSET 35
#define WALL_LAST_WINDOW_OFFSET 46
#define WALL_FIRST_BROKEN_WALL_OFFSET 47
#define WALL_LAST_BROKEN_WALL_OFFSET 54
#define WALL_FIRST_APPENDED_WALL_OFFSET 55
#define WALL_LAST_APPENDED_WALL_OFFSET 56
#define WALL_FIRST_WEATHERED_WALL_OFFSET 57
#define WALL_LAST_WEATHERED_WALL_OFFSET 64
//I've added these definitions to add readability, and minimize conversion time for changes
//incase there are new values, etc.
#define OSTRUCTS_NUMELEMENTS ( LASTOSTRUCT - FIRSTFULLSTRUCT + 22 )
#define OSTRUCTS1_NUMELEMENTS 5
#define OSTRUCTS2_NUMELEMENTS 12
#define BANKSLIST_NUMELEMENTS 5
#define ROADSLIST_NUMELEMENTS 1
#define DEBRISLIST_NUMELEMENTS ( LASTDEBRIS - DEBRISROCKS + 2 + 1 ) //+1 for ANOTHERDEBRIS
#define SINGLEWALL_NUMELEMENTS ( (LASTWALL-FIRSTWALL+1) * 2 )
#define SINGLEDOOR_NUMELEMENTS (( LASTDOOR - FIRSTDOOR + 1 ) * 5)
#define SINGLEWINDOW_NUMELEMENTS ( LASTWALL - FIRSTWALL + 1 )
#define SINGLEROOF_NUMELEMENTS ( (LASTROOF-FIRSTROOF+1) + (LASTSLANTROOF-FIRSTSLANTROOF+1) + \
(LASTWALL-FIRSTWALL+1) + (SECONDONROOF-FIRSTONROOF+1) )
#define SINGLENEWROOF_NUMELEMENTS (LASTROOF-FIRSTROOF+1)
#define SINGLEBROKENWALL_NUMELEMENTS ( (LASTDECORATIONS-FIRSTDECORATIONS+1) + (LASTWALL-FIRSTWALL+1)*2 )
#define SINGLEDECOR_NUMELEMENTS ( LASTISTRUCT - FIRSTISTRUCT + 1 )
#define SINGLEDECAL_NUMELEMENTS ( LASTWALLDECAL - FIRSTWALLDECAL + EIGTHWALLDECAL - FIFTHWALLDECAL + 3 )
#define SINGLEFLOOR_NUMELEMENTS ( LASTFLOOR - FIRSTFLOOR + 1 )
#define SINGLETOILET_NUMELEMENTS ( EIGHTISTRUCT - FIFTHISTRUCT + 1 )
//#define ROOM_NUMELEMENTS ( (LASTWALL-FIRSTWALL+1) + (LASTFLOOR-FIRSTFLOOR+1) + \
// (LASTROOF-FIRSTROOF+1) + (LASTSLANTROOF-FIRSTSLANTROOF+1) )
#define ROOM_NUMELEMENTS ( (LASTWALL-FIRSTWALL+1) + (LASTFLOOR-FIRSTFLOOR+1) + \
(LASTROOF-FIRSTROOF+1) + (2 ))
//This is a special case for trees which may have varying numbers. There was a problem
//in which we loaded a new tileset which had one less tree in it. When we called BuildSelectionWindow(),
//it would crash because it thought there was an extra tree which was now invalid.
UINT16 gusNumOStructs = 0;
// List of objects to display in the selection window
DisplaySpec OStructs[ OSTRUCTS_NUMELEMENTS ];
DisplaySpec OStructs1[ OSTRUCTS1_NUMELEMENTS ];
DisplaySpec OStructs2[ OSTRUCTS2_NUMELEMENTS ];
DisplaySpec BanksList[ BANKSLIST_NUMELEMENTS ];
DisplaySpec RoadsList[ ROADSLIST_NUMELEMENTS ];
DisplaySpec DebrisList[ DEBRISLIST_NUMELEMENTS ];
DisplaySpec SingleWall[ SINGLEWALL_NUMELEMENTS ];
DisplaySpec SingleDoor[ SINGLEDOOR_NUMELEMENTS ];
DisplaySpec SingleWindow[ SINGLEWINDOW_NUMELEMENTS ];
DisplaySpec SingleRoof[ SINGLEROOF_NUMELEMENTS ];
DisplaySpec SingleNewRoof[ SINGLENEWROOF_NUMELEMENTS ];
DisplaySpec SingleBrokenWall[ SINGLEBROKENWALL_NUMELEMENTS ];
DisplaySpec SingleDecor[ SINGLEDECOR_NUMELEMENTS ];
DisplaySpec SingleDecal[ SINGLEDECAL_NUMELEMENTS ];
DisplaySpec SingleFloor[ SINGLEFLOOR_NUMELEMENTS ];
DisplaySpec SingleToilet[ SINGLETOILET_NUMELEMENTS ];
DisplaySpec Room[ ROOM_NUMELEMENTS ];
//These are all of the different selection lists. Changing the max_selections will
//change the number of selections values you can have at a time. This is Bret's gay code,
//though I've cleaned it up a lot.
Selections SelOStructs[MAX_SELECTIONS] = { {FIRSTFULLSTRUCT, 0, 1} }; // Default selections
Selections SelOStructs1[MAX_SELECTIONS] = { {FOURTHOSTRUCT, 0, 1} }; // Default selections
Selections SelOStructs2[MAX_SELECTIONS] = { {THIRDOSTRUCT, 0, 1} }; // Default selections
Selections SelBanks[MAX_SELECTIONS] = { {FIRSTCLIFF, 0, 1} };
Selections SelRoads[MAX_SELECTIONS] = { {FIRSTROAD, 0, 1} };
Selections SelDebris[MAX_SELECTIONS] = { {DEBRISROCKS, 0, 1} };
Selections SelSingleWall[MAX_SELECTIONS] = { {FIRSTWALL, 0, 1} };
Selections SelSingleDoor[MAX_SELECTIONS] = { {FIRSTDOOR, 0, 1} };
Selections SelSingleWindow[MAX_SELECTIONS] = { {FIRSTWALL, 44, 1} };
Selections SelSingleRoof[MAX_SELECTIONS] = { {FIRSTROOF, 0, 1} };
Selections SelSingleNewRoof[MAX_SELECTIONS] = { {FIRSTROOF, 0, 1} };
Selections SelSingleBrokenWall[MAX_SELECTIONS] = { {FIRSTDECORATIONS, 0, 1} };
Selections SelSingleDecor[MAX_SELECTIONS]= { {FIRSTISTRUCT, 0, 1} };
Selections SelSingleDecal[MAX_SELECTIONS] = { {FIRSTWALLDECAL, 0, 1} };
Selections SelSingleFloor[MAX_SELECTIONS] = { {FIRSTFLOOR, 0, 1} };
Selections SelSingleToilet[MAX_SELECTIONS] = { {FIFTHISTRUCT, 0, 1} };
Selections SelRoom[MAX_SELECTIONS] = { {FIRSTWALL, 0, 1} };
// Number of objects currently in the selection list
INT32 iNumOStructsSelected = 1;
INT32 iNumOStructs1Selected = 1;
INT32 iNumOStructs2Selected = 1;
INT32 iNumBanksSelected = 1;
INT32 iNumRoadsSelected = 1;
INT32 iNumDebrisSelected = 1;
INT32 iNumWallsSelected = 1;
INT32 iNumDoorsSelected = 1;
INT32 iNumWindowsSelected = 1;
INT32 iNumDecorSelected = 1;
INT32 iNumDecalsSelected = 1;
INT32 iNumBrokenWallsSelected = 1;
INT32 iNumFloorsSelected = 1;
INT32 iNumToiletsSelected = 1;
INT32 iNumRoofsSelected = 1;
INT32 iNumNewRoofsSelected = 1;
INT32 iNumRoomsSelected = 1;
// Holds the previous selection list when a selection window is up. Used for canceling the selection window
Selections OldSelList[MAX_SELECTIONS];
INT32 iOldNumSelList;
// Global pointers for selection list
Selections *pSelList;
INT32 *pNumSelList;
// Global used to indicate which selection to use (changes with the PGUP/PGDWN keys in editor)
INT32 iCurBank = 0;
DisplayList *pDispList;
INT16 iTopWinCutOff,iBotWinCutOff;
DisplayList Selection;
UINT16 SelWinFillColor = 0x0000; // Black
UINT16 SelWinHilightFillColor = 0x23BA; //blue, formerly 0x000d a kind of medium dark blue (not contrasty)
//----------------------------------------------------------------------------------------------
// CreateJA2SelectionWindow
//
// Creates a selection window of the given type.
//
void CreateJA2SelectionWindow( INT16 sWhat )
{
auto selectWinWidth = 600;
const auto selectWinHeight = SCREEN_HEIGHT - 120; // From top edge to taskbar
if (iResolution > _800x600)
{
selectWinWidth = 900;
}
auto tlX = 0;
auto tlY = 0;
auto brX = tlX + selectWinWidth;
auto brY = tlY + selectWinHeight;
gSelection.window.iLeft = tlX;
gSelection.window.iTop = tlY;
gSelection.window.iRight = brX;
gSelection.window.iBottom = brY;
gSelection.displayAreaStart.iX = tlX + 1;
gSelection.displayAreaStart.iY = tlY + 15;
gSelection.displayAreaEnd.iX = brX - 1;
gSelection.displayAreaEnd.iY= brY - 1;
gSelection.spacing.iX = 2;
gSelection.spacing.iY = 2;
iTopWinCutOff = gSelection.displayAreaStart.iY;
iBotWinCutOff = gSelection.displayAreaEnd.iY;
DisplaySpec *pDSpec;
UINT16 usNSpecs;
fAllDone = FALSE;
DisableEditorTaskbar( );
// Load up the button images
iButtonIcons[ SEL_WIN_CANCEL_ICON ] = LoadGenericButtonIcon( "EDITOR//bigX.sti" );
iButtonIcons[ SEL_WIN_UP_ICON ] = LoadGenericButtonIcon( "EDITOR//lgUpArrow.sti" );
iButtonIcons[ SEL_WIN_DOWN_ICON ] = LoadGenericButtonIcon( "EDITOR//lgDownArrow.sti" );
iButtonIcons[ SEL_WIN_OK_ICON ] = LoadGenericButtonIcon( "EDITOR//checkmark.sti" );
iSelectWin = CreateHotSpot(0, 0, selectWinWidth, selectWinHeight, MSYS_PRIORITY_HIGH,
DEFAULT_MOVE_CALLBACK, SelWinClkCallback);
iOkWin = CreateIconButton((INT16)iButtonIcons[SEL_WIN_OK_ICON], 0,
BUTTON_USE_DEFAULT, selectWinWidth, 0,
40, 40, BUTTON_TOGGLE,
MSYS_PRIORITY_HIGH,
DEFAULT_MOVE_CALLBACK, OkClkCallback);
SetButtonFastHelpText(iOkWin,pDisplaySelectionWindowButtonText[0]);
iCancelWin = CreateIconButton((INT16)iButtonIcons[SEL_WIN_CANCEL_ICON], 0,
BUTTON_USE_DEFAULT, selectWinWidth, 40,
40, 40, BUTTON_TOGGLE,
MSYS_PRIORITY_HIGH,
DEFAULT_MOVE_CALLBACK, CnclClkCallback);
SetButtonFastHelpText(iCancelWin,pDisplaySelectionWindowButtonText[1]);
iScrollUp = CreateIconButton((INT16)iButtonIcons[SEL_WIN_UP_ICON], 0,
BUTTON_USE_DEFAULT, selectWinWidth, 80,
40, 160, BUTTON_NO_TOGGLE,
MSYS_PRIORITY_HIGH,
DEFAULT_MOVE_CALLBACK, UpClkCallback);
SetButtonFastHelpText(iScrollUp,pDisplaySelectionWindowButtonText[2]);
iScrollDown = CreateIconButton((INT16)iButtonIcons[SEL_WIN_DOWN_ICON], 0,
BUTTON_USE_DEFAULT, selectWinWidth, 240,
40, 160, BUTTON_NO_TOGGLE,
MSYS_PRIORITY_HIGH,
DEFAULT_MOVE_CALLBACK, DwnClkCallback);
SetButtonFastHelpText(iScrollDown,pDisplaySelectionWindowButtonText[3]);
fButtonsPresent = TRUE;
switch( sWhat )
{
case SELWIN_OSTRUCTS:
pDSpec = OStructs;
usNSpecs = gusNumOStructs;//OSTRUCTS_NUMELEMENTS;
pSelList = SelOStructs;
pNumSelList = &iNumOStructsSelected;
break;
case SELWIN_OSTRUCTS1:
pDSpec = OStructs1;
usNSpecs = OSTRUCTS1_NUMELEMENTS;
pSelList = SelOStructs1;
pNumSelList = &iNumOStructs1Selected;
break;
case SELWIN_OSTRUCTS2:
pDSpec = OStructs2;
usNSpecs = OSTRUCTS2_NUMELEMENTS;
pSelList = SelOStructs2;
pNumSelList = &iNumOStructs2Selected;
break;
case SELWIN_BANKS:
pDSpec = BanksList;
usNSpecs = BANKSLIST_NUMELEMENTS;
pSelList = SelBanks;
pNumSelList = &iNumBanksSelected;
break;
case SELWIN_ROADS:
pDSpec = RoadsList;
usNSpecs = ROADSLIST_NUMELEMENTS;
pSelList = SelRoads;
pNumSelList = &iNumRoadsSelected;
break;
case SELWIN_DEBRIS:
pDSpec = DebrisList;
usNSpecs = DEBRISLIST_NUMELEMENTS;
pSelList = SelDebris;
pNumSelList = &iNumDebrisSelected;
break;
case SELWIN_SINGLEWALL:
pDSpec = SingleWall;
usNSpecs = SINGLEWALL_NUMELEMENTS;
pSelList = SelSingleWall;
pNumSelList = &iNumWallsSelected;
break;
case SELWIN_SINGLEDOOR:
pDSpec = SingleDoor;
usNSpecs = SINGLEDOOR_NUMELEMENTS;
pSelList = SelSingleDoor;
pNumSelList = &iNumDoorsSelected;
break;
case SELWIN_SINGLEWINDOW:
pDSpec = SingleWindow;
usNSpecs = SINGLEWINDOW_NUMELEMENTS;
pSelList = SelSingleWindow;
pNumSelList = &iNumWindowsSelected;
break;
case SELWIN_SINGLEROOF:
pDSpec = SingleRoof;
usNSpecs = SINGLEROOF_NUMELEMENTS;
pSelList = SelSingleRoof;
pNumSelList = &iNumRoofsSelected;
break;
case SELWIN_SINGLENEWROOF:
pDSpec = SingleNewRoof;
usNSpecs = SINGLENEWROOF_NUMELEMENTS;
pSelList = SelSingleNewRoof;
pNumSelList = &iNumNewRoofsSelected;
break;
case SELWIN_SINGLEBROKENWALL:
pDSpec = SingleBrokenWall;
usNSpecs = SINGLEBROKENWALL_NUMELEMENTS;
pSelList = SelSingleBrokenWall;
pNumSelList = &iNumBrokenWallsSelected;
break;
case SELWIN_SINGLEDECOR:
pDSpec = SingleDecor;
usNSpecs = SINGLEDECOR_NUMELEMENTS;
pSelList = SelSingleDecor;
pNumSelList = &iNumDecorSelected;
break;
case SELWIN_SINGLEDECAL:
pDSpec = SingleDecal;
usNSpecs = SINGLEDECAL_NUMELEMENTS;
pSelList = SelSingleDecal;
pNumSelList = &iNumDecalsSelected;
break;
case SELWIN_SINGLEFLOOR:
pDSpec = SingleFloor;
usNSpecs = SINGLEFLOOR_NUMELEMENTS;
pSelList = SelSingleFloor;
pNumSelList = &iNumFloorsSelected;
break;
case SELWIN_SINGLETOILET:
pDSpec = SingleToilet;
usNSpecs = SINGLETOILET_NUMELEMENTS;
pSelList = SelSingleToilet;
pNumSelList = &iNumToiletsSelected;
break;
case SELWIN_ROOM:
pDSpec = Room;
usNSpecs = ROOM_NUMELEMENTS;
pSelList = SelRoom;
pNumSelList = &iNumRoomsSelected;
break;
default:
// If none of these, don't create anything!
AssertMsg( 0, "Unknown window creation type");
return;
}
BuildDisplayWindow( pDSpec, usNSpecs, &pDispList, &gSelection.displayAreaStart , &gSelection.displayAreaEnd,
&gSelection.spacing, CLEAR_BACKGROUND);
}
//The selection window method is initialized here. This is where all the graphics for all
//the categories are organized and loaded. If you wish to move things around, then this is
//where the initialization part is done. I have also changed this from previously being loaded
//every single time you go into a selection window which was redundant and CPU consuming.
void InitJA2SelectionWindow( void )
{
INT32 iCount;
INT32 iCount2;
INT32 iCount3;
UINT16 usETRLEObjects;
HVOBJECT hVObject;
pDispList = NULL;
// Init the display spec lists for the types of selection windows
// Trees & bushes (The tree button in the "terrain" toolbar)
for ( iCount3 = 0, iCount = 0; iCount < (LASTOSTRUCT - FIRSTFULLSTRUCT + 1); iCount++ )
{
hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTFULLSTRUCT + iCount]].hTileSurface;
usETRLEObjects = hVObject->usNumberOfObjects;
for ( iCount2 = 0; iCount2 < usETRLEObjects; iCount2 += 3, iCount3++)
{
OStructs[ iCount3 ].ubType = DISPLAY_GRAPHIC;
OStructs[ iCount3 ].hVObject = hVObject;
OStructs[ iCount3 ].usStart = (UINT16)iCount2;
OStructs[ iCount3 ].usEnd = (UINT16)iCount2;
OStructs[ iCount3 ].uiObjIndx = (FIRSTFULLSTRUCT + iCount);
}
}
OStructs[ iCount3 ].ubType = DISPLAY_GRAPHIC;
OStructs[ iCount3 ].hVObject = gTileDatabase[gTileTypeStartIndex[SIXTHOSTRUCT]].hTileSurface;
OStructs[ iCount3 ].usStart = DISPLAY_ALL_OBJECTS;
OStructs[ iCount3 ].usEnd = 0;
OStructs[ iCount3 ].uiObjIndx = SIXTHOSTRUCT;
gusNumOStructs = (UINT16)iCount3 + 1;
// Rocks & barrels! (the "1" button in the "terrain" toolbar)
OStructs1[ 0 ].ubType = DISPLAY_GRAPHIC;
OStructs1[ 0 ].hVObject = gTileDatabase[gTileTypeStartIndex[FOURTHOSTRUCT]].hTileSurface;
OStructs1[ 0 ].usStart = DISPLAY_ALL_OBJECTS;
OStructs1[ 0 ].usEnd = 0;
OStructs1[ 0 ].uiObjIndx = FOURTHOSTRUCT;
for ( iCount = 0; iCount < (THIRDOSTRUCT - FIRSTOSTRUCT); iCount++ )
{
OStructs1[ iCount + 1 ].ubType = DISPLAY_GRAPHIC;
OStructs1[ iCount + 1 ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTOSTRUCT + iCount]].hTileSurface;
OStructs1[ iCount + 1 ].usStart = DISPLAY_ALL_OBJECTS;
OStructs1[ iCount + 1 ].usEnd = 0;
OStructs1[ iCount + 1 ].uiObjIndx = FIRSTOSTRUCT + iCount;
}
// Other junk! (the "2" button in the "terrain" toolbar)
OStructs2[ 0 ].ubType = DISPLAY_GRAPHIC;
OStructs2[ 0 ].hVObject = gTileDatabase[gTileTypeStartIndex[THIRDOSTRUCT]].hTileSurface;
OStructs2[ 0 ].usStart = DISPLAY_ALL_OBJECTS;
OStructs2[ 0 ].usEnd = 0;
OStructs2[ 0 ].uiObjIndx = THIRDOSTRUCT;
OStructs2[ 1 ].ubType = DISPLAY_GRAPHIC;
OStructs2[ 1 ].hVObject = gTileDatabase[gTileTypeStartIndex[FIFTHOSTRUCT]].hTileSurface;
OStructs2[ 1 ].usStart = DISPLAY_ALL_OBJECTS;
OStructs2[ 1 ].usEnd = 0;
OStructs2[ 1 ].uiObjIndx = FIFTHOSTRUCT;
OStructs2[ 2 ].ubType = DISPLAY_GRAPHIC;
OStructs2[ 2 ].hVObject = gTileDatabase[gTileTypeStartIndex[SEVENTHOSTRUCT]].hTileSurface;
OStructs2[ 2 ].usStart = DISPLAY_ALL_OBJECTS;
OStructs2[ 2 ].usEnd = 0;
OStructs2[ 2 ].uiObjIndx = SEVENTHOSTRUCT;
OStructs2[ 3 ].ubType = DISPLAY_GRAPHIC;
OStructs2[ 3 ].hVObject = gTileDatabase[gTileTypeStartIndex[EIGHTOSTRUCT]].hTileSurface;
OStructs2[ 3 ].usStart = DISPLAY_ALL_OBJECTS;
OStructs2[ 3 ].usEnd = 0;
OStructs2[ 3 ].uiObjIndx = EIGHTOSTRUCT;
OStructs2[ 4 ].ubType = DISPLAY_GRAPHIC;
OStructs2[ 4 ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTVEHICLE]].hTileSurface;
OStructs2[ 4 ].usStart = DISPLAY_ALL_OBJECTS;
OStructs2[ 4 ].usEnd = 0;
OStructs2[ 4 ].uiObjIndx = FIRSTVEHICLE;
OStructs2[ 5 ].ubType = DISPLAY_GRAPHIC;
OStructs2[ 5 ].hVObject = gTileDatabase[gTileTypeStartIndex[SECONDVEHICLE]].hTileSurface;
OStructs2[ 5 ].usStart = DISPLAY_ALL_OBJECTS;
OStructs2[ 5 ].usEnd = 0;
OStructs2[ 5 ].uiObjIndx = SECONDVEHICLE;
OStructs2[ 6 ].ubType = DISPLAY_GRAPHIC;
OStructs2[ 6 ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTDEBRISSTRUCT]].hTileSurface;
OStructs2[ 6 ].usStart = DISPLAY_ALL_OBJECTS;
OStructs2[ 6 ].usEnd = 0;
OStructs2[ 6 ].uiObjIndx = FIRSTDEBRISSTRUCT;
OStructs2[ 7 ].ubType = DISPLAY_GRAPHIC;
OStructs2[ 7 ].hVObject = gTileDatabase[gTileTypeStartIndex[SECONDDEBRISSTRUCT]].hTileSurface;
OStructs2[ 7 ].usStart = DISPLAY_ALL_OBJECTS;
OStructs2[ 7 ].usEnd = 0;
OStructs2[ 7 ].uiObjIndx = SECONDDEBRISSTRUCT;
OStructs2[ 8 ].ubType = DISPLAY_GRAPHIC;
OStructs2[ 8 ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTLARGEEXPDEBRIS]].hTileSurface;
OStructs2[ 8 ].usStart = DISPLAY_ALL_OBJECTS;
OStructs2[ 8 ].usEnd = 0;
OStructs2[ 8 ].uiObjIndx = FIRSTLARGEEXPDEBRIS;
OStructs2[ 9 ].ubType = DISPLAY_GRAPHIC;
OStructs2[ 9 ].hVObject = gTileDatabase[gTileTypeStartIndex[SECONDLARGEEXPDEBRIS]].hTileSurface;
OStructs2[ 9 ].usStart = DISPLAY_ALL_OBJECTS;
OStructs2[ 9 ].usEnd = 0;
OStructs2[ 9 ].uiObjIndx = SECONDLARGEEXPDEBRIS;
OStructs2[ 10 ].ubType = DISPLAY_GRAPHIC;
OStructs2[ 10 ].hVObject = gTileDatabase[gTileTypeStartIndex[NINTHOSTRUCT]].hTileSurface;
OStructs2[ 10 ].usStart = DISPLAY_ALL_OBJECTS;
OStructs2[ 10 ].usEnd = 0;
OStructs2[ 10 ].uiObjIndx = NINTHOSTRUCT;
OStructs2[ 11 ].ubType = DISPLAY_GRAPHIC;
OStructs2[ 11 ].hVObject = gTileDatabase[gTileTypeStartIndex[TENTHOSTRUCT]].hTileSurface;
OStructs2[ 11 ].usStart = DISPLAY_ALL_OBJECTS;
OStructs2[ 11 ].usEnd = 0;
OStructs2[ 11 ].uiObjIndx = TENTHOSTRUCT;
// River banks and cliffs (the "river" button on the "terrain" toolbar)
BanksList[0].ubType = DISPLAY_GRAPHIC;
BanksList[0].hVObject = gTileDatabase[gTileTypeStartIndex[ANIOSTRUCT]].hTileSurface;
BanksList[0].usStart = DISPLAY_ALL_OBJECTS;
BanksList[0].usEnd = 0;
BanksList[0].uiObjIndx = ANIOSTRUCT;
BanksList[1].ubType = DISPLAY_GRAPHIC;
BanksList[1].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTCLIFF]].hTileSurface;
BanksList[1].usStart = DISPLAY_ALL_OBJECTS;
BanksList[1].usEnd = 0;
BanksList[1].uiObjIndx = FIRSTCLIFF;
BanksList[2].ubType = DISPLAY_GRAPHIC;
BanksList[2].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTCLIFFHANG]].hTileSurface;
BanksList[2].usStart = DISPLAY_ALL_OBJECTS;
BanksList[2].usEnd = 0;
BanksList[2].uiObjIndx = FIRSTCLIFFHANG;
BanksList[3].ubType = DISPLAY_GRAPHIC;
BanksList[3].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTROAD]].hTileSurface;
BanksList[3].usStart = DISPLAY_ALL_OBJECTS;
BanksList[3].usEnd = 0;
BanksList[3].uiObjIndx = FIRSTROAD;
BanksList[4].ubType = DISPLAY_GRAPHIC;
BanksList[4].hVObject = gTileDatabase[gTileTypeStartIndex[FENCESTRUCT]].hTileSurface;
BanksList[4].usStart = DISPLAY_ALL_OBJECTS;
BanksList[4].usEnd = 0;
BanksList[4].uiObjIndx = FENCESTRUCT;
RoadsList[0].ubType = DISPLAY_GRAPHIC;
RoadsList[0].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTROAD]].hTileSurface;
RoadsList[0].usStart = DISPLAY_ALL_OBJECTS;
RoadsList[0].usEnd = 0;
RoadsList[0].uiObjIndx = FIRSTROAD;
// Debris (the "bent can" button on the "terrain", and "buildings" toolbars)
for ( iCount = 0; iCount < (LASTDEBRIS - DEBRISROCKS + 1); iCount++ )
{
DebrisList[ iCount ].ubType = DISPLAY_GRAPHIC;
DebrisList[ iCount ].hVObject = gTileDatabase[gTileTypeStartIndex[DEBRISROCKS + iCount]].hTileSurface;
DebrisList[ iCount ].usStart = DISPLAY_ALL_OBJECTS;
DebrisList[ iCount ].usEnd = 0;
DebrisList[ iCount ].uiObjIndx = DEBRISROCKS + iCount;
}
// Add one more for new misc debris
DebrisList[ iCount ].ubType = DISPLAY_GRAPHIC;
DebrisList[ iCount ].hVObject = gTileDatabase[gTileTypeStartIndex[DEBRIS2MISC ] ].hTileSurface;
DebrisList[ iCount ].usStart = DISPLAY_ALL_OBJECTS;
DebrisList[ iCount ].usEnd = 0;
DebrisList[ iCount ].uiObjIndx = DEBRIS2MISC;
//Add yet another one...
iCount++;
DebrisList[ iCount ].ubType = DISPLAY_GRAPHIC;
DebrisList[ iCount ].hVObject = gTileDatabase[gTileTypeStartIndex[ANOTHERDEBRIS ] ].hTileSurface;
DebrisList[ iCount ].usStart = DISPLAY_ALL_OBJECTS;
DebrisList[ iCount ].usEnd = 0;
DebrisList[ iCount ].uiObjIndx = ANOTHERDEBRIS;
// Rooms
for ( iCount = 0; iCount < (LASTWALL - FIRSTWALL + 1); iCount++ )
{
Room[ iCount ].ubType = DISPLAY_GRAPHIC;
Room[iCount ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTWALL + iCount]].hTileSurface;
Room[ iCount ].usStart = 0;
Room[ iCount ].usEnd = 0;
Room[ iCount ].uiObjIndx = FIRSTWALL + iCount;
}
for ( iCount2 = 0; iCount2 < (LASTFLOOR - FIRSTFLOOR + 1); iCount2++, iCount++ )
{
Room[ iCount ].ubType = DISPLAY_GRAPHIC;
Room[ iCount ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTFLOOR + iCount2]].hTileSurface;
Room[ iCount ].usStart = 0;
Room[ iCount ].usEnd = 0;
Room[ iCount ].uiObjIndx = FIRSTFLOOR + iCount2;
}
for ( iCount2 = 0; iCount2 < (LASTROOF - FIRSTROOF + 1); iCount2++, iCount++ )
{
Room[ iCount ].ubType = DISPLAY_GRAPHIC;
Room[ iCount ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTROOF + iCount2]].hTileSurface;
Room[ iCount ].usStart = 0;
Room[ iCount ].usEnd = 0;
Room[ iCount ].uiObjIndx = FIRSTROOF + iCount2;
}
for ( iCount2 = 0; iCount2 < 2/*(LASTSLANTROOF - FIRSTSLANTROOF + 1)*/; iCount2++, iCount++ )
{
Room[ iCount ].ubType = DISPLAY_GRAPHIC;
Room[ iCount ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTSLANTROOF + iCount2]].hTileSurface;
Room[ iCount ].usStart = 0;
Room[ iCount ].usEnd = 0;
Room[ iCount ].uiObjIndx = FIRSTSLANTROOF + iCount2;
}
//Walls
for ( iCount = 0, iCount2 = 0; iCount < (LASTWALL - FIRSTWALL + 1); iCount++, iCount2+=2 )
{
SingleWall[ iCount2 ].ubType = DISPLAY_GRAPHIC;
SingleWall[ iCount2 ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTWALL + iCount]].hTileSurface;
SingleWall[ iCount2 ].usStart = 0;
SingleWall[ iCount2 ].usEnd = WALL_LAST_WALL_OFFSET;
SingleWall[ iCount2 ].uiObjIndx = FIRSTWALL + iCount;
//New appended walls
SingleWall[ iCount2+1 ].ubType = DISPLAY_GRAPHIC;
SingleWall[ iCount2+1 ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTWALL + iCount]].hTileSurface;
SingleWall[ iCount2+1 ].usStart = WALL_FIRST_APPENDED_WALL_OFFSET;
SingleWall[ iCount2+1 ].usEnd = WALL_LAST_APPENDED_WALL_OFFSET;
SingleWall[ iCount2+1 ].uiObjIndx = FIRSTWALL + iCount;
}
//Doors
for ( iCount = 0, iCount2 = 0; iCount < (LASTDOOR - FIRSTDOOR + 1); iCount++, iCount2+=5)
{
//closed
SingleDoor[ iCount2 ].ubType = DISPLAY_GRAPHIC;
SingleDoor[ iCount2 ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTDOOR + iCount]].hTileSurface;
SingleDoor[ iCount2 ].usStart = 0;
SingleDoor[ iCount2 ].usEnd = 0;
SingleDoor[ iCount2 ].uiObjIndx = FIRSTDOOR + iCount;
//open, closed
SingleDoor[ iCount2+1 ].ubType = DISPLAY_GRAPHIC;
SingleDoor[ iCount2+1 ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTDOOR + iCount]].hTileSurface;
SingleDoor[ iCount2+1 ].usStart = 4;
SingleDoor[ iCount2+1 ].usEnd = 5;
SingleDoor[ iCount2+1 ].uiObjIndx = FIRSTDOOR + iCount;
//open, closed
SingleDoor[ iCount2+2 ].ubType = DISPLAY_GRAPHIC;
SingleDoor[ iCount2+2 ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTDOOR + iCount]].hTileSurface;
SingleDoor[ iCount2+2 ].usStart = 9;
SingleDoor[ iCount2+2 ].usEnd = 10;
SingleDoor[ iCount2+2 ].uiObjIndx = FIRSTDOOR + iCount;
//open, closed
SingleDoor[ iCount2+3 ].ubType = DISPLAY_GRAPHIC;
SingleDoor[ iCount2+3 ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTDOOR + iCount]].hTileSurface;
SingleDoor[ iCount2+3 ].usStart = 14;
SingleDoor[ iCount2+3 ].usEnd = 15;
SingleDoor[ iCount2+3 ].uiObjIndx = FIRSTDOOR + iCount;
//open
SingleDoor[ iCount2+4 ].ubType = DISPLAY_GRAPHIC;
SingleDoor[ iCount2+4 ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTDOOR + iCount]].hTileSurface;
SingleDoor[ iCount2+4 ].usStart = 19;
SingleDoor[ iCount2+4 ].usEnd = 19;
SingleDoor[ iCount2+4 ].uiObjIndx = FIRSTDOOR + iCount;
}
//Windows
for ( iCount = 0; iCount < (LASTWALL - FIRSTWALL + 1); iCount++ )
{
SingleWindow[ iCount ].ubType = DISPLAY_GRAPHIC;
SingleWindow[ iCount ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTWALL + iCount]].hTileSurface;
SingleWindow[ iCount ].usStart = WALL_FIRST_WINDOW_OFFSET;
SingleWindow[ iCount ].usEnd = WALL_LAST_WINDOW_OFFSET;
SingleWindow[ iCount ].uiObjIndx = FIRSTWALL + iCount;
}
//Roofs and slant roofs
for ( iCount = 0; iCount < (LASTROOF - FIRSTROOF + 1); iCount++ )
{ //Flat roofs
SingleRoof[ iCount ].ubType = DISPLAY_GRAPHIC;
SingleRoof[ iCount ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTROOF + iCount]].hTileSurface;
SingleRoof[ iCount ].usStart = DISPLAY_ALL_OBJECTS;
SingleRoof[ iCount ].usEnd = 0;
SingleRoof[ iCount ].uiObjIndx = FIRSTROOF + iCount;
}
for ( iCount2 = 0; iCount2 < (LASTSLANTROOF - FIRSTSLANTROOF + 1); iCount2++, iCount++ )
{ //Slanted roofs
SingleRoof[ iCount ].ubType = DISPLAY_GRAPHIC;
SingleRoof[ iCount ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTSLANTROOF + iCount2]].hTileSurface;
SingleRoof[ iCount ].usStart = DISPLAY_ALL_OBJECTS;
SingleRoof[ iCount ].usEnd = 0;
SingleRoof[ iCount ].uiObjIndx = FIRSTSLANTROOF + iCount2;
}
for( iCount2 = 0; iCount2 < (LASTWALL - FIRSTWALL + 1); iCount2++, iCount++ )
{ //A-Frames
SingleRoof[ iCount ].ubType = DISPLAY_GRAPHIC;
SingleRoof[ iCount ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTWALL + iCount2]].hTileSurface;
SingleRoof[ iCount ].usStart = WALL_FIRST_AFRAME_OFFSET;
SingleRoof[ iCount ].usEnd = WALL_LAST_AFRAME_OFFSET;
SingleRoof[ iCount ].uiObjIndx = FIRSTWALL + iCount2;
}
for( iCount2 = 0; iCount2 < (SECONDONROOF - FIRSTONROOF + 1); iCount2++, iCount++ )
{ //On roofs
SingleRoof[ iCount ].ubType = DISPLAY_GRAPHIC;
SingleRoof[ iCount ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTONROOF + iCount2]].hTileSurface;
SingleRoof[ iCount ].usStart = DISPLAY_ALL_OBJECTS;
SingleRoof[ iCount ].usEnd = 0;
SingleRoof[ iCount ].uiObjIndx = FIRSTONROOF + iCount2;
}
//New replacement roofs
for ( iCount = 0; iCount < (LASTROOF - FIRSTROOF + 1); iCount++ )
{ //Flat roofs
SingleNewRoof[ iCount ].ubType = DISPLAY_GRAPHIC;
SingleNewRoof[ iCount ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTROOF + iCount]].hTileSurface;
SingleNewRoof[ iCount ].usStart = 9;
SingleNewRoof[ iCount ].usEnd = 9;
SingleNewRoof[ iCount ].uiObjIndx = FIRSTROOF + iCount;
}
//Broken walls
for ( iCount = 0; iCount < (LASTDECORATIONS - FIRSTDECORATIONS + 1); iCount++ )
{ //Old obsolete wall decals, but should be replaced with multitiled decals such as banners, etc.
SingleBrokenWall[ iCount ].ubType = DISPLAY_GRAPHIC;
SingleBrokenWall[ iCount ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTDECORATIONS + iCount]].hTileSurface;
SingleBrokenWall[ iCount ].usStart = DISPLAY_ALL_OBJECTS;
SingleBrokenWall[ iCount ].usEnd = 0;
SingleBrokenWall[ iCount ].uiObjIndx = FIRSTDECORATIONS + iCount;
}
for( iCount2 = 0; iCount2 < (LASTWALL - FIRSTWALL + 1); iCount2++, iCount++ )
{ //Broken walls
SingleBrokenWall[ iCount ].ubType = DISPLAY_GRAPHIC;
SingleBrokenWall[ iCount ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTWALL + iCount2]].hTileSurface;
SingleBrokenWall[ iCount ].usStart = WALL_FIRST_BROKEN_WALL_OFFSET;
SingleBrokenWall[ iCount ].usEnd = WALL_LAST_BROKEN_WALL_OFFSET;
SingleBrokenWall[ iCount ].uiObjIndx = FIRSTWALL + iCount2;
}
for( iCount2 = 0; iCount2 < (LASTWALL - FIRSTWALL + 1); iCount2++, iCount++ )
{ //Cracked and smudged walls
SingleBrokenWall[ iCount ].ubType = DISPLAY_GRAPHIC;
SingleBrokenWall[ iCount ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTWALL + iCount2]].hTileSurface;
SingleBrokenWall[ iCount ].usStart = WALL_FIRST_WEATHERED_WALL_OFFSET;
SingleBrokenWall[ iCount ].usEnd = WALL_LAST_WEATHERED_WALL_OFFSET;
SingleBrokenWall[ iCount ].uiObjIndx = FIRSTWALL + iCount2;
}
// Decorations
for ( iCount = 0; iCount < (LASTISTRUCT - FIRSTISTRUCT + 1); iCount++ )
{
SingleDecor[ iCount ].ubType = DISPLAY_GRAPHIC;
SingleDecor[ iCount ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTISTRUCT + iCount]].hTileSurface;
SingleDecor[ iCount ].usStart = DISPLAY_ALL_OBJECTS;
SingleDecor[ iCount ].usEnd = 0;
SingleDecor[ iCount ].uiObjIndx = FIRSTISTRUCT + iCount;
}
// Wall decals
for ( iCount = 0; iCount < (LASTWALLDECAL - FIRSTWALLDECAL + 1); iCount++ )
{
SingleDecal[ iCount ].ubType = DISPLAY_GRAPHIC;
SingleDecal[ iCount ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTWALLDECAL + iCount]].hTileSurface;
SingleDecal[ iCount ].usStart = DISPLAY_ALL_OBJECTS;
SingleDecal[ iCount ].usEnd = 0;
SingleDecal[ iCount ].uiObjIndx = FIRSTWALLDECAL + iCount;
}
for ( iCount2 = 0; iCount2 < (EIGTHWALLDECAL - FIFTHWALLDECAL + 1); iCount++, iCount2++ )
{
SingleDecal[ iCount ].ubType = DISPLAY_GRAPHIC;
SingleDecal[ iCount ].hVObject = gTileDatabase[gTileTypeStartIndex[FIFTHWALLDECAL + iCount2]].hTileSurface;
SingleDecal[ iCount ].usStart = DISPLAY_ALL_OBJECTS;
SingleDecal[ iCount ].usEnd = 0;
SingleDecal[ iCount ].uiObjIndx = FIFTHWALLDECAL + iCount2;
}
SingleDecal[ iCount ].ubType = DISPLAY_GRAPHIC;
SingleDecal[ iCount ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTSWITCHES]].hTileSurface;
SingleDecal[ iCount ].usStart = DISPLAY_ALL_OBJECTS;
SingleDecal[ iCount ].usEnd = 0;
SingleDecal[ iCount ].uiObjIndx = FIRSTSWITCHES;
//Floors
for ( iCount = 0; iCount < (LASTFLOOR - FIRSTFLOOR + 1); iCount++ )
{
SingleFloor[ iCount ].ubType = DISPLAY_GRAPHIC;
SingleFloor[ iCount ].hVObject = gTileDatabase[gTileTypeStartIndex[FIRSTFLOOR + iCount]].hTileSurface;
SingleFloor[ iCount ].usStart = 0;
SingleFloor[ iCount ].usEnd = 7;
SingleFloor[ iCount ].uiObjIndx = FIRSTFLOOR + iCount;
}
//Toilets
for ( iCount = 0; iCount < (EIGHTISTRUCT - FIFTHISTRUCT + 1); iCount++ )
{
SingleToilet[ iCount ].ubType = DISPLAY_GRAPHIC;
SingleToilet[ iCount ].hVObject = gTileDatabase[gTileTypeStartIndex[FIFTHISTRUCT + iCount]].hTileSurface;
SingleToilet[ iCount ].usStart = DISPLAY_ALL_OBJECTS;
SingleToilet[ iCount ].usEnd = 0;
SingleToilet[ iCount ].uiObjIndx = FIFTHISTRUCT + iCount;
}
}
//----------------------------------------------------------------------------------------------
// ShutdownJA2SelectionWindow
//
// Unloads selection window button images and makes sure any display list that may remain in memory
// is removed.
//
void ShutdownJA2SelectionWindow( void )
{
INT16 x;
for (x = 0; x < 4; x++)
UnloadGenericButtonIcon( (INT16)iButtonIcons[x] );
if (pDispList != NULL)
{
pDispList = TrashList(pDispList);
}
gfRenderWorld = TRUE;
}
//----------------------------------------------------------------------------------------------
// RemoveJA2SelectionWindow
//
// Removes the selection window from the screen.
//
void RemoveJA2SelectionWindow( void )
{
RemoveButton(iSelectWin);
RemoveButton(iCancelWin);
RemoveButton(iScrollUp);
RemoveButton(iScrollDown);
RemoveButton(iOkWin);
gfRenderSquareArea = FALSE;
if (pDispList != NULL)
{
pDispList = TrashList(pDispList);
}
gfRenderTaskbar = TRUE;
gfOverheadMapDirty = TRUE;
EnableEditorTaskbar( );
}
//----------------------------------------------------------------------------------------------
// TrashList
//
// Free the current display list for the selection window.
//
DisplayList *TrashList( DisplayList *pNode )
{
if (pNode == NULL)
return(NULL);
if (pNode->pNext != NULL)
pNode->pNext = TrashList(pNode->pNext);
if (pNode->pNext == NULL)
MemFree(pNode);
return(NULL);
}
//----------------------------------------------------------------------------------------------
// RenderSelectionWindow
//
// Displays the current selection window
//
void RenderSelectionWindow( void )
{
GUI_BUTTON *button;
INT32 iSX,iSY,iEX,iEY;
UINT16 usFillColor;
static UINT8 usFillGreen = 0;
static UINT8 usDir = 5;
if (!fButtonsPresent)
return;
ColorFillVideoSurfaceArea(FRAME_BUFFER,
gSelection.window.iLeft, gSelection.window.iTop, gSelection.window.iRight, gSelection.window.iBottom,
GenericButtonFillColors[0]
);
DrawSelections( );
MarkButtonsDirty();
RenderButtons( );
// Draw selection rectangle
if ( gfRenderSquareArea )
{
button = ButtonList[iSelectWin];
if ( button == NULL )
return;
if ( (abs( iStartClickX - button->Area.MouseXPos ) > 9) ||
(abs( iStartClickY - (button->Area.MouseYPos + iTopWinCutOff - (INT16)gSelection.displayAreaStart.iY)) > 9) )
{
// iSX = (INT32)iStartClickX;
// iEX = (INT32)button->Area.MouseXPos;
// iSY = (INT32)iStartClickY;
// iEY = (INT32)(button->Area.MouseYPos + iTopWinCutOff - (INT16)SelWinStartPoint.iY);
iSX = iStartClickX;
iSY = iStartClickY - iTopWinCutOff + gSelection.displayAreaStart.iY;
iEX = gusMouseXPos;
iEY = gusMouseYPos;
if (iEX < iSX)
{
iEX ^= iSX;
iSX ^= iEX;
iEX ^= iSX;
}
if (iEY < iSY)
{
iEY ^= iSY;
iSY ^= iEY;
iEY ^= iSY;
}
iEX = min( gSelection.displayAreaEnd.iX, iEX);
iSY = max( gSelection.displayAreaStart.iY, iSY );
iEY = min( gSelection.displayAreaEnd.iY, iEY );
iEY = max( gSelection.displayAreaStart.iY, iEY );
usFillColor = Get16BPPColor(FROMRGB(255, usFillGreen, 0));
usFillGreen += usDir;
if( usFillGreen > 250 )
usDir = 251;
else if( usFillGreen < 5 )
usDir = 5;
ColorFillVideoSurfaceArea(FRAME_BUFFER, iSX, iSY, iEX, iSY+1, usFillColor );
ColorFillVideoSurfaceArea(FRAME_BUFFER, iSX, iEY, iEX, iEY+1, usFillColor );
ColorFillVideoSurfaceArea(FRAME_BUFFER, iSX, iSY, iSX+1, iEY, usFillColor );
ColorFillVideoSurfaceArea(FRAME_BUFFER, iEX, iSY, iEX+1, iEY, usFillColor );
}
}
}
//----------------------------------------------------------------------------------------------
// SelWinClkCallback
//
// Button callback function for the main selection window. Checks if user clicked on an image,
// if so selects or de-selects that object. Also handles the multi-object selection (left-click
// and drag to get the selection rectangle)
//
void SelWinClkCallback( GUI_BUTTON *button, INT32 reason )
{
DisplayList *pNode;
BOOLEAN fDone;
INT16 iClickX,iClickY, iYInc, iXInc;
if (!(button->uiFlags & BUTTON_ENABLED))
return;
iClickX = button->Area.MouseXPos;
iClickY = button->Area.MouseYPos + iTopWinCutOff - (INT16)gSelection.displayAreaStart.iY;
if (reason & MSYS_CALLBACK_REASON_LBUTTON_DWN)
{
button->uiFlags |= BUTTON_CLICKED_ON;
iStartClickX = iClickX;
iStartClickY = iClickY;
gfRenderSquareArea = TRUE;
}
else if (reason & MSYS_CALLBACK_REASON_RBUTTON_DWN)
{
button->uiFlags |= BUTTON_CLICKED_ON;
if ( gfRenderSquareArea )
{
gfRenderSquareArea = FALSE;
return;
}
// Code to figure out what image user wants goes here
pNode = pDispList;
fDone = FALSE;
while( (pNode != NULL) && !fDone )
{
if ( (iClickX >= pNode->iX) && (iClickX < (pNode->iX + pNode->iWidth)) &&
(iClickY >= pNode->iY) && (iClickY < (pNode->iY + pNode->iHeight)) )
{
fDone = TRUE;
if ( RemoveFromSelectionList(pNode) )
pNode->fChosen = FALSE;
}
else
pNode = pNode->pNext;
}
}
else if (reason & MSYS_CALLBACK_REASON_RBUTTON_UP )
{
button->uiFlags &= (~BUTTON_CLICKED_ON);
}
else if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
{
button->uiFlags &= (~BUTTON_CLICKED_ON);
if( !gfRenderSquareArea )
return;
iEndClickX = iClickX;
iEndClickY = iClickY;
gfRenderSquareArea = FALSE;
if( iEndClickX < iStartClickX )
{
iStartClickX ^= iEndClickX;
iEndClickX ^= iStartClickX;
iStartClickX ^= iEndClickX;
}
if( iEndClickY < iStartClickY )
{
iStartClickY ^= iEndClickY;
iEndClickY ^= iStartClickY;
iStartClickY ^= iEndClickY;
}
iXInc = iYInc = 1;
for( iClickY = iStartClickY; iClickY <= iEndClickY; iClickY += iYInc )
{
iYInc = 1;
for( iClickX = iStartClickX; iClickX <= iEndClickX; iClickX += iXInc )
{
iXInc = 1;
// Code to figure out what image user wants goes here
pNode = pDispList;
fDone = FALSE;
while( (pNode != NULL) && !fDone )
{
if ( (iClickX >= pNode->iX) && (iClickX < (pNode->iX + pNode->iWidth)) &&
(iClickY >= pNode->iY) && (iClickY < (pNode->iY + pNode->iHeight)) )
{
fDone = TRUE;
AddToSelectionList(pNode);
pNode->fChosen = TRUE;
iXInc = (pNode->iX + pNode->iWidth) - iClickX;
if ( iYInc < ((pNode->iY + pNode->iHeight) - iClickY) )
iYInc = (pNode->iY + pNode->iHeight) - iClickY;
}
else
pNode = pNode->pNext;
}
}
}
}
}
//When a selection window is up, the file information of the picture will display
//at the top of the screen.
void DisplaySelectionWindowGraphicalInformation()
{
DisplayList *pNode;
BOOLEAN fDone;
//UINT16 usObjIndex, usIndex;
UINT16 y;
//Determine if there is a valid picture at cursor position.
//iRelX = gusMouseXPos;
//iRelY = gusMouseYPos + iTopWinCutOff - (INT16)gSelection.displayAreaStart.iY;
y = gusMouseYPos + iTopWinCutOff - (UINT16)gSelection.displayAreaStart.iY;
pNode = pDispList;
fDone = FALSE;
while( (pNode != NULL) && !fDone )
{
if ( (gusMouseXPos >= pNode->iX) && (gusMouseXPos < (pNode->iX + pNode->iWidth)) &&
(y >= pNode->iY) && (y < (pNode->iY + pNode->iHeight)) )
{
fDone = TRUE;
//pNode->fChosen = TRUE;
//iXInc = (pNode->iX + pNode->iWidth) - iClickX;
//if ( iYInc < ((pNode->iY + pNode->iHeight) - iClickY) )
// iYInc = (pNode->iY + pNode->iHeight) - iClickY;
}
else
pNode = pNode->pNext;
}
SetFont( FONT12POINT1 );
SetFontForeground( FONT_WHITE );
if( pNode )
{
//usObjIndex = (UINT16)pNode->uiObjIndx;
//usIndex = pNode->uiIndex;
if( !gTilesets[ giCurrentTilesetID].TileSurfaceFilenames[ pNode->uiObjIndx ][0] )
{
mprintf( 2, 2, pDisplaySelectionWindowGraphicalInformationText[0],
gTilesets[0].TileSurfaceFilenames[ pNode->uiObjIndx ],
pNode->uiIndex, gTilesets[0].zName,
gTileTypeStartIndex[pNode->uiObjIndx]+pNode->uiIndex,
gTileSurfaceName[ pNode->uiObjIndx ] );
}
else
{
mprintf( 2, 2, pDisplaySelectionWindowGraphicalInformationText[1],
gTilesets[ giCurrentTilesetID ].TileSurfaceFilenames[ pNode->uiObjIndx ],
pNode->uiIndex, gTileTypeStartIndex[pNode->uiObjIndx]+pNode->uiIndex,
gTileSurfaceName[ pNode->uiObjIndx ] );
}
}
mprintf( 390, 2, pDisplaySelectionWindowGraphicalInformationText[2], gTilesets[ giCurrentTilesetID ].zName );
}
//----------------------------------------------------------------------------------------------
// AddToSelectionList
//
// Add an object in the display list to the selection list. If the object already exists in the
// selection list, then it's count is incremented.
//
void AddToSelectionList( DisplayList *pNode )
{
INT32 iIndex, iUseIndex = -1;
for (iIndex = 0; iIndex < (*pNumSelList); iIndex++ )
{
if ( pNode->uiObjIndx == pSelList[ iIndex ].uiObject &&
pNode->uiIndex == pSelList[ iIndex ].usIndex )
{
iUseIndex = iIndex;
break;
}
}
if ( iUseIndex >= 0 )
{
// Was already in the list, so bump up the count
pSelList[ iUseIndex ].sCount++;
}
else
{
// Wasn't in the list, so add to end (if space available)
if ( (*pNumSelList) < MAX_SELECTIONS )
{
pSelList[ (*pNumSelList) ].uiObject = pNode->uiObjIndx;
pSelList[ (*pNumSelList) ].usIndex = pNode->uiIndex;
pSelList[ (*pNumSelList) ].sCount = 1;
(*pNumSelList)++;
}
}
}
//----------------------------------------------------------------------------------------------
// ClearSelectionList
//
// Removes everything from the current selection list
//
BOOLEAN ClearSelectionList( void )
{
INT32 iIndex;
DisplayList *pNode;
if (pNumSelList == NULL )
return( FALSE );
pNode = pDispList;
while ( pNode != NULL )
{
pNode->fChosen = FALSE;
pNode = pNode->pNext;
}
for (iIndex = 0; iIndex < (*pNumSelList); iIndex++ )
pSelList[ iIndex ].sCount = 0;
(*pNumSelList) = 0;
return( TRUE );
}
//----------------------------------------------------------------------------------------------
// RemoveFromSelectionList
//
// Removes the object given n a display list from the selection list. If the objects count is
// greater than one, then the count is decremented and the object remains in the list.
//
BOOLEAN RemoveFromSelectionList( DisplayList *pNode )
{
INT32 iIndex, iUseIndex = -1;
BOOLEAN fRemoved;
// Abort if no entries in list (pretend we removed a node)
if ( (*pNumSelList) <= 0 )
return( TRUE );
fRemoved = FALSE;
for (iIndex = 0; iIndex < (*pNumSelList); iIndex++ )
{
if ( pNode->uiObjIndx == pSelList[ iIndex ].uiObject &&
pNode->uiIndex == pSelList[ iIndex ].usIndex )
{
iUseIndex = iIndex;
break;
}
}
if ( iUseIndex >= 0 )
{
// Was already in the list, so bump up the count
pSelList[ iUseIndex ].sCount--;
if ( pSelList[ iUseIndex ].sCount <= 0 )
{
// Squash the list to remove old entry
for ( iIndex = iUseIndex; iIndex < ((*pNumSelList) - 1); iIndex++ )
pSelList[ iIndex ] = pSelList[ iIndex + 1 ];
(*pNumSelList)--;
fRemoved = TRUE;
}
}
return ( fRemoved );
}
//----------------------------------------------------------------------------------------------
// GetRandomSelection
//
// Randomly selects an item in the selection list. The object counts are taken into account so
// that objects with higher counts will be chosen more often.
//
INT32 GetRandomSelection( void )
{
INT32 iRandNum, iTotalCounts;
INT32 iIndex, iSelectedIndex, iNextCount;
if ( fDontUseRandom )
{
//fDontUseRandom = FALSE;//dnl ch8 210909 this was old way when random was almost always selected, new way is enable/disable through switching with key 'R'
return( iCurBank );
}
iTotalCounts = 0;
for (iIndex = 0; iIndex < (*pNumSelList); iIndex++ )
iTotalCounts += (INT32)pSelList[ iIndex ].sCount;
iRandNum = Random( iTotalCounts );
iSelectedIndex = -1;
iNextCount = 0;
for (iIndex = 0; iIndex < (*pNumSelList) && iSelectedIndex == -1; iIndex++ )
{
iNextCount += (INT32)pSelList[ iIndex ].sCount;
if ( iRandNum < iNextCount )
iSelectedIndex = iIndex;
}
return ( iSelectedIndex );
}
//----------------------------------------------------------------------------------------------
// IsInSelectionList
//
// Verifies if a particular display list object exists in the current selection list.
//
BOOLEAN IsInSelectionList( DisplayList *pNode )
{
INT32 iIndex;
BOOLEAN fFound;
fFound = FALSE;
for (iIndex = 0; iIndex < (*pNumSelList) && !fFound; iIndex++ )
{
if ( pNode->uiObjIndx == pSelList[ iIndex ].uiObject &&
pNode->uiIndex == pSelList[ iIndex ].usIndex )
{
fFound = TRUE;
}
}
return ( fFound );
}
//----------------------------------------------------------------------------------------------
// FindInSelectionList
//
// Finds an occurance of a particular display list object in the current selection list.
// if found, returns the selection list's index where it can be found. otherwise it
// returns -1
//
INT32 FindInSelectionList( DisplayList *pNode )
{
INT32 iIndex,iUseIndex;
BOOLEAN fFound;
fFound = FALSE;
iUseIndex = -1;
for (iIndex = 0; iIndex < (*pNumSelList) && !fFound; iIndex++ )
{
if ( pNode->uiObjIndx == pSelList[ iIndex ].uiObject &&
pNode->uiIndex == pSelList[ iIndex ].usIndex )
{
fFound = TRUE;
iUseIndex = iIndex;
}
}
return ( iUseIndex );
}
//----------------------------------------------------------------------------------------------
// SaveSelectionList
//
// Copies the current selection list to a save buffer. Used in case we want to cancel a
// selection window.
//
void SaveSelectionList( void )
{
INT32 iIndex;
for (iIndex = 0; iIndex < MAX_SELECTIONS; iIndex++ )
OldSelList[ iIndex ] = pSelList[ iIndex ];
iOldNumSelList = (*pNumSelList);
}
//----------------------------------------------------------------------------------------------
// RestoreSelectionList
//
// Copies the selection list in the save buffer back to the current selection list.
//
void RestoreSelectionList( void )
{
INT32 iIndex;
for (iIndex = 0; iIndex < MAX_SELECTIONS; iIndex++ )
pSelList[ iIndex ] = OldSelList[ iIndex ];
(*pNumSelList) = iOldNumSelList;
}
//----------------------------------------------------------------------------------------------
// OkClkCallback
//
// Button callback function for the selection window's OK button
void OkClkCallback( GUI_BUTTON *button, INT32 reason )
{
if (reason & MSYS_CALLBACK_REASON_LBUTTON_DWN )
{
button->uiFlags |= BUTTON_CLICKED_ON;
}
else if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
{
button->uiFlags &= (~BUTTON_CLICKED_ON);
fAllDone = TRUE;
}
}
//----------------------------------------------------------------------------------------------
// CnclClkCallback
//
// Button callback function for the selection window's CANCEL button
//
void CnclClkCallback( GUI_BUTTON *button, INT32 reason )
{
if (reason & MSYS_CALLBACK_REASON_LBUTTON_DWN )
{
button->uiFlags |= BUTTON_CLICKED_ON;
}
else if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
{
button->uiFlags &= (~BUTTON_CLICKED_ON);
fAllDone = TRUE;
RestoreSelectionList();
}
}
//----------------------------------------------------------------------------------------------
// UpClkCallback
//
// Button callback function for scrolling the selection window up
//
void UpClkCallback( GUI_BUTTON *button, INT32 reason )
{
if( reason & MSYS_CALLBACK_REASON_LBUTTON_DWN )
{
button->uiFlags |= BUTTON_CLICKED_ON;
}
else if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
{
button->uiFlags &= (~BUTTON_CLICKED_ON );
ScrollSelWinUp();
}
}
//----------------------------------------------------------------------------------------------
// ScrollSelWinUp
//
// Performs the calculations required to actually scroll a selection window up by one line.
//
void ScrollSelWinUp(void)
{
DisplayList *pNode;
INT16 iCutOff,iBotCutOff;
BOOLEAN fDone;
// Code to scroll window up!
pNode = pDispList;
iCutOff = iTopWinCutOff;
fDone = FALSE;
while( (pNode != NULL) && !fDone )
{
if (pNode->iY >= iTopWinCutOff)
{
iCutOff = pNode->iY;
pNode = pNode->pNext;
}
else
{
iCutOff = pNode->iY;
fDone = TRUE;
}
}
iBotCutOff = iBotWinCutOff - iTopWinCutOff + iCutOff;
iTopWinCutOff = iCutOff;
}
//----------------------------------------------------------------------------------------------
// ScrollSelWinDown
//
// Performs the actual calculations for scrolling a selection window down.
//
void ScrollSelWinDown(void)
{
DisplayList *pNode;
INT16 iCutOff,iBotCutOff;
BOOLEAN fDone;
pNode = pDispList;
iCutOff = iTopWinCutOff;
fDone = FALSE;
while( (pNode != NULL) && !fDone )
{
if (pNode->iY > iTopWinCutOff)
{
iCutOff = pNode->iY;
pNode = pNode->pNext;
}
else
fDone = TRUE;
}
iBotCutOff = iBotWinCutOff - iTopWinCutOff + iCutOff;
iTopWinCutOff = iCutOff;
}
//----------------------------------------------------------------------------------------------
// DwnClkCallback
//
// Button callback function to scroll the selection window down.
//
void DwnClkCallback( GUI_BUTTON *button, INT32 reason )
{
if (reason & MSYS_CALLBACK_REASON_LBUTTON_DWN)
{
button->uiFlags |= BUTTON_CLICKED_ON;
}
else if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
{
button->uiFlags &= (~BUTTON_CLICKED_ON);
ScrollSelWinDown();
}
}
//----------------------------------------------------------------------------------------------
// DrawSelections
//
// Displays the objects in the display list to the selection window.
//
void DrawSelections( void )
{
SGPRect ClipRect, NewRect;
NewRect.iLeft = gSelection.displayAreaStart.iX;
NewRect.iTop = gSelection.displayAreaStart.iY;
NewRect.iRight = gSelection.displayAreaEnd.iX;
NewRect.iBottom = gSelection.displayAreaEnd.iY;
GetClippingRect(&ClipRect);
SetClippingRect(&NewRect);
// SetFont( gpSmallFont );
SetFont( gpLargeFontType1 );
SetObjectShade( gvoLargeFontType1, 0 );
// SetObjectShade( gvoLargeFont, 0 );
DisplayWindowFunc( pDispList, iTopWinCutOff, iBotWinCutOff, &gSelection.displayAreaStart, CLEAR_BACKGROUND );
SetObjectShade( gvoLargeFontType1, 4 );
SetClippingRect(&ClipRect);
}
//----------------------------------------------------------------------------------------------
// BuildDisplayWindow
//
// Creates a display list from a display specification list. It also sets variables up for
// properly scrolling the window etc.
//
BOOLEAN BuildDisplayWindow( DisplaySpec *pDisplaySpecs, UINT16 usNumSpecs, DisplayList **pDisplayList,
SGPPoint * pUpperLeft, SGPPoint * pBottomRight,
SGPPoint * pSpacing, UINT16 fFlags )
{
INT32 iCurrX = pUpperLeft->iX;
INT32 iCurrY = pUpperLeft->iY;
UINT16 usGreatestHeightInRow = 0;
UINT16 usSpecLoop;
UINT16 usETRLELoop;
UINT16 usETRLEStart;
UINT16 usETRLEEnd;
DisplaySpec * pDisplaySpec;
ETRLEObject * pETRLEObject;
DisplayList *pCurNode;
SaveSelectionList();
for (usSpecLoop = 0; usSpecLoop < usNumSpecs; usSpecLoop++)
{
pDisplaySpec = &(pDisplaySpecs[usSpecLoop]);
if (pDisplaySpec->ubType == DISPLAY_GRAPHIC)
{
if( !pDisplaySpec->hVObject )
return FALSE;
usETRLEStart = pDisplaySpec->usStart;
usETRLEEnd = pDisplaySpec->usEnd;
if ( usETRLEStart == DISPLAY_ALL_OBJECTS )
{
usETRLEStart = 0;
usETRLEEnd = pDisplaySpec->hVObject->usNumberOfObjects - 1;
}
if( usETRLEStart > usETRLEEnd )
return FALSE;
if( usETRLEEnd >= pDisplaySpec->hVObject->usNumberOfObjects )
return FALSE;
for( usETRLELoop = usETRLEStart; usETRLELoop <= usETRLEEnd; usETRLELoop++)
{
pETRLEObject = &(pDisplaySpec->hVObject->pETRLEObject[usETRLELoop]);
if ((iCurrX + pETRLEObject->usWidth > pBottomRight->iX) || (fFlags & ONE_COLUMN))
{
if (fFlags & ONE_ROW)
{
break;
}
iCurrX = pUpperLeft->iX;
iCurrY += usGreatestHeightInRow + pSpacing->iY;
usGreatestHeightInRow = 0;
}
if ((pCurNode = (DisplayList *)MemAlloc(sizeof(DisplayList))) != FALSE)
{
pCurNode->hObj = pDisplaySpec->hVObject;
pCurNode->uiIndex = usETRLELoop;
pCurNode->iX = (INT16)iCurrX;
pCurNode->iY = (INT16)iCurrY;
pCurNode->iWidth = pETRLEObject->usWidth;
pCurNode->iHeight = pETRLEObject->usHeight;
pCurNode->pNext = *pDisplayList;
pCurNode->uiObjIndx = pDisplaySpec->uiObjIndx;
if ( IsInSelectionList( pCurNode ) )
pCurNode->fChosen = TRUE;
else
pCurNode->fChosen = FALSE;
*pDisplayList = pCurNode;
}
else
return(FALSE);
if (pETRLEObject->usHeight > usGreatestHeightInRow)
{
usGreatestHeightInRow = pETRLEObject->usHeight;
}
iCurrX += pETRLEObject->usWidth + pSpacing->iX;
}
}
}
return( TRUE );
}
//----------------------------------------------------------------------------------------------
// DisplayWindowFunc
//
// Blits the actual object images in the display list on the selection window. The objects that
// have been selected (in the selection list) are highlighted and the count placed in the upper
// left corner of the image.
//
BOOLEAN DisplayWindowFunc( DisplayList *pNode, INT16 iTopCutOff, INT16 iBottomCutOff, SGPPoint *pUpperLeft, UINT16 fFlags)
{
INT16 iCurrY;
INT16 sTempOffsetX;
INT16 sTempOffsetY;
BOOLEAN fReturnVal;
ETRLEObject * pETRLEObject;
UINT16 usFillColor;
INT16 sCount;
if ( pNode == NULL )
return(TRUE);
if ( pNode->iY < iTopCutOff )
return(TRUE);
fReturnVal = FALSE;
if (DisplayWindowFunc(pNode->pNext, iTopCutOff, iBottomCutOff, pUpperLeft, fFlags))
{
iCurrY = (INT16) pUpperLeft->iY + pNode->iY - iTopCutOff;
if ( iCurrY > iBottomCutOff )
return(TRUE);
pETRLEObject = &(pNode->hObj->pETRLEObject[pNode->uiIndex]);
// We have to store the offset data in temp variables before zeroing them and blitting
sTempOffsetX = pETRLEObject->sOffsetX;
sTempOffsetY = pETRLEObject->sOffsetY;
// Set the offsets used for blitting to 0
pETRLEObject->sOffsetX = 0;
pETRLEObject->sOffsetY = 0;
if (fFlags & CLEAR_BACKGROUND)
{
usFillColor = SelWinFillColor;
if (pNode->fChosen)
usFillColor = SelWinHilightFillColor;
ColorFillVideoSurfaceArea( FRAME_BUFFER, pNode->iX, iCurrY,
pNode->iX + pNode->iWidth,
iCurrY + pNode->iHeight, usFillColor);
}
sCount = 0;
if (pNode->fChosen)
sCount = pSelList[ FindInSelectionList( pNode ) ].sCount;
SetObjectShade( pNode->hObj, DEFAULT_SHADE_LEVEL );
fReturnVal = BltVideoObject( FRAME_BUFFER, pNode->hObj, pNode->uiIndex,
(UINT16)pNode->iX, (UINT16)iCurrY,
VO_BLT_SRCTRANSPARENCY, NULL);
if ( sCount != 0)
{
SetFontShade(LARGEFONT1, FONT_SHADE_WHITE);
gprintf( pNode->iX, iCurrY, L"%d", sCount );
}
pETRLEObject->sOffsetX = sTempOffsetX;
pETRLEObject->sOffsetY = sTempOffsetY;
}
return(fReturnVal);
}
#endif