root/cafu/trunk/CaWE/ChildFrame.cpp

Revision 493, 61.7 KB (checked in by Carsten, 2 months ago)

CaWE:

  • Added support for opening files from the command line.
  • Improved auto-detection of related game config when opening files.
  • Menu item File, Configure CaWE... used to use C as the accelerator key, which was also used with Close. Removed the ambiguity by changing the accelerator key to i.
Line 
1/*
2=================================================================================
3This file is part of Cafu, the open-source game engine and graphics engine
4for multiplayer, cross-platform, real-time 3D action.
5Copyright (C) 2002-2012 Carsten Fuchs Software.
6
7Cafu is free software: you can redistribute it and/or modify it under the terms
8of the GNU General Public License as published by the Free Software Foundation,
9either version 3 of the License, or (at your option) any later version.
10
11Cafu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13PURPOSE. See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with Cafu. If not, see <http://www.gnu.org/licenses/>.
17
18For support and more information about Cafu, visit us at <http://www.cafu.de>.
19=================================================================================
20*/
21
22#include "ChildFrame.hpp"
23#include "ChildFrameViewWin2D.hpp"
24#include "ChildFrameViewWin3D.hpp"
25#include "Camera.hpp"
26#include "DialogConsole.hpp"
27#include "DialogCustomCompile.hpp"
28#include "DialogEditSurfaceProps.hpp"
29#include "DialogInspector.hpp"
30#include "DialogTerrainEdit.hpp"
31#include "GameConfig.hpp"
32#include "MapDocument.hpp"
33#include "Options.hpp"
34#include "ParentFrame.hpp"
35#include "Tool.hpp"
36#include "ToolbarMaterials.hpp"
37#include "ToolbarGroups.hpp"
38#include "ToolCamera.hpp"
39#include "ToolTerrainEdit.hpp"
40#include "ToolManager.hpp"
41
42#include "wx/wx.h"
43#include "wx/artprov.h"
44#include "wx/aui/auibar.h"
45#include "wx/confbase.h"
46#include "wx/filename.h"
47#include "wx/process.h"
48#include "wx/stdpaths.h"
49
50
51#ifdef __WXMSW__
52static const wxString CompileScriptName="tempCompileScriptCaWE.bat";
53#else
54static const wxString CompileScriptName="./tempCompileScriptCaWE.bat";
55#endif
56
57
58// TODO:
59// 1. Rename: Some toolbars are panels now, some dialogs are panels now...
60// 2. Menu icons...
61// 3. Update the pane captions properly, e.g. "2D view, top (XY), zoom: ...".
62// 4. properly load/save the perspectives, i.e. with the list of open 2D and 3D views.
63// 5. Toolbar toggles for: Texture locking und Options.general.NewUVsFaceAligned.
64
65
66AutoSaveTimerT::AutoSaveTimerT(MapDocumentT* Doc, unsigned long ChildFrameNr)
67    : m_Doc(Doc),
68      m_AutoSaveName(wxStandardPaths::Get().GetUserDataDir()+"/"+wxString::Format("autosave%lu.cmap", ChildFrameNr))
69{
70}
71
72
73void AutoSaveTimerT::Notify()
74{
75    // Auto-save the document under name m_AutoSaveName, overwriting any existing file.
76    if (wxFileExists(m_AutoSaveName)) wxRemoveFile(m_AutoSaveName);
77    m_Doc->OnSaveDocument(m_AutoSaveName, true);
78}
79
80
81AutoSaveTimerT::~AutoSaveTimerT()
82{
83    // Note that the document is already deleted when we get here!
84
85    // On closing the child frame, delete the corresponding auto-saved file,
86    // because the user is assumed to save it himself, as is usual when closing CaWE.
87    // In fact, we only get here after a successful save or if the user explicitly denied the saving a modified file.
88    if (wxFileExists(m_AutoSaveName)) wxRemoveFile(m_AutoSaveName);
89}
90
91
92/// A class that acts as an observer of the map document and the tools for the child frame.
93/// It updates the associated child frames status bar, tool options bar, etc.
94/// Note that the child frame could also derive from the observer classes and thus be the observer itself,
95/// but having the functionality encapsulated in a separate class like this increases clarity.
96class ChildFrameT::UpdaterT : public ObserverT, public ToolsObserverT
97{
98    public:
99
100    UpdaterT(ChildFrameT* ChildFrame);
101    ~UpdaterT();
102
103    // Methods inherited from ObserverT.
104    void NotifySubjectChanged(SubjectT* Subject, MapDocOtherDetailT OtherDetail);
105    void NotifySubjectChanged_Selection(SubjectT* Subject, const ArrayT<MapElementT*>& OldSelection, const ArrayT<MapElementT*>& NewSelection);
106 // void NotifySubjectChanged_Created(const ArrayT<MapElementT*>& MapElements);
107 // void NotifySubjectChanged_Deleted(SubjectT* Subject, const ArrayT<MapElementT*>& MapElements);
108 // void NotifySubjectChanged_Modified(SubjectT* Subject, const ArrayT<MapElementT*>& MapElements, MapElemModDetailE Detail);
109 // void NotifySubjectChanged_Modified(SubjectT* Subject, const ArrayT<MapElementT*>& MapElements, MapElemModDetailE Detail, const ArrayT<BoundingBox3fT>& OldBounds);
110 // void NotifySubjectChanged_Modified(SubjectT* Subject, const ArrayT<MapElementT*>& MapElements, MapElemModDetailE Detail, const wxString& Key);
111    void NotifySubjectDies(SubjectT* dyingSubject) { }  // The subjects always live longer than this updater (in contrast to the view windows etc.).
112
113    // Methods inherited from ToolsObserverT.
114    void NotifySubjectChanged(ToolsSubjectT* Subject, ToolT* Tool, ToolsUpdatePriorityT Priority);
115
116
117    private:
118
119    ChildFrameT* m_ChildFrame;
120    ToolT*       m_PrevTool;
121};
122
123
124ChildFrameT::UpdaterT::UpdaterT(ChildFrameT* ChildFrame)
125    : m_ChildFrame(ChildFrame),
126      m_PrevTool(NULL)
127{
128    m_ChildFrame->m_Doc->RegisterObserver(this);
129    m_ChildFrame->m_ToolManager->RegisterObserver(this);
130
131    // Issue the initial notifications.
132    NotifySubjectChanged(m_ChildFrame->m_Doc, UPDATE_GRID);
133    NotifySubjectChanged_Selection(m_ChildFrame->m_Doc, m_ChildFrame->m_Doc->GetSelection(), m_ChildFrame->m_Doc->GetSelection());
134    NotifySubjectChanged(m_ChildFrame->m_ToolManager, m_ChildFrame->m_ToolManager->GetActiveTool(), UPDATE_NOW);
135}
136
137
138ChildFrameT::UpdaterT::~UpdaterT()
139{
140    m_ChildFrame->m_Doc->UnregisterObserver(this);
141    m_ChildFrame->m_ToolManager->UnregisterObserver(this);
142}
143
144
145void ChildFrameT::UpdaterT::NotifySubjectChanged(SubjectT* Subject, MapDocOtherDetailT OtherDetail)
146{
147    switch (OtherDetail)
148    {
149        case UPDATE_GRID:
150            m_ChildFrame->SetStatusText(wxString::Format(" Snap: %s  Grid: %d ",
151                m_ChildFrame->m_Doc->IsSnapEnabled() ? "On" : "Off", m_ChildFrame->m_Doc->GetGridSpacing()), SBP_GRID_SNAP);
152            break;
153
154        case UPDATE_POINTFILE:
155            break;
156
157        case UPDATE_GLOBALOPTIONS:
158            break;
159    }
160}
161
162
163void ChildFrameT::UpdaterT::NotifySubjectChanged_Selection(SubjectT* Subject, const ArrayT<MapElementT*>& OldSelection, const ArrayT<MapElementT*>& NewSelection)
164{
165    switch (NewSelection.Size())
166    {
167        case 0:
168            m_ChildFrame->SetStatusText(" Nothing is selected.", SBP_SELECTION);
169            break;
170
171        case 1:
172            m_ChildFrame->SetStatusText(wxString(" ")+NewSelection[0]->GetDescription(), SBP_SELECTION);
173            break;
174
175        default:
176            m_ChildFrame->SetStatusText(wxString::Format(" %lu items are selected.", NewSelection.Size()), SBP_SELECTION);
177            break;
178    }
179}
180
181
182void ChildFrameT::UpdaterT::NotifySubjectChanged(ToolsSubjectT* Subject, ToolT* Tool, ToolsUpdatePriorityT Priority)
183{
184    if (Tool->IsActiveTool())
185    {
186        if (Tool!=m_PrevTool)
187        {
188            const ArrayT<ToolT*>& Tools  =m_ChildFrame->m_ToolManager->GetTools();
189            wxWindow*             Toolbar=NULL;
190
191            // Show the options bar of the active tool, hide everything else.
192            for (unsigned long ToolNr=0; ToolNr<Tools.Size(); ToolNr++)
193            {
194                wxWindow* OptionsBar=Tools[ToolNr]->GetOptionsBar();
195
196                if (!OptionsBar) continue;
197
198                OptionsBar->Show(Tools[ToolNr]->IsActiveTool());
199
200                if (!Toolbar) Toolbar=OptionsBar->GetParent();
201            }
202
203            if (Toolbar) Toolbar->Layout();
204            m_PrevTool=Tool;
205        }
206
207        // Update the status bar.
208        Tool->UpdateStatusBar(m_ChildFrame);
209    }
210}
211
212
213BEGIN_EVENT_TABLE(ChildFrameT, wxMDIChildFrame)
214    EVT_CLOSE(ChildFrameT::OnClose)
215    EVT_IDLE(ChildFrameT::OnIdle)
216    EVT_END_PROCESS(wxID_ANY, ChildFrameT::OnProcessEnd)
217
218    EVT_MENU_RANGE     (ID_MENU_FILE_CLOSE,            ID_MENU_FILE_SAVEAS,             ChildFrameT::OnMenuFile)
219    EVT_UPDATE_UI_RANGE(ID_MENU_FILE_CLOSE,            ID_MENU_FILE_SAVEAS,             ChildFrameT::OnMenuFileUpdate)
220    EVT_MENU_RANGE     (ID_MENU_EDIT_ENTITY_INSPECTOR, ID_MENU_EDIT_ENTITY_INSPECTOR,   ChildFrameT::OnMenuEdit)
221    EVT_UPDATE_UI_RANGE(ID_MENU_EDIT_ENTITY_INSPECTOR, ID_MENU_EDIT_ENTITY_INSPECTOR,   ChildFrameT::OnMenuEditUpdate)
222    EVT_MENU_RANGE     (ID_MENU_VIEW_TOOLBARS,         ID_MENU_VIEW_CENTER_3D_VIEWS,    ChildFrameT::OnMenuView)
223    EVT_UPDATE_UI_RANGE(ID_MENU_VIEW_TOOLBARS,         ID_MENU_VIEW_CENTER_3D_VIEWS,    ChildFrameT::OnMenuViewUpdate)
224    EVT_BUTTON         (ID_MENU_VIEW_CENTER_2D_VIEWS,                                   ChildFrameT::OnMenuView)
225    EVT_MENU_RANGE     (ID_MENU_TOOLS_TOOL_SELECTION,  ID_MENU_TOOLS_TOOL_EDITVERTICES, ChildFrameT::OnMenuTools)
226    EVT_UPDATE_UI_RANGE(ID_MENU_TOOLS_TOOL_SELECTION,  ID_MENU_TOOLS_TOOL_EDITVERTICES, ChildFrameT::OnMenuToolsUpdate)
227    EVT_MENU_RANGE     (ID_MENU_COMPILE_FLAG_SAVE_MAP, ID_MENU_COMPILE_ABORT,           ChildFrameT::OnMenuCompile)
228
229    EVT_ACTIVATE(ChildFrameT::OnWindowActivate)
230    EVT_AUI_PANE_CLOSE(ChildFrameT::OnAuiPaneClose)
231    // EVT_SIZE(ChildFrameT::OnSize)
232END_EVENT_TABLE()
233
234
235// About the wxMDIChildFrame constructor:
236// Although the parent should actually be the parent frames MDI *client* (sub-)window, according to wx documentation
237// it is fine to pass the MDI parent window itself (rather than its client window) here. See wxMDIChildFrame documentation.
238// Contrary to wx docs, the wxDocMDIChildFrame even *requires* a pointer to wxMDIParentFrame here (not just to a wxFrame, as the docs say)!
239ChildFrameT::ChildFrameT(ParentFrameT* Parent, const wxString& Title, MapDocumentT* Document)
240    : wxMDIChildFrame(Parent, wxID_ANY, Title, wxDefaultPosition, wxSize(800, 600), wxDEFAULT_FRAME_STYLE | wxMAXIMIZE),
241      m_Parent(Parent),      // Must use a fixed size in place of wxDefaultSize, see <http://trac.wxwidgets.org/ticket/12490> for details.
242      m_AUIManager(this),
243      m_AUIDefaultPerspective(""),
244      m_Doc(Document),
245      m_LastSavedAtCommandNr(0),
246      m_AutoSaveTimer(m_Doc, Parent->m_ChildFrames.Size()),
247      m_ToolManager(NULL),
248      m_MaterialsToolbar(NULL),
249      m_GroupsToolbar(NULL),
250      m_ConsoleDialog(NULL),
251      m_SurfacePropsDialog(NULL),
252      m_TerrainEditorDialog(NULL),
253      m_Updater(NULL),
254      FileMenu(NULL),
255      CompileMenu(NULL),
256      CurrentProcess(NULL),
257      CurrentProcessID(0),
258      PendingCompileCommands(),
259      m_ViewWindows()
260{
261    // Register us with the parents list of children.
262    m_Parent->m_ChildFrames.PushBack(this);
263
264    // Should really pass this in the MapDocumentT ctor (the mapdoc should be a member of us).
265    // Correction: NO!  While the doc should be a member of us, it might be *created* before us so that its ctor may throw exceptions,
266    // and then be given to us (we become the owner). In this case, we have to set us as the child frame here - no chance to do it
267    // in the docs ctor. However, I wonder why the doc should know us in the first place...?
268    m_Doc->SetChildFrame(this);
269
270    // Register the document as our first event handler.
271    PushEventHandler(m_Doc);
272
273
274    // Create the menu.
275    wxMenuBar *item0 = new wxMenuBar;
276
277    FileMenu = new wxMenu;
278
279    wxMenu* NewMenu = new wxMenu;
280
281    NewMenu->Append(ParentFrameT::ID_MENU_FILE_NEW_MAP,   wxT("New &Map\tCtrl+N"), wxT(""));
282    NewMenu->Append(ParentFrameT::ID_MENU_FILE_NEW_MODEL, wxT("New M&odel\tCtrl+Shift+N"), wxT(""));
283    NewMenu->Append(ParentFrameT::ID_MENU_FILE_NEW_GUI,   wxT("New &GUI\tCtrl+Alt+N"), wxT(""));
284    NewMenu->Append(ParentFrameT::ID_MENU_FILE_NEW_FONT,  wxT("New &Font"), wxT(""));
285
286    FileMenu->AppendSubMenu(NewMenu, wxT("&New"));
287
288    FileMenu->Append(ParentFrameT::ID_MENU_FILE_OPEN, wxT("&Open...\tCtrl+O"), wxT("") );
289    FileMenu->Append(ID_MENU_FILE_CLOSE, wxT("&Close\tCtrl+F4"), wxT("") );
290    FileMenu->Append(ID_MENU_FILE_SAVE, wxT("&Save\tCtrl+S"), wxT("") );
291    FileMenu->Append(ID_MENU_FILE_SAVEAS, wxT("Save &As..."), wxT("") );
292    FileMenu->AppendSeparator();
293    FileMenu->Append(ParentFrameT::ID_MENU_FILE_CONFIGURE, wxT("Conf&igure CaWE..."), wxT("") );
294    FileMenu->Append(ParentFrameT::ID_MENU_FILE_EXIT, wxT("E&xit"), wxT("") );
295    m_Parent->m_FileHistory.UseMenu(FileMenu);
296    m_Parent->m_FileHistory.AddFilesToMenu(FileMenu);
297    item0->Append( FileMenu, wxT("&File") );
298
299    wxMenu* item2 = new wxMenu;
300    item2->Append( wxID_UNDO, wxT("&Undo\tCtrl+Z"), wxT("") );
301    item2->Append( wxID_REDO, wxT("&Redo\tCtrl+Y"), wxT("") );
302    item2->AppendSeparator();
303    item2->Append( wxID_CUT, wxT("Cu&t\tCtrl+X"), wxT("") );
304    item2->Append( wxID_COPY, wxT("&Copy\tCtrl+C"), wxT("") );
305    item2->Append( wxID_PASTE, wxT("&Paste\tCtrl+V"), wxT("") );
306    item2->Append(ID_MENU_EDIT_PASTE_SPECIAL, wxT("Paste &Special..."), wxT("") );
307    item2->Append(ID_MENU_EDIT_DELETE, wxT("&Delete\tShift+Del"), wxT("") );
308    item2->AppendSeparator();
309    item2->Append(ID_MENU_EDIT_SELECT_NONE, wxT("Select &None\tCtrl+Q"), wxT("") );
310    item2->Append( wxID_SELECTALL, wxT("Select &All"), wxT("") );
311    item2->AppendSeparator();
312    item2->AppendCheckItem(ID_MENU_EDIT_ENTITY_INSPECTOR, wxT("Object &Properties\tAlt+Enter"), wxT("") );
313    item0->Append( item2, wxT("&Edit") );
314
315    wxMenu* item3 = new wxMenu;
316    item3->AppendCheckItem(ID_MENU_MAP_SNAP_TO_GRID, wxT("&Snap to grid\tShift+W"), wxT("") ); item3->Check(ID_MENU_MAP_SNAP_TO_GRID, m_Doc->IsSnapEnabled());
317    item3->AppendCheckItem(ID_MENU_MAP_SHOW_GRID_2D, wxT("Sho&w grid\tShift+R"), wxT("") );    item3->Check(ID_MENU_MAP_SHOW_GRID_2D, m_Doc->Is2DGridEnabled());
318 // item3->AppendCheckItem(ID_MENU_MAP_SHOW_GRID_3D, wxT("Show 3D grid\tShift+R"), wxT("") );  item3->Check(ID_MENU_MAP_SHOW_GRID_3D, m_Doc->Is3DGridEnabled());  // Maybe later.
319
320    wxMenu* item4 = new wxMenu;
321    item4->Append(ID_MENU_MAP_FINER_GRID, wxT("&Finer Grid\t["), wxT("") );
322    item4->Append(ID_MENU_MAP_COARSER_GRID, wxT("&Coarser Grid\t]"), wxT("") );
323    item3->Append(ID_MENU_MAP_GRID_SETTINGS, wxT("&Grid settings"), item4 );
324
325    item3->AppendSeparator();
326    item3->Append(ID_MENU_MAP_GOTO_PRIMITIVE, wxT("G&o to Primitive...\tShift+Ctrl+G"), wxT("") );
327    item3->Append(ID_MENU_MAP_SHOW_INFO, wxT("Show &Information..."), wxT("") );
328    item3->Append(ID_MENU_MAP_CHECK_FOR_PROBLEMS, wxT("&Check for Problems...\tAlt+P"), wxT("") );
329    item3->Append(ID_MENU_MAP_PROPERTIES, wxT("&Map Properties..."), wxT("") );
330    item3->AppendSeparator();
331    item3->Append(ID_MENU_MAP_LOAD_POINTFILE, wxT("&Load Pointfile..."), wxT("") );
332    item3->Append(ID_MENU_MAP_UNLOAD_POINTFILE, wxT("&Unload Pointfile"), wxT("") );
333    item0->Append( item3, wxT("&Map") );
334
335    wxMenu* item6 = new wxMenu;
336
337    wxMenu* item7 = new wxMenu;
338    item7->AppendCheckItem(ID_MENU_VIEW_TOOLBARS_FILE, wxT("&General"), wxT("") );
339    item7->AppendCheckItem(ID_MENU_VIEW_TOOLBARS_TOOLS, wxT("&Tools"), wxT("") );
340    item6->Append(ID_MENU_VIEW_TOOLBARS, wxT("&Toolbars"), item7 );
341
342    wxMenu* ViewPanelsMenu=new wxMenu;
343    ViewPanelsMenu->AppendCheckItem(ID_MENU_VIEW_PANELS_TOOLOPTIONS, wxT("&Tool Options"), wxT("") );
344    ViewPanelsMenu->AppendCheckItem(ID_MENU_VIEW_PANELS_MATERIALS,   wxT("&Materials"), wxT("") );
345    ViewPanelsMenu->AppendCheckItem(ID_MENU_VIEW_PANELS_GROUPS,      wxT("&Groups"), wxT("") );
346    ViewPanelsMenu->AppendCheckItem(ID_MENU_VIEW_PANELS_INSPECTOR,   wxT("Object &Properties"), wxT("") );
347    ViewPanelsMenu->AppendCheckItem(ID_MENU_VIEW_PANELS_CONSOLE,     wxT("&Console"), wxT("") );
348    item6->Append(ID_MENU_VIEW_PANELS, wxT("&Panels"), ViewPanelsMenu);
349
350    item6->Append(ID_MENU_VIEW_NEW_2D_VIEW, "New &2D view", "Opens a new 2D view on the map");
351    item6->Append(ID_MENU_VIEW_NEW_3D_VIEW, "New &3D view", "Opens a new 3D view on the map");
352    item6->AppendSeparator();
353
354    item6->Append(ID_MENU_VIEW_LOAD_USER_PERSPECTIVE, "&Load user window layout", "Loads the user defined window layout");
355    item6->Append(ID_MENU_VIEW_SAVE_USER_PERSPECTIVE, "&Save user window layout", "Saves the current window layout");
356    item6->Append(ID_MENU_VIEW_LOAD_DEFAULT_PERSPECTIVE, "Load &default window layout", "Restores the default window layout");
357    item6->AppendSeparator();
358    item6->Append(ID_MENU_VIEW_CENTER_2D_VIEWS, wxT("Center &2D Views on Selection\tCtrl+E"), wxT("") );
359    item6->Append(ID_MENU_VIEW_CENTER_3D_VIEWS, wxT("Center &3D Views on Selection"), wxT("") );
360    item6->AppendSeparator();
361    item6->Append(ID_MENU_VIEW_SHOW_ENTITY_INFO, wxT("Show Entity &Info"), wxT(""), wxITEM_CHECK);
362    item6->Append(ID_MENU_VIEW_SHOW_ENTITY_TARGETS, wxT("Show Entity &Targets"), wxT(""), wxITEM_CHECK );
363    item6->AppendSeparator();
364    item6->Append(ID_MENU_VIEW_HIDE_SELECTED_OBJECTS, wxT("H&ide Selected Objects"), wxT("") );
365    item6->Append(ID_MENU_VIEW_SHOW_HIDDEN_OBJECTS, wxT("&Show Hidden Objects"), wxT("") );
366    item0->Append( item6, wxT("&View") );
367
368    wxMenu* item8 = new wxMenu;
369    item8->AppendRadioItem(ID_MENU_TOOLS_TOOL_SELECTION,             wxT("Selection\tShift+S"), wxT(""));
370    item8->AppendRadioItem(ID_MENU_TOOLS_TOOL_CAMERA,                wxT("Camera\tShift+C"), wxT(""));
371    item8->AppendRadioItem(ID_MENU_TOOLS_TOOL_NEWBRUSH,              wxT("New Brush\tShift+B"), wxT(""));
372    item8->AppendRadioItem(ID_MENU_TOOLS_TOOL_NEWENTITY,             wxT("New Entity\tShift+E"), wxT(""));
373    item8->AppendRadioItem(ID_MENU_TOOLS_TOOL_NEWBEZIERPATCH,        wxT("New Bezier Patch\tShift+P"), wxT(""));
374    item8->AppendRadioItem(ID_MENU_TOOLS_TOOL_NEWTERRAIN,            wxT("New Terrain\tShift+T"), wxT(""));
375    item8->AppendRadioItem(ID_MENU_TOOLS_TOOL_NEWLIGHT,              wxT("New Light\tShift+L"), wxT(""));
376    item8->AppendRadioItem(ID_MENU_TOOLS_TOOL_NEWDECAL,              wxT("New Decal\tShift+D"), wxT(""));
377    item8->AppendRadioItem(ID_MENU_TOOLS_TOOL_EDITSURFACEPROPERTIES, wxT("Edit Surface Properties\tShift+A"), wxT(""));
378    item8->AppendRadioItem(ID_MENU_TOOLS_TOOL_TERRAINEDITOR,         wxT("Terrain Editor\tShift+F"), wxT(""));
379    item8->AppendRadioItem(ID_MENU_TOOLS_TOOL_CLIP,                  wxT("Clip Brushes\tShift+X"), wxT(""));
380    item8->AppendRadioItem(ID_MENU_TOOLS_TOOL_EDITVERTICES,          wxT("Edit Brush Vertices\tShift+V"), wxT(""));
381    item8->AppendSeparator();
382    item8->Append(ID_MENU_TOOLS_CARVE, wxT("&Carve\tShift+Ctrl+C"), wxT("") );
383    item8->Append(ID_MENU_TOOLS_MAKE_HOLLOW, wxT("Make Hollow\tCtrl+H"), wxT("") );
384    item8->AppendSeparator();
385    item8->Append(ID_MENU_TOOLS_GROUP, wxT("&Group\tCtrl+G"), wxT("") );
386    item8->AppendSeparator();
387    item8->Append(ID_MENU_TOOLS_ASSIGN_PRIM_TO_ENTITY, wxT("&Tie to Entity\tCtrl+T"), wxT("") );
388    item8->Append(ID_MENU_TOOLS_ASSIGN_PRIM_TO_WORLD, wxT("&Move to World\tShift+Ctrl+W"), wxT("") );
389    item8->AppendSeparator();
390    item8->Append(ID_MENU_TOOLS_REPLACE_MATERIALS, wxT("R&eplace Materials"), wxT("") );
391    item8->AppendCheckItem(ID_MENU_TOOLS_MATERIAL_LOCK, wxT("Material &Lock\tShift+L"), wxT("") );
392    item8->AppendSeparator();
393    item8->Append(ID_MENU_TOOLS_SNAP_SELECTION_TO_GRID, wxT("Snap Selection to Grid\tCtrl+B"), wxT("") );
394    item8->Append(ID_MENU_TOOLS_TRANSFORM, wxT("Transform\tCtrl+M"), wxT("") );
395
396    wxMenu* item9 = new wxMenu;
397    item9->Append(ID_MENU_TOOLS_ALIGN_LEFT, wxT("to &Left"), wxT("") );
398    item9->Append(ID_MENU_TOOLS_ALIGN_RIGHT, wxT("to &Right"), wxT("") );
399    item9->Append(ID_MENU_TOOLS_ALIGN_HOR_CENTER, wxT("to &hor. Center"), wxT("") );
400    item9->Append(ID_MENU_TOOLS_ALIGN_TOP, wxT("to &Top"), wxT("") );
401    item9->Append(ID_MENU_TOOLS_ALIGN_BOTTOM, wxT("to &Bottom"), wxT("") );
402    item9->Append(ID_MENU_TOOLS_ALIGN_VERT_CENTER, wxT("to &vert. Center"), wxT("") );
403    item8->Append(ID_MENU_TOOLS_ALIGN, wxT("&Align Objects"), item9 );
404
405    wxMenu* item10 = new wxMenu;
406    item10->Append(ID_MENU_TOOLS_MIRROR_HOR, wxT("&Horizontally\tCtrl+L"), wxT("") );
407    item10->Append(ID_MENU_TOOLS_MIRROR_VERT, wxT("&Vertically\tCtrl+I"), wxT("") );
408    item8->Append(ID_MENU_TOOLS_MIRROR, wxT("M&irror Objects"), item10 );
409
410    item0->Append( item8, wxT("&Tools") );
411
412    CompileMenu=new wxMenu;
413    CompileMenu->AppendCheckItem(ID_MENU_COMPILE_FLAG_SAVE_MAP,   "1. &Save Map",     ""); CompileMenu->Check(ID_MENU_COMPILE_FLAG_SAVE_MAP,   true);
414    CompileMenu->AppendCheckItem(ID_MENU_COMPILE_FLAG_RUN_BSP,    "2. Run Ca&BSP",    ""); CompileMenu->Check(ID_MENU_COMPILE_FLAG_RUN_BSP,    true); CompileMenu->Enable(ID_MENU_COMPILE_FLAG_RUN_BSP, false);
415    CompileMenu->AppendCheckItem(ID_MENU_COMPILE_FLAG_RUN_PVS,    "3. Run Ca&PVS",    ""); CompileMenu->Check(ID_MENU_COMPILE_FLAG_RUN_PVS,    true);
416    CompileMenu->AppendCheckItem(ID_MENU_COMPILE_FLAG_RUN_LIGHT,  "4. Run Ca&Light",  ""); CompileMenu->Check(ID_MENU_COMPILE_FLAG_RUN_LIGHT,  false);  // Intentionally off per default, in order to make sure that first-time users are not confronted with a multi-hour CaLight session.
417    CompileMenu->AppendCheckItem(ID_MENU_COMPILE_FLAG_RUN_ENGINE, "5. Start &Engine", ""); CompileMenu->Check(ID_MENU_COMPILE_FLAG_RUN_ENGINE, true);
418    CompileMenu->AppendSeparator();
419    CompileMenu->Append(ID_MENU_COMPILE_QUICK,   "Run &Quick...",        "");
420    CompileMenu->Append(ID_MENU_COMPILE_NORMAL,  "Run &Normal...",       "");
421    CompileMenu->Append(ID_MENU_COMPILE_QUALITY, "Run &High Quality...", "");
422    CompileMenu->Append(ID_MENU_COMPILE_CUSTOM,  "Run Custom...",        "");
423    CompileMenu->AppendSeparator();
424    CompileMenu->Append(ID_MENU_COMPILE_ABORT, "Abort", ""); CompileMenu->Enable(ID_MENU_COMPILE_ABORT, false);
425    item0->Append(CompileMenu, wxT("&Compile") );
426
427    wxMenu* item12 = new wxMenu;
428    item12->Append(ParentFrameT::ID_MENU_HELP_CONTENTS, wxT("&CaWE Help\tF1"), wxT("") );
429    item12->AppendSeparator();
430    item12->Append(ParentFrameT::ID_MENU_HELP_CAFU_WEBSITE, wxT("Cafu &Website"), wxT("") );
431    item12->Append(ParentFrameT::ID_MENU_HELP_CAFU_FORUM, wxT("Cafu &Forum"), wxT("") );
432    item12->AppendSeparator();
433    item12->Append(ParentFrameT::ID_MENU_HELP_ABOUT, wxT("&About..."), wxT("") );
434    item0->Append(item12, wxT("&Help") );
435
436    SetMenuBar(item0);
437    SetMinSize(wxSize(400,300));
438
439
440    // Create the status bar at the bottom of the frame.
441    int StatusBarWidths[6]={ -1, 200, 130, 130, 100, 120 };
442
443    CreateStatusBar(6, wxST_SIZEGRIP);                  // Create the status bar with 6 panes.
444    SetStatusWidths(6, StatusBarWidths);                // Set the widths of the individual panes.
445    SetStatusBarPane(SBP_MENU_HELP);                    // Use the first pane (number 0) for displaying menu and toolbar help.
446    SetStatusText(" Welcome to CaWE!", SBP_MENU_HELP);  // Set an initial text in the first pane.
447
448
449    // Create the toolbars.
450    wxAuiToolBar* ToolbarFile=new wxAuiToolBar(this, wxID_ANY);
451    ToolbarFile->AddTool(ParentFrameT::ID_MENU_FILE_NEW_GUI, "New", wxArtProvider::GetBitmap(wxART_NEW, wxART_TOOLBAR), "Create a new file");
452    ToolbarFile->AddTool(ParentFrameT::ID_MENU_FILE_OPEN,    "Open", wxArtProvider::GetBitmap(wxART_FILE_OPEN, wxART_TOOLBAR), "Open an existing file");
453    ToolbarFile->AddTool(ID_MENU_FILE_SAVE,                  "Save", wxArtProvider::GetBitmap(wxART_FILE_SAVE, wxART_TOOLBAR), "Save the file");
454    ToolbarFile->AddTool(ID_MENU_FILE_SAVEAS,                "Save as", wxArtProvider::GetBitmap(wxART_FILE_SAVE_AS, wxART_TOOLBAR), "Save the file under a different name");
455    ToolbarFile->AddSeparator();
456    ToolbarFile->AddTool(wxID_UNDO,           "Undo", wxArtProvider::GetBitmap(wxART_UNDO, wxART_TOOLBAR), "Undo the last action");
457    ToolbarFile->AddTool(wxID_REDO,           "Redo", wxArtProvider::GetBitmap(wxART_REDO, wxART_TOOLBAR), "Redo the previously undone action");
458    ToolbarFile->AddSeparator();
459    ToolbarFile->AddTool(wxID_CUT,            "Cut", wxArtProvider::GetBitmap(wxART_CUT, wxART_TOOLBAR), "Cut");
460    ToolbarFile->AddTool(wxID_COPY,           "Copy", wxArtProvider::GetBitmap(wxART_COPY, wxART_TOOLBAR), "Copy");
461    ToolbarFile->AddTool(wxID_PASTE,          "Paste", wxArtProvider::GetBitmap(wxART_PASTE, wxART_TOOLBAR), "Paste");
462    ToolbarFile->AddTool(ID_MENU_EDIT_DELETE, "Delete", wxArtProvider::GetBitmap(wxART_DELETE, wxART_TOOLBAR), "Delete");
463    ToolbarFile->Realize();
464
465    // Note that we cannot have separators between these tools, because they must all be in the same radio group.
466    wxAuiToolBar* ToolbarTools=new wxAuiToolBar(this, wxID_ANY);
467    ToolbarTools->AddTool(ID_MENU_TOOLS_TOOL_SELECTION,             "Selection",               wxArtProvider::GetBitmap("MapEditor/tool-selection",          wxART_TOOLBAR, wxSize(21, 18)), "Selection", wxITEM_RADIO);
468    ToolbarTools->AddTool(ID_MENU_TOOLS_TOOL_CAMERA,                "Camera",                  wxArtProvider::GetBitmap("MapEditor/tool-camera",             wxART_TOOLBAR, wxSize(21, 18)), "Camera", wxITEM_RADIO);
469    ToolbarTools->AddTool(ID_MENU_TOOLS_TOOL_NEWBRUSH,              "New Brush",               wxArtProvider::GetBitmap("MapEditor/tool-new-brush",          wxART_TOOLBAR, wxSize(21, 18)), "New Brush", wxITEM_RADIO);
470    ToolbarTools->AddTool(ID_MENU_TOOLS_TOOL_NEWENTITY,             "New Entity",              wxArtProvider::GetBitmap("MapEditor/tool-new-entity",         wxART_TOOLBAR, wxSize(21, 18)), "New Entity", wxITEM_RADIO);
471    ToolbarTools->AddTool(ID_MENU_TOOLS_TOOL_NEWBEZIERPATCH,        "New Bezier Patch",        wxArtProvider::GetBitmap("MapEditor/tool-new-bezierpatch",    wxART_TOOLBAR, wxSize(21, 18)), "New Bezier Patch", wxITEM_RADIO);
472    ToolbarTools->AddTool(ID_MENU_TOOLS_TOOL_NEWTERRAIN,            "New Terrain",             wxArtProvider::GetBitmap("MapEditor/tool-new-terrain",        wxART_TOOLBAR, wxSize(21, 18)), "New Terrain", wxITEM_RADIO);
473    ToolbarTools->AddTool(ID_MENU_TOOLS_TOOL_NEWLIGHT,              "New Light",               wxArtProvider::GetBitmap("MapEditor/tool-new-light",          wxART_TOOLBAR, wxSize(21, 18)), "New Light", wxITEM_RADIO);
474    ToolbarTools->AddTool(ID_MENU_TOOLS_TOOL_NEWDECAL,              "New Decal",               wxArtProvider::GetBitmap("MapEditor/tool-new-decal",          wxART_TOOLBAR, wxSize(21, 18)), "New Decal", wxITEM_RADIO);
475    ToolbarTools->AddTool(ID_MENU_TOOLS_TOOL_EDITSURFACEPROPERTIES, "Edit Surface Properties", wxArtProvider::GetBitmap("MapEditor/tool-edit-surface-props", wxART_TOOLBAR, wxSize(21, 18)), "Edit Surface Properties", wxITEM_RADIO);
476    ToolbarTools->AddTool(ID_MENU_TOOLS_TOOL_TERRAINEDITOR,         "Edit Terrain",            wxArtProvider::GetBitmap("MapEditor/tool-edit-terrain",       wxART_TOOLBAR, wxSize(21, 18)), "Edit Terrain", wxITEM_RADIO);
477    ToolbarTools->AddTool(ID_MENU_TOOLS_TOOL_CLIP,                  "Clip Brushes",            wxArtProvider::GetBitmap("MapEditor/tool-clip",               wxART_TOOLBAR, wxSize(21, 18)), "Clip Brushes", wxITEM_RADIO);
478    ToolbarTools->AddTool(ID_MENU_TOOLS_TOOL_EDITVERTICES,          "Edit Brush Vertices",     wxArtProvider::GetBitmap("MapEditor/tool-edit-vertices",      wxART_TOOLBAR, wxSize(21, 18)), "Edit Brush Vertices", wxITEM_RADIO);
479    ToolbarTools->Realize();
480
481    m_AUIManager.AddPane(ToolbarFile, wxAuiPaneInfo().ToolbarPane().
482                         Name("File Toolbar").Caption("File Toolbar").
483                         Top().Row(0).Position(0).LeftDockable(false).RightDockable(false));
484
485    m_AUIManager.AddPane(ToolbarTools, wxAuiPaneInfo().ToolbarPane().
486                         Name("Tools Toolbar").Caption("Tools Toolbar").
487                         Top().Row(0).Position(1).LeftDockable(false).RightDockable(false));
488
489
490    wxPanel* ToolbarToolOptions=new wxPanel(this, -1, wxDefaultPosition, wxSize(852, 30));
491    m_ToolManager=new ToolManagerT(*m_Doc, ToolbarToolOptions);     // Allocate our tool manager.
492    // This can NOT be called here - it will attempt to update the status bar and the tool options bars,
493    // which do not yet exist at this point. Instead, the call is made below, near the end of this constructor.
494    // m_ToolManager->SetActiveTool(GetToolTIM().FindTypeInfoByName("ToolSelectionT"));
495
496    wxSizer* TTOSizer=new wxBoxSizer(wxVERTICAL);   // The sizer makes sure that the individual panels each extend to the full width and height of the toolbar.
497
498    // Add all tool options bars to the sizer (initially hidden).
499    for (unsigned long ToolNr=0; ToolNr<m_ToolManager->GetTools().Size(); ToolNr++)
500    {
501        ToolT*    Tool      =m_ToolManager->GetTools()[ToolNr];
502        wxWindow* OptionsBar=Tool->GetOptionsBar();
503
504        if (!OptionsBar) continue;
505
506        OptionsBar->Hide();
507        TTOSizer->Add(OptionsBar, 1, wxGROW);
508    }
509
510    ToolbarToolOptions->SetSizer(TTOSizer);
511    // TTOSizer->SetSizeHints(ToolbarToolOptions);      // When this line is activated ("commented in"), the size of the pane gets wrong.
512
513    m_AUIManager.AddPane(ToolbarToolOptions, wxAuiPaneInfo().
514                         Name("Tool Options").Caption("Tool Options").
515                         Top().Row(1));
516
517
518    // Create the toolbars and non-modal dialogs.
519    // Note that most if not all of these wxAUI panes have extra style wxWS_EX_BLOCK_EVENTS set,
520    // so that they do not propagate their events to us, but behave as if they were derived from wxDialog.
521    m_MaterialsToolbar=new MaterialsToolbarT(this, m_Doc);
522    m_AUIManager.AddPane(m_MaterialsToolbar, wxAuiPaneInfo().
523                         Name("Materials").Caption("Materials").
524                         Left().Position(0));
525
526    m_GroupsToolbar=new GroupsToolbarT(this, m_Doc);
527    m_AUIManager.AddPane(m_GroupsToolbar, wxAuiPaneInfo().
528                         Name("Groups").Caption("Groups").
529                         Left().Position(1));
530
531    m_InspectorDialog=new InspectorDialogT(this, m_Doc);
532    m_AUIManager.AddPane(m_InspectorDialog, wxAuiPaneInfo().
533                         Name("Properties").Caption("Object Properties").
534                         Float().Hide());
535
536    m_ConsoleDialog=new ConsoleDialogT(this);
537    m_AUIManager.AddPane(m_ConsoleDialog, wxAuiPaneInfo().
538                         Name("Console").Caption("Console").
539                         BestSize(400, 300).
540                         Bottom().Hide());
541
542    m_SurfacePropsDialog=new EditSurfacePropsDialogT(this, m_Doc);
543    m_AUIManager.AddPane(m_SurfacePropsDialog, wxAuiPaneInfo().
544                         Name("Surface Properties").Caption("Surface Properties").
545                         Float().Hide());
546
547    m_TerrainEditorDialog=new TerrainEditorDialogT(this, *m_Doc->GetGameConfig(), static_cast<ToolTerrainEditorT*>(m_ToolManager->GetTool(ToolTerrainEditorT::TypeInfo)));
548    m_AUIManager.AddPane(m_TerrainEditorDialog, wxAuiPaneInfo().
549                         Name("Terrain Editor").Caption("Terrain Editor").
550                         Float().Hide());
551
552
553    ViewWindow3DT* CenterPaneView=new ViewWindow3DT(this, this, NULL, (ViewWindowT::ViewTypeT)wxConfigBase::Get()->Read("Splitter/ViewType00", ViewWindowT::VT_3D_FULL_MATS));
554    m_AUIManager.AddPane(CenterPaneView, wxAuiPaneInfo().
555                         Name("Main View").Caption(CenterPaneView->GetCaption()).
556                         CenterPane().CaptionVisible().MaximizeButton().MinimizeButton());
557
558    ViewWindow2DT* ViewTopRight=new ViewWindow2DT(this, this, (ViewWindowT::ViewTypeT)wxConfigBase::Get()->Read("Splitter/ViewType01", ViewWindowT::VT_2D_XY));
559    m_AUIManager.AddPane(ViewTopRight, wxAuiPaneInfo().
560                         // Name("xy").
561                         Caption(ViewTopRight->GetCaption()).
562                         DestroyOnClose().Right().Position(0).MaximizeButton().MinimizeButton());
563
564    ViewWindow2DT* ViewBottomRight=new ViewWindow2DT(this, this, (ViewWindowT::ViewTypeT)wxConfigBase::Get()->Read("Splitter/ViewType11", ViewWindowT::VT_2D_XZ));
565    m_AUIManager.AddPane(ViewBottomRight, wxAuiPaneInfo().
566                         // Name("xy").
567                         Caption(ViewBottomRight->GetCaption()).
568                         DestroyOnClose().Right().Position(1).MaximizeButton().MinimizeButton());
569
570
571    // Save the AUI perspective that we set up in this ctor code as the "default perspective".
572    m_AUIDefaultPerspective=m_AUIManager.SavePerspective();
573
574    // Load the AUI user perspective (implies a call to m_AUIManager.Update()).
575    m_AUIManager.LoadPerspective(wxConfigBase::Get()->Read("MapEditor_AUIUserPerspective", m_AUIDefaultPerspective));
576
577
578    // Activate the Selection tool as the default tool (having initially no tool active at all can be quite confusing for users).
579    // This cannot be done near the creation of the tool manager above, because then the status bar and tool options bars do not yet exist.
580    m_ToolManager->SetActiveTool(GetToolTIM().FindTypeInfoByName("ToolSelectionT"));
581
582#ifndef __WXGTK__
583    Centre(wxBOTH);
584#endif
585    if (!IsMaximized()) Maximize(true);     // Also have wxMAXIMIZE set as frame style.
586    Show(true);
587
588    m_Updater=new UpdaterT(this);
589
590    // Start the autosave timer.
591    int Minutes=0;
592    wxConfigBase::Get()->Read("General/AutoSave Interval", &Minutes, 10);
593    if (Minutes>0) m_AutoSaveTimer.Start(Minutes*60*1000);
594              else m_AutoSaveTimer.Stop();
595}
596
597
598ChildFrameT::~ChildFrameT()
599{
600    m_AutoSaveTimer.Stop();
601
602    if (CurrentProcess!=NULL)
603    {
604        CurrentProcess->Detach();
605        CurrentProcess=NULL;
606        CurrentProcessID=0;
607    }
608
609    m_Parent->m_FileHistory.RemoveMenu(FileMenu);
610
611    delete m_Updater;
612    m_Updater=NULL;
613
614    delete m_ToolManager;
615    m_ToolManager=NULL;
616
617    // Unregister us from the parents list of children.
618    const int Index=m_Parent->m_ChildFrames.Find(this);
619    m_Parent->m_ChildFrames.RemoveAt(Index);
620
621    // Remove the document as our first event handler.
622    PopEventHandler();
623
624    // Delete the document.
625    delete m_Doc;
626    m_Doc=NULL;
627
628    // Uninit the AUI manager.
629    m_AUIManager.UnInit();
630}
631
632
633Vector3fT ChildFrameT::GuessUserVisiblePoint() const
634{
635    Vector3fT     Point(0, 0, 0);   // TODO: Init along the view dir of the MRU camera instead? Or m_SelectionBB.GetCenter()?
636    unsigned long HaveAxes=0;       // Bit i is set if we have a coordinate for the i-th axis.
637
638    for (unsigned long ViewWinNr=0; ViewWinNr<m_ViewWindows.Size() && HaveAxes<7; ViewWinNr++)
639    {
640        const ViewWindow2DT* ViewWin2D =dynamic_cast<ViewWindow2DT*>(m_ViewWindows[ViewWinNr]); if (!ViewWin2D) continue;
641        const int            HorzAxis  =ViewWin2D->GetAxesInfo().HorzAxis;
642        const int            VertAxis  =ViewWin2D->GetAxesInfo().VertAxis;
643        const wxRect         ClientRect=wxRect(wxPoint(0, 0), ViewWin2D->GetClientSize());
644        const Vector3fT      Center    =ViewWin2D->WindowToWorld(wxPoint(ClientRect.x+ClientRect.width/2, ClientRect.y+ClientRect.height/2), 0.0f);
645
646        if ((HaveAxes & (1ul << HorzAxis))==0)
647        {
648            Point[HorzAxis]=Center[HorzAxis];
649            HaveAxes|=(1ul << HorzAxis);
650        }
651
652        if ((HaveAxes & (1ul << VertAxis))==0)
653        {
654            Point[VertAxis]=Center[VertAxis];
655            HaveAxes|=(1ul << VertAxis);
656        }
657    }
658
659    return Point;
660}
661
662
663void ChildFrameT::All2DViews_Zoom(float ZoomFactor)
664{
665    for (unsigned long ViewWinNr=0; ViewWinNr<m_ViewWindows.Size(); ViewWinNr++)
666    {
667        ViewWindowT*   ViewWin  =m_ViewWindows[ViewWinNr];
668        ViewWindow2DT* ViewWin2D=dynamic_cast<ViewWindow2DT*>(ViewWin);
669
670        if (ViewWin2D)
671        {
672            ViewWin2D->SetZoom(ZoomFactor);
673            ViewWin2D->Refresh();
674        }
675    }
676}
677
678
679void ChildFrameT::All2DViews_Center(const Vector3fT& CenterPoint)
680{
681    for (unsigned long ViewWinNr=0; ViewWinNr<m_ViewWindows.Size(); ViewWinNr++)
682    {
683        ViewWindowT*   ViewWin  =m_ViewWindows[ViewWinNr];
684        ViewWindow2DT* ViewWin2D=dynamic_cast<ViewWindow2DT*>(ViewWin);
685
686        if (ViewWin2D)
687        {
688            ViewWin2D->CenterView(CenterPoint);
689         // ViewWin2D->Refresh();   // Already in CenterView().
690        }
691    }
692}
693
694
695bool ChildFrameT::IsPaneShown(wxWindow* Pane)
696{
697    wxAuiPaneInfo& PaneInfo=m_AUIManager.GetPane(Pane);
698
699    if (!PaneInfo.IsOk()) return false;
700
701    return PaneInfo.IsShown();
702}
703
704
705void ChildFrameT::ShowPane(wxWindow* Pane, bool DoShow)
706{
707    wxAuiPaneInfo& PaneInfo=m_AUIManager.GetPane(Pane);
708
709    if (!PaneInfo.IsOk()) return;
710
711    PaneInfo.Show(DoShow);
712
713    if (DoShow && PaneInfo.IsFloating() && PaneInfo.floating_pos==wxDefaultPosition)
714        PaneInfo.FloatingPosition(ClientToScreen(wxPoint(20, 20)));
715
716    m_AUIManager.Update();
717}
718
719
720void ChildFrameT::SetCaption(wxWindow* Pane, const wxString& Caption)
721{
722    wxAuiPaneInfo& PaneInfo=m_AUIManager.GetPane(Pane);
723
724    if (!PaneInfo.IsOk()) return;
725
726    PaneInfo.Caption(Caption);
727    m_AUIManager.Update();
728}
729
730
731/**********************/
732/*** Event Handlers ***/
733/**********************/
734
735void ChildFrameT::OnClose(wxCloseEvent& CE)
736{
737    if (!CE.CanVeto())
738    {
739        Destroy();
740        return;
741    }
742
743    if (m_Doc->GetHistory().GetLastSaveSuggestedCommandID()==m_LastSavedAtCommandNr)
744    {
745        // Our document has not been modified since the last save - close this window.
746        Destroy();
747        return;
748    }
749
750    // This "Save Confirmation Alert" essentially follows the GNOME Human Interface Guidelines,
751    // see http://developer.gnome.org/hig-book/ for details.
752    wxMessageDialog Msg(NULL, "Save changes to map \"" + m_Doc->GetFileName() + "\" before closing?", "CaWE Map Editor", wxYES_NO | wxCANCEL);
753
754    Msg.SetExtendedMessage("If you close without saving, your changes will be discarded.");
755    Msg.SetYesNoLabels("Save", "Close without Saving");
756
757    switch (Msg.ShowModal())
758    {
759        case wxID_YES:
760            if (!m_Doc->Save())
761            {
762                // The document could not be saved - keep the window open.
763                CE.Veto();
764                return;
765            }
766
767            if (m_Doc->GetHistory().GetLastSaveSuggestedCommandID()!=m_LastSavedAtCommandNr)
768            {
769                // The save was successful, but maybe it was a map export rather than a native cmap save.
770                // In this case, also keep the window open.
771                wxMessageBox("The map was exported, not saved. Please save the map before leaving.", "Map not closed.", wxOK | wxICON_INFORMATION);
772                CE.Veto();
773                return;
774            }
775
776            // The map was successfully saved - close the window.
777            Destroy();
778            return;
779
780        case wxID_NO:
781            Destroy();
782            return;
783
784        default:    // wxID_CANCEL
785            CE.Veto();
786            return;
787    }
788}
789
790
791void ChildFrameT::OnIdle(wxIdleEvent& IE)
792{
793    // We have a compile process running - forward its output to the console.
794    // This code is duplicated in ChildFrameT::OnProcessEnd(), to make sure we don't miss anything.
795    if (CurrentProcess && CurrentProcess->IsInputAvailable())
796    {
797        wxInputStream* InStream=CurrentProcess->GetInputStream();
798        char           Buffer[256];
799
800        while (InStream->CanRead())
801        {
802            InStream->Read(Buffer, 255);
803
804            size_t count=InStream->LastRead();
805
806#ifdef __WXGTK__
807            if (count==0) break;   // This apparently can happen under wxGTK; I don't know why.
808#endif
809            wxASSERT(count>0 && count<256);
810            Buffer[count]=0;
811
812            m_ConsoleDialog->Print(Buffer, wxLIGHT_GREY);
813        }
814    }
815
816    // The following things are only performed if the child frame is the active childframe.
817    ChildFrameT* ActiveChild=dynamic_cast<ChildFrameT*>(m_Parent->GetActiveChild());
818
819    if (this==ActiveChild)
820    {
821        // Set the proper window title with or without a trailing "*", depending on the current save state.
822        // The extra check (GetTitle()!=NewTitle) is necessary in order to prevent the title from flickering...
823        // can we implement an entirely different solution here, e.g. as in the GUI editor?
824        wxString NewTitle=m_Doc->GetFileName() + (m_Doc->GetHistory().GetLastSaveSuggestedCommandID()==m_LastSavedAtCommandNr ? "" : "*");
825        if (GetTitle()!=NewTitle) SetTitle(NewTitle);
826
827        // Cache materials for the childframes game configuration (one material per idle event).
828        m_Doc->GetGameConfig()->GetMatMan().LazilyUpdateProxies();
829
830        // Update the map documents BSP tree (regarding map elements that have moved or otherwise changed their bounding-box).
831        const unsigned long ElemsUpdated=m_Doc->GetBspTree()->Update();
832
833        if (ElemsUpdated>0)
834        {
835            wxLogDebug("OrthoBspTreeT::Update() updated %lu map elements.", ElemsUpdated);
836        }
837
838        // Update all 3D views.
839        for (unsigned long ViewWinNr=0; ViewWinNr<m_ViewWindows.Size(); ViewWinNr++)
840        {
841            ViewWindowT*   ViewWin  =m_ViewWindows[ViewWinNr];
842            ViewWindow3DT* ViewWin3D=dynamic_cast<ViewWindow3DT*>(ViewWin);
843
844            if (ViewWin3D)
845            {
846                ViewWin3D->Refresh(false);
847                ViewWin3D->Update();
848            }
849        }
850    }
851
852    IE.RequestMore();
853}
854
855
856void ChildFrameT::OnProcessEnd(wxProcessEvent& PE)
857{
858    // Code duplicated from ChildFrameT::OnIdle(), to make sure we don't miss anything.
859    if (CurrentProcess && CurrentProcess->IsInputAvailable())
860    {
861        wxInputStream* InStream=CurrentProcess->GetInputStream();
862        char           Buffer[256];
863
864        while (InStream->CanRead())
865        {
866            InStream->Read(Buffer, 255);
867
868            size_t count=InStream->LastRead();
869
870#ifdef __WXGTK__
871            if (count==0) break;   // This apparently can happen under wxGTK; I don't know why.
872#endif
873            wxASSERT(count>0 && count<256);
874            Buffer[count]=0;
875
876            m_ConsoleDialog->Print(Buffer, wxLIGHT_GREY);
877        }
878    }
879
880    if (PE.GetExitCode()!=0)
881    {
882        EndCompiling(wxString::Format("\nError: Map compilation process %i exited with code %i.\n", PE.GetPid(), PE.GetExitCode()), wxRED);
883        return;
884    }
885
886    if (PendingCompileCommands.Size()==0)
887    {
888        EndCompiling("\nMap compilation ended successfully.");
889        return;
890    }
891
892    m_ConsoleDialog->Print("\nMap compilation: Running command '"+PendingCompileCommands[0]+"'\n", wxBLUE);
893
894    // Delete previous compile process.
895    delete CurrentProcess;
896    CurrentProcess=NULL;
897    CurrentProcessID=0;
898
899    // Start new compile process.
900    CurrentProcess=new wxProcess(this);
901    CurrentProcess->Redirect();
902
903    if (PendingCompileCommands[0].StartsWith(Options.general.EngineExe))
904        CurrentProcessID=wxExecute(PendingCompileCommands[0], wxEXEC_ASYNC | wxEXEC_NOHIDE, CurrentProcess);
905    else
906        CurrentProcessID=wxExecute(PendingCompileCommands[0], wxEXEC_ASYNC, CurrentProcess);
907
908    PendingCompileCommands.RemoveAtAndKeepOrder(0);
909
910    if (CurrentProcessID<=0)
911        EndCompiling("\nCould not execute the map compilation process!\n", wxRED);
912}
913
914
915void ChildFrameT::OnMenuFile(wxCommandEvent& CE)
916{
917    switch (CE.GetId())
918    {
919        case ID_MENU_FILE_CLOSE:
920        {
921            // Close() generates a EVT_CLOSE event which is handled by our OnClose() handler.
922            // See wx Window Deletion Overview for more details.
923            Close();
924            break;
925        }
926
927        case ID_MENU_FILE_SAVE:
928        {
929            const bool SaveOK=m_Doc->Save();
930
931            if (SaveOK && m_Doc->GetFileName().Right(5).MakeLower()==".cmap")
932            {
933                // Mark the document as "not modified" only if the save was successful AND in cmap file format.
934                // All other file formats are exported formats, and may not be able to store all information that is stored in a cmap file.
935                // Thus data loss may occur if the document is only saved in an exported, but not in cmap file format.
936                // Considering file *exports* not as file *saves* (that mark the document as "not modified" when successful)
937                // makes sure that on application exit, the user is warned about possible data loss in such cases.
938                m_LastSavedAtCommandNr=m_Doc->GetHistory().GetLastSaveSuggestedCommandID();
939                m_Parent->m_FileHistory.AddFileToHistory(m_Doc->GetFileName());
940            }
941            break;
942        }
943
944        case ID_MENU_FILE_SAVEAS:
945        {
946            const bool SaveOK=m_Doc->SaveAs();
947
948            if (SaveOK && m_Doc->GetFileName().Right(5).MakeLower()==".cmap")
949            {
950                // Mark the document as "not modified" only if the save was successful AND in cmap file format.
951                // All other file formats are exported formats, and may not be able to store all information that is stored in a cmap file.
952                // Thus data loss may occur if the document is only saved in an exported, but not in cmap file format.
953                // Considering file *exports* not as file *saves* (that mark the document as "not modified" when successful)
954                // makes sure that on application exit, the user is warned about possible data loss in such cases.
955                m_LastSavedAtCommandNr=m_Doc->GetHistory().GetLastSaveSuggestedCommandID();
956                m_Parent->m_FileHistory.AddFileToHistory(m_Doc->GetFileName());
957            }
958            break;
959        }
960    }
961}
962
963
964void ChildFrameT::OnMenuFileUpdate(wxUpdateUIEvent& UE)
965{
966    switch (UE.GetId())
967    {
968        case ID_MENU_FILE_SAVE:
969            UE.Enable(m_Doc->GetHistory().GetLastSaveSuggestedCommandID()!=m_LastSavedAtCommandNr);
970            break;
971    }
972}
973
974
975void ChildFrameT::OnMenuEdit(wxCommandEvent& CE)
976{
977    switch (CE.GetId())
978    {
979        case ID_MENU_EDIT_ENTITY_INSPECTOR:
980        {
981            wxAuiPaneInfo& PaneInfo=m_AUIManager.GetPane(m_InspectorDialog);
982
983            if (!PaneInfo.IsShown())
984            {
985                const int BestPage=m_InspectorDialog->GetBestPage(m_Doc->GetSelection());
986
987                m_InspectorDialog->ChangePage(BestPage);
988            }
989
990            PaneToggleShow(PaneInfo);
991            break;
992        }
993    }
994}
995
996
997void ChildFrameT::OnMenuEditUpdate(wxUpdateUIEvent& UE)
998{
999    switch (UE.GetId())
1000    {
1001        case ID_MENU_EDIT_ENTITY_INSPECTOR:
1002            UE.Check(m_AUIManager.GetPane(m_InspectorDialog).IsShown());
1003            break;
1004    }
1005}
1006
1007
1008void ChildFrameT::PaneToggleShow(wxAuiPaneInfo& PaneInfo)
1009{
1010    if (!PaneInfo.IsOk()) return;
1011
1012    const bool DoShow=!PaneInfo.IsShown();
1013    PaneInfo.Show(DoShow);
1014
1015    if (DoShow && PaneInfo.IsFloating() && PaneInfo.floating_pos==wxDefaultPosition)
1016        PaneInfo.FloatingPosition(ClientToScreen(wxPoint(20, 20)));
1017
1018    m_AUIManager.Update();
1019}
1020
1021
1022void ChildFrameT::OnMenuView(wxCommandEvent& CE)
1023{
1024    switch (CE.GetId())
1025    {
1026        case ID_MENU_VIEW_TOOLBARS_FILE:
1027            PaneToggleShow(m_AUIManager.GetPane("File Toolbar"));
1028            break;
1029
1030        case ID_MENU_VIEW_TOOLBARS_TOOLS:
1031            PaneToggleShow(m_AUIManager.GetPane("Tools Toolbar"));
1032            break;
1033
1034        case ID_MENU_VIEW_PANELS_TOOLOPTIONS:
1035            PaneToggleShow(m_AUIManager.GetPane("Tool Options"));
1036            break;
1037
1038        case ID_MENU_VIEW_PANELS_MATERIALS:
1039            PaneToggleShow(m_AUIManager.GetPane(m_MaterialsToolbar));
1040            break;
1041
1042        case ID_MENU_VIEW_PANELS_GROUPS:
1043            PaneToggleShow(m_AUIManager.GetPane(m_GroupsToolbar));
1044            break;
1045
1046        case ID_MENU_VIEW_PANELS_INSPECTOR:
1047            PaneToggleShow(m_AUIManager.GetPane(m_InspectorDialog));
1048            break;
1049
1050        case ID_MENU_VIEW_PANELS_CONSOLE:
1051            PaneToggleShow(m_AUIManager.GetPane(m_ConsoleDialog));
1052            break;
1053
1054        case ID_MENU_VIEW_NEW_2D_VIEW:
1055        {
1056            ViewWindow2DT* NewView=new ViewWindow2DT(this, this, ViewWindowT::VT_2D_XY);
1057            m_AUIManager.AddPane(NewView, wxAuiPaneInfo().
1058                                 // Name("xy").
1059                                 Caption(NewView->GetCaption()).
1060                                 DestroyOnClose().Float().MaximizeButton().MinimizeButton());
1061
1062            m_AUIManager.Update();
1063            break;
1064        }
1065
1066        case ID_MENU_VIEW_NEW_3D_VIEW:
1067        {
1068            ViewWindow3DT* NewView=new ViewWindow3DT(this, this, new CameraT(), (ViewWindowT::ViewTypeT)wxConfigBase::Get()->Read("Splitter/ViewType00", ViewWindowT::VT_3D_FULL_MATS));
1069            m_AUIManager.AddPane(NewView, wxAuiPaneInfo().
1070                                 // Name("xy").
1071                                 Caption(NewView->GetCaption()).
1072                                 DestroyOnClose().Float().MaximizeButton().MinimizeButton());
1073
1074            m_AUIManager.Update();
1075            break;
1076        }
1077
1078        case ID_MENU_VIEW_LOAD_DEFAULT_PERSPECTIVE:
1079            m_AUIManager.LoadPerspective(m_AUIDefaultPerspective);
1080            break;
1081
1082        case ID_MENU_VIEW_LOAD_USER_PERSPECTIVE:
1083            m_AUIManager.LoadPerspective(wxConfigBase::Get()->Read("MapEditor_AUIUserPerspective", m_AUIManager.SavePerspective()));
1084            break;
1085
1086        case ID_MENU_VIEW_SAVE_USER_PERSPECTIVE:
1087            wxConfigBase::Get()->Write("MapEditor_AUIUserPerspective", m_AUIManager.SavePerspective());
1088            break;
1089
1090        case ID_MENU_VIEW_CENTER_2D_VIEWS:
1091            All2DViews_Center(m_Doc->GetMostRecentSelBB().GetCenter());
1092            break;
1093
1094        case ID_MENU_VIEW_CENTER_3D_VIEWS:
1095        {
1096            const BoundingBox3fT& SelBB=m_Doc->GetMostRecentSelBB();
1097            const Vector3fT       Pos  =SelBB.GetCenter();
1098
1099            for (unsigned long ViewWinNr=0; ViewWinNr<m_ViewWindows.Size(); ViewWinNr++)
1100            {
1101                ViewWindowT*   ViewWin  =m_ViewWindows[ViewWinNr];
1102                ViewWindow3DT* ViewWin3D=dynamic_cast<ViewWindow3DT*>(ViewWin);
1103
1104                if (ViewWin3D)
1105                {
1106                    const CameraT& Camera=ViewWin3D->GetCamera();
1107
1108                    ViewWin3D->MoveCamera(Pos-Camera.GetYAxis()*(std::max(Camera.ViewDirLength, length(SelBB.Max-SelBB.Min)/* /2.0f */)));
1109                    break;  // Only do this for the MRU 3D view - it really doesn't make sense to do it for all.
1110                }
1111            }
1112
1113            break;
1114        }
1115    }
1116}
1117
1118
1119void ChildFrameT::OnMenuViewUpdate(wxUpdateUIEvent& UE)
1120{
1121    switch (UE.GetId())
1122    {
1123        case ID_MENU_VIEW_TOOLBARS_FILE:
1124            UE.Check(m_AUIManager.GetPane("File Toolbar").IsShown());
1125            break;
1126
1127        case ID_MENU_VIEW_TOOLBARS_TOOLS:
1128            UE.Check(m_AUIManager.GetPane("Tools Toolbar").IsShown());
1129            break;
1130
1131        case ID_MENU_VIEW_PANELS_TOOLOPTIONS:
1132            UE.Check(m_AUIManager.GetPane("Tool Options").IsShown());
1133            break;
1134
1135        case ID_MENU_VIEW_PANELS_MATERIALS:
1136            UE.Check(m_AUIManager.GetPane(m_MaterialsToolbar).IsShown());
1137            break;
1138
1139        case ID_MENU_VIEW_PANELS_GROUPS:
1140            UE.Check(m_AUIManager.GetPane(m_GroupsToolbar).IsShown());
1141            break;
1142
1143        case ID_MENU_VIEW_PANELS_INSPECTOR:
1144            UE.Check(m_AUIManager.GetPane(m_InspectorDialog).IsShown());
1145            break;
1146
1147        case ID_MENU_VIEW_PANELS_CONSOLE:
1148            UE.Check(m_AUIManager.GetPane(m_ConsoleDialog).IsShown());
1149            break;
1150    }
1151}
1152
1153
1154void ChildFrameT::OnMenuTools(wxCommandEvent& CE)
1155{
1156    // Find the tool whose wxWidgets event ID matches CE.GetId().
1157    const ArrayT<ToolT*>& Tools=m_ToolManager->GetTools();
1158
1159    for (unsigned long ToolNr=0; ToolNr<Tools.Size(); ToolNr++)
1160    {
1161        ToolT* Tool=Tools[ToolNr];
1162
1163        if (Tool->GetWxEventID()==CE.GetId())
1164        {
1165            m_ToolManager->SetActiveTool(Tool->GetType());
1166            break;
1167        }
1168    }
1169}
1170
1171
1172void ChildFrameT::OnMenuToolsUpdate(wxUpdateUIEvent& UE)
1173{
1174    const ToolT* ActiveTool=m_ToolManager->GetActiveTool();
1175
1176    UE.Check(ActiveTool && ActiveTool->GetWxEventID()==UE.GetId());
1177}
1178
1179
1180void ChildFrameT::OnMenuCompile(wxCommandEvent& CE)
1181{
1182    switch (CE.GetId())
1183    {
1184        case ID_MENU_COMPILE_QUICK:
1185        case ID_MENU_COMPILE_NORMAL:
1186        case ID_MENU_COMPILE_QUALITY:
1187        case ID_MENU_COMPILE_CUSTOM:
1188        {
1189            if (CurrentProcess!=NULL)
1190            {
1191                wxMessageBox("Another process is already running.\nWait until it is finished, then try again.");
1192                return;
1193            }
1194
1195            wxASSERT(PendingCompileCommands.Size()==0 && CurrentProcessID==0);
1196
1197            if (CompileMenu->IsChecked(ID_MENU_COMPILE_FLAG_SAVE_MAP))
1198            {
1199                // Do a regular map save.
1200                m_Doc->Save();
1201            }
1202
1203            CustomCompileDialogT CustomCompileDialog(this);
1204
1205            // If compile mode is CUSTOM, show Custom Compile Options dialog.
1206            if (CE.GetId()==ID_MENU_COMPILE_CUSTOM)
1207            {
1208                if (CustomCompileDialog.ShowModal()!=wxID_OK) return;
1209            }
1210
1211            // Console Fenster anzeigen.
1212            m_AUIManager.GetPane(m_ConsoleDialog).Show();
1213            m_AUIManager.Update();
1214
1215            if (CE.GetId()==ID_MENU_COMPILE_QUICK  ) m_ConsoleDialog->Print(wxString("\n> compile (quick) "  )+m_Doc->GetFileName()+"\n");
1216            if (CE.GetId()==ID_MENU_COMPILE_NORMAL ) m_ConsoleDialog->Print(wxString("\n> compile (normal) " )+m_Doc->GetFileName()+"\n");
1217            if (CE.GetId()==ID_MENU_COMPILE_QUALITY) m_ConsoleDialog->Print(wxString("\n> compile (quality) ")+m_Doc->GetFileName()+"\n");
1218            if (CE.GetId()==ID_MENU_COMPILE_CUSTOM ) m_ConsoleDialog->Print(wxString("\n> compile (custom) " )+m_Doc->GetFileName()+"\n");
1219
1220
1221            // Test the document file name for validity, and construct the target .cw file name from it.
1222            wxFileName MapName(m_Doc->GetFileName());
1223
1224            if (!MapName.IsOk())
1225            {
1226                m_ConsoleDialog->Print("Map file name \""+MapName.GetFullPath()+"\" is malformed.\n", wxRED);
1227                return;
1228            }
1229
1230         // MapName.Normalize();
1231            MapName.MakeRelativeTo(".");   // Make it relative to the current working directory.
1232
1233            if (MapName.GetExt()!="cmap")
1234            {
1235                m_ConsoleDialog->Print("Map file name \""+MapName.GetFullPath()+"\" doesn't end with \".cmap\".\n", wxRED);
1236                return;
1237            }
1238
1239            wxFileName WorldName(m_Doc->GetGameConfig()->ModDir+"/Worlds/"+MapName.GetName()+".cw");
1240            WorldName.MakeRelativeTo("."); // Make it relative to the current working directory.
1241
1242
1243            // Create the compile commands.
1244            {
1245                if (CompileMenu->IsChecked(ID_MENU_COMPILE_FLAG_RUN_BSP))
1246                {
1247                    if (!wxFileExists(Options.general.BSPExe))
1248                    {
1249                        EndCompiling("\nMap compilation error: '"+Options.general.BSPExe+"' File not found.\n", wxRED);
1250                        return;
1251                    }
1252
1253                    wxString Params="";
1254
1255                    if (CE.GetId()==ID_MENU_COMPILE_CUSTOM) Params=" "+CustomCompileDialog.GetCaBSPOptions();
1256
1257                    PendingCompileCommands.PushBack(Options.general.BSPExe+" \""+MapName.GetFullPath()+"\" \""+WorldName.GetFullPath()+"\""+Params);
1258                }
1259
1260                if (CompileMenu->IsChecked(ID_MENU_COMPILE_FLAG_RUN_PVS))
1261                {
1262                    if (!wxFileExists(Options.general.PVSExe))
1263                    {
1264                        EndCompiling("\nMap compilation error: '"+Options.general.PVSExe+"' File not found.\n", wxRED);
1265                        return;
1266                    }
1267
1268                    wxString Params="";
1269
1270                    if (CE.GetId()==ID_MENU_COMPILE_QUICK)  Params=" -maxRecDepthSL 15";
1271                    if (CE.GetId()==ID_MENU_COMPILE_CUSTOM) Params=" "+CustomCompileDialog.GetCaPVSOptions();
1272
1273                    PendingCompileCommands.PushBack(Options.general.PVSExe+" \""+WorldName.GetFullPath()+"\""+Params);
1274                }
1275
1276                if (CompileMenu->IsChecked(ID_MENU_COMPILE_FLAG_RUN_LIGHT))
1277                {
1278                    if (!wxFileExists(Options.general.LightExe))
1279                    {
1280                        EndCompiling("\nMap compilation error: '"+Options.general.LightExe+"' File not found.\n", wxRED);
1281                        return;
1282                    }
1283
1284                    wxFileName ModDirName=wxFileName::DirName(m_Doc->GetGameConfig()->ModDir);
1285                    wxString   Params    ="";
1286
1287                    ModDirName.MakeRelativeTo(".");
1288
1289                    if (CE.GetId()==ID_MENU_COMPILE_QUICK  ) Params=" -fast";
1290                    if (CE.GetId()==ID_MENU_COMPILE_QUALITY) Params=" -StopUE 0.1";
1291                    if (CE.GetId()==ID_MENU_COMPILE_CUSTOM ) Params=" "+CustomCompileDialog.GetCaLightOptions();
1292
1293                    PendingCompileCommands.PushBack(Options.general.LightExe+" \""+WorldName.GetFullPath()+"\" -gd="+ModDirName.GetFullPath()+Params);
1294                }
1295
1296                if (CompileMenu->IsChecked(ID_MENU_COMPILE_FLAG_RUN_ENGINE))
1297                {
1298                    if (!wxFileExists(Options.general.EngineExe))
1299                    {
1300                        EndCompiling("\nMap compilation error: '"+Options.general.EngineExe+"' File not found.\n", wxRED);
1301                        return;
1302                    }
1303
1304                    wxString Params="";
1305
1306                    if (CE.GetId()==ID_MENU_COMPILE_CUSTOM) Params=" "+CustomCompileDialog.GetEngineOptions();
1307
1308                    PendingCompileCommands.PushBack(Options.general.EngineExe +
1309                        " -svGame \"" + m_Doc->GetGameConfig()->Name + "\"" +
1310                        " -svWorld \"" + WorldName.GetName() + "\"" + Params);
1311                }
1312            }
1313
1314            // Disable the compile buttons. These are re-enabled in ChildFrameT::EndCompiling().
1315            CompileMenu->Enable(ID_MENU_COMPILE_QUICK,   false);
1316            CompileMenu->Enable(ID_MENU_COMPILE_NORMAL,  false);
1317            CompileMenu->Enable(ID_MENU_COMPILE_QUALITY, false);
1318            CompileMenu->Enable(ID_MENU_COMPILE_CUSTOM,  false);
1319            CompileMenu->Enable(ID_MENU_COMPILE_ABORT,   true);
1320
1321            // Create dummy process event and call end process to trigger compilation start.
1322            wxProcessEvent PE;  // Note: Is initialized with exit code 0.
1323            OnProcessEnd(PE);
1324
1325            break;
1326        }
1327
1328        case ID_MENU_COMPILE_ABORT:
1329        {
1330            if (CurrentProcessID==0)
1331            {
1332                wxMessageBox("There is currently no process running that could be aborted.");
1333                return;
1334            }
1335
1336            m_AUIManager.GetPane(m_ConsoleDialog).Show();
1337            m_AUIManager.Update();
1338
1339            wxKillError KillErr=wxProcess::Kill(CurrentProcessID, wxSIGKILL);
1340            m_ConsoleDialog->Print(wxString::Format("The compile process with ID %i has been terminated. Kill result: %i.\n", CurrentProcessID, KillErr), wxRED);
1341
1342            // The TERM signal triggers a call to CurrentProcess->OnTerminate() and thus a call to ChildFrameT::OnProcessEnd().
1343            //     wxASSERT(CurrentProcess==NULL && CurrentProcessID==0);
1344            // doesn't work here though, because the event system must be running so that the event can actually be processed.
1345            break;
1346        }
1347
1348        default:
1349            // We must also handle the ID_MENU_COMPILE_FLAG_* menu events here, locally in ChildFrameT.
1350            // Otherwise, the event is propagated to the parent window, where it's ID triggers an entirely unrelated action!
1351            break;
1352    }
1353}
1354
1355
1356void ChildFrameT::OnWindowActivate(wxActivateEvent& AE)
1357{
1358    AE.Skip();
1359
1360    if (!AE.GetActive()) return;
1361
1362    // To make sure the proper default material is always set, we reset it here according to current material toolbar MRU.
1363    ArrayT<EditorMaterialI*> Materials=m_MaterialsToolbar->GetMRUMaterials();
1364
1365    wxASSERT(Materials.Size()>0);
1366
1367    m_Doc->GetGameConfig()->GetMatMan().SetDefaultMaterial(Materials[0]);
1368}
1369
1370
1371void ChildFrameT::OnAuiPaneClose(wxAuiManagerEvent& AE)
1372{
1373    if (AE.GetPane()->window==m_SurfacePropsDialog || AE.GetPane()->window==m_TerrainEditorDialog)
1374    {
1375        // Reset the tool back to "Selection", this will close the specific panes.
1376        m_ToolManager->SetActiveTool(GetToolTIM().FindTypeInfoByName("ToolSelectionT"));
1377    }
1378    else
1379    {
1380        // Let the default action occur (the pane is closed).
1381        AE.Skip();
1382    }
1383}
1384
1385
1386/* void ChildFrameT::OnSize(wxSizeEvent& SE)
1387{
1388    // wxLogDebug("ChildFrameT::OnSize");
1389    // HorSplitterRatio=float(SplitterWindowParent->GetSashPosition())/float(GetClientSize().y);
1390    // VerSplitterRatio=float(SplitterWindowTop   ->GetSashPosition())/float(GetClientSize().x);
1391    // wxLogDebug("%f %f     %i %i       %i %i", HorSplitterRatio, VerSplitterRatio, GetClientSize().x, SplitterWindowParent->GetClientSize().y, SplitterWindowParent->GetSashPosition(), SplitterWindowTop->GetSashPosition());
1392
1393    SplitterWindowParent->SetSashPosition(HorSplitterRatio*SplitterWindowParent->GetClientSize().y);
1394    SplitterWindowTop   ->SetSashPosition(VerSplitterRatio*SplitterWindowTop   ->GetClientSize().x);
1395    SplitterWindowBottom->SetSashPosition(VerSplitterRatio*SplitterWindowBottom->GetClientSize().x);
1396
1397    SE.Skip();
1398}*/
1399
1400
1401void ChildFrameT::EndCompiling(const wxString& ConsoleMessage, const wxColour* Colour)
1402{
1403    delete CurrentProcess;
1404    CurrentProcess=NULL;
1405    CurrentProcessID=0;
1406
1407    PendingCompileCommands.Clear();
1408
1409    CompileMenu->Enable(ID_MENU_COMPILE_QUICK,   true);
1410    CompileMenu->Enable(ID_MENU_COMPILE_NORMAL,  true);
1411    CompileMenu->Enable(ID_MENU_COMPILE_QUALITY, true);
1412    CompileMenu->Enable(ID_MENU_COMPILE_CUSTOM,  true);
1413    CompileMenu->Enable(ID_MENU_COMPILE_ABORT,   false);
1414
1415    m_ConsoleDialog->Print(ConsoleMessage, Colour);
1416}
Note: See TracBrowser for help on using the browser.