MegaGlest/source/glest_map_editor/main.cpp

1778 lines
57 KiB
C++

// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Martiño Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "main.h"
#include <ctime>
#include "conversion.h"
#include "icons.h"
#include "platform_common.h"
#include "config.h"
#include <iostream>
#include"platform_util.h"
#include <wx/stdpaths.h>
#ifndef WIN32
#include <errno.h>
#endif
#include "common_scoped_ptr.h"
//#include <memory>
using namespace Shared::Util;
using namespace Shared::PlatformCommon;
using namespace Glest::Game;
using namespace std;
namespace Glest { namespace Game {
string getGameReadWritePath(string lookupKey) {
string path = "";
if(path == "" && getenv("GLESTHOME") != NULL) {
path = getenv("GLESTHOME");
if(path != "" && EndsWith(path, "/") == false && EndsWith(path, "\\") == false) {
path += "/";
}
//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());
}
return path;
}
}}
namespace MapEditor {
const string mapeditorVersionString = "v3.13-dev";
const string MainWindow::winHeader = "MegaGlest Map Editor " + mapeditorVersionString;
// ===============================================
// class Global functions
// ===============================================
wxString ToUnicode(const char* str) {
return wxString(str, wxConvUTF8);
}
wxString ToUnicode(const string& str) {
return wxString(str.c_str(), wxConvUTF8);
}
// ===============================================
// class MainWindow
// ===============================================
MainWindow::MainWindow(string appPath)
: wxFrame(NULL, -1, ToUnicode(winHeader), wxPoint(0,0), wxSize(1024, 768))
, glCanvas(NULL)
, program(NULL)
, lastX(0)
, lastY(0)
, panel(NULL)
, menuBar(NULL)
, fileDialog(NULL)
, currentBrush(btHeight)
, height(0)
, surface(1)
, radius(1)
, object(0)
, resource(0)
, startLocation(1)
, enabledGroup(ctHeight)
, fileModified(false)
, boxsizer(NULL)
,startupSettingsInited(false) {
menuFile=NULL;
menuEdit=NULL;
menuEditMirror=NULL;
menuView=NULL;
menuBrush=NULL;
menuBrushHeight=NULL;
menuBrushGradient=NULL;
menuBrushSurface=NULL;
menuBrushObject=NULL;
menuBrushResource=NULL;
menuBrushStartLocation=NULL;
menuRadius=NULL;
fileDialog=NULL;
resourceUnderMouse=0;
objectUnderMouse=0;
// default values for random height calculation that turned out to be quite useful
randomWithReset=true;
randomMinimumHeight=-300;
randomMaximumHeight=400;
randomChanceDivider=30;
randomRecursions=3;
this->appPath = appPath;
Properties::setApplicationPath(executable_path(appPath));
this->panel = new wxPanel(this, wxID_ANY);
}
void MainWindow::onToolPlayer(wxCommandEvent& event){
PopupMenu(menuBrushStartLocation);
}
void MainToolBar::onMouseMove(wxMouseEvent &event) {
#ifdef WIN32
if(this->GetParent() != NULL && this->GetParent()->GetParent() != NULL) {
MainWindow *mainWindow = dynamic_cast<MainWindow *>(this->GetParent()->GetParent());
if(mainWindow != NULL) {
mainWindow->refreshMapRender();
}
}
#endif
event.Skip();
}
BEGIN_EVENT_TABLE(MainToolBar, wxToolBar)
EVT_MOTION(MainToolBar::onMouseMove)
END_EVENT_TABLE()
void MainWindow::init(string fname) {
//menus
menuBar = new wxMenuBar();
//file
menuFile = new wxMenu();
menuFile->Append(wxID_NEW);
menuFile->Append(wxID_OPEN);
menuFile->AppendSeparator();
menuFile->Append(wxID_SAVE);
menuFile->Append(wxID_SAVEAS);
menuFile->AppendSeparator();
menuFile->Append(wxID_EXIT);
menuBar->Append(menuFile, wxT("&File"));
//edit
menuEdit = new wxMenu();
menuEdit->Append(miEditUndo, wxT("&Undo\tCTRL+Z"));
menuEdit->Append(miEditRedo, wxT("&Redo\tCTRL+Y"));
menuEdit->AppendSeparator();
// menuEdit->Append(miEditReset, wxT("Rese&t..."));
menuEdit->Append(miEditResetPlayers, wxT("Reset &Players..."));
menuEdit->Append(miEditResize, wxT("Re&size..."));
menuEdit->Append(miEditFlipDiagonal, wxT("Flip &Diagonal"));
menuEdit->Append(miEditFlipX, wxT("Flip &X"));
menuEdit->Append(miEditFlipY, wxT("Flip &Y"));
// Mirror submenu-------------------------------------------
menuEditMirror = new wxMenu();
menuEditMirror->Append(miEditMirrorX, wxT("Copy &Left to Right"));
menuEditMirror->Append(miEditMirrorY, wxT("Copy &Top to Bottom"));
menuEditMirror->Append(miEditMirrorXY, wxT("Copy &BottomLeft to TopRight"));
menuEditMirror->AppendSeparator();
menuEditMirror->Append(miEditRotatecopyX, wxT("&Rotate Left to Right"));
menuEditMirror->Append(miEditRotatecopyY, wxT("Rotate T&op to Bottom"));
menuEditMirror->Append(miEditRotatecopyXY, wxT("Rotate Botto&mLeft to TopRight"));
menuEditMirror->Append(miEditRotatecopyCorner, wxT("Rotate TopLeft &corner to TopRight"));
menuEdit->Append(miEditMirror, wxT("&Mirror"), menuEditMirror);
// ---------------------------------------------------------
menuEdit->Append(miEditRandomizeHeights, wxT("Randomize &Heights"));
menuEdit->Append(miEditRandomize, wxT("Randomi&ze Players"));
menuEdit->Append(miEditSwitchSurfaces, wxT("Switch Sur&faces..."));
menuEdit->Append(miEditInfo, wxT("&Info..."));
menuEdit->Append(miEditAdvanced, wxT("&Advanced..."));
menuBar->Append(menuEdit, wxT("&Edit"));
//view
menuView = new wxMenu();
menuView->Append(miViewResetZoomAndPos, wxT("&Reset zoom and pos"));
menuView->AppendCheckItem(miViewGrid, wxT("&Grid"));
menuView->AppendCheckItem(miViewHeightMap, wxT("H&eightMap"));
menuView->AppendCheckItem(miHideWater, wxT("Hide&Water"));
menuView->AppendSeparator();
menuView->Append(miViewHelp, wxT("&Help..."));
menuView->Append(miViewAbout, wxT("&About..."));
menuBar->Append(menuView, wxT("&View"));
//brush
// menuBrush = new wxMenu();
//surface
menuBrushSurface = new wxMenu();
menuBrushSurface->AppendCheckItem(miBrushSurface + 1, wxT("&Grass"));
menuBrushSurface->AppendCheckItem(miBrushSurface + 2, wxT("S&econdary grass"));
menuBrushSurface->AppendCheckItem(miBrushSurface + 3, wxT("&Road"));
menuBrushSurface->AppendCheckItem(miBrushSurface + 4, wxT("&Stone"));
menuBrushSurface->AppendCheckItem(miBrushSurface + 5, wxT("Gr&ound"));
menuBar->Append(menuBrushSurface, wxT("&Surface"));
//resources
menuBrushResource = new wxMenu();
//menuBrushResource->AppendCheckItem(miBrushResource + 1, wxT("&0 - None"));
menuBrushResource->AppendCheckItem(miBrushResource+2, wxT("&Gold (unwalkable)"));
menuBrushResource->AppendCheckItem(miBrushResource+3, wxT("&Stone (unwalkable)"));
menuBrushResource->AppendCheckItem(miBrushResource+4, wxT("&3 - custom"));
menuBrushResource->AppendCheckItem(miBrushResource+5, wxT("&4 - custom"));
menuBrushResource->AppendCheckItem(miBrushResource+6, wxT("&5 - custom"));
menuBar->Append(menuBrushResource, wxT("&Resource"));
//objects
menuBrushObject = new wxMenu();
menuBrushObject->AppendCheckItem(miBrushObject+1, wxT("&None (erase)\tALT+0"));
menuBrushObject->AppendSeparator();
menuBrushObject->AppendCheckItem(miBrushObject+2, wxT("&Tree (harvestable)"));
menuBrushObject->AppendCheckItem(miBrushObject+3, wxT("&Dead tree/Cactuses/Thornbush"));
menuBrushObject->AppendCheckItem(miBrushObject+4, wxT("&Stone"));
menuBrushObject->AppendCheckItem(miBrushObject+5, wxT("&Bush/Grass/Fern (walkable)"));
menuBrushObject->AppendCheckItem(miBrushObject+6, wxT("&Water object/Reed/Papyrus (walkable)"));
menuBrushObject->AppendCheckItem(miBrushObject+7, wxT("Big tree/&Old palm"));
menuBrushObject->AppendCheckItem(miBrushObject+8, wxT("&Hanged/Impaled "));
menuBrushObject->AppendCheckItem(miBrushObject+9, wxT("St&atues"));
menuBrushObject->AppendCheckItem(miBrushObject+10, wxT("&Mountain"));
menuBrushObject->AppendCheckItem(miBrushObject+11, wxT("&Invisible blocking object"));
menuBar->Append(menuBrushObject, wxT("&Object"));
// ZombiePirate height brush
menuBrushGradient = new wxMenu();
for (int i = 0; i < heightCount; ++i) {
menuBrushGradient->AppendCheckItem(miBrushGradient + i + 1, ToUnicode((i>4?"&":"") +intToStr(i - heightCount / 2)));
}
menuBar->Append(menuBrushGradient, wxT("&Gradient"));
// Glest height brush
menuBrushHeight = new wxMenu();
for (int i = 0; i < heightCount; ++i) {
menuBrushHeight->AppendCheckItem(miBrushHeight + i + 1, ToUnicode((i>4?"&":"") +intToStr(i - heightCount / 2)));
}
menuBrushHeight->Check(miBrushHeight + (heightCount + 1) / 2, true);
menuBar->Append(menuBrushHeight, wxT("&Height"));
enabledGroup = ctHeight;
//radius
menuRadius = new wxMenu();
for (int i = 1; i <= radiusCount; ++i) {
menuRadius->AppendCheckItem(miRadius + i, ToUnicode("&" + intToStr(i) + " (diameter "+intToStr(i*2-1)+ ")"+ "\tALT+" + intToStr(i)));
}
menuRadius->Check(miRadius + 1, true);
menuBar->Append(menuRadius, wxT("R&adius"));
//players
menuBrushStartLocation = new wxMenu();
wxMenuItem *pmi1 = new wxMenuItem(menuBrushStartLocation, miBrushStartLocation + 1, wxT("Player &1 Red"));
pmi1->SetBitmap(wxBitmap(brush_players_red));
menuBrushStartLocation->Append(pmi1);
wxMenuItem *pmi2 = new wxMenuItem(menuBrushStartLocation, miBrushStartLocation + 2, wxT("Player &2 Blue"));
pmi2->SetBitmap(wxBitmap(brush_players_blue));
menuBrushStartLocation->Append(pmi2);
wxMenuItem *pmi3 = new wxMenuItem(menuBrushStartLocation, miBrushStartLocation + 3, wxT("Player &3 Green"));
pmi3->SetBitmap(wxBitmap(brush_players_green));
menuBrushStartLocation->Append(pmi3);
wxMenuItem *pmi4 = new wxMenuItem(menuBrushStartLocation, miBrushStartLocation + 4, wxT("Player &4 Yellow"));
pmi4->SetBitmap(wxBitmap(brush_players_yellow));
menuBrushStartLocation->Append(pmi4);
wxMenuItem *pmi5 = new wxMenuItem(menuBrushStartLocation, miBrushStartLocation + 5, wxT("Player &5 White"));
pmi5->SetBitmap(wxBitmap(brush_players_white));
menuBrushStartLocation->Append(pmi5);
wxMenuItem *pmi6 = new wxMenuItem(menuBrushStartLocation, miBrushStartLocation + 6, wxT("Player &6 Cyan"));
pmi6->SetBitmap(wxBitmap(brush_players_cyan));
menuBrushStartLocation->Append(pmi6);
wxMenuItem *pmi7 = new wxMenuItem(menuBrushStartLocation, miBrushStartLocation + 7, wxT("Player &7 Orange"));
pmi7->SetBitmap(wxBitmap(brush_players_orange));
menuBrushStartLocation->Append(pmi7);
wxMenuItem *pmi8 = new wxMenuItem(menuBrushStartLocation, miBrushStartLocation + 8, wxT("Player &8 Pink")); // = Light Magenta :-)
pmi8->SetBitmap(wxBitmap(brush_players_pink));
menuBrushStartLocation->Append(pmi8);
menuBar->Append(menuBrushStartLocation, wxT("&Player"));
//menuBar->Append(menuBrush, wxT("&Brush"));
SetMenuBar(menuBar);
fileName = "New (unsaved) map";
int status_widths[siCOUNT] = {
10, // empty
-25, // File name
-6, // File type
-20, // Current Object
-14, // Brush Type
-20, // Brush 'Value'
-10, // Brush Radius
-25, // Position
};
CreateStatusBar(siCOUNT);
GetStatusBar()->SetStatusWidths(siCOUNT, status_widths);
SetStatusText(wxT("File: ") + ToUnicode(fileName), siFILE_NAME);
SetStatusText(wxT(".mgm"), siFILE_TYPE);
SetStatusText(wxT("Object: None (Erase)"), siCURR_OBJECT);
SetStatusText(wxT("Brush: Height"), siBRUSH_TYPE);
SetStatusText(wxT("Value: 0"), siBRUSH_VALUE);
SetStatusText(wxT("Radius: 1"), siBRUSH_RADIUS);
SetStatusText(wxT("Pos (Ingame): 0"), siPOS_VALUE);
wxToolBar *toolbar = new MainToolBar(this->panel, wxID_ANY);
toolbar->AddTool(miEditUndo, _("undo"), wxBitmap(edit_undo), _("Undo"));
toolbar->AddTool(miEditRedo, _("redo"), wxBitmap(edit_redo), _("Redo"));
toolbar->AddTool(miEditRandomizeHeights, _("randomizeHeights"), wxBitmap(edit_randomize_heights), _("Randomize Heights"));
// toolbar->AddTool(miEditRandomize, _("randomize"), wxBitmap(edit_randomize), _("Randomize"));
toolbar->AddTool(miEditSwitchSurfaces, _("switch"), wxBitmap(edit_switch_surfaces), _("Switch Surfaces"));
toolbar->AddSeparator();
toolbar->AddTool(miBrushSurface + 1, _("brush_grass1"), wxBitmap(brush_surface_grass1), _("Grass"));
toolbar->AddTool(miBrushSurface + 2, _("brush_grass2"), wxBitmap(brush_surface_grass2), _("Secondary grass"));
toolbar->AddTool(miBrushSurface + 3, _("brush_road"), wxBitmap(brush_surface_road), _("Road"));
toolbar->AddTool(miBrushSurface + 4, _("brush_stone"), wxBitmap(brush_surface_stone), _("Stone"));
toolbar->AddTool(miBrushSurface + 5, _("brush_custom"), wxBitmap(brush_surface_custom), _("Ground"));
toolbar->AddSeparator();
toolbar->AddTool(miBrushResource + 2, _("resource1"), wxBitmap(brush_resource_1_gold), _("gold (unwalkable)"));
toolbar->AddTool(miBrushResource + 3, _("resource2"), wxBitmap(brush_resource_2_stone), _("stone (unwalkable)"));
toolbar->AddTool(miBrushResource + 4, _("resource3"), wxBitmap(brush_resource_3), _("custom3"));
toolbar->AddTool(miBrushResource + 5, _("resource4"), wxBitmap(brush_resource_4), _("custom4"));
toolbar->AddTool(miBrushResource + 6, _("resource5"), wxBitmap(brush_resource_5), _("custom5"));
toolbar->AddSeparator();
toolbar->AddTool(miBrushObject + 1, _("brush_none"), wxBitmap(brush_none), _("None (erase)"));
toolbar->AddTool(miBrushObject + 2, _("brush_tree"), wxBitmap(brush_object_tree), _("Tree (unwalkable/harvestable)"));
toolbar->AddTool(miBrushObject + 3, _("brush_dead_tree"), wxBitmap(brush_object_dead_tree), _("Dead tree/Cactuses/Thornbush (unwalkable)"));
toolbar->AddTool(miBrushObject + 4, _("brush_stone"), wxBitmap(brush_object_stone), _("Stone (unwalkable/not harvestable)"));
toolbar->AddTool(miBrushObject + 5, _("brush_bush"), wxBitmap(brush_object_bush), _("Bush/Grass/Fern (walkable)"));
toolbar->AddTool(miBrushObject + 6, _("brush_water"), wxBitmap(brush_object_water_object), _("Water object/Reed/Papyrus (walkable)"));
toolbar->AddTool(miBrushObject + 7, _("brush_c1_bigtree"), wxBitmap(brush_object_c1_bigtree), _("Big tree/Old palm (unwalkable/not harvestable)"));
toolbar->AddTool(miBrushObject + 8, _("brush_c2_hanged"), wxBitmap(brush_object_c2_hanged), _("Hanged/Impaled (unwalkable)"));
toolbar->AddTool(miBrushObject + 9, _("brush_c3_statue"), wxBitmap(brush_object_c3_statue), _("Statues (unwalkable)"));
toolbar->AddTool(miBrushObject +10, _("brush_c4_bigrock"), wxBitmap(brush_object_c4_bigrock), _("Mountain (unwalkable)"));
toolbar->AddTool(miBrushObject +11, _("brush_c5_blocking"), wxBitmap(brush_object_c5_blocking), _("Invisible blocking object (unwalkable)"));
toolbar->AddSeparator();
toolbar->AddTool(toolPlayer, _("brush_player"), wxBitmap(brush_players_player), _("Player start position"));
toolbar->Realize();
wxToolBar *toolbar2 = new MainToolBar(this->panel, wxID_ANY);
toolbar2->AddTool(miBrushGradient + 1, _("brush_gradient_n5"), wxBitmap(brush_gradient_n5));
toolbar2->AddTool(miBrushGradient + 2, _("brush_gradient_n4"), wxBitmap(brush_gradient_n4));
toolbar2->AddTool(miBrushGradient + 3, _("brush_gradient_n3"), wxBitmap(brush_gradient_n3));
toolbar2->AddTool(miBrushGradient + 4, _("brush_gradient_n2"), wxBitmap(brush_gradient_n2));
toolbar2->AddTool(miBrushGradient + 5, _("brush_gradient_n1"), wxBitmap(brush_gradient_n1));
toolbar2->AddTool(miBrushGradient + 6, _("brush_gradient_0"), wxBitmap(brush_gradient_0));
toolbar2->AddTool(miBrushGradient + 7, _("brush_gradient_p1"), wxBitmap(brush_gradient_p1));
toolbar2->AddTool(miBrushGradient + 8, _("brush_gradient_p2"), wxBitmap(brush_gradient_p2));
toolbar2->AddTool(miBrushGradient + 9, _("brush_gradient_p3"), wxBitmap(brush_gradient_p3));
toolbar2->AddTool(miBrushGradient +10, _("brush_gradient_p4"), wxBitmap(brush_gradient_p4));
toolbar2->AddTool(miBrushGradient +11, _("brush_gradient_p5"), wxBitmap(brush_gradient_p5));
toolbar2->AddSeparator();
toolbar2->AddTool(miBrushHeight + 1, _("brush_height_n5"), wxBitmap(brush_height_n5));
toolbar2->AddTool(miBrushHeight + 2, _("brush_height_n4"), wxBitmap(brush_height_n4));
toolbar2->AddTool(miBrushHeight + 3, _("brush_height_n3"), wxBitmap(brush_height_n3));
toolbar2->AddTool(miBrushHeight + 4, _("brush_height_n2"), wxBitmap(brush_height_n2));
toolbar2->AddTool(miBrushHeight + 5, _("brush_height_n1"), wxBitmap(brush_height_n1));
toolbar2->AddTool(miBrushHeight + 6, _("brush_height_0"), wxBitmap(brush_height_0));
toolbar2->AddTool(miBrushHeight + 7, _("brush_height_p1"), wxBitmap(brush_height_p1));
toolbar2->AddTool(miBrushHeight + 8, _("brush_height_p2"), wxBitmap(brush_height_p2));
toolbar2->AddTool(miBrushHeight + 9, _("brush_height_p3"), wxBitmap(brush_height_p3));
toolbar2->AddTool(miBrushHeight +10, _("brush_height_p4"), wxBitmap(brush_height_p4));
toolbar2->AddTool(miBrushHeight +11, _("brush_height_p5"), wxBitmap(brush_height_p5));
toolbar2->AddSeparator();
toolbar2->AddTool(miRadius + 1, _("radius1"), wxBitmap(radius_1), _("1 (1x1)"));
toolbar2->AddTool(miRadius + 2, _("radius2"), wxBitmap(radius_2), _("2 (3x3)"));
toolbar2->AddTool(miRadius + 3, _("radius3"), wxBitmap(radius_3), _("3 (5x5)"));
toolbar2->AddTool(miRadius + 4, _("radius4"), wxBitmap(radius_4), _("4 (7x7)"));
toolbar2->AddTool(miRadius + 5, _("radius5"), wxBitmap(radius_5), _("5 (9x9)"));
toolbar2->AddTool(miRadius + 6, _("radius6"), wxBitmap(radius_6), _("6 (11x11)"));
toolbar2->AddTool(miRadius + 7, _("radius7"), wxBitmap(radius_7), _("7 (13x13)"));
toolbar2->AddTool(miRadius + 8, _("radius8"), wxBitmap(radius_8), _("8 (15x15)"));
toolbar2->AddTool(miRadius + 9, _("radius9"), wxBitmap(radius_9), _("9 (17x17)"));
toolbar2->Realize();
Config &config = Config::getInstance();
string userData = config.getString("UserData_Root","");
if(userData != "") {
endPathWithSlash(userData);
}
//std::cout << "A" << std::endl;
wxInitAllImageHandlers();
#ifdef WIN32
//std::cout << "B" << std::endl;
// #if defined(__MINGW32__)
wxIcon icon(ToUnicode("IDI_ICON1"));
// #else
// wxIcon icon("IDI_ICON1");
// #endif
#else
//std::cout << "B" << std::endl;
wxIcon icon;
string iniFilePath = extractDirectoryPathFromFile(config.getFileName(false));
string icon_file = iniFilePath + "editor.ico";
std::ifstream testFile(icon_file.c_str());
if(testFile.good()) {
testFile.close();
icon.LoadFile(ToUnicode(icon_file.c_str()),wxBITMAP_TYPE_ICO);
}
#endif
//std::cout << "C" << std::endl;
SetIcon(icon);
fileDialog = new wxFileDialog(this);
string defaultPath = userData + "maps/";
fileDialog->SetDirectory(ToUnicode(defaultPath));
//printf("Default Path [%s]\n",defaultPath.c_str());
lastPaintEvent.start();
boxsizer = new wxBoxSizer(wxVERTICAL);
boxsizer->Add(toolbar, 0, wxEXPAND);
boxsizer->Add(toolbar2, 0, wxEXPAND);
//boxsizer->Add(glCanvas, 1, wxEXPAND);
this->panel->SetSizer(boxsizer);
//this->Layout();
//program = new Program(glCanvas->GetClientSize().x, glCanvas->GetClientSize().y);
fileName = "New (unsaved) Map";
//printf("Does file exist, fname [%s]\n",fname.c_str());
if (fname.empty() == false && fileExists(fname)) {
//printf("YES file exist, fname [%s]\n",fname.c_str());
//program->loadMap(fname);
currentFile = fname;
fileName = cutLastExt(extractFileFromDirectoryPath(fname.c_str()));
fileDialog->SetPath(ToUnicode(fname));
}
SetTitle(ToUnicode(currentFile + " - " + winHeader));
//setDirty(false);
//setExtension();
initGlCanvas();
#if wxCHECK_VERSION(2, 9, 3)
//glCanvas->setCurrentGLContext();
//printf("setcurrent #1\n");
#elif wxCHECK_VERSION(2, 9, 1)
#else
if(glCanvas) glCanvas->SetCurrent();
//printf("setcurrent #2\n");
#endif
if(startupSettingsInited == false) {
startupSettingsInited = true;
setupStartupSettings();
}
}
void MainWindow::onClose(wxCloseEvent &event) {
if(program != NULL && program->getMap()->getHasChanged() == true) {
if( wxMessageDialog(NULL, ToUnicode("Do you want to save the current map?"),
ToUnicode("Question"), wxYES_NO | wxYES_DEFAULT).ShowModal() == wxID_YES) {
wxCommandEvent ev;
MainWindow::onMenuFileSave(ev);
}
}
delete program;
program = NULL;
//delete glCanvas;
if(glCanvas) glCanvas->Destroy();
glCanvas = NULL;
this->Destroy();
}
void MainWindow::initGlCanvas(){
if(glCanvas == NULL) {
int args[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_MIN_ALPHA, 8 };
glCanvas = new GlCanvas(this, this->panel, args);
boxsizer->Add(glCanvas, 1, wxEXPAND);
}
}
void MainWindow::setupStartupSettings() {
//gl canvas
if(glCanvas == NULL) {
initGlCanvas();
boxsizer->Add(glCanvas, 1, wxEXPAND);
this->panel->SetSizer(boxsizer);
this->Layout();
}
glCanvas->setCurrentGLContext();
glCanvas->SetFocus();
string playerName = Config::getInstance().getString("NetPlayerName","");
program = new Program(glCanvas->GetClientSize().x, glCanvas->GetClientSize().y, playerName);
fileName = "New (unsaved) Map";
//printf("#0 file load [%s]\n",currentFile.c_str());
if (!currentFile.empty() && fileExists(currentFile)) {
//printf("#0 exists file load [%s]\n",currentFile.c_str());
program->loadMap(currentFile);
//currentFile = fname;
fileName = cutLastExt(extractFileFromDirectoryPath(currentFile.c_str()));
fileDialog->SetPath(ToUnicode(currentFile));
}
SetTitle(ToUnicode(currentFile + " - " + winHeader));
setDirty(false);
setExtension();
}
MainWindow::~MainWindow() {
delete fileDialog;
fileDialog = NULL;
delete program;
program = NULL;
delete glCanvas;
glCanvas = NULL;
}
void MainWindow::setDirty(bool val) {
wxPaintEvent ev;
onPaint(ev);
if (fileModified && val) {
return;
}
fileModified = val;
if (fileModified) {
SetStatusText(wxT("File: ") + ToUnicode(fileName) + wxT("*"), siFILE_NAME);
} else {
SetStatusText(wxT("File: ") + ToUnicode(fileName), siFILE_NAME);
}
}
void MainWindow::setExtension() {
if (currentFile.empty() || program == NULL) {
return;
}
string extnsn = ext(currentFile);
//printf("#A currentFile [%s] extnsn [%s]\n",currentFile.c_str(),extnsn.c_str());
if (extnsn == "gbm" || extnsn == "mgm") {
currentFile = cutLastExt(currentFile);
}
SetStatusText(wxT(".mgm"), siFILE_TYPE);
currentFile += ".mgm";
}
void MainWindow::onMouseDown(wxMouseEvent &event, int x, int y) {
if (event.LeftIsDown() && program != NULL) {
program->setUndoPoint(enabledGroup);
program->setRefAlt(x, y);
change(x, y);
if (!isDirty()) {
setDirty(true);
}
wxPaintEvent ev;
onPaint(ev);
}
event.Skip();
}
// for the mousewheel
void MainWindow::onMouseWheelDown(wxMouseEvent &event) {
if(program == NULL) {
return;
}
wxPaintEvent ev;
program->incCellSize(1);
onPaint(ev);
}
void MainWindow::onMouseWheelUp(wxMouseEvent &event) {
if(program == NULL) {
return;
}
wxPaintEvent ev;
program->incCellSize(-1);
onPaint(ev);
}
void MainWindow::onMouseMove(wxMouseEvent &event, int x, int y) {
if(program == NULL) {
return;
}
bool repaint = false;
if (event.LeftIsDown()) {
change(x, y);
repaint = true;
} else if (event.MiddleIsDown()) {
int dif = (y - lastY);
if (dif != 0) {
program->incCellSize(dif / abs(dif));
repaint = true;
}
} else if (event.RightIsDown()) {
program->setOfset(x - lastX, y - lastY);
repaint = true;
} else {
int currResource = program->getResource(x, y);
if (currResource > 0) {
SetStatusText(wxT("Resource: ") + ToUnicode(resource_descs[currResource]), siCURR_OBJECT);
resourceUnderMouse = currResource;
objectUnderMouse = 0;
} else {
int currObject = program->getObject(x, y);
SetStatusText(wxT("Object: ") + ToUnicode(object_descs[currObject]), siCURR_OBJECT);
resourceUnderMouse = 0;
objectUnderMouse = currObject;
}
SetStatusText(wxT("Pos (Ingame): ")
+ ToUnicode(intToStr(program->getCellX(x))
+ ","
+ intToStr(program->getCellY(y))
+ " ("
+ intToStr(2*(program->getCellX(x)))
+ ","
+ intToStr(2*(program->getCellY(y)))
+ ")"), siPOS_VALUE);
//#ifdef WIN32
//repaint = true;
//#endif
}
lastX = x;
lastY = y;
if (repaint) {
wxPaintEvent ev;
onPaint(ev);
}
event.Skip();
}
void MainWindow::onPaint(wxPaintEvent &event) {
//printf("onPaint map\n");
if(!IsShown()) {
//printf("onPaint skip map\n");
event.Skip();
return;
}
//#if wxCHECK_VERSION(2, 9, 3)
//#elif wxCHECK_VERSION(2, 9, 1)
// glCanvas->setCurrentGLContext();
//#endif
//static bool contextSet = false;
//if(contextSet == false) {
// contextSet = true;
glCanvas->setCurrentGLContext();
//}
//printf("lastPaintEvent.getMillis() map\n");
if(lastPaintEvent.getMillis() < 30) {
sleep(1);
event.Skip();
return;
}
//printf("wxPaintDC dc map\n");
wxPaintDC dc(this); // "In a paint event handler must always create a wxPaintDC object even if you do not use it. (?)
// Otherwise, under MS Windows, refreshing for this and other windows will go wrong"
// http://docs.wxwidgets.org/2.6/wx_wxpaintevent.html
lastPaintEvent.start();
if(panel) panel->Refresh(false);
if(menuBar) menuBar->Refresh(false);
refreshMapRender();
event.Skip();
}
void MainWindow::refreshMapRender() {
//printf("refreshMapRender map\n");
if(program && glCanvas) {
program->renderMap(glCanvas->GetClientSize().x, glCanvas->GetClientSize().y);
glCanvas->SwapBuffers();
}
}
void MainWindow::onMenuFileLoad(wxCommandEvent &event) {
if(program == NULL) {
return;
}
try {
fileDialog->SetMessage(wxT("Select Glestmap to load"));
fileDialog->SetWildcard(wxT("Glest&Mega Map (*.gbm *.mgm)|*.gbm;*.mgm|Glest Map (*.gbm)|*.gbm|Mega Map (*.mgm)|*.mgm"));
if (fileDialog->ShowModal() == wxID_OK) {
#ifdef WIN32
const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(wxFNCONV(fileDialog->GetPath()));
currentFile = tmp_buf;
auto_ptr<wchar_t> wstr(Ansi2WideString(currentFile.c_str()));
currentFile = utf8_encode(wstr.get());
#else
//currentFile = fileDialog->GetPath().ToAscii();
const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(fileDialog->GetPath());
currentFile = tmp_buf;
#endif
//printf("#1 file load [%s]\n",currentFile.c_str());
program->loadMap(currentFile);
fileName = cutLastExt(extractFileFromDirectoryPath(currentFile.c_str()));
setDirty(false);
setExtension();
SetTitle(ToUnicode(winHeader + "; " + currentFile));
}
}
catch (const string &e) {
MsgDialog(this, ToUnicode(e), wxT("Exception"), wxOK | wxICON_ERROR).ShowModal();
}
catch (const exception &e) {
MsgDialog(this, ToUnicode(e.what()), wxT("Exception"), wxOK | wxICON_ERROR).ShowModal();
}
}
void MainWindow::onMenuFileSave(wxCommandEvent &event) {
if(program == NULL) {
return;
}
if (currentFile.empty()) {
wxCommandEvent ev;
onMenuFileSaveAs(ev);
}
else {
setExtension();
//printf("#1 save load [%s]\n",currentFile.c_str());
program->saveMap(currentFile);
setDirty(false);
}
}
void MainWindow::onMenuFileSaveAs(wxCommandEvent &event) {
if(program == NULL) {
return;
}
#if wxCHECK_VERSION(2, 9, 1)
wxFileDialog fd(this, wxT("Select file"), wxT(""), wxT(""), wxT("*.mgm|*.gbm"), wxFD_SAVE);
#else
wxFileDialog fd(this, wxT("Select file"), wxT(""), wxT(""), wxT("*.mgm|*.gbm"), wxSAVE);
#endif
if(fileDialog->GetPath() != ToUnicode("")) {
fd.SetPath(fileDialog->GetPath());
}
else {
Config &config = Config::getInstance();
string userData = config.getString("UserData_Root","");
if(userData != "") {
endPathWithSlash(userData);
}
string defaultPath = userData + "maps/";
fd.SetDirectory(ToUnicode(defaultPath));
}
fd.SetWildcard(wxT("MegaGlest Map (*.mgm)|*.mgm|Glest Map (*.gbm)|*.gbm"));
if (fd.ShowModal() == wxID_OK) {
#ifdef WIN32
const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(wxFNCONV(fd.GetPath()));
currentFile = tmp_buf;
auto_ptr<wchar_t> wstr(Ansi2WideString(currentFile.c_str()));
currentFile = utf8_encode(wstr.get());
#else
//currentFile = fd.GetPath().ToAscii();
const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(fd.GetPath());
currentFile = tmp_buf;
#endif
fileDialog->SetPath(fd.GetPath());
setExtension();
//printf("#2 file save [%s]\n",currentFile.c_str());
program->saveMap(currentFile);
fileName = cutLastExt(extractFileFromDirectoryPath(currentFile.c_str()));
setDirty(false);
}
SetTitle(ToUnicode(winHeader + "; " + currentFile));
}
void MainWindow::onMenuFileExit(wxCommandEvent &event) {
Close();
}
void MainWindow::onMenuEditUndo(wxCommandEvent &event) {
if(program == NULL) {
return;
}
// std::cout << "Undo Pressed" << std::endl;
if (program->undo()) {
wxPaintEvent e;
onPaint(e);
setDirty();
}
}
void MainWindow::onMenuEditRedo(wxCommandEvent &event) {
if(program == NULL) {
return;
}
if (program->redo()) {
wxPaintEvent e;
onPaint(e);
setDirty();
}
}
void MainWindow::onMenuEditReset(wxCommandEvent &event) {
if(program == NULL) {
return;
}
program->setUndoPoint(ctAll);
SimpleDialog simpleDialog;
simpleDialog.addValue("Width", "128","(must be 16,32,64,128,256,512...)"); // must be an exponent of two
simpleDialog.addValue("Height", "128","(must be 16,32,64,128,256,512...)");
simpleDialog.addValue("Surface", "1","(Default surface material)");
simpleDialog.addValue("Altitude", "10","(Default surface height)");
simpleDialog.addValue("Number of players", "8");
if (!simpleDialog.show()) return;
try {
program->reset(
strToInt(simpleDialog.getValue("Width")),
strToInt(simpleDialog.getValue("Height")),
strToInt(simpleDialog.getValue("Altitude")),
strToInt(simpleDialog.getValue("Surface")));
program->resetFactions(strToInt(simpleDialog.getValue("Number of players")));
}
catch (const exception &e) {
MsgDialog(this, ToUnicode(e.what()), wxT("Exception"), wxOK | wxICON_ERROR).ShowModal();
}
currentFile = "";
fileName = "New (unsaved) map";
wxPaintEvent ev;
onPaint(ev);
}
void MainWindow::onMenuEditResetPlayers(wxCommandEvent &event) {
if(program == NULL) {
return;
}
SimpleDialog simpleDialog;
simpleDialog.addValue("Number of players", intToStr(program->getMap()->getMaxFactions()));
if (!simpleDialog.show("Reset players")) return;
try {
program->resetFactions(strToInt(simpleDialog.getValue("Number of players")));
}
catch (const exception &e) {
MsgDialog(this, ToUnicode(e.what()), wxT("Exception"), wxOK | wxICON_ERROR).ShowModal();
}
setDirty();
setExtension();
}
void MainWindow::onMenuEditFlipDiagonal(wxCommandEvent &event) {
if(program == NULL) {
return;
}
program->setUndoPoint(ctAll);
program->flipDiagonal();
setDirty();
}
void MainWindow::onMenuEditResize(wxCommandEvent &event) {
if(program == NULL) {
return;
}
SimpleDialog simpleDialog;
simpleDialog.addValue("Width", intToStr(program->getMap()->getW()),"(must be 16,32,64,128,256,512...)");
simpleDialog.addValue("Height", intToStr(program->getMap()->getH()),"(must be 16,32,64,128,256,512...)");
simpleDialog.addValue("Surface", "1","(surface material for new area around map)");
simpleDialog.addValue("Altitude", "10","(surface height for new area around map)");
if (!simpleDialog.show("Resize - expand around, shrink to topleft")) return;
try {
program->resize(
strToInt(simpleDialog.getValue("Width")),
strToInt(simpleDialog.getValue("Height")),
strToInt(simpleDialog.getValue("Altitude")),
strToInt(simpleDialog.getValue("Surface")));
}
catch (const exception &e) {
MsgDialog(this, ToUnicode(e.what()), wxT("Exception"), wxOK | wxICON_ERROR).ShowModal();
}
setDirty();
}
void MainWindow::onMenuEditFlipX(wxCommandEvent &event) {
if(program == NULL) {
return;
}
program->setUndoPoint(ctAll);
program->flipX();
setDirty();
}
void MainWindow::onMenuEditFlipY(wxCommandEvent &event) {
if(program == NULL) {
return;
}
program->setUndoPoint(ctAll);
program->flipY();
setDirty();
}
void MainWindow::onMenuEditMirrorX(wxCommandEvent &event) { // copy left to right
if(program == NULL) {
return;
}
program->setUndoPoint(ctAll);
program->mirrorX();
setDirty();
}
void MainWindow::onMenuEditMirrorY(wxCommandEvent &event) { // copy top to bottom
if(program == NULL) {
return;
}
program->setUndoPoint(ctAll);
program->mirrorY();
setDirty();
}
void MainWindow::onMenuEditMirrorXY(wxCommandEvent &event) { // copy bottomleft tp topright
if(program == NULL) {
return;
}
program->setUndoPoint(ctAll);
program->mirrorXY();
setDirty();
}
void MainWindow::onMenuEditRotatecopyX(wxCommandEvent &event) { // copy left to right, rotated
if(program == NULL) {
return;
}
program->setUndoPoint(ctAll);
program->rotatecopyX();
setDirty();
}
void MainWindow::onMenuEditRotatecopyY(wxCommandEvent &event) { // copy top to bottom, rotated
if(program == NULL) {
return;
}
program->setUndoPoint(ctAll);
program->rotatecopyY();
setDirty();
}
void MainWindow::onMenuEditRotatecopyXY(wxCommandEvent &event) { // copy bottomleft to topright, rotated
if(program == NULL) {
return;
}
program->setUndoPoint(ctAll);
program->rotatecopyXY();
setDirty();
}
void MainWindow::onMenuEditRotatecopyCorner(wxCommandEvent &event) { // copy top left 1/4 to top right 1/4, rotated
if(program == NULL) {
return;
}
program->setUndoPoint(ctAll);
program->rotatecopyCorner();
setDirty();
}
void MainWindow::onMenuEditRandomizeHeights(wxCommandEvent &event) {
if(program == NULL) {
return;
}
while(true){
SimpleDialog simpleDialog;
simpleDialog.addValue("Initial Reset", boolToStr(randomWithReset),"(1 = true, 0 = false) If set to '0' no height reset is done before calculating");
simpleDialog.addValue("Min Height", intToStr(randomMinimumHeight),"Lowest random height. example: -300 or below if you want water , 0 if you don't want water.");
simpleDialog.addValue("Max Height", intToStr(randomMaximumHeight),"Max random height. A good value is 400");
simpleDialog.addValue("Chance Divider", intToStr(randomChanceDivider),"Defines how often you get a hill or hole default is 30. Bigger number, less hills/holes.");
simpleDialog.addValue("Smooth Recursions", intToStr(randomRecursions),"Number of recursions cycles to smooth the hills and holes. 0<x<50 default is 3.");
if (!simpleDialog.show("Randomize Height")) return;
try {
string checkValue = simpleDialog.getValue("Initial Reset");
if(checkValue != "" && strToInt(checkValue) > 1) {
randomWithReset = true;
}
else {
randomWithReset = strToBool(simpleDialog.getValue("Initial Reset"));
}
randomMinimumHeight=strToInt(simpleDialog.getValue("Min Height"));
randomMaximumHeight=strToInt(simpleDialog.getValue("Max Height"));
randomChanceDivider=strToInt(simpleDialog.getValue("Chance Divider"));
randomRecursions=strToInt(simpleDialog.getValue("Smooth Recursions"));
// set insane inputs to something that does not crash
if(randomMinimumHeight>=randomMaximumHeight) randomMinimumHeight=randomMaximumHeight-1;
if(randomChanceDivider<1) randomChanceDivider=1;
// set randomRecursions to something useful
if(randomRecursions<0) randomRecursions=0;
if(randomRecursions>50) randomRecursions=50;
program->setUndoPoint(ctAll);
program->randomizeMapHeights(randomWithReset, randomMinimumHeight, randomMaximumHeight,
randomChanceDivider, randomRecursions);
}
catch (const exception &e) {
MsgDialog(this, ToUnicode(e.what()), wxT("Exception"), wxOK | wxICON_ERROR).ShowModal();
}
setDirty();
}
}
void MainWindow::onMenuEditRandomize(wxCommandEvent &event) {
if(program == NULL) {
return;
}
program->setUndoPoint(ctAll);
program->randomizeFactions();
setDirty();
}
void MainWindow::onMenuEditSwitchSurfaces(wxCommandEvent &event) {
if(program == NULL) {
return;
}
SimpleDialog simpleDialog;
simpleDialog.addValue("Surface1", "1","replace this surface with...");
simpleDialog.addValue("Surface2", "2","...this and vice versa");
if (!simpleDialog.show("Switch surfaces")) return;
try {
program->setUndoPoint(ctSurface);
program->switchMapSurfaces(
strToInt(simpleDialog.getValue("Surface1")),
strToInt(simpleDialog.getValue("Surface2")));
}
catch (const exception &e) {
MsgDialog(this, ToUnicode(e.what()), wxT("Exception"), wxOK | wxICON_ERROR).ShowModal();
}
setDirty();
}
void MainWindow::onMenuEditInfo(wxCommandEvent &event) {
if(program == NULL) {
return;
}
SimpleDialog simpleDialog;
simpleDialog.addValue("Title", program->getMap()->getTitle());
simpleDialog.addValue("Description", program->getMap()->getDesc());
simpleDialog.addValue("Author", program->getMap()->getAuthor());
if (!simpleDialog.show("Info",true)) return;
bool ischanged = program->setMapTitle(simpleDialog.getValue("Title"));
ischanged = (program->setMapDesc(simpleDialog.getValue("Description")) || ischanged);
ischanged = (program->setMapAuthor(simpleDialog.getValue("Author")) || ischanged);
if (ischanged)
if (!isDirty()) {
setDirty(true);
}
}
void MainWindow::onMenuEditAdvanced(wxCommandEvent &event) {
if(program == NULL) {
return;
}
SimpleDialog simpleDialog;
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.");
simpleDialog.addValue("Water Level", intToStr(program->getMap()->getWaterLevel()),"water is visible below this, and walkable until 1.5 less");
simpleDialog.addValue("Cliff Level", intToStr(program->getMap()->getCliffLevel()),"neighboring fields with at least this heights difference are cliffs");
simpleDialog.addValue("Camera Height", intToStr(program->getMap()->getCameraHeight()),"you can give a camera height here default is 0 ;ignored if <20");
if (!simpleDialog.show("Advanced")) return;
try {
program->setMapAdvanced(
strToInt(simpleDialog.getValue("Height Factor")),
strToInt(simpleDialog.getValue("Water Level")),
strToInt(simpleDialog.getValue("Cliff Level")),
strToInt(simpleDialog.getValue("Camera Height")));
}
catch (const exception &e) {
MsgDialog(this, ToUnicode(e.what()), wxT("Exception"), wxOK | wxICON_ERROR).ShowModal();
}
setDirty();
}
void MainWindow::onMenuViewResetZoomAndPos(wxCommandEvent &event) {
if(program == NULL) {
return;
}
program->resetOfset();
wxPaintEvent e;
onPaint(e);
}
void MainWindow::onMenuViewGrid(wxCommandEvent &event) {
if(program == NULL) {
return;
}
menuView->Check(miViewGrid, program->setGridOnOff()); // miViewGrid event.GetId()
wxPaintEvent e;
onPaint(e);
}
void MainWindow::onMenuViewHeightMap(wxCommandEvent &event) {
if(program == NULL) {
return;
}
menuView->Check(miViewHeightMap, program->setHeightMapOnOff()); // miViewGrid event.GetId()
wxPaintEvent e;
onPaint(e);
}
void MainWindow::onMenuHideWater(wxCommandEvent &event) {
if(program == NULL) {
return;
}
menuView->Check(miHideWater, program->setHideWaterOnOff()); // miViewGrid event.GetId()
wxPaintEvent e;
onPaint(e);
}
void MainWindow::onMenuViewAbout(wxCommandEvent &event) {
MsgDialog(
this,
wxT("\n Glest Map Editor\n Copyright 2004-2010 The Glest Team\n Copyright 2010-2017 The MegaGlest Team \n"),
wxT("About")).ShowModal();
}
void MainWindow::onMenuViewHelp(wxCommandEvent &event) {
MsgDialog(this,
wxT("Draw with left mouse\nMove viewport with right mouse drag\nZoom with center mouse drag, or mousewheel\n\n\
You can change brush in the same category with key 1-9\n\
and change category with their first letter (keys S, R, O, G, H)\n\
Press Space to set brush to the resource or object under the mouse cursor\n\
To center things in the map shift it with Shift-Up/Down/Left/Right keys\n\
Height tool (blue) builds with integer height steps 0-20, \nwhile Gradient tool (red) uses any real number \n\
Units can go over water as long as it is less than 1.5 deep\n\n\
A good idea is to put some stone, gold and tree near starting position\n\
Starting position needs an open area for the tower and the starting units\n"),
wxT("Help")).ShowModal();
/* 5 away and 10x10 empty area? */
}
void MainWindow::onMenuBrushHeight(wxCommandEvent &e) {
uncheckBrush();
menuBrushHeight->Check(e.GetId(), true);
height = e.GetId() - miBrushHeight - heightCount / 2 - 1;
enabledGroup = ctHeight;
currentBrush = btHeight;
SetStatusText(wxT("Brush: Height"), siBRUSH_TYPE);
SetStatusText(wxT("Value: ") + ToUnicode(intToStr(height)), siBRUSH_VALUE);
}
void MainWindow::onMenuBrushGradient(wxCommandEvent &e) {
uncheckBrush();
menuBrushGradient->Check(e.GetId(), true);
height = e.GetId() - miBrushGradient - heightCount / 2 - 1;
enabledGroup = ctGradient;
currentBrush = btGradient;
SetStatusText(wxT("Brush: Gradient"), siBRUSH_TYPE);
SetStatusText(wxT("Value: ") + ToUnicode(intToStr(height)), siBRUSH_VALUE);
}
void MainWindow::onMenuBrushSurface(wxCommandEvent &e) {
uncheckBrush();
menuBrushSurface->Check(e.GetId(), true);
surface = e.GetId() - miBrushSurface;
enabledGroup = ctSurface;
currentBrush = btSurface;
SetStatusText(wxT("Brush: Surface"), siBRUSH_TYPE);
SetStatusText(
wxT("Value: ") + ToUnicode(intToStr(surface)) + wxT(" ")
+ ToUnicode(surface_descs[surface - 1]), siBRUSH_VALUE);
}
void MainWindow::onMenuBrushObject(wxCommandEvent &e) {
uncheckBrush();
menuBrushObject->Check(e.GetId(), true);
object = e.GetId() - miBrushObject - 1;
enabledGroup = ctObject;
currentBrush = btObject;
SetStatusText(wxT("Brush: Object"), siBRUSH_TYPE);
SetStatusText(
wxT("Value: ") + ToUnicode(intToStr(object)) + wxT(" ")
+ ToUnicode(object_descs[object]), siBRUSH_VALUE);
}
void MainWindow::onMenuBrushResource(wxCommandEvent &e) {
uncheckBrush();
menuBrushResource->Check(e.GetId(), true);
resource = e.GetId() - miBrushResource - 1;
enabledGroup = ctResource;
currentBrush = btResource;
SetStatusText(wxT("Brush: Resource"), siBRUSH_TYPE);
SetStatusText(
wxT("Value: ") + ToUnicode(intToStr(resource)) + wxT(" ")
+ ToUnicode(resource_descs[resource]), siBRUSH_VALUE);
}
void MainWindow::onMenuBrushStartLocation(wxCommandEvent &e) {
uncheckBrush();
menuBrushStartLocation->Check(e.GetId(), true);
startLocation = e.GetId() - miBrushStartLocation;
enabledGroup = ctLocation;
currentBrush = btStartLocation;
SetStatusText(wxT("Brush: Start Locations"), siBRUSH_TYPE);
SetStatusText(wxT("Value: ") + ToUnicode(intToStr(startLocation)), siBRUSH_VALUE);
}
void MainWindow::onMenuRadius(wxCommandEvent &e) {
uncheckRadius();
menuRadius->Check(e.GetId(), true);
radius = e.GetId() - miRadius;
SetStatusText(wxT("Radius: ") + ToUnicode(intToStr(radius)), siBRUSH_RADIUS);
}
void MainWindow::change(int x, int y) {
if(program == NULL) {
return;
}
switch (enabledGroup) {
case ctHeight:
program->glestChangeMapHeight(x, y, height, radius);
break;
case ctSurface:
program->changeMapSurface(x, y, surface, radius);
break;
case ctObject:
program->changeMapObject(x, y, object, radius);
break;
case ctResource:
program->changeMapResource(x, y, resource, radius);
break;
case ctLocation:
program->changeStartLocation(x, y, startLocation - 1);
break;
case ctGradient:
program->pirateChangeMapHeight(x, y, height, radius);
break;
}
}
void MainWindow::uncheckBrush() {
for (int i = 0; i < heightCount; ++i) {
menuBrushHeight->Check(miBrushHeight + i + 1, false);
}
for (int i = 0; i < heightCount; ++i) {
menuBrushGradient->Check(miBrushGradient + i + 1, false);
}
for (int i = 0; i < surfaceCount; ++i) {
menuBrushSurface->Check(miBrushSurface + i + 1, false);
}
for (int i = 0; i < objectCount; ++i) {
menuBrushObject->Check(miBrushObject + i + 1, false);
}
for (int i = 0; i < resourceCount; ++i) {
menuBrushResource->Check(miBrushResource + i + 1, false);
}
for (int i = 0; i < startLocationCount; ++i) {
menuBrushStartLocation->Check(miBrushStartLocation + i + 1, false);
}
}
void MainWindow::uncheckRadius() {
for (int i = 1; i <= radiusCount; ++i) {
menuRadius->Check(miRadius + i, false);
}
}
void MainWindow::onKeyDown(wxKeyEvent &e) {
if(program == NULL) {
return;
}
if(e.GetModifiers() == wxMOD_CONTROL || e.GetModifiers() == wxMOD_ALT){
e.Skip();
}
// WARNING: don't add any Ctrl or ALt key shortcuts below those are reserved for internal menu use.
if (currentBrush == btSurface) { // surface texture
if (e.GetKeyCode() >= '1' && e.GetKeyCode() <= '5') {
surface = e.GetKeyCode() - 48; // '1'-'5' == 1-5
wxCommandEvent evt(wxEVT_NULL, miBrushSurface + surface);
onMenuBrushSurface(evt);
return;
}
}
if (currentBrush == btObject) {
bool valid = true;
if (e.GetKeyCode() >= '1' && e.GetKeyCode() <= '9') {
object = e.GetKeyCode() - 48; // '1'-'9' == 1-9
} else if (e.GetKeyCode() == '0') { // '0' == 10
object = 10;
} else if (e.GetKeyCode() == '-') { // '-' == 0
object = 0;
} else {
valid = false;
}
if (valid) {
wxCommandEvent evt(wxEVT_NULL, miBrushObject + object + 1);
onMenuBrushObject(evt);
return;
}
}
if (currentBrush == btResource) {
if (e.GetKeyCode() >= '0' && e.GetKeyCode() <= '5') {
resource = e.GetKeyCode() - 48; // '0'-'5' == 0-5
wxCommandEvent evt(wxEVT_NULL, miBrushResource + resource + 1);
onMenuBrushResource(evt);
return;
}
}
if (currentBrush == btStartLocation) {
if (e.GetKeyCode() >= '1' && e.GetKeyCode() <= '8') {
startLocation = e.GetKeyCode() - 48; // '1'-'8' == 0-7
wxCommandEvent evt(wxEVT_NULL, miBrushStartLocation + startLocation);
onMenuBrushStartLocation(evt);
return;
}
}
if (e.GetKeyCode() == 'H') {
wxCommandEvent evt(wxEVT_NULL, miBrushHeight + height + heightCount / 2 + 1);
onMenuBrushHeight(evt);
} else if (e.GetKeyCode() == ' ') {
if (resourceUnderMouse != 0) {
wxCommandEvent evt(wxEVT_NULL, miBrushResource + resourceUnderMouse + 1);
onMenuBrushResource(evt);
} else {
wxCommandEvent evt(wxEVT_NULL, miBrushObject + objectUnderMouse + 1);
onMenuBrushObject(evt);
}
} else if (e.GetKeyCode() == 'G') {
wxCommandEvent evt(wxEVT_NULL, miBrushGradient + height + heightCount / 2 + 1);
onMenuBrushGradient(evt);
} else if (e.GetKeyCode() == 'S') {
wxCommandEvent evt(wxEVT_NULL, miBrushSurface + surface);
onMenuBrushSurface(evt);
} else if (e.GetKeyCode() == 'O') {
wxCommandEvent evt(wxEVT_NULL, miBrushObject + object + 1);
onMenuBrushObject(evt);
} else if (e.GetKeyCode() == 'R') {
wxCommandEvent evt(wxEVT_NULL, miBrushResource + resource + 1);
onMenuBrushResource(evt);
} else if (e.GetKeyCode() == 'L') {
wxCommandEvent evt(wxEVT_NULL, miBrushStartLocation + startLocation + 1);
onMenuBrushStartLocation(evt);
} else if (e.GetKeyCode() == WXK_LEFT && e.GetModifiers() == wxMOD_SHIFT) { // shift-left/right/up/down to shift the map one square
program->setUndoPoint(ctAll);
program->shiftLeft();
setDirty();
} else if (e.GetKeyCode() == WXK_RIGHT && e.GetModifiers() == wxMOD_SHIFT) {
program->setUndoPoint(ctAll);
program->shiftRight();
setDirty();
} else if (e.GetKeyCode() == WXK_UP && e.GetModifiers() == wxMOD_SHIFT) {
program->setUndoPoint(ctAll);
program->shiftUp();
setDirty();
} else if (e.GetKeyCode() == WXK_DOWN && e.GetModifiers() == wxMOD_SHIFT) {
program->setUndoPoint(ctAll);
program->shiftDown();
setDirty();
} else {
e.Skip();
}
}
BEGIN_EVENT_TABLE(MainWindow, wxFrame)
EVT_CLOSE(MainWindow::onClose)
// these are 'handled' by GlCanvas and funneled to these handlers. See BEGIN_EVENT_TABLE(GlCanvas, wxGLCanvas) below.
//EVT_LEFT_DOWN(MainWindow::onMouseDown)
//EVT_MOTION(MainWindow::onMouseMove)
//EVT_KEY_DOWN(MainWindow::onKeyDown)
EVT_MENU(wxID_NEW, MainWindow::onMenuEditReset)
EVT_MENU(wxID_OPEN, MainWindow::onMenuFileLoad)
EVT_MENU(wxID_SAVE, MainWindow::onMenuFileSave)
EVT_MENU(wxID_SAVEAS, MainWindow::onMenuFileSaveAs)
EVT_MENU(wxID_EXIT, MainWindow::onMenuFileExit)
EVT_MENU(miEditUndo, MainWindow::onMenuEditUndo)
EVT_MENU(miEditRedo, MainWindow::onMenuEditRedo)
EVT_MENU(miEditResetPlayers, MainWindow::onMenuEditResetPlayers)
EVT_MENU(miEditResize, MainWindow::onMenuEditResize)
EVT_MENU(miEditFlipDiagonal, MainWindow::onMenuEditFlipDiagonal)
EVT_MENU(miEditFlipX, MainWindow::onMenuEditFlipX)
EVT_MENU(miEditFlipY, MainWindow::onMenuEditFlipY)
EVT_MENU(miEditMirrorX, MainWindow::onMenuEditMirrorX)
EVT_MENU(miEditMirrorY, MainWindow::onMenuEditMirrorY)
EVT_MENU(miEditMirrorXY, MainWindow::onMenuEditMirrorXY)
EVT_MENU(miEditRotatecopyX, MainWindow::onMenuEditRotatecopyX)
EVT_MENU(miEditRotatecopyY, MainWindow::onMenuEditRotatecopyY)
EVT_MENU(miEditRotatecopyXY, MainWindow::onMenuEditRotatecopyXY)
EVT_MENU(miEditRotatecopyCorner, MainWindow::onMenuEditRotatecopyCorner)
EVT_MENU(miEditRandomizeHeights, MainWindow::onMenuEditRandomizeHeights)
EVT_MENU(miEditRandomize, MainWindow::onMenuEditRandomize)
EVT_MENU(miEditSwitchSurfaces, MainWindow::onMenuEditSwitchSurfaces)
EVT_MENU(miEditInfo, MainWindow::onMenuEditInfo)
EVT_MENU(miEditAdvanced, MainWindow::onMenuEditAdvanced)
EVT_MENU(miViewResetZoomAndPos, MainWindow::onMenuViewResetZoomAndPos)
EVT_MENU(miViewGrid, MainWindow::onMenuViewGrid)
EVT_MENU(miViewHeightMap, MainWindow::onMenuViewHeightMap)
EVT_MENU(miHideWater, MainWindow::onMenuHideWater)
EVT_MENU(miViewAbout, MainWindow::onMenuViewAbout)
EVT_MENU(miViewHelp, MainWindow::onMenuViewHelp)
EVT_MENU_RANGE(miBrushHeight + 1, miBrushHeight + heightCount, MainWindow::onMenuBrushHeight)
EVT_MENU_RANGE(miBrushGradient + 1, miBrushGradient + heightCount, MainWindow::onMenuBrushGradient)
EVT_MENU_RANGE(miBrushSurface + 1, miBrushSurface + surfaceCount, MainWindow::onMenuBrushSurface)
EVT_MENU_RANGE(miBrushObject + 1, miBrushObject + objectCount, MainWindow::onMenuBrushObject)
EVT_MENU_RANGE(miBrushResource + 1, miBrushResource + resourceCount, MainWindow::onMenuBrushResource)
EVT_MENU_RANGE(miBrushStartLocation + 1, miBrushStartLocation + startLocationCount, MainWindow::onMenuBrushStartLocation)
EVT_MENU_RANGE(miRadius, miRadius + radiusCount, MainWindow::onMenuRadius)
EVT_PAINT(MainWindow::onPaint)
EVT_TOOL(toolPlayer, MainWindow::onToolPlayer)
END_EVENT_TABLE()
// =====================================================
// class GlCanvas
// =====================================================
GlCanvas::GlCanvas(MainWindow *mainWindow, wxWindow *parent, int *args)
#if wxCHECK_VERSION(2, 9, 1)
: wxGLCanvas(parent, -1, args, wxDefaultPosition, wxDefaultSize, 0, wxT("GLCanvas")) {
this->context = new wxGLContext(this);
#else
: wxGLCanvas(parent, -1, wxDefaultPosition, wxDefaultSize, 0, wxT("GLCanvas"), args) {
this->context = NULL;
#endif
this->mainWindow = mainWindow;
}
GlCanvas::~GlCanvas() {
delete this->context;
this->context = NULL;
}
void GlCanvas::setCurrentGLContext() {
#ifndef __APPLE__
#if wxCHECK_VERSION(2, 9, 1)
if(this->context == NULL) {
this->context = new wxGLContext(this);
}
#endif
if(this->context) {
this->SetCurrent(*this->context);
}
#else
this->SetCurrent();
#endif
}
void translateCoords(wxWindow *wnd, int &x, int &y) {
/*
#ifdef WIN32
int cx, cy;
wnd->GetPosition(&cx, &cy);
x += cx;
y += cy;
#endif
*/
}
// for the mousewheel
void GlCanvas::onMouseWheel(wxMouseEvent &event) {
if(event.GetWheelRotation()>0) mainWindow->onMouseWheelDown(event);
else mainWindow->onMouseWheelUp(event);
}
void GlCanvas::onMouseDown(wxMouseEvent &event) {
int x, y;
event.GetPosition(&x, &y);
translateCoords(this, x, y);
mainWindow->onMouseDown(event, x, y);
}
void GlCanvas::onMouseMove(wxMouseEvent &event) {
int x, y;
event.GetPosition(&x, &y);
translateCoords(this, x, y);
mainWindow->onMouseMove(event, x, y);
}
void GlCanvas::onKeyDown(wxKeyEvent &event) {
int x, y;
event.GetPosition(&x, &y);
translateCoords(this, x, y);
mainWindow->onKeyDown(event);
}
void GlCanvas::onPaint(wxPaintEvent &event) {
// wxPaintDC dc(this); //N "In a paint event handler must always create a wxPaintDC object even if you do not use it. (?)
// mainWindow->program->renderMap(GetClientSize().x, GetClientSize().y);
// SwapBuffers();
// event.Skip();
//printf("gl onPaint skip map\n");
mainWindow->onPaint(event);
}
BEGIN_EVENT_TABLE(GlCanvas, wxGLCanvas)
EVT_KEY_DOWN(GlCanvas::onKeyDown)
EVT_MOUSEWHEEL(GlCanvas::onMouseWheel)
EVT_LEFT_DOWN(GlCanvas::onMouseDown)
EVT_MOTION(GlCanvas::onMouseMove)
EVT_PAINT(GlCanvas::onPaint) // Because the drawing area needs to be repainted too.
END_EVENT_TABLE()
// ===============================================
// class SimpleDialog
// ===============================================
void SimpleDialog::addValue(const string &key, const string &value, const string &help) {
values.push_back(pair<string, string>(key, value+"|"+help)); // I guess I need map<,> instead but I don't know how to do it
}
string SimpleDialog::getValue(const string &key) {
for (unsigned int i = 0; i < values.size(); ++i) {
if (values[i].first == key) {
return values[i].second;
}
}
return "";
}
bool SimpleDialog::show(const string &title, bool wide) {
Create(NULL, -1, ToUnicode(title));
wxSizer *sizer2 = new wxBoxSizer(wxVERTICAL);
wxSizer *sizer = new wxFlexGridSizer(3);
vector<wxTextCtrl*> texts;
for (Values::iterator it = values.begin(); it != values.end(); ++it) {
size_t helptextpos = it->second.find_first_of('|');
sizer->Add(new wxStaticText(this, -1, ToUnicode(it->first)), 0, wxALL, 5);
wxTextCtrl *text = new wxTextCtrl(this, -1, ToUnicode(it->second.substr(0,helptextpos)));
if(wide) text->SetMinSize( wxSize((text->GetSize().GetWidth())*4, text->GetSize().GetHeight())); // 4 time as wide as default
sizer->Add(text, 0, wxALL, 5);
texts.push_back(text);
sizer->Add(new wxStaticText(this, -1, ToUnicode(it->second.substr(helptextpos+1))), 0, wxALL, 5);
}
sizer2->Add(sizer);
sizer2->Add(CreateButtonSizer(wxOK|wxCANCEL),0,wxALIGN_RIGHT); // enable Cancel button
SetSizerAndFit(sizer2);
ShowModal();
if(m_returnCode==wxID_CANCEL) return false; // don't change values if canceled
for (unsigned int i = 0; i < texts.size(); ++i) {
#ifdef WIN32
const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(wxFNCONV(texts[i]->GetValue()));
values[i].second = tmp_buf;
#else
values[i].second = texts[i]->GetValue().ToAscii();
#endif
}
return true;
}
// ===============================================
// class App
// ===============================================
bool App::OnInit() {
SystemFlags::VERBOSE_MODE_ENABLED = false;
SystemFlags::ENABLE_THREADED_LOGGING = false;
string fileparam;
if(argc==2){
if(argv[1][0]=='-') { // any flag gives help and exits program.
std::cout << "MegaGlest map editor " << mapeditorVersionString << " [Using " << (const char *)wxConvCurrent->cWX2MB(wxVERSION_STRING) << "]" << std::endl << std::endl;
std::cout << "glest_map_editor [MGM FILE]" << std::endl << std::endl;
std::cout << "Creates or edits glest/megaglest maps." << std::endl;
std::cout << "Draw with left mouse button" << std::endl;
std::cout << "Move map with right mouse button" << std::endl;
std::cout << "Zoom with middle mouse button or mousewheel" << std::endl;
// std::cout << " ~ more helps should be written here ~" << std::endl;
std::cout << std::endl;
exit (0);
}
//#if defined(__MINGW32__)
const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(argv[1]);
fileparam = tmp_buf;
#ifdef WIN32
auto_ptr<wchar_t> wstr(Ansi2WideString(fileparam.c_str()));
fileparam = utf8_encode(wstr.get());
#endif
//#else
// fileparam = wxFNCONV(argv[1]);
//#endif
}
#if defined(wxMAJOR_VERSION) && defined(wxMINOR_VERSION) && defined(wxRELEASE_NUMBER) && defined(wxSUBRELEASE_NUMBER)
printf("Using wxWidgets version [%d.%d.%d.%d]\n",wxMAJOR_VERSION,wxMINOR_VERSION,wxRELEASE_NUMBER,wxSUBRELEASE_NUMBER);
#endif
wxString exe_path = wxStandardPaths::Get().GetExecutablePath();
//wxString path_separator = wxFileName::GetPathSeparator();
//exe_path = exe_path.BeforeLast(path_separator[0]);
//exe_path += path_separator;
string appPath;
//#if defined(__MINGW32__)
#ifdef WIN32
const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(wxFNCONV(exe_path));
appPath = tmp_buf;
auto_ptr<wchar_t> wstr(Ansi2WideString(appPath.c_str()));
appPath = utf8_encode(wstr.get());
#else
appPath = wxFNCONV(exe_path);
#endif
//#else
// const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(wxFNCONV(exe_path));
// appPath = tmp_buf;
//#endif
mainWindow = new MainWindow(appPath);
mainWindow->Show();
mainWindow->init(fileparam);
mainWindow->Update();
#ifdef WIN32
wxPoint pos = mainWindow->GetScreenPosition();
wxSize size = mainWindow->GetSize();
mainWindow->SetSize(pos.x, pos.y, 1, 1, wxSIZE_FORCE);
//mainWindow->Update();
mainWindow->SetSize(pos.x, pos.y, size.x-1, size.y, wxSIZE_FORCE);
mainWindow->Update();
#endif
return true;
}
int App::MainLoop() {
try {
//throw megaglest_runtime_error("test");
return wxApp::MainLoop();
}
catch (const exception &e) {
MsgDialog(NULL, ToUnicode(e.what()), wxT("Exception")).ShowModal();
}
return 0;
}
int App::OnExit() {
SystemFlags::Close();
SystemFlags::SHUTDOWN_PROGRAM_MODE=true;
return 0;
}
MsgDialog::MsgDialog(wxWindow *parent,
const wxString& message,
const wxString& caption,
long style,
const wxPoint& pos) {
m_sizerText = NULL;
if ( !wxDialog::Create(parent, wxID_ANY, caption,
pos, wxDefaultSize,
style) ) {
return;
}
m_sizerText = new wxBoxSizer(wxVERTICAL);
wxStaticText *label = new wxStaticText(this, wxID_ANY, message);
wxFont font(*wxNORMAL_FONT);
font.SetPointSize(font.GetPointSize());
font.SetWeight(wxFONTWEIGHT_NORMAL);
label->SetFont(font);
m_sizerText->Add(label, wxSizerFlags().Centre().Border());
wxSizer *sizerIconAndText = new wxBoxSizer(wxHORIZONTAL);
sizerIconAndText->Add(m_sizerText, wxSizerFlags(1).Expand());
wxSizer *sizerTop = new wxBoxSizer(wxVERTICAL);
sizerTop->Add(sizerIconAndText, wxSizerFlags(1).Expand().Border());
wxSizer *sizerBtns = CreateButtonSizer(wxOK);
if ( sizerBtns )
{
sizerTop->Add(sizerBtns, wxSizerFlags().Expand().Border());
}
SetSizerAndFit(sizerTop);
CentreOnScreen();
}
MsgDialog::~MsgDialog() {
}
}// end namespace
IMPLEMENT_APP(MapEditor::App)