Files
source/Editor/Editor Taskbar Utils.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

1065 lines
35 KiB
C++

#ifdef JA2EDITOR
#include <stdio.h>
#include "types.h"
#include "mousesystem.h"
#include "Button System.h"
#include "Font Control.h"
#include "Isometric Utils.h"
#include "WorldDat.h"
#include "Render Dirty.h"
#include "sysutil.h"
#include "WordWrap.h"
#include "environment.h"
#include "Interface Items.h"
#include "Soldier Find.h"
#include "World Items.h"
#include "Text.h"
#include "overhead map.h"
#include "Cursor Modes.h"
#include "editscreen.h"
#include "EditorTerrain.h"
#include "Cursor Modes.h"
#include "EditorItems.h"
#include "EditorMercs.h"
#include "EditorBuildings.h"
#include "EditorMapInfo.h"
#include "EditorDefines.h"
#include "Editor Taskbar Utils.h"
#include "Editor Taskbar Creation.h"
#include "Editor Callback Prototypes.h"
#include "Editor Modes.h"
#include "Text Input.h"
#include "Item Statistics.h"
#include "Map Information.h"
#include "Sector Summary.h"
#include "Item Statistics.h"
#include "pits.h"
#include "Soldier Find.h"
#include "lighting.h"
#include "Keys.h"
#include "InterfaceItemImages.h"
#include "renderworld.h"//dnl ch78 271113
void RenderEditorInfo();
//editor icon storage vars
INT32 giEditMercDirectionIcons[2];
UINT32 guiMercInventoryPanel;
UINT32 guiOmertaMap;
UINT32 guiMercInvPanelBuffers[9];
UINT32 guiMercTempBuffer;
INT32 giEditMercImage[2];
UINT32 guiExclamation;
UINT32 guiKeyImage;
//editor Mouseregion storage vars
MOUSE_REGION TerrainTileButtonRegion[ NUM_TERRAIN_TILE_REGIONS ];
MOUSE_REGION ItemsRegion;
MOUSE_REGION MercRegion;
MOUSE_REGION EditorRegion;
void EnableEditorRegion( INT8 bRegionID )
{
switch( bRegionID )
{
case BASE_TERRAIN_TILE_REGION_ID:
case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
MSYS_EnableRegion( &TerrainTileButtonRegion[ bRegionID ] );
break;
case ITEM_REGION_ID:
MSYS_EnableRegion( &ItemsRegion );
break;
case MERC_REGION_ID:
MSYS_EnableRegion( &MercRegion );
break;
}
}
void DisableEditorRegion( INT8 bRegionID )
{
switch( bRegionID )
{
case BASE_TERRAIN_TILE_REGION_ID:
case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8://dnl ch78 261113
MSYS_DisableRegion( &TerrainTileButtonRegion[ bRegionID ] );
break;
case ITEM_REGION_ID:
MSYS_DisableRegion( &ItemsRegion );
break;
case MERC_REGION_ID:
MSYS_DisableRegion( &MercRegion );
break;
}
}
void RemoveEditorRegions()
{
INT32 x;
MSYS_RemoveRegion( &EditorRegion );
for(x = BASE_TERRAIN_TILE_REGION_ID; x < NUM_TERRAIN_TILE_REGIONS; x++ )
{
MSYS_RemoveRegion( &TerrainTileButtonRegion[ x ] );
}
MSYS_RemoveRegion( &ItemsRegion );
MSYS_RemoveRegion( &MercRegion );
}
void InitEditorRegions()
{
INT32 x;
//By doing this, all of the buttons underneath are blanketed and can't be used anymore.
//Any new buttons will cover this up as well. Think of it as a barrier between the editor buttons,
//and the game's interface panel buttons and regions.
MSYS_DefineRegion( &EditorRegion, 0, SCREEN_HEIGHT - 120, SCREEN_WIDTH, SCREEN_HEIGHT, MSYS_PRIORITY_NORMAL, 0, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK );
//Create the regions for the terrain tile selections
for( x = 0; x < NUM_TERRAIN_TILE_REGIONS; x++ )
{
MSYS_DefineRegion(&TerrainTileButtonRegion[x],(INT16)(iScreenWidthOffset + 261+x*42), 2 * iScreenHeightOffset + 369,(INT16)(iScreenWidthOffset + 303+x*42),2 * iScreenHeightOffset + 391,
MSYS_PRIORITY_NORMAL, 0, MSYS_NO_CALLBACK,(MOUSE_CALLBACK)TerrainTileButtonRegionCallback);
MSYS_SetRegionUserData( &TerrainTileButtonRegion[x], 0, x );
MSYS_DisableRegion( &TerrainTileButtonRegion[x] );
}
gfShowTerrainTileButtons=FALSE;
//Create the region for the items selection window.
MSYS_DefineRegion( &ItemsRegion, iScreenWidthOffset + 100, 2 * iScreenHeightOffset + 360, iScreenWidthOffset + 540, 2 * iScreenHeightOffset + 440, MSYS_PRIORITY_NORMAL, 0,
(MOUSE_CALLBACK)MouseMovedInItemsRegion, (MOUSE_CALLBACK)MouseClickedInItemsRegion );
MSYS_DisableRegion( &ItemsRegion );
//Create the region for the merc inventory panel.
MSYS_DefineRegion( &MercRegion, iScreenWidthOffset + 175, 2 * iScreenHeightOffset + 361, iScreenWidthOffset + 450, 2 * iScreenHeightOffset + 460, MSYS_PRIORITY_NORMAL, 0,
MouseMovedInMercRegion, MouseClickedInMercRegion );
MSYS_DisableRegion( &MercRegion );
}
void LoadEditorImages()
{
VOBJECT_DESC VObjectDesc;
//Set up the merc inventory panel
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
sprintf( VObjectDesc.ImageFile, "EDITOR\\InvPanel.sti" );
if( !AddVideoObject( &VObjectDesc, &guiMercInventoryPanel ) )
AssertMsg( 0, "Failed to load data\\editor\\InvPanel.sti" );
//Set up small omerta map
sprintf( VObjectDesc.ImageFile, "EDITOR\\omerta.sti" );
if( !AddVideoObject( &VObjectDesc, &guiOmertaMap ) )
AssertMsg( 0, "Failed to load data\\editor\\omerta.sti" );
//Set up the merc directional buttons.
giEditMercDirectionIcons[0] = LoadGenericButtonIcon("EDITOR//arrowsoff.sti");
giEditMercDirectionIcons[1] = LoadGenericButtonIcon("EDITOR//arrowson.sti");
giEditMercImage[0] = LoadButtonImage("EDITOR\\leftarrow.sti",0,1,2,3,4);
giEditMercImage[1] = LoadButtonImage("EDITOR\\rightarrow.sti",0,1,2,3,4);
sprintf( VObjectDesc.ImageFile, "EDITOR\\Exclamation.sti" );
if( !AddVideoObject( &VObjectDesc, &guiExclamation ) )
AssertMsg( 0, "Failed to load data\\editor\\Exclamation.sti" );
sprintf( VObjectDesc.ImageFile, "EDITOR\\KeyImage.sti" );
if( !AddVideoObject( &VObjectDesc, &guiKeyImage ) )
AssertMsg( 0, "Failed to load data\\editor\\KeyImage.sti" );
}
void DeleteEditorImages()
{
//The merc inventory panel
DeleteVideoObjectFromIndex( guiMercInventoryPanel );
DeleteVideoObjectFromIndex( guiOmertaMap );
//The merc directional buttons
UnloadGenericButtonIcon( (INT16)giEditMercDirectionIcons[0] );
UnloadGenericButtonIcon( (INT16)giEditMercDirectionIcons[1] );
UnloadButtonImage( giEditMercImage[0] );
UnloadButtonImage( giEditMercImage[1] );
}
void CreateEditorBuffers()
{
INT32 i;
VSURFACE_DESC vs_desc;
UINT16 usUselessWidth, usUselessHeight;
UINT8 ubBitDepth;
//create buffer for the transition slot for merc items. This slot contains the newly
//selected item graphic in it's inventory size version. This buffer is then scaled down
//into the associated merc inventory panel slot buffer which is approximately 20% smaller.
GetCurrentVideoSettings( &usUselessWidth, &usUselessHeight, &ubBitDepth );
vs_desc.fCreateFlags = VSURFACE_CREATE_DEFAULT | VSURFACE_SYSTEM_MEM_USAGE;
vs_desc.usWidth = 60;
vs_desc.usHeight = 25;
vs_desc.ubBitDepth = ubBitDepth;
if( !AddVideoSurface( &vs_desc, &guiMercTempBuffer ) )
AssertMsg( 0, "Failed to allocate memory for merc tempitem buffer." );
//create the nine buffers for the merc's inventory slots.
vs_desc.usHeight = MERCINV_SLOT_HEIGHT;
for( i = 0; i < 9; i++ )
{
vs_desc.usWidth = i<3 ? MERCINV_SMSLOT_WIDTH : MERCINV_LGSLOT_WIDTH;
if( !AddVideoSurface( &vs_desc, &guiMercInvPanelBuffers[i] ) )
AssertMsg( 0, "Failed to allocate memory for merc item[] buffers." );
}
}
void DeleteEditorBuffers()
{
INT32 i;
DeleteVideoSurfaceFromIndex( guiMercTempBuffer );
for( i = 0; i < 9; i++ )
{
DeleteVideoSurfaceFromIndex( guiMercInvPanelBuffers[ i ] );
}
}
void ShowEditorToolbar( INT32 iNewTaskMode )
{
switch( iNewTaskMode )
{
case TASK_TERRAIN: ShowEditorButtons( FIRST_TERRAIN_BUTTON, LAST_TERRAIN_BUTTON ); break;
case TASK_BUILDINGS: ShowEditorButtons( FIRST_BUILDINGS_BUTTON, LAST_BUILDINGS_BUTTON ); break;
case TASK_ITEMS: ShowEditorButtons( FIRST_ITEMS_BUTTON, LAST_ITEMS_BUTTON ); break;
case TASK_MERCS: ShowEditorButtons( FIRST_MERCS_TEAMMODE_BUTTON, LAST_MERCS_TEAMMODE_BUTTON ); break;
case TASK_MAPINFO: ShowEditorButtons( FIRST_MAPINFO_BUTTON, LAST_MAPINFO_BUTTON ); break;
case TASK_OPTIONS: ShowEditorButtons( FIRST_OPTIONS_BUTTON, LAST_OPTIONS_BUTTON ); break;
default: return;
}
}
void HideEditorToolbar( INT32 iOldTaskMode )
{
INT32 i, iStart, iEnd;
switch( iOldTaskMode )
{
case TASK_TERRAIN: iStart = FIRST_TERRAIN_BUTTON; iEnd = LAST_TERRAIN_BUTTON; break;
case TASK_BUILDINGS: iStart = FIRST_BUILDINGS_BUTTON; iEnd = LAST_BUILDINGS_BUTTON; break;
case TASK_ITEMS: iStart = FIRST_ITEMS_BUTTON; iEnd = LAST_ITEMS_BUTTON; break;
case TASK_MERCS: iStart = FIRST_MERCS_BUTTON; iEnd = LAST_MERCS_BUTTON; break;
case TASK_MAPINFO: iStart = FIRST_MAPINFO_BUTTON; iEnd = LAST_MAPINFO_BUTTON; break;
case TASK_OPTIONS: iStart = FIRST_OPTIONS_BUTTON; iEnd = LAST_OPTIONS_BUTTON; break;
default: return;
}
for( i = iStart; i <= iEnd; i++ )
{
HideButton( iEditorButton[ i ] );
UnclickEditorButton( i );
}
}
void CreateEditorTaskbar()
{
InitEditorRegions();
LoadEditorImages();
CreateEditorBuffers();
CreateEditorTaskbarInternal();
HideItemStatsPanel();
}
void DeleteEditorTaskbar()
{
INT32 x;
iOldTaskMode = iCurrentTaskbar;
for( x = 0; x < NUMBER_EDITOR_BUTTONS; x++ )
RemoveButton( iEditorButton[ x ] );
RemoveEditorRegions();
DeleteEditorImages();
DeleteEditorBuffers();
}
void DoTaskbar(void)
{
if(!iTaskMode || iTaskMode == iCurrentTaskbar )
{
return;
}
gfRenderTaskbar = TRUE;
HideEditorToolbar( iCurrentTaskbar );
//Special code when exiting previous editor tab
switch( iCurrentTaskbar )
{
case TASK_TERRAIN:
UnclickEditorButton( TAB_TERRAIN );
HideTerrainTileButtons();
break;
case TASK_BUILDINGS:
UnclickEditorButton( TAB_BUILDINGS );
KillTextInputMode();
break;
case TASK_ITEMS:
UnclickEditorButton( TAB_ITEMS );
HideItemStatsPanel();
if( eInfo.fActive )
ClearEditorItemsInfo();
gfShowPits = FALSE;
RemoveAllPits();
break;
case TASK_MERCS:
UnclickEditorButton( TAB_MERCS );
IndicateSelectedMerc( SELECT_NO_MERC );
SetMercEditingMode( MERC_NOMODE );
break;
case TASK_MAPINFO:
UnclickEditorButton( TAB_MAPINFO );
ExtractAndUpdateMapInfo();
KillTextInputMode();
HideExitGrids();
break;
case TASK_OPTIONS:
UnclickEditorButton( TAB_OPTIONS );
KillTextInputMode();
break;
}
//Setup the new tab mode
iCurrentTaskbar = iTaskMode;
ShowEditorToolbar( iTaskMode );
iTaskMode = TASK_NONE;
//Special code when entering a new editor tab
switch( iCurrentTaskbar )
{
case TASK_MERCS:
ClickEditorButton( TAB_MERCS );
ClickEditorButton( MERCS_ENEMY);
iDrawMode = DRAW_MODE_ENEMY;
SetMercEditingMode( MERC_TEAMMODE );
fBuildingShowRoofs = FALSE;
UpdateRoofsView();
//dnl ch78 261113
if(gfShowPlayers)
ClickEditorButton(MERCS_PLAYERTOGGLE);
if(gfShowEnemies)
ClickEditorButton(MERCS_ENEMYTOGGLE);
if(gfShowCreatures)
ClickEditorButton(MERCS_CREATURETOGGLE);
if(gfShowRebels)
ClickEditorButton(MERCS_REBELTOGGLE);
if(gfShowCivilians)
ClickEditorButton(MERCS_CIVILIANTOGGLE);
break;
case TASK_TERRAIN:
ClickEditorButton( TAB_TERRAIN );
ShowTerrainTileButtons();
SetEditorTerrainTaskbarMode( TERRAIN_FGROUND_TEXTURES );
break;
case TASK_BUILDINGS:
ClickEditorButton( TAB_BUILDINGS );
if(fBuildingShowRoofs)
ClickEditorButton( BUILDING_TOGGLE_ROOF_VIEW );
if(fBuildingShowWalls)
ClickEditorButton( BUILDING_TOGGLE_WALL_VIEW );
if(fBuildingShowRoomInfo)
ClickEditorButton( BUILDING_TOGGLE_INFO_VIEW );
if( gfCaves )
{
ClickEditorButton( BUILDING_CAVE_DRAWING );
iDrawMode = DRAW_MODE_CAVES;
}
else
{
ClickEditorButton( BUILDING_NEW_ROOM );
iDrawMode = DRAW_MODE_ROOM;
}
TerrainTileDrawMode = TERRAIN_TILES_BRETS_STRANGEMODE;
SetEditorSmoothingMode( gMapInformation.ubEditorSmoothingType );
gusSelectionType = gusSavedBuildingSelectionType;
SetupTextInputForBuildings();
break;
case TASK_ITEMS:
SetFont( FONT10ARIAL );
SetFontForeground( FONT_YELLOW );
ClickEditorButton( TAB_ITEMS );
ClickEditorButton( ITEMS_WEAPONS + eInfo.uiItemType - TBAR_MODE_ITEM_WEAPONS );
InitEditorItemsInfo( eInfo.uiItemType );
ShowItemStatsPanel();
gfShowPits = TRUE;
AddAllPits();
iDrawMode = DRAW_MODE_PLACE_ITEM;
break;
case TASK_MAPINFO:
ClickEditorButton( TAB_MAPINFO );
if ( gfFakeLights )
ClickEditorButton( MAPINFO_TOGGLE_FAKE_LIGHTS );
ClickEditorButton( MAPINFO_ADD_LIGHT1_SOURCE );
iDrawMode = DRAW_MODE_LIGHT;
TerrainTileDrawMode = TERRAIN_TILES_BRETS_STRANGEMODE;
SetupTextInputForMapInfo();
//dnl ch80 011213
SetEditorSmoothingMode(gMapInformation.ubEditorSmoothingType);
ChangeLightDefault(gbDefaultLightType);
break;
case TASK_OPTIONS:
iDrawMode = DRAW_MODE_NOTHING;//dnl ch22 210909
ClickEditorButton( TAB_OPTIONS );
TerrainTileDrawMode = TERRAIN_TILES_NODRAW;
if (gfResizeMapOnLoading)
ClickEditorButton(OPTIONS_RESIZE_MAP_ON_LOADING);
if (gfVanillaMode)
ClickEditorButton(OPTIONS_VANILLA_MODE);
SetupTextInputForOptions();
break;
}
}
//Disables the task bar, but leaves it on screen. Used when a selection window is up.
void DisableEditorTaskbar(void)
{
INT32 x;
for(x = 0; x < NUMBER_EDITOR_BUTTONS; x++ )
DisableButton( iEditorButton[ x ] );
}
void EnableEditorTaskbar(void)
{
INT32 x;
for(x = 0; x < NUMBER_EDITOR_BUTTONS; x++ )
EnableButton( iEditorButton[ x ] );
//Keep permanent buttons disabled.
DisableButton( iEditorButton[ MERCS_1 ] );
DisableButton( iEditorButton[ MAPINFO_LIGHT_PANEL ] );
DisableButton( iEditorButton[ MAPINFO_RADIO_PANEL ] );
DisableButton( iEditorButton[ ITEMSTATS_PANEL ] );
DisableButton( iEditorButton[ MERCS_PLAYERTOGGLE ] );
DisableButton( iEditorButton[ MERCS_PLAYER ] );
if( iCurrentTaskbar == TASK_ITEMS )
DetermineItemsScrolling();
}
//A specialized mprint function that'll restore the editor panel underneath the
//string before rendering the string. This is obviously only useful for drawing text
//in the editor taskbar.
void mprintfEditor(INT16 x, INT16 y, STR16 pFontString, ...)
{
va_list argptr;
CHAR16 string[512];
UINT16 uiStringLength, uiStringHeight;
Assert( pFontString != NULL );
va_start( argptr, pFontString ); // Set up variable argument pointer
vswprintf( string, pFontString, argptr); // process gprintf string (get output str)
va_end( argptr );
uiStringLength = StringPixLength( string, FontDefault );
uiStringHeight = GetFontHeight( FontDefault );
ClearTaskbarRegion( x, y, (INT16)(x+uiStringLength), (INT16)(y+uiStringHeight) );
mprintf( x, y, string );
}
void ClearTaskbarRegion( INT16 sLeft, INT16 sTop, INT16 sRight, INT16 sBottom )
{
ColorFillVideoSurfaceArea( ButtonDestBuffer, sLeft, sTop, sRight, sBottom, gusEditorTaskbarColor );
if( !sLeft )
{
ColorFillVideoSurfaceArea( ButtonDestBuffer, 0, sTop, 1, sBottom, gusEditorTaskbarHiColor );
sLeft++;
}
if( sTop == (SCREEN_HEIGHT - 120) )
{
ColorFillVideoSurfaceArea( ButtonDestBuffer, sLeft, 2 * iScreenHeightOffset + 360, sRight, 2 * iScreenHeightOffset + 361, gusEditorTaskbarHiColor );
sTop++;
}
if( sBottom == SCREEN_HEIGHT )
ColorFillVideoSurfaceArea( ButtonDestBuffer, sLeft, 2 * iScreenHeightOffset + 479, sRight, 2 * iScreenHeightOffset + 480, gusEditorTaskbarLoColor );
if( sRight == SCREEN_WIDTH )
ColorFillVideoSurfaceArea( ButtonDestBuffer, iScreenWidthOffset + 639, sTop, iScreenWidthOffset + 640, sBottom, gusEditorTaskbarLoColor );
InvalidateRegion( sLeft, sTop, sRight, sBottom );
}
//Kris:
//This is a new function which duplicates the older "yellow info boxes" that
//are common throughout the editor. This draws the yellow box with the indentation
//look.
void DrawEditorInfoBox( STR16 str, UINT32 uiFont, UINT16 x, UINT16 y, UINT16 w, UINT16 h )
{
UINT16 usFillColorDark, usFillColorLight, usFillColorBack;
UINT16 x2, y2;
UINT16 usStrWidth;
x2 = x + w;
y2 = y + h;
usFillColorDark = Get16BPPColor(FROMRGB(24, 61, 81));
usFillColorLight = Get16BPPColor(FROMRGB(136, 138, 135));
usFillColorBack = Get16BPPColor(FROMRGB(250, 240, 188));
ColorFillVideoSurfaceArea(ButtonDestBuffer, x, y, x2, y2, usFillColorDark);
ColorFillVideoSurfaceArea(ButtonDestBuffer, x + 1, y + 1, x2, y2, usFillColorLight);
ColorFillVideoSurfaceArea(ButtonDestBuffer, x + 1, y + 1, x2 - 1, y2 - 1, usFillColorBack);
usStrWidth = StringPixLength( str, uiFont );
if( usStrWidth > w )
{ //the string is too long, so use the wrapped method
y += 1;
DisplayWrappedString( x, y, w, 2, uiFont, FONT_BLACK, str, FONT_BLACK, TRUE, CENTER_JUSTIFIED );
return;
}
//center the string vertically and horizontally.
SetFont( uiFont );
SetFontForeground( FONT_BLACK );
SetFontShadow( FONT_BLACK );
x += (w - (UINT16)StringPixLength( str, uiFont )) / 2;
y += (h - (UINT16)GetFontHeight( uiFont)) / 2;
mprintf( x, y, L"%s", str );
InvalidateRegion( x, y, x2, y2 );
}
void ClickEditorButton( INT32 iEditorButtonID )
{
GUI_BUTTON *butn;
if ( iEditorButtonID < 0 || iEditorButtonID >= NUMBER_EDITOR_BUTTONS )
return;
if ( iEditorButton[ iEditorButtonID ] != -1 )
{
butn = ButtonList[ iEditorButton[ iEditorButtonID ] ];
if( butn )
butn->uiFlags |= BUTTON_CLICKED_ON;
}
}
void UnclickEditorButton( INT32 iEditorButtonID )
{
GUI_BUTTON *butn;
if ( iEditorButtonID < 0 || iEditorButtonID >= NUMBER_EDITOR_BUTTONS )
return;
if ( iEditorButton[ iEditorButtonID ] != -1 )
{
butn = ButtonList[ iEditorButton[ iEditorButtonID ] ];
if( butn )
butn->uiFlags &= (~BUTTON_CLICKED_ON);
}
}
void HideEditorButton( INT32 iEditorButtonID )
{
HideButton( iEditorButton[ iEditorButtonID ] );
}
void ShowEditorButton( INT32 iEditorButtonID )
{
ShowButton( iEditorButton[ iEditorButtonID ] );
}
void DisableEditorButton( INT32 iEditorButtonID )
{
DisableButton( iEditorButton[ iEditorButtonID ] );
}
void EnableEditorButton( INT32 iEditorButtonID )
{
EnableButton( iEditorButton[ iEditorButtonID ] );
}
void ClickEditorButtons( INT32 iFirstEditorButtonID, INT32 iLastEditorButtonID )
{
INT32 i;
GUI_BUTTON *b;
for( i = iFirstEditorButtonID; i <= iLastEditorButtonID; i++ )
{
Assert( iEditorButton[ i ] != -1 );
b = ButtonList[ iEditorButton[ i ] ];
Assert( b );
b->uiFlags |= BUTTON_CLICKED_ON;
}
}
void UnclickEditorButtons( INT32 iFirstEditorButtonID, INT32 iLastEditorButtonID )
{
INT32 i;
GUI_BUTTON *b;
for( i = iFirstEditorButtonID; i <= iLastEditorButtonID; i++ )
{
Assert( iEditorButton[ i ] != -1 );
b = ButtonList[ iEditorButton[ i ] ];
Assert( b );
b->uiFlags &= (~BUTTON_CLICKED_ON);
}
}
void HideEditorButtons( INT32 iFirstEditorButtonID, INT32 iLastEditorButtonID )
{
INT32 i;
for( i = iFirstEditorButtonID; i <= iLastEditorButtonID; i++ )
HideButton( iEditorButton[ i ] );
}
void ShowEditorButtons( INT32 iFirstEditorButtonID, INT32 iLastEditorButtonID )
{
INT32 i;
for( i = iFirstEditorButtonID; i <= iLastEditorButtonID; i++ )
ShowButton( iEditorButton[ i ] );
}
void DisableEditorButtons( INT32 iFirstEditorButtonID, INT32 iLastEditorButtonID )
{
INT32 i;
for( i = iFirstEditorButtonID; i <= iLastEditorButtonID; i++ )
DisableButton( iEditorButton[ i ] );
}
void EnableEditorButtons( INT32 iFirstEditorButtonID, INT32 iLastEditorButtonID )
{
INT32 i;
for( i = iFirstEditorButtonID; i <= iLastEditorButtonID; i++ )
EnableButton( iEditorButton[ i ] );
}
void RenderMapEntryPointsAndLights()
{
INT32 sGridNo;
INT16 sScreenX, sScreenY;
INT32 i;
if( gfSummaryWindowActive )
return;
SetFont( FONT10ARIAL );
SetFontForeground( FONT_YELLOW );
SetFontShadow( FONT_NEARBLACK );
sGridNo = gMapInformation.sNorthGridNo;
if( sGridNo != -1 )
{
GetGridNoScreenPos( sGridNo, 0, &sScreenX, &sScreenY );
if( sScreenY >= (- 20) && sScreenY < (2 * iScreenHeightOffset + 340) && sScreenX >= (- 40) && sScreenX < SCREEN_WIDTH )
{
DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 40, 2, FONT10ARIAL, FONT_YELLOW, iRenderMapEntryPointsAndLightsText[0], FONT_BLACK, TRUE, CENTER_JUSTIFIED );
}
}
sGridNo = gMapInformation.sWestGridNo;
if( sGridNo != -1 )
{
GetGridNoScreenPos( sGridNo, 0, &sScreenX, &sScreenY );
if( sScreenY >= (- 20) && sScreenY < (2 * iScreenHeightOffset + 340) && sScreenX >= (- 40) && sScreenX < SCREEN_WIDTH )
{
DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 40, 2, FONT10ARIAL, FONT_YELLOW, iRenderMapEntryPointsAndLightsText[1], FONT_BLACK, TRUE, CENTER_JUSTIFIED );
}
}
sGridNo = gMapInformation.sEastGridNo;
if( sGridNo != -1 )
{
GetGridNoScreenPos( sGridNo, 0, &sScreenX, &sScreenY );
if( sScreenY >= (- 20) && sScreenY < (2 * iScreenHeightOffset + 340) && sScreenX >= (- 40) && sScreenX < SCREEN_WIDTH )
{
DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 40, 2, FONT10ARIAL, FONT_YELLOW, iRenderMapEntryPointsAndLightsText[2], FONT_BLACK, TRUE, CENTER_JUSTIFIED );
}
}
sGridNo = gMapInformation.sSouthGridNo;
if( sGridNo != -1 )
{
GetGridNoScreenPos( sGridNo, 0, &sScreenX, &sScreenY );
if( sScreenY >= ( - 20) && sScreenY < (2 * iScreenHeightOffset + 340) && sScreenX >= (- 40) && sScreenX < SCREEN_WIDTH )
{
DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 40, 2, FONT10ARIAL, FONT_YELLOW, iRenderMapEntryPointsAndLightsText[3], FONT_BLACK, TRUE, CENTER_JUSTIFIED );
}
}
sGridNo = gMapInformation.sCenterGridNo;
if( sGridNo != -1 )
{
GetGridNoScreenPos( sGridNo, 0, &sScreenX, &sScreenY );
if( sScreenY >= (- 20) && sScreenY < (2 * iScreenHeightOffset + 340) && sScreenX >= (- 40) && sScreenX < SCREEN_WIDTH )
{
DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 40, 2, FONT10ARIAL, FONT_YELLOW, iRenderMapEntryPointsAndLightsText[4], FONT_BLACK, TRUE, CENTER_JUSTIFIED );
}
}
sGridNo = gMapInformation.sIsolatedGridNo;
if( sGridNo != -1 )
{
GetGridNoScreenPos( sGridNo, 0, &sScreenX, &sScreenY );
if( sScreenY >= (- 20) && sScreenY < (2 * iScreenHeightOffset + 340) && sScreenX >= (- 40) && sScreenX < SCREEN_WIDTH )
{
DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 40, 2, FONT10ARIAL, FONT_YELLOW, iRenderMapEntryPointsAndLightsText[5], FONT_BLACK, TRUE, CENTER_JUSTIFIED );
}
}
//Do the lights now.
for( i = 0; i < MAX_LIGHT_SPRITES; i++ )
{
if( LightSprites[ i ].uiFlags & LIGHT_SPR_ACTIVE )
{
// Check for light out of bounds. This actually happens in Drassen.
if (LightSprites[ i ].iY < 0 || LightSprites[ i ].iY > WORLD_ROWS ||
LightSprites[ i ].iX < 0 || LightSprites[ i ].iX > WORLD_COLS)
{
LightSprites[ i ].uiFlags &= (~LIGHT_SPR_ACTIVE);
continue;
}
sGridNo = LightSprites[ i ].iY * WORLD_COLS + LightSprites[ i ].iX;
GetGridNoScreenPos( sGridNo, 0, &sScreenX, &sScreenY );
if( sScreenY >= (- 50) && sScreenY < (2 * iScreenHeightOffset + 300) && sScreenX >= (- 40) && sScreenX < SCREEN_WIDTH )
{
if( LightSprites[ i ].uiFlags & LIGHT_PRIMETIME )
DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 50, 2, FONT10ARIAL, FONT_ORANGE, iRenderMapEntryPointsAndLightsText[6], FONT_BLACK, TRUE, CENTER_JUSTIFIED );
else if( LightSprites[ i ].uiFlags & LIGHT_NIGHTTIME )
DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 50, 2, FONT10ARIAL, FONT_RED, iRenderMapEntryPointsAndLightsText[7], FONT_BLACK, TRUE, CENTER_JUSTIFIED );
else
DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 50, 2, FONT10ARIAL, FONT_YELLOW, iRenderMapEntryPointsAndLightsText[8], FONT_BLACK, TRUE, CENTER_JUSTIFIED );
}
}
}
}
void BuildTriggerName( OBJECTTYPE *pItem, STR16 szItemName )
{
if( pItem->usItem == SWITCH )
{
if( (*pItem)[0]->data.misc.bFrequency == PANIC_FREQUENCY )
swprintf( szItemName, iBuildTriggerNameText[0] );
else if( (*pItem)[0]->data.misc.bFrequency == PANIC_FREQUENCY_2 )
swprintf( szItemName, iBuildTriggerNameText[1] );
else if( (*pItem)[0]->data.misc.bFrequency == PANIC_FREQUENCY_3 )
swprintf( szItemName, iBuildTriggerNameText[2] );
else
swprintf( szItemName, iBuildTriggerNameText[3], (*pItem)[0]->data.misc.bFrequency - 50 );
}
else
{ //action item
if( (*pItem)[0]->data.misc.bDetonatorType == BOMB_PRESSURE )
swprintf( szItemName, iBuildTriggerNameText[4] );
else if( (*pItem)[0]->data.misc.bFrequency == PANIC_FREQUENCY )
swprintf( szItemName, iBuildTriggerNameText[5] );
else if( (*pItem)[0]->data.misc.bFrequency == PANIC_FREQUENCY_2 )
swprintf( szItemName, iBuildTriggerNameText[6] );
else if( (*pItem)[0]->data.misc.bFrequency == PANIC_FREQUENCY_3 )
swprintf( szItemName, iBuildTriggerNameText[7] );
else
swprintf( szItemName, iBuildTriggerNameText[8], (*pItem)[0]->data.misc.bFrequency - 50 );
}
}
void RenderDoorLockInfo()
{
INT16 i, xp, yp;
INT16 sScreenX, sScreenY;
CHAR16 str[ 50 ];
for( i = 0; i < gubNumDoors; i++ )
{
GetGridNoScreenPos( DoorTable[ i ].sGridNo, 0, &sScreenX, &sScreenY );
if( sScreenY > (2 * iScreenHeightOffset + 390) )
continue;
if( DoorTable[ i ].ubLockID != 255 )
swprintf( str, L"%S", LockTable[ DoorTable[ i ].ubLockID ].ubEditorName );
else
swprintf( str, iRenderDoorLockInfoText[0] );
xp = sScreenX - 10;
yp = sScreenY - 40;
DisplayWrappedString( xp, yp, 60, 2, FONT10ARIAL, FONT_LTKHAKI, str, FONT_BLACK, TRUE, CENTER_JUSTIFIED );
if( DoorTable[ i ].ubTrapID )
{
SetFont( FONT10ARIAL );
SetFontForeground( FONT_RED );
SetFontShadow( FONT_NEARBLACK );
switch( DoorTable[ i ].ubTrapID )
{
case EXPLOSION:
swprintf( str, iRenderDoorLockInfoText[1] );
break;
case ELECTRIC:
swprintf( str, iRenderDoorLockInfoText[2] );
break;
case SIREN:
swprintf( str, iRenderDoorLockInfoText[3] );
break;
case SILENT_ALARM:
swprintf( str, iRenderDoorLockInfoText[4] );
break;
case SUPER_ELECTRIC:
swprintf( str, iRenderDoorLockInfoText[5] );
break;
// WANNE: Fix a vanilla glitch in the editor: The text for the brothel siren trap was missing.
// Fixed by Tron (Stracciatella): Revision: 6253
case BROTHEL_SIREN:
swprintf( str, iRenderDoorLockInfoText[6] );
break;
}
xp = sScreenX + 20 - StringPixLength( str, FONT10ARIAL ) / 2;
yp = sScreenY;
mprintf( xp, yp, str );
swprintf( str, iRenderDoorLockInfoText[7], DoorTable[ i ].ubTrapLevel );
xp = sScreenX + 20 - StringPixLength( str, FONT10ARIAL ) / 2;
mprintf( xp, yp+10, str );
}
}
}
void RenderSelectedItemBlownUp()
{
UINT32 uiVideoObjectIndex;
HVOBJECT hVObject;
INT16 sScreenX, sScreenY, xp, yp;
ITEM_POOL *pItemPool;
CHAR16 szItemName[ SIZE_ITEM_NAME ];
INT32 i, iStackIndex;
INT16 sWidth, sHeight, sOffsetX, sOffsetY;
GetGridNoScreenPos( gsItemGridNo, 0, &sScreenX, &sScreenY );
if( sScreenY > (2 * iScreenHeightOffset + 340) )
return;
//Display the enlarged item graphic
uiVideoObjectIndex = GetInterfaceGraphicForItem( &Item[ gpItem->usItem ] );
GetVideoObject( &hVObject, uiVideoObjectIndex );
UINT16 usGraphicNum = g_bUsePngItemImages ? 0 : Item[ gpItem->usItem ].ubGraphicNum;
sWidth = hVObject->pETRLEObject[ usGraphicNum ].usWidth;
sOffsetX = hVObject->pETRLEObject[ usGraphicNum ].sOffsetX;
xp = sScreenX + (40 - sWidth - sOffsetX*2) / 2;
sHeight = hVObject->pETRLEObject[ usGraphicNum ].usHeight;
sOffsetY = hVObject->pETRLEObject[ usGraphicNum ].sOffsetY;
yp = sScreenY + (20 - sHeight - sOffsetY*2) / 2;
BltVideoObjectOutlineFromIndex( FRAME_BUFFER, uiVideoObjectIndex, usGraphicNum, xp, yp, Get16BPPColor(FROMRGB(0, 140, 170)), TRUE );
//Display the item name above it
SetFont( FONT10ARIAL );
SetFontForeground( FONT_YELLOW );
SetFontShadow( FONT_NEARBLACK );
if( gpItem->usItem == ACTION_ITEM || gpItem->usItem == SWITCH )
{
BuildTriggerName( gpItem, szItemName );
}
else if( Item[ gpItem->usItem ].usItemClass == IC_KEY )
{
swprintf( szItemName, L"%S", LockTable[ (*gpItem)[0]->data.key.ubKeyID ].ubEditorName );
}
else
{
LoadItemInfo( gpItem->usItem, szItemName, NULL );
}
xp = sScreenX - (StringPixLength( szItemName, FONT10ARIAL ) - 40) / 2;
yp -= 10;
mprintf( xp, yp, szItemName );
if( gpItem->usItem == ACTION_ITEM )
{
STR16 pStr;
pStr = GetActionItemName( gpItem );
xp = sScreenX - (StringPixLength( pStr, FONT10ARIALBOLD ) - 40) / 2;
yp += 10;
SetFont( FONT10ARIALBOLD );
SetFontForeground( FONT_LTKHAKI );
mprintf( xp, yp, pStr );
SetFontForeground( FONT_YELLOW );
}
else
{
// Display item index no
xp = sScreenX + 2;
yp += 10;
SetFont( BLOCKFONTNARROW );
SetFontForeground( FONT_LTGREEN );
mprintf( xp, yp, L"%d", Item[ gpItem->usItem ].uiIndex );
}
//Display current item stack index and number of items in stack
i = 0;
GetItemPoolFromGround( gsItemGridNo, &pItemPool );
Assert( pItemPool );
//Count the number of items in the current pool
while( pItemPool )
{
i++;
if ( gpItemPool == pItemPool )
iStackIndex = i;
pItemPool = pItemPool->pNext;
}
xp = sScreenX;
yp = sScreenY + 10;
SetFont( FONT10ARIAL );
SetFontForeground( FONT_YELLOW );
//Omit current item stack index if only 1 item in stack
if ( i == 1 )
mprintf( xp, yp, L"%d", i );
else
mprintf( xp - 6, yp, L"%d/%d", iStackIndex , i );
//If the item is hidden, render a blinking H (just like DG)
if( gWorldItems[ gpItemPool->iItemIndex ].bVisible == HIDDEN_ITEM ||
gWorldItems[ gpItemPool->iItemIndex ].bVisible == BURIED )
{
SetFont( FONT10ARIALBOLD );
if( GetJA2Clock() % 1000 > 500 )
{
SetFontForeground( 249 );
}
mprintf( sScreenX + 16, sScreenY + 7, L"H" );
InvalidateRegion( sScreenX + 16, sScreenY + 7, sScreenX + 24, sScreenY + 27 );
}
}
void RenderEditorInfo( )
{
CHAR16 FPSText[ 50 ];
static INT32 iSpewWarning = 0;
INT32 iMapIndexD;
//dnl ch52 091009
SetFont(FONT12ARIAL);
SetFontShadow(FONT_NEARBLACK);
SetFontForeground(FONT_GRAY2);
SetFontBackground(FONT_BLACK);
//dnl ch1 101009 Display the mapindex position
if(GetMouseMapPos(&iMapIndexD))
{
INT16 sGridX, sGridY;
GetMouseXY(&sGridX, &sGridY);
swprintf(FPSText, L"%4d %4d %6d ", sGridX, sGridY, iMapIndexD);
}
else
swprintf(FPSText, L" ");
mprintfEditor( (UINT16)(iScreenWidthOffset + 50-StringPixLength( FPSText, FONT12POINT1 )/2), 2 * iScreenHeightOffset + 463, FPSText );
switch( iCurrentTaskbar )
{
case TASK_OPTIONS:
mprintf(iScreenWidthOffset+71+15, SCREEN_HEIGHT-117, iRenderEditorInfoText[0]);//dnl ch33 160909
if( !gfWorldLoaded || giCurrentTilesetID < 0 )
mprintf( iScreenWidthOffset + 260, 2 * iScreenHeightOffset + 445, iRenderEditorInfoText[1] );
else
mprintf( iScreenWidthOffset + 260, 2 * iScreenHeightOffset + 445, iRenderEditorInfoText[2], gubFilename, gTilesets[ giCurrentTilesetID ].zName );
// TODO.MAP
mprintf(iScreenWidthOffset+20, SCREEN_HEIGHT-40, iRenderEditorInfoText[3]);
UpdateOptions();
break;
case TASK_TERRAIN:
// WANNE: Comment this two lines, because we always get an exception here.
//if( gusSelectionType == LINESELECTION )
// swprintf( wszSelType[LINESELECTION], L"Width: %d", gusSelectionWidth );
DrawEditorInfoBox( wszSelType[gusSelectionType], FONT12POINT1, iScreenWidthOffset + 220, 2 * iScreenHeightOffset + 430, 60, 30 );
swprintf( FPSText, L"%d%%", gusSelectionDensity );
DrawEditorInfoBox( FPSText, FONT12POINT1, iScreenWidthOffset + 310, 2 * iScreenHeightOffset + 430, 40, 30 );
break;
case TASK_ITEMS:
RenderEditorItemsInfo();
UpdateItemStatsPanel();
break;
case TASK_BUILDINGS:
UpdateBuildingsInfo();
// WANNE: Comment this two lines, because we always get an exception here.
//if( gusSelectionType == LINESELECTION )
// swprintf( wszSelType[LINESELECTION], L"%d", gusSelectionWidth );
DrawEditorInfoBox( wszSelType[gusSelectionType], FONT12POINT1, iScreenWidthOffset + 530, 2 * iScreenHeightOffset + 430, 60, 30 );
break;
case TASK_MERCS:
UpdateMercsInfo();
#ifdef JA113DEMO
DisableButton (iEditorButton[ MERCS_CIVILIANTOGGLE ]);
DisableButton (iEditorButton[ MERCS_CIVILIAN ]);
#endif
break;
case TASK_MAPINFO:
UpdateMapInfo();
// WANNE: EDITOR: Comment this two lines, because we always get an exception here!
//if( gusSelectionType == LINESELECTION )
// swprintf( wszSelType[LINESELECTION], L"Width: %d", gusSelectionWidth );
DrawEditorInfoBox( wszSelType[gusSelectionType], FONT12POINT1, iScreenWidthOffset + 440, 2 * iScreenHeightOffset + 430, 60, 30 );
break;
}
}
//This is in ButtonSystem.c as a hack. Because we need to save the buffer whenever we do a full
//taskbar render, we need to draw the buttons without hilites, hence this flag. This flag is
//always true in ButtonSystem.c, so it won't effect anything else.
extern BOOLEAN gfGotoGridNoUI;
extern BOOLEAN gfKeyboardItemCreationUI;
void ProcessEditorRendering()
{
BOOLEAN fSaveBuffer = FALSE;
if( gfRenderTaskbar ) //do a full taskbar render.
{
if(iCurrentTaskbar == TASK_OPTIONS && !gfSummaryWindowActive)//dnl ch52 091009
{
CHAR8 szNewText[4+1];
sprintf(szNewText, "%d", iNewMapWorldRows=WORLD_ROWS);
SetInputFieldStringWith8BitString(1, szNewText);
sprintf(szNewText, "%d", iNewMapWorldCols=WORLD_COLS);
SetInputFieldStringWith8BitString(2, szNewText);
DisableTextField(2);
}
ClearTaskbarRegion( 0, SCREEN_HEIGHT - 120, SCREEN_WIDTH, SCREEN_HEIGHT );
RenderTerrainTileButtons();
MarkButtonsDirty();
gfRenderTaskbar = FALSE;
fSaveBuffer = TRUE;
gfRenderDrawingMode = TRUE;
gfRenderHilights = FALSE;
gfRenderMercInfo = TRUE;
}
if( gfRenderDrawingMode )
{
if( iCurrentTaskbar == TASK_BUILDINGS || iCurrentTaskbar == TASK_TERRAIN || iCurrentTaskbar == TASK_ITEMS )
{
ShowCurrentDrawingMode();
gfRenderDrawingMode = FALSE;
}
}
//render dynamically changed buttons only
RenderButtons( );
if( gfSummaryWindowActive )
RenderSummaryWindow();
else if( !gfGotoGridNoUI && !gfKeyboardItemCreationUI && !InOverheadMap() && !gfEditingDoor )//dnl ch86 220214
RenderMercStrings();
if( gfEditingDoor )
RenderDoorEditingWindow();
if( TextInputMode() )
RenderAllTextFields();
RenderEditorInfo();
if( !gfSummaryWindowActive && !gfGotoGridNoUI && !gfKeyboardItemCreationUI && !InOverheadMap() && !gfEditingDoor )//dnl ch86 220214
{
if( gpItem && gsItemGridNo != -1 )
RenderSelectedItemBlownUp();
if( iCurrentTaskbar == TASK_MAPINFO )
RenderMapEntryPointsAndLights();
if( iDrawMode == DRAW_MODE_PLACE_ITEM && eInfo.uiItemType == TBAR_MODE_ITEM_KEYS ||
iDrawMode == DRAW_MODE_DOORKEYS )
RenderDoorLockInfo();
}
if( fSaveBuffer )
BlitBufferToBuffer( FRAME_BUFFER, guiSAVEBUFFER, 0, 2 * iScreenHeightOffset + 360, SCREEN_WIDTH, 120 );
//Make sure this is TRUE at all times.
//It is set to false when before we save the buffer, so the buttons don't get
//rendered with hilites, in case the mouse is over one.
gfRenderHilights = TRUE;
if(!gfSummaryWindowActive && !gfScrollInertia && !gfEditingDoor)//dnl ch77 131113 //dnl ch78 271113 //dnl ch86 210214
RenderButtonsFastHelp();
}
#endif