Files
source/Editor/selectwin.cpp
T
00fb898600 Delete builddefines.h
Nothing was left in it but the include of profiler.h, and 132 translation units
were including it for that alone. Fifteen files were leaning on profiler.h to
drag in <set>, <vector> and <ostream> for them; those now include what they use.

This is the commit that moves line numbers. Removing an include line shifts
__LINE__ by one for everything below it, and __LINE__ is an immediate operand in
every Assert() and DebugMsg() call, so the four game executables differ from
their predecessors by roughly a thousand 32-bit constants each. Every one of
those is accounted for: each is a single immediate that moved by -1 where the
builddefines.h include went away, or +1 where a <set>/<vector> include was
added. Nothing else in .text, .rdata or .data moves, no object file's section
sizes change, and symbolize_crash and Ja2Export stay bit-identical.

The one non-immediate difference is that the 24 Editor translation units of the
non-editor apps stop emitting __Avx2WmemEnabledWeakValue, a 4-byte weak COMDAT
they only ever instantiated through profiler.h's <vector>. It is a UCRT weak
default that other translation units still provide.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 01:07:26 -03:00

1697 lines
54 KiB
C++

// WANNE: EDITOR: todo
#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