Files
source/Editor/Editor Taskbar Utils.cpp
T
Overhaul b07d18f9f4 Editor: Disable light sprites that are not in bounds. Actually happens in some sectors (ie Drassen)
Editor:  Fix for use of uninitialized variable in undo
Editor:  Fix for clipping bounds that are offscreen (causes crash)
Fix for AP bonus reading from INI
Fix mine indexes when looking for creature infestation of mines
Final (?) fix for militia reinforcements.  Also a change:  If you refuse reinforcements, none will come for the entirety of the battle
Increase size of cover and LOS grids to fit max radius
Fix for uninitialized light level in DistanceVisible
Move CheckForEndOfBattle to end of ReduceAttackBusy, to remove a possible militia invalidate upon promotion
Change the way Alt-L handles reloading


git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@1142 3b4a5df2-a311-0410-b5c6-a8a6f20db521
2007-08-01 08:58:34 +00:00

1007 lines
32 KiB
C++

// WANNE: EDITOR?
#ifdef PRECOMPILEDHEADERS
#include "Editor All.h"
#else
#include "builddefines.h"
#endif
#ifdef JA2EDITOR
#ifndef PRECOMPILEDHEADERS
#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"
#endif
void RenderEditorInfo();
extern ITEM_POOL *gpItemPool;
//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:
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 );
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();
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();
break;
case TASK_OPTIONS:
ClickEditorButton( TAB_OPTIONS );
TerrainTileDrawMode = TERRAIN_TILES_NODRAW;
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 );
}
// WANNE: EDITOR continue
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()
{
INT16 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, L"North Entry Point", 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, L"West Entry Point", 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, L"East Entry Point", 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, L"South Entry Point", 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, L"Center Entry Point", 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, L"Isolated Entry Point", 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, L"Prime", FONT_BLACK, TRUE, CENTER_JUSTIFIED );
else if( LightSprites[ i ].uiFlags & LIGHT_NIGHTTIME )
DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 50, 2, FONT10ARIAL, FONT_RED, L"Night", FONT_BLACK, TRUE, CENTER_JUSTIFIED );
else
DisplayWrappedString( sScreenX, (INT16)(sScreenY-5), 50, 2, FONT10ARIAL, FONT_YELLOW, L"24Hour", FONT_BLACK, TRUE, CENTER_JUSTIFIED );
}
}
}
}
void BuildTriggerName( OBJECTTYPE *pItem, STR16 szItemName )
{
if( pItem->usItem == SWITCH )
{
if( pItem->bFrequency == PANIC_FREQUENCY )
swprintf( szItemName, L"Panic Trigger1" );
else if( pItem->bFrequency == PANIC_FREQUENCY_2 )
swprintf( szItemName, L"Panic Trigger2" );
else if( pItem->bFrequency == PANIC_FREQUENCY_3 )
swprintf( szItemName, L"Panic Trigger3" );
else
swprintf( szItemName, L"Trigger%d", pItem->bFrequency - 50 );
}
else
{ //action item
if( pItem->bDetonatorType == BOMB_PRESSURE )
swprintf( szItemName, L"Pressure Action" );
else if( pItem->bFrequency == PANIC_FREQUENCY )
swprintf( szItemName, L"Panic Action1" );
else if( pItem->bFrequency == PANIC_FREQUENCY_2 )
swprintf( szItemName, L"Panic Action2" );
else if( pItem->bFrequency == PANIC_FREQUENCY_3 )
swprintf( szItemName, L"Panic Action3" );
else
swprintf( szItemName, L"Action%d", pItem->bFrequency - 50 );
}
}
// WANNE: EDITOR?
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, L"No Lock ID" );
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, L"Explosion Trap" );
break;
case ELECTRIC:
swprintf( str, L"Electric Trap" );
break;
case SIREN:
swprintf( str, L"Siren Trap" );
break;
case SILENT_ALARM:
swprintf( str, L"Silent Alarm" );
break;
case SUPER_ELECTRIC:
swprintf( str, L"Super Electric Trap" );
break;
}
xp = sScreenX + 20 - StringPixLength( str, FONT10ARIAL ) / 2;
yp = sScreenY;
mprintf( xp, yp, str );
swprintf( str, L"Trap Level %d", DoorTable[ i ].ubTrapLevel );
xp = sScreenX + 20 - StringPixLength( str, FONT10ARIAL ) / 2;
mprintf( xp, yp+10, str );
}
}
}
// WANNE: EDITOR?
void RenderSelectedItemBlownUp()
{
UINT32 uiVideoObjectIndex;
HVOBJECT hVObject;
INT16 sScreenX, sScreenY, xp, yp;
ITEM_POOL *pItemPool;
CHAR16 szItemName[ SIZE_ITEM_NAME ];
INT32 i;
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 );
sWidth = hVObject->pETRLEObject[ Item[ gpItem->usItem ].ubGraphicNum ].usWidth;
sOffsetX = hVObject->pETRLEObject[ Item[ gpItem->usItem ].ubGraphicNum ].sOffsetX;
xp = sScreenX + (40 - sWidth - sOffsetX*2) / 2;
sHeight = hVObject->pETRLEObject[ Item[ gpItem->usItem ].ubGraphicNum ].usHeight;
sOffsetY = hVObject->pETRLEObject[ Item[ gpItem->usItem ].ubGraphicNum ].sOffsetY;
yp = sScreenY + (20 - sHeight - sOffsetY*2) / 2;
BltVideoObjectOutlineFromIndex( FRAME_BUFFER, uiVideoObjectIndex, Item[ gpItem->usItem ].ubGraphicNum, 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->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 );
}
//Count the number of items in the current pool, and display that.
i = 0;
GetItemPool( gsItemGridNo, &pItemPool, 0 );
Assert( pItemPool );
while( pItemPool )
{
i++;
pItemPool = pItemPool->pNext;
}
xp = sScreenX;
yp = sScreenY + 10;
mprintf( xp, yp, L"%d", 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;
UINT16 uiMapIndex;
SetFont( FONT12POINT1 );
SetFontForeground( FONT_BLACK );
SetFontBackground( FONT_BLACK );
//Display the mapindex position
if( GetMouseMapPos( &uiMapIndex ) )
swprintf( FPSText, L" (%d) ", uiMapIndex );
else
swprintf( FPSText, L" " );
mprintfEditor( (UINT16)(iScreenWidthOffset + 50-StringPixLength( FPSText, FONT12POINT1 )/2), 2 * iScreenHeightOffset + 463, FPSText );
switch( iCurrentTaskbar )
{
case TASK_OPTIONS:
if( !gfWorldLoaded || giCurrentTilesetID < 0 )
mprintf( iScreenWidthOffset + 260, 2 * iScreenHeightOffset + 445, L"No map currently loaded." );
else
mprintf( iScreenWidthOffset + 260, 2 * iScreenHeightOffset + 445, L"File: %S, Current Tileset: %s",
gubFilename, gTilesets[ giCurrentTilesetID ].zName );
break;
case TASK_TERRAIN:
// 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 + 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: EDITOR: 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();
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;
void ProcessEditorRendering()
{
BOOLEAN fSaveBuffer = FALSE;
if( gfRenderTaskbar ) //do a full taskbar render.
{
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 && !InOverheadMap() )
RenderMercStrings();
if( gfEditingDoor )
RenderDoorEditingWindow();
if( TextInputMode() )
RenderAllTextFields();
RenderEditorInfo();
if( !gfSummaryWindowActive && !gfGotoGridNoUI && !InOverheadMap() )
{
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 )
// WANNE: EDITOR?
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;
RenderButtonsFastHelp();
}
#endif