1 // CoMET - The Crimson Fields Map Editing Tool
2 // Copyright (C) 2002-2007 Jens Granseuer
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 //
18
19 ////////////////////////////////////////////////////////////////////////
20 // edwindow.cpp
21 ////////////////////////////////////////////////////////////////////////
22
23 #include "edwindow.h"
24 #include "extwindow.h"
25 #include "extwindow2.h"
26 #include "gamewindow.h"
27 #include "filewindow.h"
28 #include "gfxwidget.h"
29 #include "fileio.h"
30 #include "strutil.h"
31 #include "main.h"
32
33 ////////////////////////////////////////////////////////////////////////
34 // NAME : EdWindow::EdWindow
35 // DESCRIPTION: Create the editing window.
36 // PARAMETERS : mapdir - directory containing the map files
37 // view - pointer to the view to use
38 // RETURNS : -
39 ////////////////////////////////////////////////////////////////////////
40
EdWindow(const string & mapdir,View * view)41 EdWindow::EdWindow( const string &mapdir, View *view ) :
42 Window( view->x, view->y, view->w, view->h, 0, view ),
43 mission(NULL),
44 panel( view->w - DEFAULT_TILE_WIDTH * 4 - DEFAULT_SLIDER_SIZE - 20,
45 view->y, DEFAULT_TILE_WIDTH * 4 + DEFAULT_SLIDER_SIZE + 20, view->h ),
46 mv( this,
47 Rect( DEFAULT_SLIDER_SIZE, 0,
48 w - panel.w - DEFAULT_SLIDER_SIZE, h - DEFAULT_SLIDER_SIZE),
49 MV_DISABLE|MV_DISABLE_FOG ),
50 mode(ED_MODE_VIEW), selected(-1), mapdir(mapdir) {
51
52 unsigned short height = MIN( DEFAULT_TILE_HEIGHT * 6 + 4, h / 3 - 10 );
53 unit_wd = new UnitWidget( L_ID_UNITS, panel.x + 5,
54 panel.y + panel.h - 6 - height,
55 panel.w - 10, height, 0, NULL, this, NULL );
56 unit_wd->SetHook( this );
57
58 tile_wd = new TileWidget( L_ID_TILES, unit_wd->x,
59 panel.y + sfont->Height() + 15,
60 unit_wd->w, panel.h - height - sfont->Height() - 30,
61 0, NULL, this, NULL );
62 tile_wd->SetHook( this );
63
64 ud_wd = new SliderWidget( S_ID_VERT, 0, 0, DEFAULT_SLIDER_SIZE, mv.Height(),
65 0, 0, 0, 1, WIDGET_VSCROLL, NULL, this );
66 ud_wd->SetHook( this );
67 lr_wd = new SliderWidget( S_ID_HORIZ, DEFAULT_SLIDER_SIZE, h - DEFAULT_SLIDER_SIZE,
68 mv.Width(), DEFAULT_SLIDER_SIZE,
69 0, 0, 0, 1, WIDGET_HSCROLL, NULL, this );
70 lr_wd->SetHook( this );
71 }
72
73 ////////////////////////////////////////////////////////////////////////
74 // NAME : EdWindow::~EdWindow
75 // DESCRIPTION: Delete the editing window.
76 // PARAMETERS : -
77 // RETURNS : -
78 ////////////////////////////////////////////////////////////////////////
79
~EdWindow(void)80 EdWindow::~EdWindow( void ) {
81 delete mission;
82 }
83
84 ////////////////////////////////////////////////////////////////////////
85 // NAME : EdWindow::Draw
86 // DESCRIPTION: Draw the editing window.
87 // PARAMETERS : -
88 // RETURNS : -
89 ////////////////////////////////////////////////////////////////////////
90
Draw(void)91 void EdWindow::Draw( void ) {
92 mv.Draw();
93 DrawBack( panel );
94 DrawBox( panel, BOX_RAISED );
95
96 Widget *wd = widgets;
97 while ( wd ) {
98 if ( !wd->Hidden() ) wd->Draw();
99 wd = wd->next;
100 }
101
102 PrintCursorPos();
103 }
104
105 ////////////////////////////////////////////////////////////////////////
106 // NAME : EdWindow::PrintCursorPos
107 // DESCRIPTION: Print current cursor position to the panel.
108 // PARAMETERS : -
109 // RETURNS : -
110 ////////////////////////////////////////////////////////////////////////
111
PrintCursorPos(void)112 void EdWindow::PrintCursorPos( void ) {
113 Rect coord( panel.x + 5, panel.y + 5, panel.w - 10, sfont->Height() );
114 char posbuf[16];
115 DrawBack( coord );
116
117 if ( mission ) {
118 sprintf( posbuf, "X/Y: %d/%d", mv.Cursor().x, mv.Cursor().y );
119 sfont->Write( posbuf, this, coord.x, coord.y );
120
121 MapObject *obj = mission->GetMap().GetMapObject( mv.Cursor() );
122 if ( obj && obj->Name() ) {
123 string name = StringUtil::strprintf( "(%s)", obj->Name() );
124 sfont->WriteEllipsis( name.c_str(), this,
125 coord.x + sfont->TextWidth( posbuf ) + 5, coord.y, coord );
126 }
127 }
128 }
129
130 ////////////////////////////////////////////////////////////////////////
131 // NAME : EdWindow::HandleEvent
132 // DESCRIPTION: React on user input.
133 // PARAMETERS : event - event received by the event handler
134 // RETURNS : GUI status
135 ////////////////////////////////////////////////////////////////////////
136
HandleEvent(const SDL_Event & event)137 GUI_Status EdWindow::HandleEvent( const SDL_Event &event ) {
138
139 if ( !mission ) {
140 if ( event.type == SDL_KEYDOWN )
141 ShowContextMenu( Point(-1, -1) );
142 else if ( event.type == SDL_MOUSEBUTTONDOWN )
143 ShowContextMenu( Point(event.button.x - x, event.button.y - y) );
144
145 return GUI_OK;
146 }
147
148 GUI_Status rc = Window::HandleEvent( event );
149 if ( rc == GUI_OK ) {
150
151 // check for keyboard commands
152 if ( event.type == SDL_KEYDOWN ) {
153
154 switch ( event.key.keysym.sym ) {
155 case SDLK_KP1: case SDLK_KP2: case SDLK_KP3:
156 case SDLK_KP4: case SDLK_KP6: case SDLK_KP7:
157 case SDLK_KP8: case SDLK_KP9:
158 case SDLK_LEFT: case SDLK_RIGHT: case SDLK_UP: case SDLK_DOWN:
159 MoveCursor( event.key.keysym.sym );
160 break;
161 case SDLK_SPACE: // equivalent to left mouse button
162 LeftMouseButton( mv.Cursor() );
163 break;
164 case SDLK_q:
165 Quit();
166 break;
167 case SDLK_ESCAPE:
168 tile_wd->Select( -1 );
169 unit_wd->Select( -1 );
170 break;
171 case SDLK_RETURN:
172 ShowContextMenu( mv.Cursor() );
173
174 case SDLK_u: { // edit unit
175 Unit *u = mv.GetMap()->GetUnit( mv.Cursor() );
176 if ( u ) {
177 EdUnitWindow *euw = new EdUnitWindow( *u, *mission, view );
178 euw->SetMapView( mv );
179 }
180 break; }
181 case SDLK_b: { // edit building
182 Building *b = mv.GetMap()->GetBuilding( mv.Cursor() );
183 if ( b ) new EdBuildingWindow( *b, *mission, view );
184 break; }
185
186 default:
187 break;
188 }
189
190 } else if ( event.type == SDL_MOUSEBUTTONDOWN ) {
191 Point pos;
192 bool validhex = !mv.Pixel2Hex( event.button.x - x, event.button.y - y, pos );
193
194 if ( event.button.button == SDL_BUTTON_LEFT ) {
195 if ( validhex ) LeftMouseButton( pos );
196 } else if ( event.button.button == SDL_BUTTON_RIGHT ) {
197 ShowContextMenu( validhex ? pos : Point(-1,-1) );
198 }
199
200 } else if ( event.type == SDL_MOUSEMOTION ) {
201 // handle just like a mouse button if LMB is down and
202 // user is terraforming
203 if ( (mode == ED_MODE_TERRAIN) &&
204 (event.motion.state & SDL_BUTTON( SDL_BUTTON_LEFT )) &&
205 !ud_wd->Clicked() && !lr_wd->Clicked() ) {
206 Point pos;
207 if ( !mv.Pixel2Hex( event.motion.x, event.motion.y, pos ) )
208 LeftMouseButton( pos );
209 }
210 }
211
212 }
213 return rc;
214 }
215
216 ////////////////////////////////////////////////////////////////////////
217 // NAME : EdWindow::MoveCursor
218 // DESCRIPTION: Move the cursor in reaction to a key event.
219 // PARAMETERS : key - the key code used to give the order
220 // RETURNS : -
221 ////////////////////////////////////////////////////////////////////////
222
MoveCursor(int key)223 void EdWindow::MoveCursor( int key ) {
224 Direction dir;
225
226 switch ( key ) {
227 case SDLK_KP1: dir = SOUTHWEST; break;
228 case SDLK_DOWN:
229 case SDLK_KP2: dir = SOUTH; break;
230 case SDLK_KP3: dir = SOUTHEAST; break;
231 case SDLK_KP7: dir = NORTHWEST; break;
232 case SDLK_UP:
233 case SDLK_KP8: dir = NORTH; break;
234 case SDLK_KP9: dir = NORTHEAST; break;
235 case SDLK_LEFT:
236 case SDLK_KP4: dir = WEST; break;
237 case SDLK_RIGHT:
238 case SDLK_KP6: dir = EAST; break;
239 default: return;
240 }
241
242 Point dest;
243 if ( !mv.GetMap()->Dir2Hex( mv.Cursor(), dir, dest ) ) SetCursor( dest );
244 }
245
246 ////////////////////////////////////////////////////////////////////////
247 // NAME : EdWindow::SetCursor
248 // DESCRIPTION: Set the cursor to a new hex on the map. Contrary to the
249 // low-level function in MapView this updates the display
250 // at the old and new position if necessary.
251 // PARAMETERS : cursor - new cursor position
252 // RETURNS : -
253 ////////////////////////////////////////////////////////////////////////
254
SetCursor(const Point & cursor)255 void EdWindow::SetCursor( const Point &cursor ) {
256 Rect upd;
257
258 if ( mv.CursorEnabled() ) {
259 upd = mv.SetCursor( Point(-1,-1) ); // disable cursor for hex update
260 Show( upd ); // update previous cursor position
261 }
262
263 upd = mv.SetCursor( cursor );
264 Show( upd );
265
266 PrintCursorPos();
267 Show( panel );
268 }
269
270 ////////////////////////////////////////////////////////////////////////
271 // NAME : EdWindow::LeftMouseButton
272 // DESCRIPTION: Left mouse button has been pressed. See what we can do.
273 // PARAMETERS : hex - hex the button was clicked over
274 // RETURNS : -
275 ////////////////////////////////////////////////////////////////////////
276
LeftMouseButton(const Point & hex)277 void EdWindow::LeftMouseButton( const Point &hex ) {
278 Map *map = mv.GetMap();
279
280 if ( mode == ED_MODE_TERRAIN ) {
281 if ( map->IsBuilding( hex ) && map->GetBuilding(hex) &&
282 !(map->GetTerrainSet()->GetTerrainInfo(selected)->tt_type & TT_ENTRANCE) )
283 new NoteWindow( "Warning", "You have just removed a shop entrance. "
284 "The corresponding shop has NOT been deleted! "
285 "(to do so restore the entrance and delete the shop before "
286 "erasing the entrance)", 0, view );
287 map->SetHexType( hex, selected );
288 } else if ( mode == ED_MODE_UNIT ) {
289 if ( map->GetMapObject(hex) ) new NoteWindow( "Error", "Hex occupied.", 0, view );
290 else {
291 UnitSet *us = map->GetUnitSet();
292 const UnitType *ut = us->GetUnitInfo( selected < us->NumTiles() ?
293 selected : selected - us->NumTiles() );
294 mission->CreateUnit( ut, selected < us->NumTiles() ? PLAYER_ONE : PLAYER_TWO, hex );
295 }
296 }
297
298 SetCursor( hex );
299 }
300
301 ////////////////////////////////////////////////////////////////////////
302 // NAME : EdWindow::LoadMission
303 // DESCRIPTION: Load a mission from file and attach it to the display.
304 // PARAMETERS : file - name of mission data file
305 // filereq - pop up file requester
306 // RETURNS : pointer to Mission object on success, NULL on error
307 ////////////////////////////////////////////////////////////////////////
308
LoadMission(const char * file,bool filereq)309 Mission *EdWindow::LoadMission( const char *file, bool filereq ) {
310 string fn;
311 Mission *ms = NULL;
312
313 if ( filereq )
314 fn = GetFileName( file, ".lev", mapdir, WIN_FILE_LOAD );
315 else fn = file;
316
317 if ( fn.length() > 0 ) {
318 ms = new Mission();
319 if ( ms ) {
320 int err = ms->Load( fn.c_str() );
321 if ( err ) {
322 delete ms;
323 new NoteWindow( "Error", "Couldn't load map. This could be a file type mismatch.", 0, view );
324 } else {
325 SetNewMission( ms );
326 }
327 }
328 }
329
330 return ms;
331 }
332
333 ////////////////////////////////////////////////////////////////////////
334 // NAME : EdWindow::SaveMission
335 // DESCRIPTION: Save a mission to file.
336 // PARAMETERS : file - name of mission data file
337 // filereq - pop up file requester
338 // RETURNS : GUI status
339 ////////////////////////////////////////////////////////////////////////
340
SaveMission(const char * file,bool filereq)341 GUI_Status EdWindow::SaveMission( const char *file, bool filereq ) {
342 string fn;
343 GUI_Status rc = GUI_OK;
344
345 if ( filereq )
346 fn = GetFileName( file, ".lev", mapdir, WIN_FILE_SAVE );
347 else fn = file;
348
349 if ( fn.length() > 0 ) {
350 if ( mission->Save( fn.c_str() ) != 0 ) {
351 new NoteWindow( "Error", "Could not save mission!", WIN_CENTER, view );
352 }
353 }
354 return rc;
355 }
356
357 ////////////////////////////////////////////////////////////////////////
358 // NAME : EdWindow::ExportMission
359 // DESCRIPTION: Save a mission to a plain text file.
360 // PARAMETERS : file - default name of mission data file
361 // filereq - pop up file requester
362 // RETURNS : GUI status
363 ////////////////////////////////////////////////////////////////////////
364
ExportMission(const char * file,bool filereq)365 GUI_Status EdWindow::ExportMission( const char *file, bool filereq ) {
366 string fn;
367 GUI_Status rc = GUI_OK;
368
369 if ( filereq )
370 fn = GetFileName( file, ".src", mapdir, WIN_FILE_SAVE );
371 else fn = file;
372
373 if ( fn.length() > 0 ) mission->Export( fn.c_str() );
374 return rc;
375 }
376
377 ////////////////////////////////////////////////////////////////////////
378 // NAME : EdWindow::GetFileName
379 // DESCRIPTION: Get the name of a file to load or to save to. Pop up a
380 // file requester.
381 // PARAMETERS : filename - default filename
382 // suffix - filename suffix
383 // dirname - name of directory to look in
384 // flag - WIN_FILE_LOAD or WIN_FILE_SAVE
385 // RETURNS : file name or empty string on error
386 ////////////////////////////////////////////////////////////////////////
387
GetFileName(const char * filename,const char * suffix,const string & dirname,int flag) const388 string EdWindow::GetFileName( const char *filename, const char *suffix,
389 const string &dirname, int flag ) const {
390 string file( filename );
391 if ( file.length() > 0 ) file.append( suffix );
392
393 bool filesel;
394 do {
395 GUI_Status rc;
396 DialogWindow *dw;
397 bool done = false;
398 FileWindow *fw = new FileWindow( dirname.c_str(), file.c_str(),
399 suffix, flag, view );
400 fw->ok->SetID( 1 );
401 fw->cancel->SetID( 0 );
402
403 do {
404 filesel = false;
405 rc = fw->EventLoop();
406
407 if ( rc == 1 ) {
408 file = fw->GetFile();
409 if ( file.length() != 0 ) {
410 view->CloseWindow( fw );
411 done = true;
412 }
413 } else if ( rc == 0 ) {
414 view->CloseWindow( fw );
415 file.assign( "" );
416 done = true;
417 }
418
419 } while ( !done );
420
421 if ( file.length() > 0 && (flag == WIN_FILE_SAVE) && File::Exists( file ) ) {
422 // if file exists let user confirm the write
423 char *conmsg = new char[ file.length() + 20 ];
424 strcpy( conmsg, file.c_str() );
425 strcat( conmsg, " exists. Overwrite?" );
426 dw = new DialogWindow( NULL, conmsg, "_Yes|_No", 1, 0, view );
427 dw->SetButtonID( 0, 1 );
428 dw->SetButtonID( 1, 0 );
429 rc = dw->EventLoop();
430 view->CloseWindow( dw );
431 if ( rc == 0 ) {
432 filesel = true;
433 file = file_part( file );
434 }
435 delete [] conmsg;
436 }
437
438 } while ( filesel );
439
440 return file;
441 }
442
443 ////////////////////////////////////////////////////////////////////////
444 // NAME : EdWindow::WidgetActivated
445 // DESCRIPTION: This method is called when the user selects one of the
446 // widgets associated with this window - the tiles or units
447 // list, the map scrollers, or one of a number of buttons
448 // including the main menu.
449 // PARAMETERS : widget - pointer to calling widget
450 // win - parent window of calling widget
451 // RETURNS : GUI status
452 ////////////////////////////////////////////////////////////////////////
453
WidgetActivated(Widget * widget,Window * win)454 GUI_Status EdWindow::WidgetActivated( Widget *widget, Window *win ) {
455 GUI_Status rc = GUI_OK;
456
457 if ( win == this ) {
458
459 switch ( widget->ID() ) {
460 case L_ID_UNITS:
461 if ( unit_wd->Selected() == -1 ) {
462 if ( tile_wd->Selected() == -1 ) {
463 mode = ED_MODE_VIEW;
464 selected = -1;
465 }
466 } else {
467 mode = ED_MODE_UNIT;
468 selected = unit_wd->Selected();
469 tile_wd->Select( -1 );
470 }
471 break;
472 case L_ID_TILES:
473 if ( tile_wd->Selected() == -1 ) {
474 if ( unit_wd->Selected() == -1 ) {
475 mode = ED_MODE_VIEW;
476 selected = -1;
477 }
478 } else {
479 mode = ED_MODE_TERRAIN;
480 selected = tile_wd->Selected();
481 unit_wd->Select( -1 );
482 }
483 break;
484
485 case S_ID_VERT: {
486 Point offset = mv.GetOffsets();
487 mv.Scroll( 0, ud_wd->Level() - offset.y );
488 Show( mv );
489 break; }
490 case S_ID_HORIZ: {
491 Point offset = mv.GetOffsets();
492 mv.Scroll( lr_wd->Level() - offset.x, 0 );
493 Show( mv );
494 break; }
495 }
496
497 } else {
498
499 Map *map = mv.GetMap();
500
501 // context menu?
502 if ( widget->ID() >= B_ID_TILE_GRAB )
503 static_cast<MenuWindow *>(win)->CloseParent();
504 view->CloseWindow(win);
505
506 switch ( widget->ID() ) {
507 case B_ID_NEW: {
508 NewMissionWindow *nmw = new NewMissionWindow( view );
509 nmw->SetHook( this, B_ID_NEW_MISSION_OK );
510 break; }
511 case B_ID_LOAD:
512 LoadMission( "", true );
513 break;
514 case B_ID_SAVE:
515 rc = SaveMission( mission->GetTitle().c_str(), true );
516 break;
517 case B_ID_EXPORT:
518 rc = ExportMission( mission->GetTitle().c_str(), true );
519 break;
520 case B_ID_VALIDATE:
521 ValidateMission();
522 break;
523 case B_ID_SETTINGS:
524 new EdMissionSetupWindow( *mission, view );
525 break;
526 case B_ID_QUIT:
527 Quit();
528 break;
529
530 case B_ID_TILE_GRAB:
531 tile_wd->Select( map->HexTypeID(selected_hex) );
532 break;
533 case B_ID_TILE_SWAP:
534 SwapTiles( map->HexTypeID(selected_hex), selected );
535 break;
536
537 case B_ID_UNIT_INFO:
538 new UnitInfoWindow( map->GetUnit( selected_hex )->Type()->ID(), *map, view );
539 break;
540 case B_ID_UNIT_EDIT: {
541 EdUnitWindow *euw = new EdUnitWindow( *(map->GetUnit( selected_hex )), *mission, view );
542 euw->SetMapView( mv );
543 break; }
544 case B_ID_UNIT_DEL:
545 mission->DeleteUnit( map->GetUnit(selected_hex) );
546 Show( mv.UpdateHex( selected_hex ) );
547 PrintCursorPos();
548 Show( panel );
549 break;
550
551 case B_ID_BLD_CREATE:
552 mission->CreateBuilding( PLAYER_ONE, selected_hex ); // fall through
553 case B_ID_BLD_EDIT:
554 new EdBuildingWindow( *(map->GetBuilding( selected_hex )),
555 *mission, view );
556 break;
557 case B_ID_BLD_DEL:
558 mission->DeleteBuilding( map->GetBuilding( selected_hex ) );
559 PrintCursorPos();
560 Show( panel );
561 break;
562
563 case B_ID_EVENTS:
564 new EdEventsWindow( *mission, view );
565 break;
566
567 case B_ID_MESSAGES:
568 new EdMsgWindow( mission->GetMessages(), view );
569 break;
570
571 case B_ID_NEW_MISSION_OK: {
572 NewMissionWindow *nmw = static_cast<NewMissionWindow *>(win);
573 if ( nmw->GetMission() )
574 SetNewMission( nmw->GetMission() );
575 break; }
576 }
577
578 }
579
580 return rc;
581 }
582
583 ////////////////////////////////////////////////////////////////////////
584 // NAME : EdWindow::Quit
585 // DESCRIPTION: Ask user for confirmation and leave the editor.
586 // PARAMETERS : -
587 // RETURNS : -
588 ////////////////////////////////////////////////////////////////////////
589
Quit(void) const590 void EdWindow::Quit( void ) const {
591 DialogWindow *req = new DialogWindow( NULL, "Do you really want to quit?",
592 "_Yes|_No", 1, 0, view );
593 req->SetButtonID( 0, GUI_QUIT );
594 }
595
596 ////////////////////////////////////////////////////////////////////////
597 // NAME : EdWindow::ShowContextMenu
598 // DESCRIPTION: Open a pop-up menu with with context-dependent options.
599 // PARAMETERS : clicked - hex coordinates of the mouse click or -1,-1 if
600 // no specific hex was selected
601 // RETURNS : -
602 ////////////////////////////////////////////////////////////////////////
603
ShowContextMenu(const Point & clicked)604 void EdWindow::ShowContextMenu( const Point &clicked ) {
605 MenuWindow *menu = new MenuWindow( PROGRAMNAME, this, view );
606
607 if ( mission ) {
608 if ( clicked != Point(-1,-1) ) {
609 Map *map = mv.GetMap();
610 Unit *u = map->GetUnit( clicked );
611 selected_hex = clicked;
612
613 // tile sub-menu
614 menu->AddMenu( 0, 0, "_Tile" );
615 menu->AddItem( 1, B_ID_TILE_GRAB, 0, "_Grab" );
616 menu->AddItem( 1, B_ID_TILE_SWAP,
617 (mode == ED_MODE_TERRAIN ? 0 : WIDGET_DISABLED),
618 "_Swap" );
619
620 if ( u ) { // unit sub-menu
621 menu->AddMenu( 0, 0, "_Unit" );
622 menu->AddItem( 1, B_ID_UNIT_INFO, 0, "_Info" );
623 menu->AddItem( 1, B_ID_UNIT_EDIT, 0, "_Edit..." );
624 menu->AddItem( 1, B_ID_UNIT_DEL, 0, "_Delete" );
625 }
626
627 if ( map->IsBuilding( clicked ) ) {
628 Building *b = map->GetBuilding( clicked );
629
630 menu->AddMenu( 0, 0, "_Building" );
631 if ( b ) {
632 menu->AddItem( 1, B_ID_BLD_EDIT, 0, "_Edit..." );
633 menu->AddItem( 1, B_ID_BLD_DEL, 0, "_Delete" );
634 } else menu->AddItem( 1, B_ID_BLD_CREATE, 0, "_Create..." );
635 }
636 }
637
638 menu->AddItem( 0, B_ID_EVENTS, 0, "_Events..." );
639 menu->AddItem( 0, B_ID_MESSAGES, 0, "_Messages..." );
640 menu->AddBar( 0 );
641 }
642
643 // file ops
644 menu->AddMenu( 0, 0, "_Project" );
645 menu->AddItem( 1, B_ID_NEW, 0, "_New..." );
646 menu->AddItem( 1, B_ID_LOAD, 0, "_Load..." );
647 menu->AddItem( 1, B_ID_SAVE, (mission ? 0 : WIDGET_DISABLED),
648 "_Save..." );
649 menu->AddItem( 1, B_ID_EXPORT, (mission ? 0 : WIDGET_DISABLED),
650 "_Export..." );
651 menu->AddItem( 1, B_ID_VALIDATE, (mission ? 0 : WIDGET_DISABLED),
652 "_Validate" );
653 menu->AddItem( 1, B_ID_SETTINGS, (mission ? 0 : WIDGET_DISABLED),
654 "Se_ttings" );
655 menu->AddItem( 1, B_ID_QUIT, 0, "_Quit..." );
656
657 menu->Layout();
658 }
659
660 ////////////////////////////////////////////////////////////////////////
661 // NAME : EdWindow::SwapTiles
662 // DESCRIPTION: Replace each occurence of one tile on the map with
663 // another tile.
664 // PARAMETERS : t1 - identifier of the tiles to be replaced
665 // t2 - identifier of the tiles to replace t1
666 // RETURNS : -
667 ////////////////////////////////////////////////////////////////////////
668
SwapTiles(unsigned short t1,unsigned short t2)669 void EdWindow::SwapTiles( unsigned short t1, unsigned short t2 ) {
670 Map *map = mv.GetMap();
671 Point p;
672
673 for ( p.y = 0; p.y < map->Height(); ++p.y ) {
674 for ( p.x = 0; p.x < map->Width(); ++p.x ) {
675 if ( map->HexTypeID(p) == t1 ) map->SetHexType( p, t2 );
676 }
677 }
678
679 mv.Draw();
680 Show( mv );
681 }
682
683 ////////////////////////////////////////////////////////////////////////
684 // NAME : EdWindow::ValidateMission
685 // DESCRIPTION: Check mission integrity.
686 // PARAMETERS : -
687 // RETURNS : -
688 ////////////////////////////////////////////////////////////////////////
689
ValidateMission(void) const690 void EdWindow::ValidateMission( void ) const {
691 stringstream msg;
692
693 if ( mission->Validate( msg ) > 0 ) {
694 new MessageWindow( "Validation Results", msg.str().c_str(), view );
695 } else {
696 new NoteWindow( "Validation successful",
697 "No errors or warnings have been detected.", 0, view );
698 }
699 }
700
701 ////////////////////////////////////////////////////////////////////////
702 // NAME : EdWindow::SetNewMission
703 // DESCRIPTION: Change the current mission.
704 // PARAMETERS : ms - new mission
705 // RETURNS : -
706 ////////////////////////////////////////////////////////////////////////
707
SetNewMission(Mission * ms)708 void EdWindow::SetNewMission( Mission *ms ) {
709 delete mission;
710
711 mv.Disable();
712 mode = ED_MODE_VIEW;
713
714 mission = ms;
715 Map &map = mission->GetMap();
716 mv.SetMap( &map );
717 mv.SetCursor( Point(0,0) );
718
719 tile_wd->SetTerrainSet( map.GetTerrainSet() );
720 unit_wd->SetUnitSet( map.GetUnitSet() );
721
722 short max = MAX( map.Height() * mv.TileHeight() +
723 mv.TileShiftY() - mv.Height(), 0 );
724 ud_wd->Adjust( 0, max, mv.Height() );
725 ud_wd->ScrollTo( 0 );
726
727 max = MAX( map.Width() * (mv.TileWidth() - mv.TileShiftX()) +
728 mv.TileShiftX() - mv.Width(), 0 );
729 lr_wd->Adjust( 0, max, mv.Width() );
730 lr_wd->ScrollTo( 0 );
731
732 mv.Enable();
733 Draw();
734 Show();
735 }
736
737