1 #include "Directories.h"
2 #include "Font.h"
3 #include "HImage.h"
4 #include "Handle_Items.h"
5 #include "Local.h"
6 #include "Sys_Globals.h"
7 #include "Timer_Control.h"
8 #include "Types.h"
9 #include "MouseSystem.h"
10 #include "Button_System.h"
11 #include "Font_Control.h"
12 #include "Isometric_Utils.h"
13 #include "VObject.h"
14 #include "WorldDat.h"
15 #include "Render_Dirty.h"
16 #include "SysUtil.h"
17 #include "WordWrap.h"
18 #include "Environment.h"
19 #include "Interface_Items.h"
20 #include "Soldier_Find.h"
21 #include "World_Items.h"
22 #include "Text.h"
23 #include "Overhead_Map.h"
24 #include "Cursor_Modes.h"
25 #include "EditScreen.h"
26 #include "EditorTerrain.h"
27 #include "EditorItems.h"
28 #include "EditorMercs.h"
29 #include "EditorBuildings.h"
30 #include "EditorMapInfo.h"
31 #include "EditorDefines.h"
32 #include "Editor_Taskbar_Utils.h"
33 #include "Editor_Taskbar_Creation.h"
34 #include "Editor_Callback_Prototypes.h"
35 #include "Editor_Modes.h"
36 #include "Text_Input.h"
37 #include "Item_Statistics.h"
38 #include "Map_Information.h"
39 #include "Sector_Summary.h"
40 #include "Pits.h"
41 #include "Lighting.h"
42 #include "Keys.h"
43 #include "Debug.h"
44 #include "JAScreens.h"
45 #include "Video.h"
46 #include "VSurface.h"
47
48 #include "ContentManager.h"
49 #include "GameInstance.h"
50
51 #include <string_theory/format>
52 #include <string_theory/string>
53
54 #include <stdarg.h>
55
56
57 //editor icon storage vars
58 INT32 giEditMercDirectionIcons[2];
59 SGPVObject* guiMercInventoryPanel;
60 SGPVObject* guiOmertaMap;
61 SGPVSurface* guiMercInvPanelBuffers[9];
62 SGPVSurface* guiMercTempBuffer;
63 SGPVObject* guiExclamation;
64 SGPVObject* guiKeyImage;
65
66 //editor Mouseregion storage vars
67 static MOUSE_REGION TerrainTileButtonRegion[NUM_TERRAIN_TILE_REGIONS];
68 static MOUSE_REGION ItemsRegion;
69 static MOUSE_REGION MercRegion;
70 static MOUSE_REGION EditorRegion;
71
EnableEditorRegion(INT8 bRegionID)72 void EnableEditorRegion( INT8 bRegionID )
73 {
74 switch( bRegionID )
75 {
76 case BASE_TERRAIN_TILE_REGION_ID:
77 case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
78 TerrainTileButtonRegion[bRegionID].Enable();
79 break;
80 case ITEM_REGION_ID:
81 ItemsRegion.Enable();
82 break;
83 case MERC_REGION_ID:
84 MercRegion.Enable();
85 break;
86 }
87 }
88
DisableEditorRegion(INT8 bRegionID)89 void DisableEditorRegion( INT8 bRegionID )
90 {
91 switch( bRegionID )
92 {
93 case BASE_TERRAIN_TILE_REGION_ID:
94 case 1: case 2: case 3: case 4: case 5: case 6: case 7:
95 TerrainTileButtonRegion[bRegionID].Disable();
96 break;
97 case ITEM_REGION_ID:
98 ItemsRegion.Disable();
99 break;
100 case MERC_REGION_ID:
101 MercRegion.Disable();
102 break;
103 }
104 }
105
106
RemoveEditorRegions(void)107 static void RemoveEditorRegions(void)
108 {
109 INT32 x;
110 MSYS_RemoveRegion( &EditorRegion );
111 for(x = BASE_TERRAIN_TILE_REGION_ID; x < NUM_TERRAIN_TILE_REGIONS; x++ )
112 {
113 MSYS_RemoveRegion( &TerrainTileButtonRegion[ x ] );
114 }
115 MSYS_RemoveRegion( &ItemsRegion );
116 MSYS_RemoveRegion( &MercRegion );
117 }
118
119
InitEditorRegions()120 static void InitEditorRegions()
121 {
122 /* By doing this, all of the buttons underneath are blanketed and can't be
123 * used anymore. Any new buttons will cover this up as well. Think of it as a
124 * barrier between the editor buttons and the game's interface panel buttons
125 * and regions. */
126 MSYS_DefineRegion(&EditorRegion, 0, EDITOR_TASKBAR_POS_Y, SCREEN_WIDTH, SCREEN_HEIGHT, MSYS_PRIORITY_NORMAL, 0, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK);
127
128 // Create the regions for the terrain tile selections.
129 UINT16 x = 261;
130 UINT16 const y = EDITOR_TASKBAR_POS_Y + 9;
131 INT32 idx = 0;
132 FOR_EACHX(MOUSE_REGION, i, TerrainTileButtonRegion, x += 42)
133 {
134 MOUSE_REGION& r = *i;
135 MSYS_DefineRegion(&r, x, y, x + 42, y + 22, MSYS_PRIORITY_NORMAL, 0, MSYS_NO_CALLBACK, TerrainTileButtonRegionCallback);
136 MSYS_SetRegionUserData(&r, 0, idx++);
137 r.Disable();
138 }
139 gfShowTerrainTileButtons = FALSE;
140
141 // Create the region for the items selection window.
142 MSYS_DefineRegion(&ItemsRegion, 100, EDITOR_TASKBAR_POS_Y, 540, EDITOR_TASKBAR_POS_Y + 80, MSYS_PRIORITY_NORMAL, 0, MouseMovedInItemsRegion, MouseClickedInItemsRegion);
143 ItemsRegion.Disable();
144
145 // Create the region for the merc inventory panel.
146 MSYS_DefineRegion(&MercRegion, 175, EDITOR_TASKBAR_POS_Y + 1, 450, EDITOR_TASKBAR_POS_Y + 80, MSYS_PRIORITY_NORMAL, 0, MouseMovedInMercRegion, MouseClickedInMercRegion);
147 MercRegion.Disable();
148 }
149
150
LoadEditorImages(void)151 static void LoadEditorImages(void)
152 {
153 //Set up the merc inventory panel
154 guiMercInventoryPanel = AddVideoObjectFromFile(EDITORDIR "/invpanel.sti");
155 //Set up small omerta map
156 guiOmertaMap = AddVideoObjectFromFile(EDITORDIR "/omerta.sti");
157 //Set up the merc directional buttons.
158 giEditMercDirectionIcons[0] = LoadGenericButtonIcon(EDITORDIR "/arrowsoff.sti");
159 giEditMercDirectionIcons[1] = LoadGenericButtonIcon(EDITORDIR "/arrowson.sti");
160
161 guiExclamation = AddVideoObjectFromFile(EDITORDIR "/exclamation.sti");
162 guiKeyImage = AddVideoObjectFromFile(EDITORDIR "/keyimage.sti");
163 }
164
165
DeleteEditorImages(void)166 static void DeleteEditorImages(void)
167 {
168 //The merc inventory panel
169 DeleteVideoObject(guiMercInventoryPanel);
170 DeleteVideoObject(guiOmertaMap);
171 //The merc directional buttons
172 UnloadGenericButtonIcon( (INT16)giEditMercDirectionIcons[0] );
173 UnloadGenericButtonIcon( (INT16)giEditMercDirectionIcons[1] );
174 }
175
176
CreateEditorBuffers(void)177 static void CreateEditorBuffers(void)
178 {
179 INT32 i;
180
181 //create buffer for the transition slot for merc items. This slot contains the newly
182 //selected item graphic in it's inventory size version. This buffer is then scaled down
183 //into the associated merc inventory panel slot buffer which is approximately 20% smaller.
184 guiMercTempBuffer = AddVideoSurface(60, 25, PIXEL_DEPTH);
185
186 //create the nine buffers for the merc's inventory slots.
187 for( i = 0; i < 9; i++ )
188 {
189 guiMercInvPanelBuffers[i] = AddVideoSurface(i < 3 ? MERCINV_SMSLOT_WIDTH : MERCINV_LGSLOT_WIDTH, MERCINV_SLOT_HEIGHT, PIXEL_DEPTH);
190 guiMercInvPanelBuffers[i]->SetTransparency(0);
191 }
192 }
193
194
DeleteEditorBuffers(void)195 static void DeleteEditorBuffers(void)
196 {
197 INT32 i;
198 DeleteVideoSurface(guiMercTempBuffer);
199 for( i = 0; i < 9; i++ )
200 {
201 DeleteVideoSurface(guiMercInvPanelBuffers[i]);
202 }
203 }
204
205
ShowEditorToolbar(TaskMode const iNewTaskMode)206 static void ShowEditorToolbar(TaskMode const iNewTaskMode)
207 {
208 switch( iNewTaskMode )
209 {
210 case TASK_TERRAIN:
211 ShowEditorButtons(FIRST_TERRAIN_BUTTON, LAST_TERRAIN_BUTTON);
212 break;
213 case TASK_BUILDINGS:
214 ShowEditorButtons(FIRST_BUILDINGS_BUTTON, LAST_BUILDINGS_BUTTON);
215 break;
216 case TASK_ITEMS:
217 ShowEditorButtons(FIRST_ITEMS_BUTTON, LAST_ITEMS_BUTTON);
218 break;
219 case TASK_MERCS:
220 ShowEditorButtons(FIRST_MERCS_TEAMMODE_BUTTON, LAST_MERCS_TEAMMODE_BUTTON);
221 break;
222 case TASK_MAPINFO:
223 ShowEditorButtons(FIRST_MAPINFO_BUTTON, LAST_MAPINFO_BUTTON);
224 break;
225 case TASK_OPTIONS:
226 ShowEditorButtons(FIRST_OPTIONS_BUTTON, LAST_OPTIONS_BUTTON);
227 break;
228 default:
229 return;
230 }
231 }
232
233
HideEditorToolbar(TaskMode const iOldTaskMode)234 static void HideEditorToolbar(TaskMode const iOldTaskMode)
235 {
236 INT32 i, iStart, iEnd;
237 switch( iOldTaskMode )
238 {
239 case TASK_TERRAIN:
240 iStart = FIRST_TERRAIN_BUTTON;
241 iEnd = LAST_TERRAIN_BUTTON;
242 break;
243 case TASK_BUILDINGS:
244 iStart = FIRST_BUILDINGS_BUTTON;
245 iEnd = LAST_BUILDINGS_BUTTON;
246 break;
247 case TASK_ITEMS:
248 iStart = FIRST_ITEMS_BUTTON;
249 iEnd = LAST_ITEMS_BUTTON;
250 break;
251 case TASK_MERCS:
252 iStart = FIRST_MERCS_BUTTON;
253 iEnd = LAST_MERCS_BUTTON;
254 break;
255 case TASK_MAPINFO:
256 iStart = FIRST_MAPINFO_BUTTON;
257 iEnd = LAST_MAPINFO_BUTTON;
258 break;
259 case TASK_OPTIONS:
260 iStart = FIRST_OPTIONS_BUTTON;
261 iEnd = LAST_OPTIONS_BUTTON;
262 break;
263 default:
264 return;
265 }
266 for( i = iStart; i <= iEnd; i++ )
267 {
268 HideButton( iEditorButton[ i ] );
269 UnclickEditorButton( i );
270 }
271 }
272
CreateEditorTaskbar()273 void CreateEditorTaskbar()
274 {
275 InitEditorRegions();
276 LoadEditorImages();
277 CreateEditorBuffers();
278 CreateEditorTaskbarInternal();
279 HideItemStatsPanel();
280 }
281
282
DeleteEditorTaskbar()283 void DeleteEditorTaskbar()
284 {
285 iOldTaskMode = iCurrentTaskbar;
286
287 FOR_EACH(GUIButtonRef, i, iEditorButton) RemoveButton(*i);
288
289 RemoveEditorRegions();
290 DeleteEditorImages();
291 DeleteEditorBuffers();
292 }
293
294
DoTaskbar(void)295 void DoTaskbar(void)
296 {
297 if (iTaskMode == TASK_NONE || iTaskMode == iCurrentTaskbar)
298 {
299 return;
300 }
301
302 gfRenderTaskbar = TRUE;
303
304 HideEditorToolbar( iCurrentTaskbar );
305
306 //Special code when exiting previous editor tab
307 switch( iCurrentTaskbar )
308 {
309 case TASK_TERRAIN:
310 UnclickEditorButton( TAB_TERRAIN );
311 HideTerrainTileButtons();
312 break;
313 case TASK_BUILDINGS:
314 UnclickEditorButton( TAB_BUILDINGS );
315 KillTextInputMode();
316 break;
317 case TASK_ITEMS:
318 UnclickEditorButton( TAB_ITEMS );
319 HideItemStatsPanel();
320 if( eInfo.fActive )
321 ClearEditorItemsInfo();
322 gfShowPits = FALSE;
323 RemoveAllPits();
324 break;
325 case TASK_MERCS:
326 UnclickEditorButton( TAB_MERCS );
327 IndicateSelectedMerc( SELECT_NO_MERC );
328 SetMercEditingMode( MERC_NOMODE );
329 break;
330 case TASK_MAPINFO:
331 UnclickEditorButton( TAB_MAPINFO );
332 ExtractAndUpdateMapInfo();
333 KillTextInputMode();
334 HideExitGrids();
335 break;
336 case TASK_OPTIONS:
337 UnclickEditorButton( TAB_OPTIONS );
338 break;
339 default:
340 break;
341 }
342
343 //Setup the new tab mode
344 iCurrentTaskbar = iTaskMode;
345 ShowEditorToolbar( iTaskMode );
346 iTaskMode = TASK_NONE;
347
348 //Special code when entering a new editor tab
349 switch( iCurrentTaskbar )
350 {
351 case TASK_MERCS:
352 ClickEditorButton( TAB_MERCS );
353 ClickEditorButton( MERCS_ENEMY);
354 iDrawMode = DRAW_MODE_ENEMY;
355 SetMercEditingMode( MERC_TEAMMODE );
356 fBuildingShowRoofs = FALSE;
357 UpdateRoofsView();
358 break;
359 case TASK_TERRAIN:
360 ClickEditorButton( TAB_TERRAIN );
361 ShowTerrainTileButtons();
362 SetEditorTerrainTaskbarMode( TERRAIN_FGROUND_TEXTURES );
363 break;
364 case TASK_BUILDINGS:
365 ClickEditorButton( TAB_BUILDINGS );
366 if(fBuildingShowRoofs)
367 ClickEditorButton( BUILDING_TOGGLE_ROOF_VIEW );
368 if(fBuildingShowWalls)
369 ClickEditorButton( BUILDING_TOGGLE_WALL_VIEW );
370 if(fBuildingShowRoomInfo)
371 ClickEditorButton( BUILDING_TOGGLE_INFO_VIEW );
372 if( gfCaves )
373 {
374 ClickEditorButton( BUILDING_CAVE_DRAWING );
375 iDrawMode = DRAW_MODE_CAVES;
376 }
377 else
378 {
379 ClickEditorButton( BUILDING_NEW_ROOM );
380 iDrawMode = DRAW_MODE_ROOM;
381 }
382 TerrainTileDrawMode = TERRAIN_TILES_BRETS_STRANGEMODE;
383 SetEditorSmoothingMode( gMapInformation.ubEditorSmoothingType );
384 gusSelectionType = gusSavedBuildingSelectionType;
385 SetupTextInputForBuildings();
386 break;
387 case TASK_ITEMS:
388 SetFont( FONT10ARIAL );
389 SetFontForeground( FONT_YELLOW );
390 ClickEditorButton( TAB_ITEMS );
391 ClickEditorButton( ITEMS_WEAPONS + eInfo.uiItemType - TBAR_MODE_ITEM_WEAPONS );
392 InitEditorItemsInfo( eInfo.uiItemType );
393 ShowItemStatsPanel();
394 gfShowPits = TRUE;
395 AddAllPits();
396 iDrawMode = DRAW_MODE_PLACE_ITEM;
397 break;
398 case TASK_MAPINFO:
399 ClickEditorButton( TAB_MAPINFO );
400 if ( gfFakeLights )
401 ClickEditorButton( MAPINFO_TOGGLE_FAKE_LIGHTS );
402 ClickEditorButton( MAPINFO_ADD_LIGHT1_SOURCE );
403 iDrawMode = DRAW_MODE_LIGHT;
404 TerrainTileDrawMode = TERRAIN_TILES_BRETS_STRANGEMODE;
405 SetupTextInputForMapInfo();
406 break;
407 case TASK_OPTIONS:
408 ClickEditorButton( TAB_OPTIONS );
409 iDrawMode = DRAW_MODE_NOTHING;
410 TerrainTileDrawMode = TERRAIN_TILES_NODRAW;
411 break;
412 default:
413 break;
414 }
415 }
416
417
DisableEditorTaskbar()418 void DisableEditorTaskbar()
419 {
420 FOR_EACH(GUIButtonRef, i, iEditorButton) DisableButton(*i);
421 }
422
423
EnableEditorTaskbar(void)424 void EnableEditorTaskbar(void)
425 {
426 INT32 x;
427
428 for(x = 0; x < NUMBER_EDITOR_BUTTONS; x++ )
429 EnableButton( iEditorButton[ x ] );
430 //Keep permanent buttons disabled.
431 DisableButton( iEditorButton[ MERCS_1 ] );
432 DisableButton( iEditorButton[ MAPINFO_LIGHT_PANEL ] );
433 DisableButton( iEditorButton[ MAPINFO_RADIO_PANEL ] );
434 DisableButton( iEditorButton[ ITEMSTATS_PANEL ] );
435 DisableButton( iEditorButton[ MERCS_PLAYERTOGGLE ] );
436 DisableButton( iEditorButton[ MERCS_PLAYER ] );
437 if( iCurrentTaskbar == TASK_ITEMS )
438 DetermineItemsScrolling();
439 }
440
441 //A specialized mprint function that'll restore the editor panel underneath the
442 //string before rendering the string. This is obviously only useful for drawing text
443 //in the editor taskbar.
MPrintEditor(INT16 x,INT16 y,const ST::string & str)444 void MPrintEditor(INT16 x, INT16 y, const ST::string& str)
445 {
446 UINT16 uiStringLength, uiStringHeight;
447
448 uiStringLength = StringPixLength( str, FontDefault );
449 uiStringHeight = GetFontHeight( FontDefault );
450
451 ClearTaskbarRegion( x, y, (INT16)(x+uiStringLength), (INT16)(y+uiStringHeight) );
452 MPrint(x, TASKBAR_Y + y, str);
453 }
454
ClearTaskbarRegion(INT16 sLeft,INT16 sTop,INT16 sRight,INT16 sBottom)455 void ClearTaskbarRegion( INT16 sLeft, INT16 sTop, INT16 sRight, INT16 sBottom )
456 {
457 sTop += TASKBAR_Y;
458 sBottom += TASKBAR_Y;
459 ColorFillVideoSurfaceArea( ButtonDestBuffer, sLeft, sTop, sRight, sBottom, gusEditorTaskbarColor );
460
461 if( !sLeft )
462 {
463 ColorFillVideoSurfaceArea( ButtonDestBuffer, 0, sTop, 1, sBottom, gusEditorTaskbarHiColor );
464 sLeft++;
465 }
466 if( sTop == EDITOR_TASKBAR_POS_Y )
467 {
468 ColorFillVideoSurfaceArea( ButtonDestBuffer, sLeft, EDITOR_TASKBAR_POS_Y, sRight, EDITOR_TASKBAR_POS_Y+1, gusEditorTaskbarHiColor );
469 sTop++;
470 }
471 if (sBottom == SCREEN_HEIGHT)
472 {
473 ColorFillVideoSurfaceArea(ButtonDestBuffer, sLeft, SCREEN_HEIGHT - 1, sRight, SCREEN_HEIGHT, gusEditorTaskbarLoColor);
474 }
475 if (sRight == SCREEN_WIDTH)
476 {
477 ColorFillVideoSurfaceArea(ButtonDestBuffer, SCREEN_WIDTH - 1, sTop, SCREEN_WIDTH, sBottom, gusEditorTaskbarLoColor);
478 }
479
480 InvalidateRegion( sLeft, sTop, sRight, sBottom );
481 }
482
483
484 //Kris:
485 //This is a new function which duplicates the older "yellow info boxes" that
486 //are common throughout the editor. This draws the yellow box with the indentation
487 //look.
DrawEditorInfoBox(const ST::string & str,SGPFont const font,UINT16 x,UINT16 y,UINT16 w,UINT16 h)488 void DrawEditorInfoBox(const ST::string& str, SGPFont const font, UINT16 x, UINT16 y, UINT16 w, UINT16 h)
489 {
490 UINT16 usFillColorDark, usFillColorLight, usFillColorBack;
491 UINT16 x2, y2;
492
493 y += TASKBAR_Y;
494 x2 = x + w;
495 y2 = y + h;
496
497 usFillColorDark = Get16BPPColor(FROMRGB(24, 61, 81));
498 usFillColorLight = Get16BPPColor(FROMRGB(136, 138, 135));
499 usFillColorBack = Get16BPPColor(FROMRGB(250, 240, 188));
500
501 ColorFillVideoSurfaceArea(ButtonDestBuffer, x, y, x2, y2, usFillColorDark);
502 ColorFillVideoSurfaceArea(ButtonDestBuffer, x + 1, y + 1, x2, y2, usFillColorLight);
503 ColorFillVideoSurfaceArea(ButtonDestBuffer, x + 1, y + 1, x2 - 1, y2 - 1, usFillColorBack);
504
505 UINT16 const usStrWidth = StringPixLength(str, font);
506 if( usStrWidth > w )
507 { //the string is too long, so use the wrapped method
508 y += 1;
509 DisplayWrappedString(x, y, w, 2, font, FONT_BLACK, str, FONT_BLACK, CENTER_JUSTIFIED | MARK_DIRTY);
510 return;
511 }
512 //center the string vertically and horizontally.
513 SetFontAttributes(font, FONT_BLACK, NO_SHADOW);
514 x += (w - StringPixLength(str, font)) / 2;
515 y += (h - GetFontHeight(font)) / 2;
516 MPrint(x, y, str);
517 InvalidateRegion( x, y, x2, y2 );
518 }
519
ClickEditorButton(INT32 iEditorButtonID)520 void ClickEditorButton( INT32 iEditorButtonID )
521 {
522 if ( iEditorButtonID < 0 || iEditorButtonID >= NUMBER_EDITOR_BUTTONS )
523 return;
524 GUIButtonRef const b = iEditorButton[iEditorButtonID];
525 if (b) b->uiFlags |= BUTTON_CLICKED_ON;
526 }
527
UnclickEditorButton(INT32 iEditorButtonID)528 void UnclickEditorButton( INT32 iEditorButtonID )
529 {
530 if ( iEditorButtonID < 0 || iEditorButtonID >= NUMBER_EDITOR_BUTTONS )
531 return;
532 GUIButtonRef const b = iEditorButton[iEditorButtonID];
533 if (b) b->uiFlags &= ~BUTTON_CLICKED_ON;
534 }
535
HideEditorButton(INT32 iEditorButtonID)536 void HideEditorButton( INT32 iEditorButtonID )
537 {
538 HideButton( iEditorButton[ iEditorButtonID ] );
539 }
540
ShowEditorButton(INT32 iEditorButtonID)541 void ShowEditorButton( INT32 iEditorButtonID )
542 {
543 ShowButton( iEditorButton[ iEditorButtonID ] );
544 }
545
DisableEditorButton(INT32 iEditorButtonID)546 void DisableEditorButton( INT32 iEditorButtonID )
547 {
548 DisableButton( iEditorButton[ iEditorButtonID ] );
549 }
550
EnableEditorButton(INT32 iEditorButtonID)551 void EnableEditorButton( INT32 iEditorButtonID )
552 {
553 EnableButton( iEditorButton[ iEditorButtonID ] );
554 }
555
556
UnclickEditorButtons(INT32 iFirstEditorButtonID,INT32 iLastEditorButtonID)557 void UnclickEditorButtons( INT32 iFirstEditorButtonID, INT32 iLastEditorButtonID )
558 {
559 INT32 i;
560 for( i = iFirstEditorButtonID; i <= iLastEditorButtonID; i++ )
561 {
562 GUIButtonRef const b = iEditorButton[i];
563 Assert( b );
564 b->uiFlags &= (~BUTTON_CLICKED_ON);
565 }
566 }
567
HideEditorButtons(INT32 iFirstEditorButtonID,INT32 iLastEditorButtonID)568 void HideEditorButtons( INT32 iFirstEditorButtonID, INT32 iLastEditorButtonID )
569 {
570 INT32 i;
571 for( i = iFirstEditorButtonID; i <= iLastEditorButtonID; i++ )
572 HideButton( iEditorButton[ i ] );
573 }
574
ShowEditorButtons(INT32 iFirstEditorButtonID,INT32 iLastEditorButtonID)575 void ShowEditorButtons( INT32 iFirstEditorButtonID, INT32 iLastEditorButtonID )
576 {
577 INT32 i;
578 for( i = iFirstEditorButtonID; i <= iLastEditorButtonID; i++ )
579 ShowButton( iEditorButton[ i ] );
580 }
581
DisableEditorButtons(INT32 iFirstEditorButtonID,INT32 iLastEditorButtonID)582 void DisableEditorButtons( INT32 iFirstEditorButtonID, INT32 iLastEditorButtonID )
583 {
584 INT32 i;
585 for( i = iFirstEditorButtonID; i <= iLastEditorButtonID; i++ )
586 DisableButton( iEditorButton[ i ] );
587 }
588
EnableEditorButtons(INT32 iFirstEditorButtonID,INT32 iLastEditorButtonID)589 void EnableEditorButtons( INT32 iFirstEditorButtonID, INT32 iLastEditorButtonID )
590 {
591 INT32 i;
592 for( i = iFirstEditorButtonID; i <= iLastEditorButtonID; i++ )
593 EnableButton( iEditorButton[ i ] );
594 }
595
596
RenderEntryPoint(INT16 const gridno,const ST::string & label)597 static void RenderEntryPoint(INT16 const gridno, const ST::string& label)
598 {
599 if (gridno == -1) return;
600 INT16 x;
601 INT16 y;
602 GetGridNoScreenPos(gridno, 0, &x, &y);
603 if (x < -40 || SCREEN_WIDTH <= x || y < -20 || TASKBAR_Y - 20 <= y) return;
604 DisplayWrappedString(x, y - 5, 40, 2, FONT10ARIAL, FONT_YELLOW, label, FONT_BLACK, CENTER_JUSTIFIED | MARK_DIRTY);
605 }
606
607
RenderMapEntryPointsAndLights(void)608 static void RenderMapEntryPointsAndLights(void)
609 {
610 if (gfSummaryWindowActive) return;
611
612 SetFontShadow(FONT_NEARBLACK);
613 RenderEntryPoint(gMapInformation.sNorthGridNo, "North Entry Point");
614 RenderEntryPoint(gMapInformation.sWestGridNo, "West Entry Point");
615 RenderEntryPoint(gMapInformation.sEastGridNo, "East Entry Point");
616 RenderEntryPoint(gMapInformation.sSouthGridNo, "South Entry Point");
617 RenderEntryPoint(gMapInformation.sCenterGridNo, "Center Entry Point");
618 RenderEntryPoint(gMapInformation.sIsolatedGridNo, "Isolated Entry Point");
619
620 //Do the lights now.
621 CFOR_EACH_LIGHT_SPRITE(l)
622 {
623 INT16 x;
624 INT16 y;
625 INT16 const gridno = l->iY * WORLD_COLS + l->iX;
626 GetGridNoScreenPos(gridno, 0, &x, &y);
627 if (x < -40 || SCREEN_WIDTH <= x || y < -50 || TASKBAR_Y - 60 <= y) continue;
628
629 UINT8 colour;
630 ST::string text;
631 if (l->uiFlags & LIGHT_PRIMETIME)
632 {
633 colour = FONT_ORANGE;
634 text = "Prime";
635 }
636 else if (l->uiFlags & LIGHT_NIGHTTIME)
637 {
638 colour = FONT_RED;
639 text = "Night";
640 }
641 else
642 {
643 colour = FONT_YELLOW;
644 text = "24Hour";
645 }
646 DisplayWrappedString(x, y - 5, 50, 2, FONT10ARIAL, colour, text, FONT_BLACK, CENTER_JUSTIFIED | MARK_DIRTY);
647 }
648 }
649
650
BuildTriggerName(OBJECTTYPE const & o)651 static ST::string BuildTriggerName(OBJECTTYPE const& o)
652 {
653 if (o.usItem == SWITCH)
654 {
655 switch (o.bFrequency)
656 {
657 case PANIC_FREQUENCY: return "Panic Trigger1";
658 case PANIC_FREQUENCY_2: return "Panic Trigger2";
659 case PANIC_FREQUENCY_3: return "Panic Trigger3";
660 default: return ST::format("Trigger{}", o.bFrequency - 50);
661 }
662 }
663 else
664 { // Action item
665 if (o.bDetonatorType == BOMB_PRESSURE)
666 {
667 return "Pressure Action";
668 }
669 else switch (o.bFrequency)
670 {
671 case PANIC_FREQUENCY: return "Panic Action1";
672 case PANIC_FREQUENCY_2: return "Panic Action2";
673 case PANIC_FREQUENCY_3: return "Panic Action3";
674 default: return ST::format("Action{}", o.bFrequency - 50);
675 }
676 }
677 }
678
679
RenderDoorLockInfo()680 static void RenderDoorLockInfo()
681 {
682 ST::string str;
683 FOR_EACH_DOOR(d)
684 {
685 INT16 screen_x;
686 INT16 screen_y;
687 GetGridNoScreenPos(d.sGridNo, 0, &screen_x, &screen_y);
688 INT16 const x = screen_x;
689 INT16 const y = screen_y;
690 if (y > 390) continue;
691
692 if (d.ubLockID != 255)
693 str = ST::format("{}", LockTable[d.ubLockID].ubEditorName);
694 else
695 str = "No Lock ID";
696 DisplayWrappedString(x - 10, y - 40, 60, 2, FONT10ARIAL, FONT_LTKHAKI, str, FONT_BLACK, CENTER_JUSTIFIED | MARK_DIRTY);
697
698 ST::string trap_type;
699 switch (d.ubTrapID)
700 {
701 case NO_TRAP: continue;
702 case EXPLOSION: trap_type = "Explosion Trap"; break;
703 case ELECTRIC: trap_type = "Electric Trap"; break;
704 case SIREN: trap_type = "Siren Trap"; break;
705 case SILENT_ALARM: trap_type = "Silent Alarm"; break;
706 case BROTHEL_SIREN: trap_type = "Brothel Siren Trap"; break;
707 case SUPER_ELECTRIC: trap_type = "Super Electric Trap"; break;
708 }
709 SetFontAttributes(FONT10ARIAL, FONT_RED);
710 MPrint(x + 20 - StringPixLength(trap_type, FONT10ARIAL) / 2, y, trap_type);
711 str = ST::format("Trap Level {}", d.ubTrapLevel);
712 MPrint(x + 20 - StringPixLength(str, FONT10ARIAL) / 2, y + 10, str);
713 }
714 }
715
716
RenderSelectedItemBlownUp(void)717 static void RenderSelectedItemBlownUp(void)
718 {
719 INT16 screen_x;
720 INT16 screen_y;
721 GetGridNoScreenPos(gsItemGridNo, 0, &screen_x, &screen_y);
722 if (screen_y > (EDITOR_TASKBAR_POS_Y - 20)) return;
723
724 OBJECTTYPE const& o = *gpItem;
725 const ItemModel * item = GCM->getItem(o.usItem);
726 INT16 x;
727 INT16 y;
728
729 // Display the enlarged item graphic
730 SGPVObject const& vo = GetInterfaceGraphicForItem(item);
731 ETRLEObject const& e = vo.SubregionProperties(item->getGraphicNum());
732 x = screen_x - e.sOffsetX + (40 - e.usWidth) / 2;
733 y = screen_y - e.sOffsetY + (20 - e.usHeight) / 2;
734 BltVideoObjectOutline(FRAME_BUFFER, &vo, item->getGraphicNum(), x, y, Get16BPPColor(FROMRGB(0, 140, 170)));
735
736 // Display the item name above it
737 SetFontAttributes(FONT10ARIAL, FONT_YELLOW);
738 ST::string item_name;
739 if (o.usItem == ACTION_ITEM || o.usItem == SWITCH)
740 {
741 item_name = BuildTriggerName(o);
742 }
743 else if (item->getItemClass() == IC_KEY)
744 {
745 item_name = ST::format("{}", LockTable[o.ubKeyID].ubEditorName);
746 }
747 else
748 {
749 item_name = ItemNames[o.usItem];
750 }
751 x = screen_x - (StringPixLength(item_name, FONT10ARIAL) - 40) / 2;
752 y -= 10;
753 MPrint(x, y, item_name);
754
755 if (o.usItem == ACTION_ITEM)
756 {
757 SetFont(FONT10ARIALBOLD);
758 SetFontForeground(FONT_LTKHAKI);
759 ST::string name = GetActionItemName(&o);
760 x = screen_x - (StringPixLength(name, FONT10ARIALBOLD) - 40) / 2;
761 y += 10;
762 MPrint(x, y, name);
763 SetFontForeground(FONT_YELLOW);
764 }
765
766 // Count the number of items in the current pool, and display that.
767 INT32 n = 0;
768 for (ITEM_POOL const* i = GetItemPool(gsItemGridNo, 0); i; i = i->pNext)
769 {
770 ++n;
771 }
772 MPrint(screen_x, screen_y + 10, ST::format("{}", n));
773
774 // If the item is hidden, render a blinking H (just like DG)
775 WORLDITEM const& wi = GetWorldItem(gpItemPool->iItemIndex);
776 if (wi.bVisible == HIDDEN_ITEM || wi.bVisible == BURIED)
777 {
778 SetFont(FONT10ARIALBOLD);
779 if (GetJA2Clock() % 1000 > 500) SetFontForeground(249);
780 MPrint(screen_x + 16, screen_y + 7, "H");
781 InvalidateRegion(screen_x + 16, screen_y + 7, screen_x + 24, screen_y + 27);
782 }
783 }
784
785
RenderEditorInfo(void)786 static void RenderEditorInfo(void)
787 {
788 ST::string FPSText;
789
790 SetFontAttributes(FONT12POINT1, FONT_BLACK, NO_SHADOW);
791
792 //Display the mapindex position
793 const GridNo iMapIndex = GetMouseMapPos();
794 if (iMapIndex != NOWHERE)
795 FPSText = ST::format(" ({}) ", iMapIndex);
796 else
797 FPSText = " ";
798 MPrintEditor(50 - StringPixLength(FPSText, FONT12POINT1) / 2, 103, FPSText);
799
800 switch( iCurrentTaskbar )
801 {
802 case TASK_OPTIONS:
803 if( !gfWorldLoaded || giCurrentTilesetID < 0 )
804 MPrint(260, EDITOR_TASKBAR_POS_Y + 85, "No map currently loaded.");
805 else
806 MPrint(260, EDITOR_TASKBAR_POS_Y + 85, ST::format("File: {}, Current Tileset: {}", g_filename, gTilesets[giCurrentTilesetID].zName));
807 break;
808 case TASK_TERRAIN:
809 if( gusSelectionType == LINESELECTION )
810 wszSelType[LINESELECTION] = ST::format("Width: {}", gusSelectionWidth);
811 DrawEditorInfoBox(wszSelType[gusSelectionType], FONT12POINT1, 220, 70, 60, 30);
812 FPSText = ST::format("{}%", gusSelectionDensity);
813 DrawEditorInfoBox(FPSText, FONT12POINT1, 310, 70, 40, 30);
814 break;
815 case TASK_ITEMS:
816 RenderEditorItemsInfo();
817 UpdateItemStatsPanel();
818 break;
819 case TASK_BUILDINGS:
820 UpdateBuildingsInfo();
821 if( gusSelectionType == LINESELECTION )
822 wszSelType[LINESELECTION] = ST::format("Width: {}", gusSelectionWidth);
823 DrawEditorInfoBox(wszSelType[gusSelectionType], FONT12POINT1, 530, 70, 60, 30);
824 break;
825 case TASK_MERCS:
826 UpdateMercsInfo();
827 break;
828 case TASK_MAPINFO:
829 UpdateMapInfo();
830 if( gusSelectionType == LINESELECTION )
831 wszSelType[LINESELECTION] = ST::format("Width: {}", gusSelectionWidth);
832 DrawEditorInfoBox(wszSelType[gusSelectionType], FONT12POINT1, 450, 70, 60, 30);
833 break;
834 default:
835 break;
836 }
837 }
838
839 //This is in ButtonSystem.c as a hack. Because we need to save the buffer whenever we do a full
840 //taskbar render, we need to draw the buttons without hilites, hence this flag. This flag is
841 //always true in ButtonSystem.c, so it won't effect anything else.
842 extern BOOLEAN gfGotoGridNoUI;
843
ProcessEditorRendering()844 void ProcessEditorRendering()
845 {
846 BOOLEAN fSaveBuffer = FALSE;
847 if( gfRenderTaskbar ) //do a full taskbar render.
848 {
849 ClearTaskbarRegion(0, 0, SCREEN_WIDTH, EDITOR_TASKBAR_HEIGHT);
850 RenderTerrainTileButtons();
851 MarkButtonsDirty();
852 gfRenderTaskbar = FALSE;
853 fSaveBuffer = TRUE;
854 gfRenderDrawingMode = TRUE;
855 gfRenderHilights = FALSE;
856 gfRenderMercInfo = TRUE;
857 }
858 if( gfRenderDrawingMode )
859 {
860 if( iCurrentTaskbar == TASK_BUILDINGS || iCurrentTaskbar == TASK_TERRAIN || iCurrentTaskbar == TASK_ITEMS )
861 {
862 ShowCurrentDrawingMode();
863 gfRenderDrawingMode = FALSE;
864 }
865 }
866 //render dynamically changed buttons only
867 RenderButtons( );
868
869 if( gfSummaryWindowActive )
870 RenderSummaryWindow();
871 else if( !gfGotoGridNoUI && !InOverheadMap() )
872 RenderMercStrings();
873
874 if( gfEditingDoor )
875 RenderDoorEditingWindow();
876
877 if( TextInputMode() )
878 RenderAllTextFields();
879 RenderEditorInfo();
880
881 if( !gfSummaryWindowActive && !gfGotoGridNoUI && !InOverheadMap() )
882 {
883 if( gpItem && gsItemGridNo != -1 )
884 RenderSelectedItemBlownUp();
885 if( iCurrentTaskbar == TASK_MAPINFO )
886 RenderMapEntryPointsAndLights();
887 if( (iDrawMode == DRAW_MODE_PLACE_ITEM && eInfo.uiItemType == TBAR_MODE_ITEM_KEYS) ||
888 iDrawMode == DRAW_MODE_DOORKEYS )
889 {
890 RenderDoorLockInfo();
891 }
892 }
893
894
895
896 if( fSaveBuffer )
897 BlitBufferToBuffer(FRAME_BUFFER, guiSAVEBUFFER, 0, EDITOR_TASKBAR_POS_Y, SCREEN_WIDTH, EDITOR_TASKBAR_HEIGHT);
898
899 //Make sure this is TRUE at all times.
900 //It is set to false when before we save the buffer, so the buttons don't get
901 //rendered with hilites, in case the mouse is over one.
902 gfRenderHilights = TRUE;
903
904 RenderButtonsFastHelp();
905
906 }
907
908
909