1 // ==============================================================
2 // This file is part of Glest (www.glest.org)
3 //
4 // Copyright (C) 2001-2008 Martiño Figueroa
5 //
6 // You can redistribute this code and/or modify it under
7 // the terms of the GNU General Public License as published
8 // by the Free Software Foundation; either version 2 of the
9 // License, or (at your option) any later version
10 // ==============================================================
11
12 #include "main.h"
13 #include <ctime>
14 #include "conversion.h"
15 #include "icons.h"
16 #include "platform_common.h"
17 #include "config.h"
18 #include <iostream>
19 #include"platform_util.h"
20 #include <wx/stdpaths.h>
21 #ifndef WIN32
22 #include <errno.h>
23 #endif
24 #include "common_scoped_ptr.h"
25 //#include <memory>
26
27 using namespace Shared::Util;
28 using namespace Shared::PlatformCommon;
29 using namespace Glest::Game;
30 using namespace std;
31
32 namespace Glest { namespace Game {
getGameReadWritePath(string lookupKey)33 string getGameReadWritePath(string lookupKey) {
34 string path = "";
35 if(path == "" && getenv("GLESTHOME") != NULL) {
36 path = getenv("GLESTHOME");
37 if(path != "" && EndsWith(path, "/") == false && EndsWith(path, "\\") == false) {
38 path += "/";
39 }
40
41 //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] path to be used for read/write files [%s]\n",__FILE__,__FUNCTION__,__LINE__,path.c_str());
42 }
43
44 return path;
45 }
46 }}
47
48 namespace MapEditor {
49
50 const string mapeditorVersionString = "v3.13.0";
51 const string MainWindow::winHeader = "MegaGlest Map Editor " + mapeditorVersionString;
52
53 // ===============================================
54 // class Global functions
55 // ===============================================
56
ToUnicode(const char * str)57 wxString ToUnicode(const char* str) {
58 return wxString(str, wxConvUTF8);
59 }
60
ToUnicode(const string & str)61 wxString ToUnicode(const string& str) {
62 return wxString(str.c_str(), wxConvUTF8);
63 }
64
65 // ===============================================
66 // class MainWindow
67 // ===============================================
68
MainWindow(string appPath)69 MainWindow::MainWindow(string appPath)
70 : wxFrame(NULL, -1, ToUnicode(winHeader), wxPoint(0,0), wxSize(1024, 768))
71 , glCanvas(NULL)
72 , program(NULL)
73 , lastX(0)
74 , lastY(0)
75 , panel(NULL)
76 , menuBar(NULL)
77 , fileDialog(NULL)
78
79 , currentBrush(btHeight)
80 , height(0)
81 , surface(1)
82 , radius(1)
83 , object(0)
84 , resource(0)
85 , startLocation(1)
86 , enabledGroup(ctHeight)
87 , fileModified(false)
88 , boxsizer(NULL)
89 ,startupSettingsInited(false) {
90
91 menuFile=NULL;
92 menuEdit=NULL;
93 menuEditMirror=NULL;
94 menuView=NULL;
95 menuBrush=NULL;
96 menuBrushHeight=NULL;
97 menuBrushGradient=NULL;
98 menuBrushSurface=NULL;
99 menuBrushObject=NULL;
100 menuBrushResource=NULL;
101 menuBrushStartLocation=NULL;
102 menuRadius=NULL;
103 fileDialog=NULL;
104 resourceUnderMouse=0;
105 objectUnderMouse=0;
106
107 // default values for random height calculation that turned out to be quite useful
108 randomWithReset=true;
109 randomMinimumHeight=-300;
110 randomMaximumHeight=400;
111 randomChanceDivider=30;
112 randomRecursions=3;
113
114 this->appPath = appPath;
115 Properties::setApplicationPath(executable_path(appPath));
116
117 this->panel = new wxPanel(this, wxID_ANY);
118 }
119
onToolPlayer(wxCommandEvent & event)120 void MainWindow::onToolPlayer(wxCommandEvent& event){
121 PopupMenu(menuBrushStartLocation);
122 }
123
onMouseMove(wxMouseEvent & event)124 void MainToolBar::onMouseMove(wxMouseEvent &event) {
125 #ifdef WIN32
126 if(this->GetParent() != NULL && this->GetParent()->GetParent() != NULL) {
127 MainWindow *mainWindow = dynamic_cast<MainWindow *>(this->GetParent()->GetParent());
128 if(mainWindow != NULL) {
129 mainWindow->refreshMapRender();
130 }
131 }
132 #endif
133 event.Skip();
134 }
135
BEGIN_EVENT_TABLE(MainToolBar,wxToolBar)136 BEGIN_EVENT_TABLE(MainToolBar, wxToolBar)
137
138 EVT_MOTION(MainToolBar::onMouseMove)
139
140 END_EVENT_TABLE()
141
142 void MainWindow::init(string fname) {
143
144 //menus
145 menuBar = new wxMenuBar();
146
147 //file
148 menuFile = new wxMenu();
149 menuFile->Append(wxID_NEW);
150 menuFile->Append(wxID_OPEN);
151 menuFile->AppendSeparator();
152 menuFile->Append(wxID_SAVE);
153 menuFile->Append(wxID_SAVEAS);
154 menuFile->AppendSeparator();
155 menuFile->Append(wxID_EXIT);
156 menuBar->Append(menuFile, wxT("&File"));
157
158 //edit
159 menuEdit = new wxMenu();
160 menuEdit->Append(miEditUndo, wxT("&Undo\tCTRL+Z"));
161 menuEdit->Append(miEditRedo, wxT("&Redo\tCTRL+Y"));
162 menuEdit->AppendSeparator();
163 // menuEdit->Append(miEditReset, wxT("Rese&t..."));
164 menuEdit->Append(miEditResetPlayers, wxT("Reset &Players..."));
165 menuEdit->Append(miEditResize, wxT("Re&size..."));
166 menuEdit->Append(miEditFlipDiagonal, wxT("Flip &Diagonal"));
167 menuEdit->Append(miEditFlipX, wxT("Flip &X"));
168 menuEdit->Append(miEditFlipY, wxT("Flip &Y"));
169
170 // Mirror submenu-------------------------------------------
171 menuEditMirror = new wxMenu();
172 menuEditMirror->Append(miEditMirrorX, wxT("Copy &Left to Right"));
173 menuEditMirror->Append(miEditMirrorY, wxT("Copy &Top to Bottom"));
174 menuEditMirror->Append(miEditMirrorXY, wxT("Copy &BottomLeft to TopRight"));
175 menuEditMirror->AppendSeparator();
176 menuEditMirror->Append(miEditRotatecopyX, wxT("&Rotate Left to Right"));
177 menuEditMirror->Append(miEditRotatecopyY, wxT("Rotate T&op to Bottom"));
178 menuEditMirror->Append(miEditRotatecopyXY, wxT("Rotate Botto&mLeft to TopRight"));
179 menuEditMirror->Append(miEditRotatecopyCorner, wxT("Rotate TopLeft &corner to TopRight"));
180 menuEdit->Append(miEditMirror, wxT("&Mirror"), menuEditMirror);
181 // ---------------------------------------------------------
182
183 menuEdit->Append(miEditRandomizeHeights, wxT("Randomize &Heights"));
184 menuEdit->Append(miEditRandomize, wxT("Randomi&ze Players"));
185 menuEdit->Append(miEditSwitchSurfaces, wxT("Switch Sur&faces..."));
186 menuEdit->Append(miEditInfo, wxT("&Info..."));
187 menuEdit->Append(miEditAdvanced, wxT("&Advanced..."));
188 menuBar->Append(menuEdit, wxT("&Edit"));
189
190 //view
191 menuView = new wxMenu();
192 menuView->Append(miViewResetZoomAndPos, wxT("&Reset zoom and pos"));
193 menuView->AppendCheckItem(miViewGrid, wxT("&Grid"));
194 menuView->AppendCheckItem(miViewHeightMap, wxT("H&eightMap"));
195 menuView->AppendCheckItem(miHideWater, wxT("Hide&Water"));
196 menuView->AppendSeparator();
197 menuView->Append(miViewHelp, wxT("&Help..."));
198 menuView->Append(miViewAbout, wxT("&About..."));
199 menuBar->Append(menuView, wxT("&View"));
200
201 //brush
202 // menuBrush = new wxMenu();
203
204 //surface
205 menuBrushSurface = new wxMenu();
206 menuBrushSurface->AppendCheckItem(miBrushSurface + 1, wxT("&Grass"));
207 menuBrushSurface->AppendCheckItem(miBrushSurface + 2, wxT("S&econdary grass"));
208 menuBrushSurface->AppendCheckItem(miBrushSurface + 3, wxT("&Road"));
209 menuBrushSurface->AppendCheckItem(miBrushSurface + 4, wxT("&Stone"));
210 menuBrushSurface->AppendCheckItem(miBrushSurface + 5, wxT("Gr&ound"));
211 menuBar->Append(menuBrushSurface, wxT("&Surface"));
212
213 //resources
214 menuBrushResource = new wxMenu();
215 //menuBrushResource->AppendCheckItem(miBrushResource + 1, wxT("&0 - None"));
216 menuBrushResource->AppendCheckItem(miBrushResource+2, wxT("&Gold (unwalkable)"));
217 menuBrushResource->AppendCheckItem(miBrushResource+3, wxT("&Stone (unwalkable)"));
218 menuBrushResource->AppendCheckItem(miBrushResource+4, wxT("&3 - custom"));
219 menuBrushResource->AppendCheckItem(miBrushResource+5, wxT("&4 - custom"));
220 menuBrushResource->AppendCheckItem(miBrushResource+6, wxT("&5 - custom"));
221 menuBar->Append(menuBrushResource, wxT("&Resource"));
222
223 //objects
224 menuBrushObject = new wxMenu();
225 menuBrushObject->AppendCheckItem(miBrushObject+1, wxT("&None (erase)\tALT+0"));
226 menuBrushObject->AppendSeparator();
227 menuBrushObject->AppendCheckItem(miBrushObject+2, wxT("&Tree (harvestable)"));
228 menuBrushObject->AppendCheckItem(miBrushObject+3, wxT("&Dead tree/Cactuses/Thornbush"));
229 menuBrushObject->AppendCheckItem(miBrushObject+4, wxT("&Stone"));
230 menuBrushObject->AppendCheckItem(miBrushObject+5, wxT("&Bush/Grass/Fern (walkable)"));
231 menuBrushObject->AppendCheckItem(miBrushObject+6, wxT("&Water object/Reed/Papyrus (walkable)"));
232 menuBrushObject->AppendCheckItem(miBrushObject+7, wxT("Big tree/&Old palm"));
233 menuBrushObject->AppendCheckItem(miBrushObject+8, wxT("&Hanged/Impaled "));
234 menuBrushObject->AppendCheckItem(miBrushObject+9, wxT("St&atues"));
235 menuBrushObject->AppendCheckItem(miBrushObject+10, wxT("&Mountain"));
236 menuBrushObject->AppendCheckItem(miBrushObject+11, wxT("&Invisible blocking object"));
237 menuBar->Append(menuBrushObject, wxT("&Object"));
238
239 // ZombiePirate height brush
240 menuBrushGradient = new wxMenu();
241 for (int i = 0; i < heightCount; ++i) {
242 menuBrushGradient->AppendCheckItem(miBrushGradient + i + 1, ToUnicode((i>4?"&":"") +intToStr(i - heightCount / 2)));
243 }
244 menuBar->Append(menuBrushGradient, wxT("&Gradient"));
245
246 // Glest height brush
247 menuBrushHeight = new wxMenu();
248 for (int i = 0; i < heightCount; ++i) {
249 menuBrushHeight->AppendCheckItem(miBrushHeight + i + 1, ToUnicode((i>4?"&":"") +intToStr(i - heightCount / 2)));
250 }
251 menuBrushHeight->Check(miBrushHeight + (heightCount + 1) / 2, true);
252 menuBar->Append(menuBrushHeight, wxT("&Height"));
253
254 enabledGroup = ctHeight;
255
256 //radius
257 menuRadius = new wxMenu();
258 for (int i = 1; i <= radiusCount; ++i) {
259 menuRadius->AppendCheckItem(miRadius + i, ToUnicode("&" + intToStr(i) + " (diameter "+intToStr(i*2-1)+ ")"+ "\tALT+" + intToStr(i)));
260 }
261 menuRadius->Check(miRadius + 1, true);
262 menuBar->Append(menuRadius, wxT("R&adius"));
263
264 //players
265 menuBrushStartLocation = new wxMenu();
266 wxMenuItem *pmi1 = new wxMenuItem(menuBrushStartLocation, miBrushStartLocation + 1, wxT("Player &1 Red"));
267 pmi1->SetBitmap(wxBitmap(brush_players_red));
268 menuBrushStartLocation->Append(pmi1);
269 wxMenuItem *pmi2 = new wxMenuItem(menuBrushStartLocation, miBrushStartLocation + 2, wxT("Player &2 Blue"));
270 pmi2->SetBitmap(wxBitmap(brush_players_blue));
271 menuBrushStartLocation->Append(pmi2);
272 wxMenuItem *pmi3 = new wxMenuItem(menuBrushStartLocation, miBrushStartLocation + 3, wxT("Player &3 Green"));
273 pmi3->SetBitmap(wxBitmap(brush_players_green));
274 menuBrushStartLocation->Append(pmi3);
275 wxMenuItem *pmi4 = new wxMenuItem(menuBrushStartLocation, miBrushStartLocation + 4, wxT("Player &4 Yellow"));
276 pmi4->SetBitmap(wxBitmap(brush_players_yellow));
277 menuBrushStartLocation->Append(pmi4);
278 wxMenuItem *pmi5 = new wxMenuItem(menuBrushStartLocation, miBrushStartLocation + 5, wxT("Player &5 White"));
279 pmi5->SetBitmap(wxBitmap(brush_players_white));
280 menuBrushStartLocation->Append(pmi5);
281 wxMenuItem *pmi6 = new wxMenuItem(menuBrushStartLocation, miBrushStartLocation + 6, wxT("Player &6 Cyan"));
282 pmi6->SetBitmap(wxBitmap(brush_players_cyan));
283 menuBrushStartLocation->Append(pmi6);
284 wxMenuItem *pmi7 = new wxMenuItem(menuBrushStartLocation, miBrushStartLocation + 7, wxT("Player &7 Orange"));
285 pmi7->SetBitmap(wxBitmap(brush_players_orange));
286 menuBrushStartLocation->Append(pmi7);
287 wxMenuItem *pmi8 = new wxMenuItem(menuBrushStartLocation, miBrushStartLocation + 8, wxT("Player &8 Pink")); // = Light Magenta :-)
288 pmi8->SetBitmap(wxBitmap(brush_players_pink));
289 menuBrushStartLocation->Append(pmi8);
290 menuBar->Append(menuBrushStartLocation, wxT("&Player"));
291 //menuBar->Append(menuBrush, wxT("&Brush"));
292
293
294 SetMenuBar(menuBar);
295
296 fileName = "New (unsaved) map";
297 int status_widths[siCOUNT] = {
298 10, // empty
299 -25, // File name
300 -6, // File type
301 -20, // Current Object
302 -14, // Brush Type
303 -20, // Brush 'Value'
304 -10, // Brush Radius
305 -25, // Position
306 };
307 CreateStatusBar(siCOUNT);
308 GetStatusBar()->SetStatusWidths(siCOUNT, status_widths);
309
310 SetStatusText(wxT("File: ") + ToUnicode(fileName), siFILE_NAME);
311 SetStatusText(wxT(".mgm"), siFILE_TYPE);
312 SetStatusText(wxT("Object: None (Erase)"), siCURR_OBJECT);
313 SetStatusText(wxT("Brush: Height"), siBRUSH_TYPE);
314 SetStatusText(wxT("Value: 0"), siBRUSH_VALUE);
315 SetStatusText(wxT("Radius: 1"), siBRUSH_RADIUS);
316 SetStatusText(wxT("Pos (Ingame): 0"), siPOS_VALUE);
317
318 wxToolBar *toolbar = new MainToolBar(this->panel, wxID_ANY);
319 toolbar->AddTool(miEditUndo, _("undo"), wxBitmap(edit_undo), _("Undo"));
320 toolbar->AddTool(miEditRedo, _("redo"), wxBitmap(edit_redo), _("Redo"));
321 toolbar->AddTool(miEditRandomizeHeights, _("randomizeHeights"), wxBitmap(edit_randomize_heights), _("Randomize Heights"));
322 // toolbar->AddTool(miEditRandomize, _("randomize"), wxBitmap(edit_randomize), _("Randomize"));
323 toolbar->AddTool(miEditSwitchSurfaces, _("switch"), wxBitmap(edit_switch_surfaces), _("Switch Surfaces"));
324 toolbar->AddSeparator();
325 toolbar->AddTool(miBrushSurface + 1, _("brush_grass1"), wxBitmap(brush_surface_grass1), _("Grass"));
326 toolbar->AddTool(miBrushSurface + 2, _("brush_grass2"), wxBitmap(brush_surface_grass2), _("Secondary grass"));
327 toolbar->AddTool(miBrushSurface + 3, _("brush_road"), wxBitmap(brush_surface_road), _("Road"));
328 toolbar->AddTool(miBrushSurface + 4, _("brush_stone"), wxBitmap(brush_surface_stone), _("Stone"));
329 toolbar->AddTool(miBrushSurface + 5, _("brush_custom"), wxBitmap(brush_surface_custom), _("Ground"));
330 toolbar->AddSeparator();
331 toolbar->AddTool(miBrushResource + 2, _("resource1"), wxBitmap(brush_resource_1_gold), _("gold (unwalkable)"));
332 toolbar->AddTool(miBrushResource + 3, _("resource2"), wxBitmap(brush_resource_2_stone), _("stone (unwalkable)"));
333 toolbar->AddTool(miBrushResource + 4, _("resource3"), wxBitmap(brush_resource_3), _("custom3"));
334 toolbar->AddTool(miBrushResource + 5, _("resource4"), wxBitmap(brush_resource_4), _("custom4"));
335 toolbar->AddTool(miBrushResource + 6, _("resource5"), wxBitmap(brush_resource_5), _("custom5"));
336 toolbar->AddSeparator();
337 toolbar->AddTool(miBrushObject + 1, _("brush_none"), wxBitmap(brush_none), _("None (erase)"));
338 toolbar->AddTool(miBrushObject + 2, _("brush_tree"), wxBitmap(brush_object_tree), _("Tree (unwalkable/harvestable)"));
339 toolbar->AddTool(miBrushObject + 3, _("brush_dead_tree"), wxBitmap(brush_object_dead_tree), _("Dead tree/Cactuses/Thornbush (unwalkable)"));
340 toolbar->AddTool(miBrushObject + 4, _("brush_stone"), wxBitmap(brush_object_stone), _("Stone (unwalkable/not harvestable)"));
341 toolbar->AddTool(miBrushObject + 5, _("brush_bush"), wxBitmap(brush_object_bush), _("Bush/Grass/Fern (walkable)"));
342 toolbar->AddTool(miBrushObject + 6, _("brush_water"), wxBitmap(brush_object_water_object), _("Water object/Reed/Papyrus (walkable)"));
343 toolbar->AddTool(miBrushObject + 7, _("brush_c1_bigtree"), wxBitmap(brush_object_c1_bigtree), _("Big tree/Old palm (unwalkable/not harvestable)"));
344 toolbar->AddTool(miBrushObject + 8, _("brush_c2_hanged"), wxBitmap(brush_object_c2_hanged), _("Hanged/Impaled (unwalkable)"));
345 toolbar->AddTool(miBrushObject + 9, _("brush_c3_statue"), wxBitmap(brush_object_c3_statue), _("Statues (unwalkable)"));
346 toolbar->AddTool(miBrushObject +10, _("brush_c4_bigrock"), wxBitmap(brush_object_c4_bigrock), _("Mountain (unwalkable)"));
347 toolbar->AddTool(miBrushObject +11, _("brush_c5_blocking"), wxBitmap(brush_object_c5_blocking), _("Invisible blocking object (unwalkable)"));
348 toolbar->AddSeparator();
349 toolbar->AddTool(toolPlayer, _("brush_player"), wxBitmap(brush_players_player), _("Player start position"));
350 toolbar->Realize();
351
352 wxToolBar *toolbar2 = new MainToolBar(this->panel, wxID_ANY);
353 toolbar2->AddTool(miBrushGradient + 1, _("brush_gradient_n5"), wxBitmap(brush_gradient_n5));
354 toolbar2->AddTool(miBrushGradient + 2, _("brush_gradient_n4"), wxBitmap(brush_gradient_n4));
355 toolbar2->AddTool(miBrushGradient + 3, _("brush_gradient_n3"), wxBitmap(brush_gradient_n3));
356 toolbar2->AddTool(miBrushGradient + 4, _("brush_gradient_n2"), wxBitmap(brush_gradient_n2));
357 toolbar2->AddTool(miBrushGradient + 5, _("brush_gradient_n1"), wxBitmap(brush_gradient_n1));
358 toolbar2->AddTool(miBrushGradient + 6, _("brush_gradient_0"), wxBitmap(brush_gradient_0));
359 toolbar2->AddTool(miBrushGradient + 7, _("brush_gradient_p1"), wxBitmap(brush_gradient_p1));
360 toolbar2->AddTool(miBrushGradient + 8, _("brush_gradient_p2"), wxBitmap(brush_gradient_p2));
361 toolbar2->AddTool(miBrushGradient + 9, _("brush_gradient_p3"), wxBitmap(brush_gradient_p3));
362 toolbar2->AddTool(miBrushGradient +10, _("brush_gradient_p4"), wxBitmap(brush_gradient_p4));
363 toolbar2->AddTool(miBrushGradient +11, _("brush_gradient_p5"), wxBitmap(brush_gradient_p5));
364 toolbar2->AddSeparator();
365 toolbar2->AddTool(miBrushHeight + 1, _("brush_height_n5"), wxBitmap(brush_height_n5));
366 toolbar2->AddTool(miBrushHeight + 2, _("brush_height_n4"), wxBitmap(brush_height_n4));
367 toolbar2->AddTool(miBrushHeight + 3, _("brush_height_n3"), wxBitmap(brush_height_n3));
368 toolbar2->AddTool(miBrushHeight + 4, _("brush_height_n2"), wxBitmap(brush_height_n2));
369 toolbar2->AddTool(miBrushHeight + 5, _("brush_height_n1"), wxBitmap(brush_height_n1));
370 toolbar2->AddTool(miBrushHeight + 6, _("brush_height_0"), wxBitmap(brush_height_0));
371 toolbar2->AddTool(miBrushHeight + 7, _("brush_height_p1"), wxBitmap(brush_height_p1));
372 toolbar2->AddTool(miBrushHeight + 8, _("brush_height_p2"), wxBitmap(brush_height_p2));
373 toolbar2->AddTool(miBrushHeight + 9, _("brush_height_p3"), wxBitmap(brush_height_p3));
374 toolbar2->AddTool(miBrushHeight +10, _("brush_height_p4"), wxBitmap(brush_height_p4));
375 toolbar2->AddTool(miBrushHeight +11, _("brush_height_p5"), wxBitmap(brush_height_p5));
376 toolbar2->AddSeparator();
377 toolbar2->AddTool(miRadius + 1, _("radius1"), wxBitmap(radius_1), _("1 (1x1)"));
378 toolbar2->AddTool(miRadius + 2, _("radius2"), wxBitmap(radius_2), _("2 (3x3)"));
379 toolbar2->AddTool(miRadius + 3, _("radius3"), wxBitmap(radius_3), _("3 (5x5)"));
380 toolbar2->AddTool(miRadius + 4, _("radius4"), wxBitmap(radius_4), _("4 (7x7)"));
381 toolbar2->AddTool(miRadius + 5, _("radius5"), wxBitmap(radius_5), _("5 (9x9)"));
382 toolbar2->AddTool(miRadius + 6, _("radius6"), wxBitmap(radius_6), _("6 (11x11)"));
383 toolbar2->AddTool(miRadius + 7, _("radius7"), wxBitmap(radius_7), _("7 (13x13)"));
384 toolbar2->AddTool(miRadius + 8, _("radius8"), wxBitmap(radius_8), _("8 (15x15)"));
385 toolbar2->AddTool(miRadius + 9, _("radius9"), wxBitmap(radius_9), _("9 (17x17)"));
386 toolbar2->Realize();
387
388 Config &config = Config::getInstance();
389
390 string userData = config.getString("UserData_Root","");
391 if(userData != "") {
392 endPathWithSlash(userData);
393 }
394
395 //std::cout << "A" << std::endl;
396 wxInitAllImageHandlers();
397 #ifdef WIN32
398 //std::cout << "B" << std::endl;
399 // #if defined(__MINGW32__)
400 wxIcon icon(ToUnicode("IDI_ICON1"));
401 // #else
402 // wxIcon icon("IDI_ICON1");
403 // #endif
404
405 #else
406 //std::cout << "B" << std::endl;
407 wxIcon icon;
408 string iniFilePath = extractDirectoryPathFromFile(config.getFileName(false));
409 string icon_file = iniFilePath + "editor.ico";
410 std::ifstream testFile(icon_file.c_str());
411 if(testFile.good()) {
412 testFile.close();
413 icon.LoadFile(ToUnicode(icon_file.c_str()),wxBITMAP_TYPE_ICO);
414 }
415 #endif
416 //std::cout << "C" << std::endl;
417 SetIcon(icon);
418 fileDialog = new wxFileDialog(this);
419 string defaultPath = userData + "maps/";
420 fileDialog->SetDirectory(ToUnicode(defaultPath));
421
422 //printf("Default Path [%s]\n",defaultPath.c_str());
423
424 lastPaintEvent.start();
425
426 boxsizer = new wxBoxSizer(wxVERTICAL);
427 boxsizer->Add(toolbar, 0, wxEXPAND);
428 boxsizer->Add(toolbar2, 0, wxEXPAND);
429 //boxsizer->Add(glCanvas, 1, wxEXPAND);
430
431 this->panel->SetSizer(boxsizer);
432 //this->Layout();
433
434 //program = new Program(glCanvas->GetClientSize().x, glCanvas->GetClientSize().y);
435
436 fileName = "New (unsaved) Map";
437
438 //printf("Does file exist, fname [%s]\n",fname.c_str());
439
440 if (fname.empty() == false && fileExists(fname)) {
441 //printf("YES file exist, fname [%s]\n",fname.c_str());
442
443 //program->loadMap(fname);
444 currentFile = fname;
445 fileName = cutLastExt(extractFileFromDirectoryPath(fname.c_str()));
446 fileDialog->SetPath(ToUnicode(fname));
447 }
448 SetTitle(ToUnicode(currentFile + " - " + winHeader));
449 //setDirty(false);
450 //setExtension();
451
452 initGlCanvas();
453 #if wxCHECK_VERSION(2, 9, 3)
454 //glCanvas->setCurrentGLContext();
455 //printf("setcurrent #1\n");
456 #elif wxCHECK_VERSION(2, 9, 1)
457
458 #else
459 if(glCanvas) glCanvas->SetCurrent();
460 //printf("setcurrent #2\n");
461 #endif
462
463 if(startupSettingsInited == false) {
464 startupSettingsInited = true;
465 setupStartupSettings();
466 }
467 }
468
onClose(wxCloseEvent & event)469 void MainWindow::onClose(wxCloseEvent &event) {
470 if(program != NULL && program->getMap()->getHasChanged() == true) {
471 if( wxMessageDialog(NULL, ToUnicode("Do you want to save the current map?"),
472 ToUnicode("Question"), wxYES_NO | wxYES_DEFAULT).ShowModal() == wxID_YES) {
473 wxCommandEvent ev;
474 MainWindow::onMenuFileSave(ev);
475 }
476 }
477 delete program;
478 program = NULL;
479
480 //delete glCanvas;
481 if(glCanvas) glCanvas->Destroy();
482 glCanvas = NULL;
483
484 this->Destroy();
485 }
486
initGlCanvas()487 void MainWindow::initGlCanvas(){
488 if(glCanvas == NULL) {
489 int args[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_MIN_ALPHA, 8 };
490 glCanvas = new GlCanvas(this, this->panel, args);
491
492 boxsizer->Add(glCanvas, 1, wxEXPAND);
493 }
494 }
495
setupStartupSettings()496 void MainWindow::setupStartupSettings() {
497
498 //gl canvas
499 if(glCanvas == NULL) {
500 initGlCanvas();
501
502 boxsizer->Add(glCanvas, 1, wxEXPAND);
503
504 this->panel->SetSizer(boxsizer);
505 this->Layout();
506 }
507 glCanvas->setCurrentGLContext();
508 glCanvas->SetFocus();
509
510 string playerName = Config::getInstance().getString("NetPlayerName","");
511 program = new Program(glCanvas->GetClientSize().x, glCanvas->GetClientSize().y, playerName);
512 fileName = "New (unsaved) Map";
513
514 //printf("#0 file load [%s]\n",currentFile.c_str());
515
516 if (!currentFile.empty() && fileExists(currentFile)) {
517 //printf("#0 exists file load [%s]\n",currentFile.c_str());
518
519 program->loadMap(currentFile);
520 //currentFile = fname;
521 fileName = cutLastExt(extractFileFromDirectoryPath(currentFile.c_str()));
522 fileDialog->SetPath(ToUnicode(currentFile));
523 }
524 SetTitle(ToUnicode(currentFile + " - " + winHeader));
525 setDirty(false);
526 setExtension();
527 }
528
~MainWindow()529 MainWindow::~MainWindow() {
530 delete fileDialog;
531 fileDialog = NULL;
532
533 delete program;
534 program = NULL;
535
536 delete glCanvas;
537 glCanvas = NULL;
538 }
539
setDirty(bool val)540 void MainWindow::setDirty(bool val) {
541 wxPaintEvent ev;
542 onPaint(ev);
543 if (fileModified && val) {
544 return;
545 }
546 fileModified = val;
547 if (fileModified) {
548 SetStatusText(wxT("File: ") + ToUnicode(fileName) + wxT("*"), siFILE_NAME);
549 } else {
550 SetStatusText(wxT("File: ") + ToUnicode(fileName), siFILE_NAME);
551 }
552 }
553
setExtension()554 void MainWindow::setExtension() {
555 if (currentFile.empty() || program == NULL) {
556 return;
557 }
558
559 string extnsn = ext(currentFile);
560
561 //printf("#A currentFile [%s] extnsn [%s]\n",currentFile.c_str(),extnsn.c_str());
562
563 if (extnsn == "gbm" || extnsn == "mgm") {
564 currentFile = cutLastExt(currentFile);
565 }
566 SetStatusText(wxT(".mgm"), siFILE_TYPE);
567 currentFile += ".mgm";
568 }
569
onMouseDown(wxMouseEvent & event,int x,int y)570 void MainWindow::onMouseDown(wxMouseEvent &event, int x, int y) {
571 if (event.LeftIsDown() && program != NULL) {
572 program->setUndoPoint(enabledGroup);
573 program->setRefAlt(x, y);
574 change(x, y);
575 if (!isDirty()) {
576 setDirty(true);
577 }
578 wxPaintEvent ev;
579 onPaint(ev);
580 }
581 event.Skip();
582 }
583
584 // for the mousewheel
onMouseWheelDown(wxMouseEvent & event)585 void MainWindow::onMouseWheelDown(wxMouseEvent &event) {
586 if(program == NULL) {
587 return;
588 }
589 wxPaintEvent ev;
590 program->incCellSize(1);
591 onPaint(ev);
592 }
593
onMouseWheelUp(wxMouseEvent & event)594 void MainWindow::onMouseWheelUp(wxMouseEvent &event) {
595 if(program == NULL) {
596 return;
597 }
598 wxPaintEvent ev;
599 program->incCellSize(-1);
600 onPaint(ev);
601 }
602
onMouseMove(wxMouseEvent & event,int x,int y)603 void MainWindow::onMouseMove(wxMouseEvent &event, int x, int y) {
604 if(program == NULL) {
605 return;
606 }
607 bool repaint = false;
608 if (event.LeftIsDown()) {
609 change(x, y);
610 repaint = true;
611 } else if (event.MiddleIsDown()) {
612 int dif = (y - lastY);
613 if (dif != 0) {
614 program->incCellSize(dif / abs(dif));
615 repaint = true;
616 }
617 } else if (event.RightIsDown()) {
618 program->setOfset(x - lastX, y - lastY);
619 repaint = true;
620 } else {
621 int currResource = program->getResource(x, y);
622 if (currResource > 0) {
623 SetStatusText(wxT("Resource: ") + ToUnicode(resource_descs[currResource]), siCURR_OBJECT);
624 resourceUnderMouse = currResource;
625 objectUnderMouse = 0;
626 } else {
627 int currObject = program->getObject(x, y);
628 SetStatusText(wxT("Object: ") + ToUnicode(object_descs[currObject]), siCURR_OBJECT);
629 resourceUnderMouse = 0;
630 objectUnderMouse = currObject;
631 }
632
633 SetStatusText(wxT("Pos (Ingame): ")
634 + ToUnicode(intToStr(program->getCellX(x))
635 + ","
636 + intToStr(program->getCellY(y))
637 + " ("
638 + intToStr(2*(program->getCellX(x)))
639 + ","
640 + intToStr(2*(program->getCellY(y)))
641 + ")"), siPOS_VALUE);
642 //#ifdef WIN32
643 //repaint = true;
644 //#endif
645 }
646 lastX = x;
647 lastY = y;
648
649 if (repaint) {
650 wxPaintEvent ev;
651 onPaint(ev);
652 }
653 event.Skip();
654 }
655
onPaint(wxPaintEvent & event)656 void MainWindow::onPaint(wxPaintEvent &event) {
657 //printf("onPaint map\n");
658
659 if(!IsShown()) {
660 //printf("onPaint skip map\n");
661
662 event.Skip();
663 return;
664 }
665
666 //#if wxCHECK_VERSION(2, 9, 3)
667
668 //#elif wxCHECK_VERSION(2, 9, 1)
669 // glCanvas->setCurrentGLContext();
670 //#endif
671
672 //static bool contextSet = false;
673 //if(contextSet == false) {
674 // contextSet = true;
675 glCanvas->setCurrentGLContext();
676 //}
677
678 //printf("lastPaintEvent.getMillis() map\n");
679 if(lastPaintEvent.getMillis() < 30) {
680 sleep(1);
681 event.Skip();
682 return;
683 }
684
685 //printf("wxPaintDC dc map\n");
686 wxPaintDC dc(this); // "In a paint event handler must always create a wxPaintDC object even if you do not use it. (?)
687 // Otherwise, under MS Windows, refreshing for this and other windows will go wrong"
688 // http://docs.wxwidgets.org/2.6/wx_wxpaintevent.html
689
690 lastPaintEvent.start();
691
692 if(panel) panel->Refresh(false);
693 if(menuBar) menuBar->Refresh(false);
694
695 refreshMapRender();
696 event.Skip();
697 }
698
refreshMapRender()699 void MainWindow::refreshMapRender() {
700 //printf("refreshMapRender map\n");
701
702 if(program && glCanvas) {
703 program->renderMap(glCanvas->GetClientSize().x, glCanvas->GetClientSize().y);
704 glCanvas->SwapBuffers();
705 }
706 }
707
onMenuFileLoad(wxCommandEvent & event)708 void MainWindow::onMenuFileLoad(wxCommandEvent &event) {
709 if(program == NULL) {
710 return;
711 }
712
713 try {
714 fileDialog->SetMessage(wxT("Select Glestmap to load"));
715 fileDialog->SetWildcard(wxT("Glest&Mega Map (*.gbm *.mgm)|*.gbm;*.mgm|Glest Map (*.gbm)|*.gbm|Mega Map (*.mgm)|*.mgm"));
716 if (fileDialog->ShowModal() == wxID_OK) {
717 #ifdef WIN32
718 const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(wxFNCONV(fileDialog->GetPath()));
719 currentFile = tmp_buf;
720
721 auto_ptr<wchar_t> wstr(Ansi2WideString(currentFile.c_str()));
722 currentFile = utf8_encode(wstr.get());
723 #else
724 //currentFile = fileDialog->GetPath().ToAscii();
725
726 const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(fileDialog->GetPath());
727 currentFile = tmp_buf;
728 #endif
729
730 //printf("#1 file load [%s]\n",currentFile.c_str());
731
732 program->loadMap(currentFile);
733 fileName = cutLastExt(extractFileFromDirectoryPath(currentFile.c_str()));
734 setDirty(false);
735 setExtension();
736 SetTitle(ToUnicode(winHeader + "; " + currentFile));
737 }
738 }
739 catch (const string &e) {
740 MsgDialog(this, ToUnicode(e), wxT("Exception"), wxOK | wxICON_ERROR).ShowModal();
741 }
742 catch (const exception &e) {
743 MsgDialog(this, ToUnicode(e.what()), wxT("Exception"), wxOK | wxICON_ERROR).ShowModal();
744 }
745
746 }
747
onMenuFileSave(wxCommandEvent & event)748 void MainWindow::onMenuFileSave(wxCommandEvent &event) {
749 if(program == NULL) {
750 return;
751 }
752
753 if (currentFile.empty()) {
754 wxCommandEvent ev;
755 onMenuFileSaveAs(ev);
756 }
757 else {
758 setExtension();
759
760 //printf("#1 save load [%s]\n",currentFile.c_str());
761
762 program->saveMap(currentFile);
763 setDirty(false);
764 }
765 }
766
onMenuFileSaveAs(wxCommandEvent & event)767 void MainWindow::onMenuFileSaveAs(wxCommandEvent &event) {
768 if(program == NULL) {
769 return;
770 }
771
772 #if wxCHECK_VERSION(2, 9, 1)
773 wxFileDialog fd(this, wxT("Select file"), wxT(""), wxT(""), wxT("*.mgm|*.gbm"), wxFD_SAVE);
774 #else
775 wxFileDialog fd(this, wxT("Select file"), wxT(""), wxT(""), wxT("*.mgm|*.gbm"), wxSAVE);
776 #endif
777
778 if(fileDialog->GetPath() != ToUnicode("")) {
779 fd.SetPath(fileDialog->GetPath());
780 }
781 else {
782 Config &config = Config::getInstance();
783 string userData = config.getString("UserData_Root","");
784 if(userData != "") {
785 endPathWithSlash(userData);
786 }
787 string defaultPath = userData + "maps/";
788 fd.SetDirectory(ToUnicode(defaultPath));
789 }
790
791 fd.SetWildcard(wxT("MegaGlest Map (*.mgm)|*.mgm|Glest Map (*.gbm)|*.gbm"));
792 if (fd.ShowModal() == wxID_OK) {
793 #ifdef WIN32
794 const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(wxFNCONV(fd.GetPath()));
795 currentFile = tmp_buf;
796
797 auto_ptr<wchar_t> wstr(Ansi2WideString(currentFile.c_str()));
798 currentFile = utf8_encode(wstr.get());
799 #else
800 //currentFile = fd.GetPath().ToAscii();
801 const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(fd.GetPath());
802 currentFile = tmp_buf;
803 #endif
804
805 fileDialog->SetPath(fd.GetPath());
806 setExtension();
807
808 //printf("#2 file save [%s]\n",currentFile.c_str());
809
810 program->saveMap(currentFile);
811 fileName = cutLastExt(extractFileFromDirectoryPath(currentFile.c_str()));
812 setDirty(false);
813 }
814 SetTitle(ToUnicode(winHeader + "; " + currentFile));
815 }
816
onMenuFileExit(wxCommandEvent & event)817 void MainWindow::onMenuFileExit(wxCommandEvent &event) {
818 Close();
819 }
820
onMenuEditUndo(wxCommandEvent & event)821 void MainWindow::onMenuEditUndo(wxCommandEvent &event) {
822 if(program == NULL) {
823 return;
824 }
825
826 // std::cout << "Undo Pressed" << std::endl;
827 if (program->undo()) {
828 wxPaintEvent e;
829 onPaint(e);
830 setDirty();
831 }
832 }
833
onMenuEditRedo(wxCommandEvent & event)834 void MainWindow::onMenuEditRedo(wxCommandEvent &event) {
835 if(program == NULL) {
836 return;
837 }
838
839 if (program->redo()) {
840 wxPaintEvent e;
841 onPaint(e);
842 setDirty();
843 }
844 }
845
onMenuEditReset(wxCommandEvent & event)846 void MainWindow::onMenuEditReset(wxCommandEvent &event) {
847 if(program == NULL) {
848 return;
849 }
850
851 program->setUndoPoint(ctAll);
852 SimpleDialog simpleDialog;
853 simpleDialog.addValue("Width", "128","(must be 16,32,64,128,256,512...)"); // must be an exponent of two
854 simpleDialog.addValue("Height", "128","(must be 16,32,64,128,256,512...)");
855 simpleDialog.addValue("Surface", "1","(Default surface material)");
856 simpleDialog.addValue("Altitude", "10","(Default surface height)");
857 simpleDialog.addValue("Number of players", "8");
858 if (!simpleDialog.show()) return;
859
860 try {
861 program->reset(
862 strToInt(simpleDialog.getValue("Width")),
863 strToInt(simpleDialog.getValue("Height")),
864 strToInt(simpleDialog.getValue("Altitude")),
865 strToInt(simpleDialog.getValue("Surface")));
866 program->resetFactions(strToInt(simpleDialog.getValue("Number of players")));
867 }
868 catch (const exception &e) {
869 MsgDialog(this, ToUnicode(e.what()), wxT("Exception"), wxOK | wxICON_ERROR).ShowModal();
870 }
871 currentFile = "";
872 fileName = "New (unsaved) map";
873
874 wxPaintEvent ev;
875 onPaint(ev);
876 }
877
onMenuEditResetPlayers(wxCommandEvent & event)878 void MainWindow::onMenuEditResetPlayers(wxCommandEvent &event) {
879 if(program == NULL) {
880 return;
881 }
882
883 SimpleDialog simpleDialog;
884 simpleDialog.addValue("Number of players", intToStr(program->getMap()->getMaxFactions()));
885 if (!simpleDialog.show("Reset players")) return;
886
887 try {
888 program->resetFactions(strToInt(simpleDialog.getValue("Number of players")));
889 }
890 catch (const exception &e) {
891 MsgDialog(this, ToUnicode(e.what()), wxT("Exception"), wxOK | wxICON_ERROR).ShowModal();
892 }
893 setDirty();
894 setExtension();
895 }
896
897
onMenuEditFlipDiagonal(wxCommandEvent & event)898 void MainWindow::onMenuEditFlipDiagonal(wxCommandEvent &event) {
899 if(program == NULL) {
900 return;
901 }
902 program->setUndoPoint(ctAll);
903 program->flipDiagonal();
904 setDirty();
905 }
906
onMenuEditResize(wxCommandEvent & event)907 void MainWindow::onMenuEditResize(wxCommandEvent &event) {
908 if(program == NULL) {
909 return;
910 }
911
912 SimpleDialog simpleDialog;
913 simpleDialog.addValue("Width", intToStr(program->getMap()->getW()),"(must be 16,32,64,128,256,512...)");
914 simpleDialog.addValue("Height", intToStr(program->getMap()->getH()),"(must be 16,32,64,128,256,512...)");
915 simpleDialog.addValue("Surface", "1","(surface material for new area around map)");
916 simpleDialog.addValue("Altitude", "10","(surface height for new area around map)");
917 if (!simpleDialog.show("Resize - expand around, shrink to topleft")) return;
918
919 try {
920 program->resize(
921 strToInt(simpleDialog.getValue("Width")),
922 strToInt(simpleDialog.getValue("Height")),
923 strToInt(simpleDialog.getValue("Altitude")),
924 strToInt(simpleDialog.getValue("Surface")));
925 }
926 catch (const exception &e) {
927 MsgDialog(this, ToUnicode(e.what()), wxT("Exception"), wxOK | wxICON_ERROR).ShowModal();
928 }
929 setDirty();
930 }
931
onMenuEditFlipX(wxCommandEvent & event)932 void MainWindow::onMenuEditFlipX(wxCommandEvent &event) {
933 if(program == NULL) {
934 return;
935 }
936
937 program->setUndoPoint(ctAll);
938 program->flipX();
939 setDirty();
940 }
941
onMenuEditFlipY(wxCommandEvent & event)942 void MainWindow::onMenuEditFlipY(wxCommandEvent &event) {
943 if(program == NULL) {
944 return;
945 }
946
947 program->setUndoPoint(ctAll);
948 program->flipY();
949 setDirty();
950 }
951
onMenuEditMirrorX(wxCommandEvent & event)952 void MainWindow::onMenuEditMirrorX(wxCommandEvent &event) { // copy left to right
953 if(program == NULL) {
954 return;
955 }
956
957 program->setUndoPoint(ctAll);
958 program->mirrorX();
959 setDirty();
960 }
961
onMenuEditMirrorY(wxCommandEvent & event)962 void MainWindow::onMenuEditMirrorY(wxCommandEvent &event) { // copy top to bottom
963 if(program == NULL) {
964 return;
965 }
966
967 program->setUndoPoint(ctAll);
968 program->mirrorY();
969 setDirty();
970 }
971
onMenuEditMirrorXY(wxCommandEvent & event)972 void MainWindow::onMenuEditMirrorXY(wxCommandEvent &event) { // copy bottomleft tp topright
973 if(program == NULL) {
974 return;
975 }
976
977 program->setUndoPoint(ctAll);
978 program->mirrorXY();
979 setDirty();
980 }
981
onMenuEditRotatecopyX(wxCommandEvent & event)982 void MainWindow::onMenuEditRotatecopyX(wxCommandEvent &event) { // copy left to right, rotated
983 if(program == NULL) {
984 return;
985 }
986
987 program->setUndoPoint(ctAll);
988 program->rotatecopyX();
989 setDirty();
990 }
991
onMenuEditRotatecopyY(wxCommandEvent & event)992 void MainWindow::onMenuEditRotatecopyY(wxCommandEvent &event) { // copy top to bottom, rotated
993 if(program == NULL) {
994 return;
995 }
996
997 program->setUndoPoint(ctAll);
998 program->rotatecopyY();
999 setDirty();
1000 }
1001
onMenuEditRotatecopyXY(wxCommandEvent & event)1002 void MainWindow::onMenuEditRotatecopyXY(wxCommandEvent &event) { // copy bottomleft to topright, rotated
1003 if(program == NULL) {
1004 return;
1005 }
1006
1007 program->setUndoPoint(ctAll);
1008 program->rotatecopyXY();
1009 setDirty();
1010 }
1011
onMenuEditRotatecopyCorner(wxCommandEvent & event)1012 void MainWindow::onMenuEditRotatecopyCorner(wxCommandEvent &event) { // copy top left 1/4 to top right 1/4, rotated
1013 if(program == NULL) {
1014 return;
1015 }
1016
1017 program->setUndoPoint(ctAll);
1018 program->rotatecopyCorner();
1019 setDirty();
1020 }
1021
1022
onMenuEditRandomizeHeights(wxCommandEvent & event)1023 void MainWindow::onMenuEditRandomizeHeights(wxCommandEvent &event) {
1024 if(program == NULL) {
1025 return;
1026 }
1027 while(true){
1028
1029 SimpleDialog simpleDialog;
1030 simpleDialog.addValue("Initial Reset", boolToStr(randomWithReset),"(1 = true, 0 = false) If set to '0' no height reset is done before calculating");
1031 simpleDialog.addValue("Min Height", intToStr(randomMinimumHeight),"Lowest random height. example: -300 or below if you want water , 0 if you don't want water.");
1032 simpleDialog.addValue("Max Height", intToStr(randomMaximumHeight),"Max random height. A good value is 400");
1033 simpleDialog.addValue("Chance Divider", intToStr(randomChanceDivider),"Defines how often you get a hill or hole default is 30. Bigger number, less hills/holes.");
1034 simpleDialog.addValue("Smooth Recursions", intToStr(randomRecursions),"Number of recursions cycles to smooth the hills and holes. 0<x<50 default is 3.");
1035 if (!simpleDialog.show("Randomize Height")) return;
1036
1037 try {
1038 string checkValue = simpleDialog.getValue("Initial Reset");
1039 if(checkValue != "" && strToInt(checkValue) > 1) {
1040 randomWithReset = true;
1041 }
1042 else {
1043 randomWithReset = strToBool(simpleDialog.getValue("Initial Reset"));
1044 }
1045 randomMinimumHeight=strToInt(simpleDialog.getValue("Min Height"));
1046 randomMaximumHeight=strToInt(simpleDialog.getValue("Max Height"));
1047 randomChanceDivider=strToInt(simpleDialog.getValue("Chance Divider"));
1048 randomRecursions=strToInt(simpleDialog.getValue("Smooth Recursions"));
1049
1050 // set insane inputs to something that does not crash
1051 if(randomMinimumHeight>=randomMaximumHeight) randomMinimumHeight=randomMaximumHeight-1;
1052 if(randomChanceDivider<1) randomChanceDivider=1;
1053
1054 // set randomRecursions to something useful
1055 if(randomRecursions<0) randomRecursions=0;
1056 if(randomRecursions>50) randomRecursions=50;
1057
1058 program->setUndoPoint(ctAll);
1059 program->randomizeMapHeights(randomWithReset, randomMinimumHeight, randomMaximumHeight,
1060 randomChanceDivider, randomRecursions);
1061 }
1062 catch (const exception &e) {
1063 MsgDialog(this, ToUnicode(e.what()), wxT("Exception"), wxOK | wxICON_ERROR).ShowModal();
1064 }
1065 setDirty();
1066 }
1067 }
1068
onMenuEditRandomize(wxCommandEvent & event)1069 void MainWindow::onMenuEditRandomize(wxCommandEvent &event) {
1070 if(program == NULL) {
1071 return;
1072 }
1073
1074 program->setUndoPoint(ctAll);
1075 program->randomizeFactions();
1076 setDirty();
1077 }
1078
onMenuEditSwitchSurfaces(wxCommandEvent & event)1079 void MainWindow::onMenuEditSwitchSurfaces(wxCommandEvent &event) {
1080 if(program == NULL) {
1081 return;
1082 }
1083
1084 SimpleDialog simpleDialog;
1085 simpleDialog.addValue("Surface1", "1","replace this surface with...");
1086 simpleDialog.addValue("Surface2", "2","...this and vice versa");
1087 if (!simpleDialog.show("Switch surfaces")) return;
1088
1089 try {
1090 program->setUndoPoint(ctSurface);
1091 program->switchMapSurfaces(
1092 strToInt(simpleDialog.getValue("Surface1")),
1093 strToInt(simpleDialog.getValue("Surface2")));
1094 }
1095 catch (const exception &e) {
1096 MsgDialog(this, ToUnicode(e.what()), wxT("Exception"), wxOK | wxICON_ERROR).ShowModal();
1097 }
1098 setDirty();
1099 }
1100
onMenuEditInfo(wxCommandEvent & event)1101 void MainWindow::onMenuEditInfo(wxCommandEvent &event) {
1102 if(program == NULL) {
1103 return;
1104 }
1105
1106 SimpleDialog simpleDialog;
1107 simpleDialog.addValue("Title", program->getMap()->getTitle());
1108 simpleDialog.addValue("Description", program->getMap()->getDesc());
1109 simpleDialog.addValue("Author", program->getMap()->getAuthor());
1110 if (!simpleDialog.show("Info",true)) return;
1111
1112 bool ischanged = program->setMapTitle(simpleDialog.getValue("Title"));
1113 ischanged = (program->setMapDesc(simpleDialog.getValue("Description")) || ischanged);
1114 ischanged = (program->setMapAuthor(simpleDialog.getValue("Author")) || ischanged);
1115 if (ischanged)
1116 if (!isDirty()) {
1117 setDirty(true);
1118 }
1119
1120 }
1121
onMenuEditAdvanced(wxCommandEvent & event)1122 void MainWindow::onMenuEditAdvanced(wxCommandEvent &event) {
1123 if(program == NULL) {
1124 return;
1125 }
1126
1127 SimpleDialog simpleDialog;
1128 simpleDialog.addValue("Height Factor", intToStr(program->getMap()->getHeightFactor()),"lower means more hill effect. Numbers above 100 are handled like this:\nx=x/100 ,so a 150 will mean 1.5 in the game.");
1129 simpleDialog.addValue("Water Level", intToStr(program->getMap()->getWaterLevel()),"water is visible below this, and walkable until 1.5 less");
1130 simpleDialog.addValue("Cliff Level", intToStr(program->getMap()->getCliffLevel()),"neighboring fields with at least this heights difference are cliffs");
1131 simpleDialog.addValue("Camera Height", intToStr(program->getMap()->getCameraHeight()),"you can give a camera height here default is 0 ;ignored if <20");
1132 if (!simpleDialog.show("Advanced")) return;
1133
1134 try {
1135 program->setMapAdvanced(
1136 strToInt(simpleDialog.getValue("Height Factor")),
1137 strToInt(simpleDialog.getValue("Water Level")),
1138 strToInt(simpleDialog.getValue("Cliff Level")),
1139 strToInt(simpleDialog.getValue("Camera Height")));
1140 }
1141 catch (const exception &e) {
1142 MsgDialog(this, ToUnicode(e.what()), wxT("Exception"), wxOK | wxICON_ERROR).ShowModal();
1143 }
1144 setDirty();
1145 }
1146
onMenuViewResetZoomAndPos(wxCommandEvent & event)1147 void MainWindow::onMenuViewResetZoomAndPos(wxCommandEvent &event) {
1148 if(program == NULL) {
1149 return;
1150 }
1151
1152 program->resetOfset();
1153 wxPaintEvent e;
1154 onPaint(e);
1155 }
1156
onMenuViewGrid(wxCommandEvent & event)1157 void MainWindow::onMenuViewGrid(wxCommandEvent &event) {
1158 if(program == NULL) {
1159 return;
1160 }
1161
1162 menuView->Check(miViewGrid, program->setGridOnOff()); // miViewGrid event.GetId()
1163 wxPaintEvent e;
1164 onPaint(e);
1165 }
1166
1167
onMenuViewHeightMap(wxCommandEvent & event)1168 void MainWindow::onMenuViewHeightMap(wxCommandEvent &event) {
1169 if(program == NULL) {
1170 return;
1171 }
1172
1173 menuView->Check(miViewHeightMap, program->setHeightMapOnOff()); // miViewGrid event.GetId()
1174 wxPaintEvent e;
1175 onPaint(e);
1176 }
onMenuHideWater(wxCommandEvent & event)1177 void MainWindow::onMenuHideWater(wxCommandEvent &event) {
1178 if(program == NULL) {
1179 return;
1180 }
1181
1182 menuView->Check(miHideWater, program->setHideWaterOnOff()); // miViewGrid event.GetId()
1183 wxPaintEvent e;
1184 onPaint(e);
1185 }
onMenuViewAbout(wxCommandEvent & event)1186 void MainWindow::onMenuViewAbout(wxCommandEvent &event) {
1187 MsgDialog(
1188 this,
1189 wxT("\n Glest Map Editor\n Copyright 2004-2010 The Glest Team\n Copyright 2010-2017 The MegaGlest Team \n"),
1190 wxT("About")).ShowModal();
1191 }
1192
onMenuViewHelp(wxCommandEvent & event)1193 void MainWindow::onMenuViewHelp(wxCommandEvent &event) {
1194 MsgDialog(this,
1195 wxT("Draw with left mouse\nMove viewport with right mouse drag\nZoom with center mouse drag, or mousewheel\n\n\
1196 You can change brush in the same category with key 1-9\n\
1197 and change category with their first letter (keys S, R, O, G, H)\n\
1198 Press Space to set brush to the resource or object under the mouse cursor\n\
1199 To center things in the map shift it with Shift-Up/Down/Left/Right keys\n\
1200 Height tool (blue) builds with integer height steps 0-20, \nwhile Gradient tool (red) uses any real number \n\
1201 Units can go over water as long as it is less than 1.5 deep\n\n\
1202 A good idea is to put some stone, gold and tree near starting position\n\
1203 Starting position needs an open area for the tower and the starting units\n"),
1204 wxT("Help")).ShowModal();
1205 /* 5 away and 10x10 empty area? */
1206 }
1207
onMenuBrushHeight(wxCommandEvent & e)1208 void MainWindow::onMenuBrushHeight(wxCommandEvent &e) {
1209 uncheckBrush();
1210 menuBrushHeight->Check(e.GetId(), true);
1211 height = e.GetId() - miBrushHeight - heightCount / 2 - 1;
1212 enabledGroup = ctHeight;
1213 currentBrush = btHeight;
1214 SetStatusText(wxT("Brush: Height"), siBRUSH_TYPE);
1215 SetStatusText(wxT("Value: ") + ToUnicode(intToStr(height)), siBRUSH_VALUE);
1216 }
1217
onMenuBrushGradient(wxCommandEvent & e)1218 void MainWindow::onMenuBrushGradient(wxCommandEvent &e) {
1219 uncheckBrush();
1220 menuBrushGradient->Check(e.GetId(), true);
1221 height = e.GetId() - miBrushGradient - heightCount / 2 - 1;
1222 enabledGroup = ctGradient;
1223 currentBrush = btGradient;
1224 SetStatusText(wxT("Brush: Gradient"), siBRUSH_TYPE);
1225 SetStatusText(wxT("Value: ") + ToUnicode(intToStr(height)), siBRUSH_VALUE);
1226 }
1227
1228
onMenuBrushSurface(wxCommandEvent & e)1229 void MainWindow::onMenuBrushSurface(wxCommandEvent &e) {
1230 uncheckBrush();
1231 menuBrushSurface->Check(e.GetId(), true);
1232 surface = e.GetId() - miBrushSurface;
1233 enabledGroup = ctSurface;
1234 currentBrush = btSurface;
1235 SetStatusText(wxT("Brush: Surface"), siBRUSH_TYPE);
1236 SetStatusText(
1237 wxT("Value: ") + ToUnicode(intToStr(surface)) + wxT(" ")
1238 + ToUnicode(surface_descs[surface - 1]), siBRUSH_VALUE);
1239 }
1240
onMenuBrushObject(wxCommandEvent & e)1241 void MainWindow::onMenuBrushObject(wxCommandEvent &e) {
1242 uncheckBrush();
1243 menuBrushObject->Check(e.GetId(), true);
1244 object = e.GetId() - miBrushObject - 1;
1245 enabledGroup = ctObject;
1246 currentBrush = btObject;
1247 SetStatusText(wxT("Brush: Object"), siBRUSH_TYPE);
1248 SetStatusText(
1249 wxT("Value: ") + ToUnicode(intToStr(object)) + wxT(" ")
1250 + ToUnicode(object_descs[object]), siBRUSH_VALUE);
1251 }
1252
onMenuBrushResource(wxCommandEvent & e)1253 void MainWindow::onMenuBrushResource(wxCommandEvent &e) {
1254 uncheckBrush();
1255 menuBrushResource->Check(e.GetId(), true);
1256 resource = e.GetId() - miBrushResource - 1;
1257 enabledGroup = ctResource;
1258 currentBrush = btResource;
1259 SetStatusText(wxT("Brush: Resource"), siBRUSH_TYPE);
1260 SetStatusText(
1261 wxT("Value: ") + ToUnicode(intToStr(resource)) + wxT(" ")
1262 + ToUnicode(resource_descs[resource]), siBRUSH_VALUE);
1263 }
1264
onMenuBrushStartLocation(wxCommandEvent & e)1265 void MainWindow::onMenuBrushStartLocation(wxCommandEvent &e) {
1266 uncheckBrush();
1267 menuBrushStartLocation->Check(e.GetId(), true);
1268 startLocation = e.GetId() - miBrushStartLocation;
1269 enabledGroup = ctLocation;
1270 currentBrush = btStartLocation;
1271 SetStatusText(wxT("Brush: Start Locations"), siBRUSH_TYPE);
1272 SetStatusText(wxT("Value: ") + ToUnicode(intToStr(startLocation)), siBRUSH_VALUE);
1273 }
1274
onMenuRadius(wxCommandEvent & e)1275 void MainWindow::onMenuRadius(wxCommandEvent &e) {
1276 uncheckRadius();
1277 menuRadius->Check(e.GetId(), true);
1278 radius = e.GetId() - miRadius;
1279 SetStatusText(wxT("Radius: ") + ToUnicode(intToStr(radius)), siBRUSH_RADIUS);
1280 }
1281
change(int x,int y)1282 void MainWindow::change(int x, int y) {
1283 if(program == NULL) {
1284 return;
1285 }
1286
1287 switch (enabledGroup) {
1288 case ctHeight:
1289 program->glestChangeMapHeight(x, y, height, radius);
1290 break;
1291 case ctSurface:
1292 program->changeMapSurface(x, y, surface, radius);
1293 break;
1294 case ctObject:
1295 program->changeMapObject(x, y, object, radius);
1296 break;
1297 case ctResource:
1298 program->changeMapResource(x, y, resource, radius);
1299 break;
1300 case ctLocation:
1301 program->changeStartLocation(x, y, startLocation - 1);
1302 break;
1303 case ctGradient:
1304 program->pirateChangeMapHeight(x, y, height, radius);
1305 break;
1306 }
1307 }
1308
uncheckBrush()1309 void MainWindow::uncheckBrush() {
1310 for (int i = 0; i < heightCount; ++i) {
1311 menuBrushHeight->Check(miBrushHeight + i + 1, false);
1312 }
1313 for (int i = 0; i < heightCount; ++i) {
1314 menuBrushGradient->Check(miBrushGradient + i + 1, false);
1315 }
1316 for (int i = 0; i < surfaceCount; ++i) {
1317 menuBrushSurface->Check(miBrushSurface + i + 1, false);
1318 }
1319 for (int i = 0; i < objectCount; ++i) {
1320 menuBrushObject->Check(miBrushObject + i + 1, false);
1321 }
1322 for (int i = 0; i < resourceCount; ++i) {
1323 menuBrushResource->Check(miBrushResource + i + 1, false);
1324 }
1325 for (int i = 0; i < startLocationCount; ++i) {
1326 menuBrushStartLocation->Check(miBrushStartLocation + i + 1, false);
1327 }
1328 }
1329
uncheckRadius()1330 void MainWindow::uncheckRadius() {
1331 for (int i = 1; i <= radiusCount; ++i) {
1332 menuRadius->Check(miRadius + i, false);
1333 }
1334 }
1335
onKeyDown(wxKeyEvent & e)1336 void MainWindow::onKeyDown(wxKeyEvent &e) {
1337 if(program == NULL) {
1338 return;
1339 }
1340
1341 if(e.GetModifiers() == wxMOD_CONTROL || e.GetModifiers() == wxMOD_ALT){
1342 e.Skip();
1343 }
1344 // WARNING: don't add any Ctrl or ALt key shortcuts below those are reserved for internal menu use.
1345
1346 if (currentBrush == btSurface) { // surface texture
1347 if (e.GetKeyCode() >= '1' && e.GetKeyCode() <= '5') {
1348 surface = e.GetKeyCode() - 48; // '1'-'5' == 1-5
1349 wxCommandEvent evt(wxEVT_NULL, miBrushSurface + surface);
1350 onMenuBrushSurface(evt);
1351 return;
1352 }
1353 }
1354 if (currentBrush == btObject) {
1355 bool valid = true;
1356 if (e.GetKeyCode() >= '1' && e.GetKeyCode() <= '9') {
1357 object = e.GetKeyCode() - 48; // '1'-'9' == 1-9
1358 } else if (e.GetKeyCode() == '0') { // '0' == 10
1359 object = 10;
1360 } else if (e.GetKeyCode() == '-') { // '-' == 0
1361 object = 0;
1362 } else {
1363 valid = false;
1364 }
1365 if (valid) {
1366 wxCommandEvent evt(wxEVT_NULL, miBrushObject + object + 1);
1367 onMenuBrushObject(evt);
1368 return;
1369 }
1370 }
1371 if (currentBrush == btResource) {
1372 if (e.GetKeyCode() >= '0' && e.GetKeyCode() <= '5') {
1373 resource = e.GetKeyCode() - 48; // '0'-'5' == 0-5
1374 wxCommandEvent evt(wxEVT_NULL, miBrushResource + resource + 1);
1375 onMenuBrushResource(evt);
1376 return;
1377 }
1378 }
1379 if (currentBrush == btStartLocation) {
1380 if (e.GetKeyCode() >= '1' && e.GetKeyCode() <= '8') {
1381 startLocation = e.GetKeyCode() - 48; // '1'-'8' == 0-7
1382 wxCommandEvent evt(wxEVT_NULL, miBrushStartLocation + startLocation);
1383 onMenuBrushStartLocation(evt);
1384 return;
1385 }
1386 }
1387 if (e.GetKeyCode() == 'H') {
1388 wxCommandEvent evt(wxEVT_NULL, miBrushHeight + height + heightCount / 2 + 1);
1389 onMenuBrushHeight(evt);
1390 } else if (e.GetKeyCode() == ' ') {
1391 if (resourceUnderMouse != 0) {
1392 wxCommandEvent evt(wxEVT_NULL, miBrushResource + resourceUnderMouse + 1);
1393 onMenuBrushResource(evt);
1394 } else {
1395 wxCommandEvent evt(wxEVT_NULL, miBrushObject + objectUnderMouse + 1);
1396 onMenuBrushObject(evt);
1397 }
1398 } else if (e.GetKeyCode() == 'G') {
1399 wxCommandEvent evt(wxEVT_NULL, miBrushGradient + height + heightCount / 2 + 1);
1400 onMenuBrushGradient(evt);
1401 } else if (e.GetKeyCode() == 'S') {
1402 wxCommandEvent evt(wxEVT_NULL, miBrushSurface + surface);
1403 onMenuBrushSurface(evt);
1404 } else if (e.GetKeyCode() == 'O') {
1405 wxCommandEvent evt(wxEVT_NULL, miBrushObject + object + 1);
1406 onMenuBrushObject(evt);
1407 } else if (e.GetKeyCode() == 'R') {
1408 wxCommandEvent evt(wxEVT_NULL, miBrushResource + resource + 1);
1409 onMenuBrushResource(evt);
1410 } else if (e.GetKeyCode() == 'L') {
1411 wxCommandEvent evt(wxEVT_NULL, miBrushStartLocation + startLocation + 1);
1412 onMenuBrushStartLocation(evt);
1413 } else if (e.GetKeyCode() == WXK_LEFT && e.GetModifiers() == wxMOD_SHIFT) { // shift-left/right/up/down to shift the map one square
1414 program->setUndoPoint(ctAll);
1415 program->shiftLeft();
1416 setDirty();
1417 } else if (e.GetKeyCode() == WXK_RIGHT && e.GetModifiers() == wxMOD_SHIFT) {
1418 program->setUndoPoint(ctAll);
1419 program->shiftRight();
1420 setDirty();
1421 } else if (e.GetKeyCode() == WXK_UP && e.GetModifiers() == wxMOD_SHIFT) {
1422 program->setUndoPoint(ctAll);
1423 program->shiftUp();
1424 setDirty();
1425 } else if (e.GetKeyCode() == WXK_DOWN && e.GetModifiers() == wxMOD_SHIFT) {
1426 program->setUndoPoint(ctAll);
1427 program->shiftDown();
1428 setDirty();
1429 } else {
1430 e.Skip();
1431 }
1432 }
1433
BEGIN_EVENT_TABLE(MainWindow,wxFrame)1434 BEGIN_EVENT_TABLE(MainWindow, wxFrame)
1435
1436 EVT_CLOSE(MainWindow::onClose)
1437
1438 // these are 'handled' by GlCanvas and funneled to these handlers. See BEGIN_EVENT_TABLE(GlCanvas, wxGLCanvas) below.
1439 //EVT_LEFT_DOWN(MainWindow::onMouseDown)
1440 //EVT_MOTION(MainWindow::onMouseMove)
1441 //EVT_KEY_DOWN(MainWindow::onKeyDown)
1442
1443 EVT_MENU(wxID_NEW, MainWindow::onMenuEditReset)
1444 EVT_MENU(wxID_OPEN, MainWindow::onMenuFileLoad)
1445 EVT_MENU(wxID_SAVE, MainWindow::onMenuFileSave)
1446 EVT_MENU(wxID_SAVEAS, MainWindow::onMenuFileSaveAs)
1447 EVT_MENU(wxID_EXIT, MainWindow::onMenuFileExit)
1448
1449 EVT_MENU(miEditUndo, MainWindow::onMenuEditUndo)
1450 EVT_MENU(miEditRedo, MainWindow::onMenuEditRedo)
1451 EVT_MENU(miEditResetPlayers, MainWindow::onMenuEditResetPlayers)
1452 EVT_MENU(miEditResize, MainWindow::onMenuEditResize)
1453 EVT_MENU(miEditFlipDiagonal, MainWindow::onMenuEditFlipDiagonal)
1454 EVT_MENU(miEditFlipX, MainWindow::onMenuEditFlipX)
1455 EVT_MENU(miEditFlipY, MainWindow::onMenuEditFlipY)
1456
1457 EVT_MENU(miEditMirrorX, MainWindow::onMenuEditMirrorX)
1458 EVT_MENU(miEditMirrorY, MainWindow::onMenuEditMirrorY)
1459 EVT_MENU(miEditMirrorXY, MainWindow::onMenuEditMirrorXY)
1460 EVT_MENU(miEditRotatecopyX, MainWindow::onMenuEditRotatecopyX)
1461 EVT_MENU(miEditRotatecopyY, MainWindow::onMenuEditRotatecopyY)
1462 EVT_MENU(miEditRotatecopyXY, MainWindow::onMenuEditRotatecopyXY)
1463 EVT_MENU(miEditRotatecopyCorner, MainWindow::onMenuEditRotatecopyCorner)
1464
1465 EVT_MENU(miEditRandomizeHeights, MainWindow::onMenuEditRandomizeHeights)
1466 EVT_MENU(miEditRandomize, MainWindow::onMenuEditRandomize)
1467 EVT_MENU(miEditSwitchSurfaces, MainWindow::onMenuEditSwitchSurfaces)
1468 EVT_MENU(miEditInfo, MainWindow::onMenuEditInfo)
1469 EVT_MENU(miEditAdvanced, MainWindow::onMenuEditAdvanced)
1470
1471 EVT_MENU(miViewResetZoomAndPos, MainWindow::onMenuViewResetZoomAndPos)
1472 EVT_MENU(miViewGrid, MainWindow::onMenuViewGrid)
1473 EVT_MENU(miViewHeightMap, MainWindow::onMenuViewHeightMap)
1474 EVT_MENU(miHideWater, MainWindow::onMenuHideWater)
1475 EVT_MENU(miViewAbout, MainWindow::onMenuViewAbout)
1476 EVT_MENU(miViewHelp, MainWindow::onMenuViewHelp)
1477
1478 EVT_MENU_RANGE(miBrushHeight + 1, miBrushHeight + heightCount, MainWindow::onMenuBrushHeight)
1479 EVT_MENU_RANGE(miBrushGradient + 1, miBrushGradient + heightCount, MainWindow::onMenuBrushGradient)
1480 EVT_MENU_RANGE(miBrushSurface + 1, miBrushSurface + surfaceCount, MainWindow::onMenuBrushSurface)
1481 EVT_MENU_RANGE(miBrushObject + 1, miBrushObject + objectCount, MainWindow::onMenuBrushObject)
1482 EVT_MENU_RANGE(miBrushResource + 1, miBrushResource + resourceCount, MainWindow::onMenuBrushResource)
1483 EVT_MENU_RANGE(miBrushStartLocation + 1, miBrushStartLocation + startLocationCount, MainWindow::onMenuBrushStartLocation)
1484 EVT_MENU_RANGE(miRadius, miRadius + radiusCount, MainWindow::onMenuRadius)
1485
1486 EVT_PAINT(MainWindow::onPaint)
1487
1488 EVT_TOOL(toolPlayer, MainWindow::onToolPlayer)
1489 END_EVENT_TABLE()
1490
1491 // =====================================================
1492 // class GlCanvas
1493 // =====================================================
1494
1495 GlCanvas::GlCanvas(MainWindow *mainWindow, wxWindow *parent, int *args)
1496 #if wxCHECK_VERSION(2, 9, 1)
1497 : wxGLCanvas(parent, -1, args, wxDefaultPosition, wxDefaultSize, 0, wxT("GLCanvas")) {
1498 this->context = new wxGLContext(this);
1499 #else
1500 : wxGLCanvas(parent, -1, wxDefaultPosition, wxDefaultSize, 0, wxT("GLCanvas"), args) {
1501 this->context = NULL;
1502 #endif
1503
1504 this->mainWindow = mainWindow;
1505 }
1506
1507 GlCanvas::~GlCanvas() {
1508 delete this->context;
1509 this->context = NULL;
1510 }
1511
1512 void GlCanvas::setCurrentGLContext() {
1513 #ifndef __APPLE__
1514
1515 #if wxCHECK_VERSION(2, 9, 1)
1516 if(this->context == NULL) {
1517 this->context = new wxGLContext(this);
1518 }
1519 #endif
1520
1521 if(this->context) {
1522 this->SetCurrent(*this->context);
1523 }
1524 #else
1525 this->SetCurrent();
1526 #endif
1527 }
1528
1529 void translateCoords(wxWindow *wnd, int &x, int &y) {
1530 /*
1531 #ifdef WIN32
1532 int cx, cy;
1533 wnd->GetPosition(&cx, &cy);
1534 x += cx;
1535 y += cy;
1536 #endif
1537 */
1538 }
1539
1540 // for the mousewheel
1541 void GlCanvas::onMouseWheel(wxMouseEvent &event) {
1542 if(event.GetWheelRotation()>0) mainWindow->onMouseWheelDown(event);
1543 else mainWindow->onMouseWheelUp(event);
1544 }
1545
1546 void GlCanvas::onMouseDown(wxMouseEvent &event) {
1547 int x, y;
1548 event.GetPosition(&x, &y);
1549 translateCoords(this, x, y);
1550 mainWindow->onMouseDown(event, x, y);
1551 }
1552
1553 void GlCanvas::onMouseMove(wxMouseEvent &event) {
1554 int x, y;
1555 event.GetPosition(&x, &y);
1556 translateCoords(this, x, y);
1557 mainWindow->onMouseMove(event, x, y);
1558 }
1559
1560 void GlCanvas::onKeyDown(wxKeyEvent &event) {
1561 int x, y;
1562 event.GetPosition(&x, &y);
1563 translateCoords(this, x, y);
1564 mainWindow->onKeyDown(event);
1565 }
1566
1567 void GlCanvas::onPaint(wxPaintEvent &event) {
1568 // wxPaintDC dc(this); //N "In a paint event handler must always create a wxPaintDC object even if you do not use it. (?)
1569 // mainWindow->program->renderMap(GetClientSize().x, GetClientSize().y);
1570 // SwapBuffers();
1571 // event.Skip();
1572 //printf("gl onPaint skip map\n");
1573 mainWindow->onPaint(event);
1574 }
1575
1576 BEGIN_EVENT_TABLE(GlCanvas, wxGLCanvas)
1577 EVT_KEY_DOWN(GlCanvas::onKeyDown)
1578 EVT_MOUSEWHEEL(GlCanvas::onMouseWheel)
1579 EVT_LEFT_DOWN(GlCanvas::onMouseDown)
1580 EVT_MOTION(GlCanvas::onMouseMove)
1581 EVT_PAINT(GlCanvas::onPaint) // Because the drawing area needs to be repainted too.
1582 END_EVENT_TABLE()
1583
1584 // ===============================================
1585 // class SimpleDialog
1586 // ===============================================
1587
1588 void SimpleDialog::addValue(const string &key, const string &value, const string &help) {
1589 values.push_back(pair<string, string>(key, value+"|"+help)); // I guess I need map<,> instead but I don't know how to do it
1590 }
1591
1592 string SimpleDialog::getValue(const string &key) {
1593 for (unsigned int i = 0; i < values.size(); ++i) {
1594 if (values[i].first == key) {
1595 return values[i].second;
1596 }
1597 }
1598 return "";
1599 }
1600
1601 bool SimpleDialog::show(const string &title, bool wide) {
1602 Create(NULL, -1, ToUnicode(title));
1603 wxSizer *sizer2 = new wxBoxSizer(wxVERTICAL);
1604 wxSizer *sizer = new wxFlexGridSizer(3);
1605
1606 vector<wxTextCtrl*> texts;
1607 for (Values::iterator it = values.begin(); it != values.end(); ++it) {
1608 size_t helptextpos = it->second.find_first_of('|');
1609 sizer->Add(new wxStaticText(this, -1, ToUnicode(it->first)), 0, wxALL, 5);
1610 wxTextCtrl *text = new wxTextCtrl(this, -1, ToUnicode(it->second.substr(0,helptextpos)));
1611 if(wide) text->SetMinSize( wxSize((text->GetSize().GetWidth())*4, text->GetSize().GetHeight())); // 4 time as wide as default
1612 sizer->Add(text, 0, wxALL, 5);
1613 texts.push_back(text);
1614 sizer->Add(new wxStaticText(this, -1, ToUnicode(it->second.substr(helptextpos+1))), 0, wxALL, 5);
1615 }
1616 sizer2->Add(sizer);
1617 sizer2->Add(CreateButtonSizer(wxOK|wxCANCEL),0,wxALIGN_RIGHT); // enable Cancel button
1618 SetSizerAndFit(sizer2);
1619
1620 ShowModal();
1621 if(m_returnCode==wxID_CANCEL) return false; // don't change values if canceled
1622
1623 for (unsigned int i = 0; i < texts.size(); ++i) {
1624 #ifdef WIN32
1625 const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(wxFNCONV(texts[i]->GetValue()));
1626 values[i].second = tmp_buf;
1627 #else
1628 values[i].second = texts[i]->GetValue().ToAscii();
1629 #endif
1630 }
1631 return true;
1632 }
1633
1634
1635 // ===============================================
1636 // class App
1637 // ===============================================
1638
1639 bool App::OnInit() {
1640 SystemFlags::VERBOSE_MODE_ENABLED = false;
1641 SystemFlags::ENABLE_THREADED_LOGGING = false;
1642
1643 string fileparam;
1644 if(argc==2){
1645 if(argv[1][0]=='-') { // any flag gives help and exits program.
1646 std::cout << "MegaGlest map editor " << mapeditorVersionString << " [Using " << (const char *)wxConvCurrent->cWX2MB(wxVERSION_STRING) << "]" << std::endl << std::endl;
1647 std::cout << "glest_map_editor [MGM FILE]" << std::endl << std::endl;
1648 std::cout << "Creates or edits glest/megaglest maps." << std::endl;
1649 std::cout << "Draw with left mouse button" << std::endl;
1650 std::cout << "Move map with right mouse button" << std::endl;
1651 std::cout << "Zoom with middle mouse button or mousewheel" << std::endl;
1652
1653 // std::cout << " ~ more helps should be written here ~" << std::endl;
1654 std::cout << std::endl;
1655 exit (0);
1656 }
1657 //#if defined(__MINGW32__)
1658 const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(argv[1]);
1659 fileparam = tmp_buf;
1660
1661 #ifdef WIN32
1662 auto_ptr<wchar_t> wstr(Ansi2WideString(fileparam.c_str()));
1663 fileparam = utf8_encode(wstr.get());
1664 #endif
1665
1666 //#else
1667 // fileparam = wxFNCONV(argv[1]);
1668 //#endif
1669 }
1670
1671 #if defined(wxMAJOR_VERSION) && defined(wxMINOR_VERSION) && defined(wxRELEASE_NUMBER) && defined(wxSUBRELEASE_NUMBER)
1672 printf("Using wxWidgets version [%d.%d.%d.%d]\n",wxMAJOR_VERSION,wxMINOR_VERSION,wxRELEASE_NUMBER,wxSUBRELEASE_NUMBER);
1673 #endif
1674
1675 wxString exe_path = wxStandardPaths::Get().GetExecutablePath();
1676 //wxString path_separator = wxFileName::GetPathSeparator();
1677 //exe_path = exe_path.BeforeLast(path_separator[0]);
1678 //exe_path += path_separator;
1679
1680 string appPath;
1681 //#if defined(__MINGW32__)
1682
1683 #ifdef WIN32
1684 const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(wxFNCONV(exe_path));
1685 appPath = tmp_buf;
1686
1687 auto_ptr<wchar_t> wstr(Ansi2WideString(appPath.c_str()));
1688 appPath = utf8_encode(wstr.get());
1689 #else
1690 appPath = wxFNCONV(exe_path);
1691 #endif
1692
1693 //#else
1694 // const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(wxFNCONV(exe_path));
1695 // appPath = tmp_buf;
1696 //#endif
1697
1698 mainWindow = new MainWindow(appPath);
1699 mainWindow->Show();
1700 mainWindow->init(fileparam);
1701 mainWindow->Update();
1702
1703 #ifdef WIN32
1704 wxPoint pos = mainWindow->GetScreenPosition();
1705 wxSize size = mainWindow->GetSize();
1706
1707 mainWindow->SetSize(pos.x, pos.y, 1, 1, wxSIZE_FORCE);
1708 //mainWindow->Update();
1709
1710 mainWindow->SetSize(pos.x, pos.y, size.x-1, size.y, wxSIZE_FORCE);
1711 mainWindow->Update();
1712 #endif
1713
1714 return true;
1715 }
1716
1717 int App::MainLoop() {
1718 try {
1719 //throw megaglest_runtime_error("test");
1720 return wxApp::MainLoop();
1721 }
1722 catch (const exception &e) {
1723 MsgDialog(NULL, ToUnicode(e.what()), wxT("Exception")).ShowModal();
1724 }
1725 return 0;
1726 }
1727
1728 int App::OnExit() {
1729 SystemFlags::Close();
1730 SystemFlags::SHUTDOWN_PROGRAM_MODE=true;
1731
1732 return 0;
1733 }
1734
1735 MsgDialog::MsgDialog(wxWindow *parent,
1736 const wxString& message,
1737 const wxString& caption,
1738 long style,
1739 const wxPoint& pos) {
1740
1741 m_sizerText = NULL;
1742 if ( !wxDialog::Create(parent, wxID_ANY, caption,
1743 pos, wxDefaultSize,
1744 style) ) {
1745 return;
1746 }
1747 m_sizerText = new wxBoxSizer(wxVERTICAL);
1748 wxStaticText *label = new wxStaticText(this, wxID_ANY, message);
1749 wxFont font(*wxNORMAL_FONT);
1750 font.SetPointSize(font.GetPointSize());
1751 font.SetWeight(wxFONTWEIGHT_NORMAL);
1752 label->SetFont(font);
1753
1754 m_sizerText->Add(label, wxSizerFlags().Centre().Border());
1755
1756 wxSizer *sizerIconAndText = new wxBoxSizer(wxHORIZONTAL);
1757 sizerIconAndText->Add(m_sizerText, wxSizerFlags(1).Expand());
1758
1759 wxSizer *sizerTop = new wxBoxSizer(wxVERTICAL);
1760 sizerTop->Add(sizerIconAndText, wxSizerFlags(1).Expand().Border());
1761
1762 wxSizer *sizerBtns = CreateButtonSizer(wxOK);
1763 if ( sizerBtns )
1764 {
1765 sizerTop->Add(sizerBtns, wxSizerFlags().Expand().Border());
1766 }
1767
1768 SetSizerAndFit(sizerTop);
1769 CentreOnScreen();
1770 }
1771 MsgDialog::~MsgDialog() {
1772
1773 }
1774
1775 }// end namespace
1776
1777 IMPLEMENT_APP(MapEditor::App)
1778