1 /*
2  Copyright (C) 2010-2014 Kristian Duske
3 
4  This file is part of TrenchBroom.
5 
6  TrenchBroom is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  TrenchBroom is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with TrenchBroom. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "ActionManager.h"
21 
22 #include "Preferences.h"
23 #include "IO/Path.h"
24 #include "View/Action.h"
25 #include "View/CommandIds.h"
26 #include "View/Menu.h"
27 #include "View/Action.h"
28 #include "View/ViewShortcut.h"
29 #include "View/wxKeyStrings.h"
30 
31 #include <wx/accel.h>
32 #include <wx/menu.h>
33 #include <wx/menuitem.h>
34 
35 namespace TrenchBroom {
36     namespace View {
instance()37         ActionManager& ActionManager::instance() {
38             static ActionManager instance;
39             return instance;
40         }
41 
~ActionManager()42         ActionManager::~ActionManager() {
43             delete m_menuBar;
44         }
45 
findRecentDocumentsMenu(const wxMenuBar * menuBar)46         wxMenu* ActionManager::findRecentDocumentsMenu(const wxMenuBar* menuBar) {
47             const size_t fileMenuIndex = static_cast<size_t>(menuBar->FindMenu("File"));
48             const wxMenu* fileMenu = menuBar->GetMenu(fileMenuIndex);
49             if (fileMenu == NULL)
50                 return NULL;
51             const wxMenuItem* recentDocumentsItem = fileMenu->FindItem(CommandIds::Menu::FileOpenRecent);
52             if (recentDocumentsItem == NULL)
53                 return NULL;
54             return recentDocumentsItem->GetSubMenu();
55         }
56 
findMenuItem(const int id) const57         const ActionMenuItem* ActionManager::findMenuItem(const int id) const {
58             return m_menuBar->findActionMenuItem(id);
59         }
60 
getShortcutEntries(ShortcutEntryList & entries)61         void ActionManager::getShortcutEntries(ShortcutEntryList& entries) {
62             m_menuBar->getShortcutEntries(entries);
63 
64             ViewShortcut::List::iterator it, end;
65             for (it = m_viewShortcuts.begin(), end = m_viewShortcuts.end(); it != end; ++it) {
66                 ViewShortcut& shortcut = *it;
67                 entries.push_back(&shortcut);
68             }
69         }
70 
getJSTable()71         String ActionManager::getJSTable() {
72             StringStream str;
73             getKeysJSTable(str);
74             getMenuJSTable(str);
75             getActionJSTable(str);
76             return str.str();
77         }
78 
getKeysJSTable(StringStream & str)79         void ActionManager::getKeysJSTable(StringStream& str) {
80             str << "var keys = { mac: {}, windows: {}, linux: {} };" << std::endl;
81             wxKeyStringsWindows().appendJS("windows", str);
82             wxKeyStringsMac().appendJS("mac", str);
83             wxKeyStringsLinux().appendJS("linux", str);
84             str << std::endl;
85         }
86 
getMenuJSTable(StringStream & str)87         void ActionManager::getMenuJSTable(StringStream& str) {
88             str << "var menu = {};" << std::endl;
89 
90             ShortcutEntryList entries;
91             m_menuBar->getShortcutEntries(entries);
92             ShortcutEntryList::const_iterator it, end;
93             for (it = entries.begin(), end = entries.end(); it != end; ++it) {
94                 const KeyboardShortcutEntry& entry = **it;
95                 str << "menu[\"" << entry.preferencePath().asString() << "\"] = " << entry.asJsonString() << ";" << std::endl;;
96             }
97         }
98 
99         void printActionPreference(StringStream& str, const Preference<KeyboardShortcut>& pref);
printActionPreference(StringStream & str,const Preference<KeyboardShortcut> & pref)100         void printActionPreference(StringStream& str, const Preference<KeyboardShortcut>& pref) {
101             str << "actions[\"" << pref.path().asString() << "\"] = " << pref.value().asJsonString() << ";" << std::endl;
102         }
103 
getActionJSTable(StringStream & str)104         void ActionManager::getActionJSTable(StringStream& str) {
105             str << "var actions = {};" << std::endl;
106 
107             ViewShortcut::List::iterator it, end;
108             for (it = m_viewShortcuts.begin(), end = m_viewShortcuts.end(); it != end; ++it) {
109                 ViewShortcut& entry = *it;
110                 str << "actions[\"" << entry.preferencePath().asString() << "\"] = " << entry.asJsonString() << ";" << std::endl;
111             }
112 
113             printActionPreference(str, Preferences::CameraFlyForward);
114             printActionPreference(str, Preferences::CameraFlyBackward);
115             printActionPreference(str, Preferences::CameraFlyLeft);
116             printActionPreference(str, Preferences::CameraFlyRight);
117         }
118 
createMenuBar(const bool withShortcuts) const119         wxMenuBar* ActionManager::createMenuBar(const bool withShortcuts) const {
120             return m_menuBar->createMenuBar(withShortcuts);
121         }
122 
isMenuShortcutPreference(const IO::Path & path) const123         bool ActionManager::isMenuShortcutPreference(const IO::Path& path) const {
124             return !path.isEmpty() && path.firstComponent().asString() == "Menu";
125         }
126 
createViewAcceleratorTable(const ActionContext context,const ActionView view) const127         wxAcceleratorTable ActionManager::createViewAcceleratorTable(const ActionContext context, const ActionView view) const {
128             AcceleratorEntryList tableEntries;
129             addViewActions(context, view, tableEntries);
130             addMenuActions(context, view, tableEntries);
131             return wxAcceleratorTable(static_cast<int>(tableEntries.size()), &tableEntries.front());
132         }
133 
addViewActions(ActionContext context,ActionView view,AcceleratorEntryList & accelerators) const134         void ActionManager::addViewActions(ActionContext context, ActionView view, AcceleratorEntryList& accelerators) const {
135             ViewShortcut::List::const_iterator it, end;
136             for (it = m_viewShortcuts.begin(), end = m_viewShortcuts.end(); it != end; ++it) {
137                 const ViewShortcut& shortcut = *it;
138                 if (shortcut.appliesToContext(context))
139                     accelerators.push_back(shortcut.acceleratorEntry(view));
140             }
141         }
142 
addMenuActions(ActionContext context,ActionView view,AcceleratorEntryList & accelerators) const143         void ActionManager::addMenuActions(ActionContext context, ActionView view, AcceleratorEntryList& accelerators) const {
144             ShortcutEntryList menuShortcuts;
145             m_menuBar->getShortcutEntries(menuShortcuts);
146             ShortcutEntryList::const_iterator it, end;
147             for (it = menuShortcuts.begin(), end = menuShortcuts.end(); it != end; ++it) {
148                 const KeyboardShortcutEntry* entry = *it;
149                 if (entry->appliesToContext(context))
150                     accelerators.push_back(entry->acceleratorEntry(view));
151             }
152         }
153 
resetShortcutsToDefaults()154         void ActionManager::resetShortcutsToDefaults() {
155             m_menuBar->resetShortcuts();
156 
157             ViewShortcut::List::iterator it, end;
158             for (it = m_viewShortcuts.begin(), end = m_viewShortcuts.end(); it != end; ++it) {
159                 ViewShortcut& shortcut = *it;
160                 shortcut.resetShortcut();
161             }
162         }
163 
ActionManager()164         ActionManager::ActionManager() :
165         m_menuBar(NULL) {
166             createMenuBar();
167             createViewShortcuts();
168         }
169 
createMenuBar()170         void ActionManager::createMenuBar() {
171             assert(m_menuBar == NULL);
172             m_menuBar = new MenuBar();
173 
174             Menu* fileMenu = m_menuBar->addMenu("File");
175             fileMenu->addUnmodifiableActionItem(wxID_NEW, "New", KeyboardShortcut('N', WXK_CONTROL));
176             fileMenu->addSeparator();
177             fileMenu->addUnmodifiableActionItem(wxID_OPEN, "Open...", KeyboardShortcut('O', WXK_CONTROL));
178             fileMenu->addMenu(CommandIds::Menu::FileOpenRecent, "Open Recent");
179             fileMenu->addSeparator();
180             fileMenu->addUnmodifiableActionItem(wxID_SAVE, "Save", KeyboardShortcut('S', WXK_CONTROL));
181             fileMenu->addUnmodifiableActionItem(wxID_SAVEAS, "Save as...", KeyboardShortcut('S', WXK_SHIFT, WXK_CONTROL));
182             fileMenu->addSeparator();
183             fileMenu->addModifiableActionItem(CommandIds::Menu::FileLoadPointFile, "Load Point File");
184             fileMenu->addModifiableActionItem(CommandIds::Menu::FileUnloadPointFile, "Unload Point File");
185             fileMenu->addSeparator();
186             fileMenu->addUnmodifiableActionItem(wxID_CLOSE, "Close", KeyboardShortcut('W', WXK_CONTROL));
187 
188             Menu* editMenu = m_menuBar->addMenu("Edit");
189             editMenu->addUnmodifiableActionItem(wxID_UNDO, "Undo", KeyboardShortcut('Z', WXK_CONTROL));
190             editMenu->addUnmodifiableActionItem(wxID_REDO, "Redo", KeyboardShortcut('Z', WXK_CONTROL, WXK_SHIFT));
191             editMenu->addSeparator();
192             editMenu->addModifiableActionItem(CommandIds::Menu::EditRepeat, "Repeat", KeyboardShortcut('R', WXK_CONTROL));
193             editMenu->addModifiableActionItem(CommandIds::Menu::EditClearRepeat, "Clear Repeatable Commands", KeyboardShortcut('R', WXK_CONTROL, WXK_SHIFT));
194             editMenu->addSeparator();
195             editMenu->addUnmodifiableActionItem(wxID_CUT, "Cut", KeyboardShortcut('X', WXK_CONTROL));
196             editMenu->addUnmodifiableActionItem(wxID_COPY, "Copy", KeyboardShortcut('C', WXK_CONTROL));
197             editMenu->addUnmodifiableActionItem(wxID_PASTE, "Paste", KeyboardShortcut('V', WXK_CONTROL));
198             editMenu->addModifiableActionItem(CommandIds::Menu::EditPasteAtOriginalPosition, "Paste at Original Position", KeyboardShortcut('V', WXK_CONTROL, WXK_ALT));
199             editMenu->addModifiableActionItem(wxID_DUPLICATE, "Duplicate", KeyboardShortcut('D', WXK_CONTROL));
200 #ifdef __APPLE__
201             editMenu->addModifiableActionItem(wxID_DELETE, "Delete", KeyboardShortcut(WXK_BACK));
202 #else
203             editMenu->addModifiableActionItem(wxID_DELETE, "Delete", KeyboardShortcut(WXK_DELETE));
204 #endif
205 
206             editMenu->addSeparator();
207             editMenu->addModifiableActionItem(CommandIds::Menu::EditSelectAll, "Select All", KeyboardShortcut('A', WXK_CONTROL));
208             editMenu->addModifiableActionItem(CommandIds::Menu::EditSelectSiblings, "Select Siblings", KeyboardShortcut('B', WXK_CONTROL));
209             editMenu->addModifiableActionItem(CommandIds::Menu::EditSelectTouching, "Select Touching", KeyboardShortcut('T', WXK_CONTROL));
210             editMenu->addModifiableActionItem(CommandIds::Menu::EditSelectInside, "Select Inside", KeyboardShortcut('E', WXK_CONTROL));
211             editMenu->addModifiableActionItem(CommandIds::Menu::EditSelectTall, "Select Tall", KeyboardShortcut('E', WXK_CONTROL, WXK_SHIFT));
212             editMenu->addModifiableActionItem(CommandIds::Menu::EditSelectByFilePosition, "Select by Line Number");
213             editMenu->addModifiableActionItem(CommandIds::Menu::EditSelectNone, "Select None", KeyboardShortcut('A', WXK_CONTROL, WXK_SHIFT));
214             editMenu->addSeparator();
215 
216             editMenu->addModifiableActionItem(CommandIds::Menu::EditGroupSelection, "Group", KeyboardShortcut('G', WXK_CONTROL));
217             editMenu->addModifiableActionItem(CommandIds::Menu::EditUngroupSelection, "Ungroup", KeyboardShortcut('G', WXK_CONTROL, WXK_SHIFT));
218             editMenu->addSeparator();
219 
220             Menu* toolMenu = editMenu->addMenu("Tools");
221             toolMenu->addModifiableCheckItem(CommandIds::Menu::EditToggleCreateComplexBrushTool, "Brush Tool", KeyboardShortcut('B'));
222             toolMenu->addModifiableCheckItem(CommandIds::Menu::EditToggleClipTool, "Clip Tool", KeyboardShortcut('C'));
223             toolMenu->addModifiableCheckItem(CommandIds::Menu::EditToggleRotateObjectsTool, "Rotate Tool", KeyboardShortcut('R'));
224             toolMenu->addModifiableCheckItem(CommandIds::Menu::EditToggleVertexTool, "Vertex Tool", KeyboardShortcut('V'));
225 
226             Menu* csgMenu = editMenu->addMenu("CSG");
227             csgMenu->addModifiableActionItem(CommandIds::Menu::EditCsgConvexMerge, "Convex Merge", KeyboardShortcut('+', WXK_CONTROL));
228             csgMenu->addModifiableActionItem(CommandIds::Menu::EditCsgSubtract, "Subtract", KeyboardShortcut('-', WXK_CONTROL));
229             csgMenu->addModifiableActionItem(CommandIds::Menu::EditCsgIntersect, "Intersect", KeyboardShortcut('#', WXK_CONTROL));
230 
231             editMenu->addSeparator();
232             editMenu->addModifiableActionItem(CommandIds::Menu::EditSnapVerticesToInteger, "Snap Vertices to Integer", KeyboardShortcut('V', WXK_SHIFT, WXK_CONTROL));
233             editMenu->addModifiableActionItem(CommandIds::Menu::EditSnapVerticesToGrid, "Snap Vertices to Grid", KeyboardShortcut('V', WXK_SHIFT, WXK_CONTROL, WXK_ALT));
234             editMenu->addSeparator();
235             editMenu->addModifiableCheckItem(CommandIds::Menu::EditToggleTextureLock, "Texture Lock");
236             editMenu->addModifiableActionItem(CommandIds::Menu::EditReplaceTexture, "Replace Texture...");
237 
238 
239             Menu* viewMenu = m_menuBar->addMenu("View");
240             Menu* gridMenu = viewMenu->addMenu("Grid");
241             gridMenu->addModifiableCheckItem(CommandIds::Menu::ViewToggleShowGrid, "Show Grid", KeyboardShortcut('0'));
242             gridMenu->addModifiableCheckItem(CommandIds::Menu::ViewToggleSnapToGrid, "Snap to Grid", KeyboardShortcut('0', WXK_ALT));
243             gridMenu->addModifiableCheckItem(CommandIds::Menu::ViewIncGridSize, "Increase Grid Size", KeyboardShortcut('+'));
244             gridMenu->addModifiableCheckItem(CommandIds::Menu::ViewDecGridSize, "Decrease Grid Size", KeyboardShortcut('-'));
245             gridMenu->addSeparator();
246             gridMenu->addModifiableCheckItem(CommandIds::Menu::ViewSetGridSize1, "Set Grid Size 1", KeyboardShortcut('1'));
247             gridMenu->addModifiableCheckItem(CommandIds::Menu::ViewSetGridSize2, "Set Grid Size 2", KeyboardShortcut('2'));
248             gridMenu->addModifiableCheckItem(CommandIds::Menu::ViewSetGridSize4, "Set Grid Size 4", KeyboardShortcut('3'));
249             gridMenu->addModifiableCheckItem(CommandIds::Menu::ViewSetGridSize8, "Set Grid Size 8", KeyboardShortcut('4'));
250             gridMenu->addModifiableCheckItem(CommandIds::Menu::ViewSetGridSize16, "Set Grid Size 16", KeyboardShortcut('5'));
251             gridMenu->addModifiableCheckItem(CommandIds::Menu::ViewSetGridSize32, "Set Grid Size 32", KeyboardShortcut('6'));
252             gridMenu->addModifiableCheckItem(CommandIds::Menu::ViewSetGridSize64, "Set Grid Size 64", KeyboardShortcut('7'));
253             gridMenu->addModifiableCheckItem(CommandIds::Menu::ViewSetGridSize128, "Set Grid Size 128", KeyboardShortcut('8'));
254             gridMenu->addModifiableCheckItem(CommandIds::Menu::ViewSetGridSize256, "Set Grid Size 256", KeyboardShortcut('9'));
255 
256             Menu* cameraMenu = viewMenu->addMenu("Camera");
257             cameraMenu->addModifiableActionItem(CommandIds::Menu::ViewMoveCameraToNextPoint, "Move to Next Point", KeyboardShortcut('.'));
258             cameraMenu->addModifiableActionItem(CommandIds::Menu::ViewMoveCameraToPreviousPoint, "Move to Previous Point", KeyboardShortcut(','));
259             cameraMenu->addModifiableActionItem(CommandIds::Menu::ViewFocusCameraOnSelection, "Focus on Selection", KeyboardShortcut('U', WXK_CONTROL));
260             cameraMenu->addModifiableActionItem(CommandIds::Menu::ViewMoveCameraToPosition, "Move Camera to...");
261             cameraMenu->addSeparator();
262 
263             viewMenu->addSeparator();
264             viewMenu->addModifiableActionItem(CommandIds::Menu::ViewIsolateSelection, "Isolate", KeyboardShortcut('I', WXK_CONTROL));
265             viewMenu->addModifiableActionItem(CommandIds::Menu::ViewHideSelection, "Hide", KeyboardShortcut('I', WXK_CONTROL, WXK_ALT));
266             viewMenu->addModifiableActionItem(CommandIds::Menu::ViewUnhideAll, "Show All", KeyboardShortcut('I', WXK_CONTROL, WXK_SHIFT));
267 
268             viewMenu->addSeparator();
269             viewMenu->addModifiableActionItem(CommandIds::Menu::ViewSwitchToMapInspector, "Switch to Map Inspector", KeyboardShortcut('1', WXK_CONTROL));
270             viewMenu->addModifiableActionItem(CommandIds::Menu::ViewSwitchToEntityInspector, "Switch to Entity Inspector", KeyboardShortcut('2', WXK_CONTROL));
271             viewMenu->addModifiableActionItem(CommandIds::Menu::ViewSwitchToFaceInspector, "Switch to Face Inspector", KeyboardShortcut('3', WXK_CONTROL));
272             viewMenu->addSeparator();
273             viewMenu->addModifiableCheckItem(CommandIds::Menu::ViewToggleInfoPanel, "Toggle Info Panel", KeyboardShortcut('4', WXK_CONTROL));
274             viewMenu->addModifiableCheckItem(CommandIds::Menu::ViewToggleInspector, "Toggle Inspector", KeyboardShortcut('5', WXK_CONTROL));
275             viewMenu->addSeparator();
276             viewMenu->addModifiableCheckItem(CommandIds::Menu::ViewToggleMaximizeCurrentView, "Maximize Current View", KeyboardShortcut(WXK_SPACE, WXK_CONTROL));
277 
278 
279 #ifndef NDEBUG
280             Menu* debugMenu = m_menuBar->addMenu("Debug");
281             debugMenu->addUnmodifiableActionItem(CommandIds::Menu::DebugPrintVertices, "Print Vertices");
282             debugMenu->addUnmodifiableActionItem(CommandIds::Menu::DebugCreateBrush, "Create Brush...");
283             debugMenu->addUnmodifiableActionItem(CommandIds::Menu::DebugCopyJSShortcuts, "Copy Javascript Shortcut Map");
284 #endif
285 
286             Menu* helpMenu = m_menuBar->addMenu("Help");
287             helpMenu->addUnmodifiableActionItem(wxID_HELP, "TrenchBroom Help");
288 
289 #ifdef __APPLE__
290             // these won't show up in the app menu if we don't add them here
291             fileMenu->addUnmodifiableActionItem(wxID_ABOUT, "About TrenchBroom");
292             fileMenu->addUnmodifiableActionItem(wxID_PREFERENCES, "Preferences...", KeyboardShortcut(',', WXK_CONTROL));
293             fileMenu->addUnmodifiableActionItem(wxID_EXIT, "Exit");
294 #else
295             viewMenu->addSeparator();
296             viewMenu->addUnmodifiableActionItem(wxID_PREFERENCES, "Preferences...");
297 
298             helpMenu->addSeparator();
299             helpMenu->addUnmodifiableActionItem(wxID_ABOUT, "About TrenchBroom");
300 #endif
301         }
302 
createViewShortcuts()303         void ActionManager::createViewShortcuts() {
304             createViewShortcut(KeyboardShortcut(WXK_RETURN), ActionContext_CreateComplexBrushTool,
305                                Action(View::CommandIds::Actions::Nothing, "", false),
306                                Action(View::CommandIds::Actions::PerformCreateBrush, "Create brush", true));
307 
308             createViewShortcut(KeyboardShortcut(WXK_RETURN, WXK_CONTROL), ActionContext_ClipTool,
309                                Action(View::CommandIds::Actions::ToggleClipSide, "Toggle clip side", true));
310             createViewShortcut(KeyboardShortcut(WXK_RETURN), ActionContext_ClipTool,
311                                Action(View::CommandIds::Actions::PerformClip, "Perform clip", true));
312 #ifdef __APPLE__
313             createViewShortcut(KeyboardShortcut(WXK_BACK, WXK_CONTROL), ActionContext_ClipTool,
314                                Action(View::CommandIds::Actions::RemoveLastClipPoint, "Delete last clip point", true));
315 #else
316             createViewShortcut(KeyboardShortcut(WXK_DELETE, WXK_CONTROL), ActionContext_ClipTool,
317                                Action(View::CommandIds::Actions::RemoveLastClipPoint, "Delete last clip point", true));
318 #endif
319 
320             createViewShortcut(KeyboardShortcut(WXK_UP), ActionContext_VertexTool,
321                                Action(View::CommandIds::Actions::MoveVerticesUp, "Move vertices up", true),
322                                Action(View::CommandIds::Actions::MoveVerticesForward, "Move vertices forward", true));
323             createViewShortcut(KeyboardShortcut(WXK_DOWN), ActionContext_VertexTool,
324                                Action(View::CommandIds::Actions::MoveVerticesDown, "Move vertices down", true),
325                                Action(View::CommandIds::Actions::MoveVerticesBackward, "Move vertices backward", true));
326             createViewShortcut(KeyboardShortcut(WXK_LEFT), ActionContext_VertexTool,
327                                Action(View::CommandIds::Actions::MoveVerticesLeft, "Move vertices left", true));
328             createViewShortcut(KeyboardShortcut(WXK_RIGHT), ActionContext_VertexTool,
329                                Action(View::CommandIds::Actions::MoveVerticesRight, "Move vertices right", true));
330             createViewShortcut(KeyboardShortcut(WXK_PAGEUP), ActionContext_VertexTool,
331                                Action(View::CommandIds::Actions::MoveVerticesForward, "Move vertices forward", true),
332                                Action(View::CommandIds::Actions::MoveVerticesUp, "Move vertices up", true));
333             createViewShortcut(KeyboardShortcut(WXK_PAGEDOWN), ActionContext_VertexTool,
334                                Action(View::CommandIds::Actions::MoveVerticesBackward, "Move vertices backward", true),
335                                Action(View::CommandIds::Actions::MoveVerticesDown, "Move vertices down", true));
336 
337             createViewShortcut(KeyboardShortcut(WXK_UP), ActionContext_RotateTool,
338                                Action(View::CommandIds::Actions::MoveRotationCenterUp, "Move rotation center up", true),
339                                Action(View::CommandIds::Actions::MoveRotationCenterForward, "Move rotation center forward", true));
340             createViewShortcut(KeyboardShortcut(WXK_DOWN), ActionContext_RotateTool,
341                                Action(View::CommandIds::Actions::MoveRotationCenterDown, "Move rotation center down", true),
342                                Action(View::CommandIds::Actions::MoveRotationCenterBackward, "Move rotation center backward", true));
343             createViewShortcut(KeyboardShortcut(WXK_LEFT), ActionContext_RotateTool,
344                                Action(View::CommandIds::Actions::MoveRotationCenterLeft, "Move rotation center left", true));
345             createViewShortcut(KeyboardShortcut(WXK_RIGHT), ActionContext_RotateTool,
346                                Action(View::CommandIds::Actions::MoveRotationCenterRight, "Move rotation center right", true));
347             createViewShortcut(KeyboardShortcut(WXK_PAGEUP), ActionContext_RotateTool,
348                                Action(View::CommandIds::Actions::MoveRotationCenterForward, "Move rotation center forward", true),
349                                Action(View::CommandIds::Actions::MoveRotationCenterUp, "Move rotation center up", true));
350             createViewShortcut(KeyboardShortcut(WXK_PAGEDOWN), ActionContext_RotateTool,
351                                Action(View::CommandIds::Actions::MoveRotationCenterBackward, "Move rotation center backward", true),
352                                Action(View::CommandIds::Actions::MoveRotationCenterDown, "Move rotation center down", true));
353 
354             createViewShortcut(KeyboardShortcut('F'), ActionContext_Any, Action(),
355                                Action(View::CommandIds::Actions::ToggleFlyMode, "Toggle fly mode", true));
356 
357             createViewShortcut(KeyboardShortcut(WXK_UP), ActionContext_NodeSelection,
358                                Action(View::CommandIds::Actions::MoveObjectsUp, "Move objects up", true),
359                                Action(View::CommandIds::Actions::MoveObjectsForward, "Move objects forward", true));
360             createViewShortcut(KeyboardShortcut(WXK_DOWN), ActionContext_NodeSelection,
361                                Action(View::CommandIds::Actions::MoveObjectsDown, "Move objects down", true),
362                                Action(View::CommandIds::Actions::MoveObjectsBackward, "Move objects backward", true));
363             createViewShortcut(KeyboardShortcut(WXK_LEFT), ActionContext_NodeSelection,
364                                Action(View::CommandIds::Actions::MoveObjectsLeft, "Move objects left", true));
365             createViewShortcut(KeyboardShortcut(WXK_RIGHT), ActionContext_NodeSelection,
366                                Action(View::CommandIds::Actions::MoveObjectsRight, "Move objects right", true));
367             createViewShortcut(KeyboardShortcut(WXK_PAGEUP), ActionContext_NodeSelection,
368                                Action(View::CommandIds::Actions::MoveObjectsForward, "Move objects forward", true),
369                                Action(View::CommandIds::Actions::MoveObjectsUp, "Move objects up", true));
370             createViewShortcut(KeyboardShortcut(WXK_PAGEDOWN), ActionContext_NodeSelection,
371                                Action(View::CommandIds::Actions::MoveObjectsBackward, "Move objects backward", true),
372                                Action(View::CommandIds::Actions::MoveObjectsDown, "Move objects down", true));
373 
374             createViewShortcut(KeyboardShortcut(WXK_UP, WXK_ALT), ActionContext_NodeSelection,
375                                Action(View::CommandIds::Actions::RollObjectsCW, "Roll objects clockwise", true));
376             createViewShortcut(KeyboardShortcut(WXK_DOWN, WXK_ALT), ActionContext_NodeSelection,
377                                Action(View::CommandIds::Actions::RollObjectsCCW, "Roll objects counter-clockwise", true));
378             createViewShortcut(KeyboardShortcut(WXK_LEFT, WXK_ALT), ActionContext_NodeSelection,
379                                Action(View::CommandIds::Actions::YawObjectsCW, "Yaw objects clockwise", true));
380             createViewShortcut(KeyboardShortcut(WXK_RIGHT, WXK_ALT), ActionContext_NodeSelection,
381                                Action(View::CommandIds::Actions::YawObjectsCCW, "Yaw objects counter-clockwise", true));
382             createViewShortcut(KeyboardShortcut(WXK_PAGEUP, WXK_ALT), ActionContext_NodeSelection,
383                                Action(View::CommandIds::Actions::PitchObjectsCW, "Pitch objects clockwise", true));
384             createViewShortcut(KeyboardShortcut(WXK_PAGEDOWN, WXK_ALT), ActionContext_NodeSelection,
385                                Action(View::CommandIds::Actions::PitchObjectsCCW, "Pitch objects counter-clockwise", true));
386 
387             createViewShortcut(KeyboardShortcut('F', WXK_CONTROL), ActionContext_NodeSelection,
388                                Action(View::CommandIds::Actions::FlipObjectsHorizontally, "Flip objects horizontally", true));
389             createViewShortcut(KeyboardShortcut('F', WXK_CONTROL, WXK_ALT), ActionContext_NodeSelection,
390                                Action(View::CommandIds::Actions::FlipObjectsVertically, "Flip objects vertically", true));
391 
392             createViewShortcut(KeyboardShortcut(WXK_UP, WXK_CONTROL), ActionContext_NodeSelection,
393                                Action(View::CommandIds::Actions::DuplicateObjectsUp, "Duplicate and move objects up", true),
394                                Action(View::CommandIds::Actions::DuplicateObjectsForward, "Duplicate and move objects forward", true));
395             createViewShortcut(KeyboardShortcut(WXK_DOWN, WXK_CONTROL), ActionContext_NodeSelection,
396                                Action(View::CommandIds::Actions::DuplicateObjectsDown, "Duplicate and move objects down", true),
397                                Action(View::CommandIds::Actions::DuplicateObjectsBackward, "Duplicate and move objects backward", true));
398             createViewShortcut(KeyboardShortcut(WXK_LEFT, WXK_CONTROL), ActionContext_NodeSelection,
399                                Action(View::CommandIds::Actions::DuplicateObjectsLeft, "Duplicate and move objects left", true));
400             createViewShortcut(KeyboardShortcut(WXK_RIGHT, WXK_CONTROL), ActionContext_NodeSelection,
401                                Action(View::CommandIds::Actions::DuplicateObjectsRight, "Duplicate and move objects right", true));
402             createViewShortcut(KeyboardShortcut(WXK_PAGEUP, WXK_CONTROL), ActionContext_NodeSelection,
403                                Action(View::CommandIds::Actions::DuplicateObjectsForward, "Duplicate and move objects forward", true),
404                                Action(View::CommandIds::Actions::DuplicateObjectsUp, "Duplicate and move objects up", true));
405             createViewShortcut(KeyboardShortcut(WXK_PAGEDOWN, WXK_CONTROL), ActionContext_NodeSelection,
406                                Action(View::CommandIds::Actions::DuplicateObjectsBackward, "Duplicate and move objects backward", true),
407                                Action(View::CommandIds::Actions::DuplicateObjectsDown, "Duplicate and move objects down", true));
408 
409             createViewShortcut(KeyboardShortcut(WXK_UP), ActionContext_FaceSelection, Action(),
410                                Action(View::CommandIds::Actions::MoveTexturesUp, "Move textures up", true));
411             createViewShortcut(KeyboardShortcut(WXK_UP, WXK_CONTROL), ActionContext_FaceSelection, Action(),
412                                Action(View::CommandIds::Actions::MoveTexturesUp, "Move textures up (fine)", true));
413             createViewShortcut(KeyboardShortcut(WXK_UP, WXK_SHIFT), ActionContext_FaceSelection, Action(),
414                                Action(View::CommandIds::Actions::MoveTexturesUp, "Move textures up (coarse)", true));
415             createViewShortcut(KeyboardShortcut(WXK_DOWN), ActionContext_FaceSelection, Action(),
416                                Action(View::CommandIds::Actions::MoveTexturesDown, "Move textures down", true));
417             createViewShortcut(KeyboardShortcut(WXK_DOWN, WXK_CONTROL), ActionContext_FaceSelection, Action(),
418                                Action(View::CommandIds::Actions::MoveTexturesDown, "Move textures down (fine)", true));
419             createViewShortcut(KeyboardShortcut(WXK_DOWN, WXK_SHIFT), ActionContext_FaceSelection, Action(),
420                                Action(View::CommandIds::Actions::MoveTexturesDown, "Move textures down (coarse)", true));
421             createViewShortcut(KeyboardShortcut(WXK_LEFT), ActionContext_FaceSelection, Action(),
422                                Action(View::CommandIds::Actions::MoveTexturesLeft, "Move textures left", true));
423             createViewShortcut(KeyboardShortcut(WXK_LEFT, WXK_CONTROL), ActionContext_FaceSelection, Action(),
424                                Action(View::CommandIds::Actions::MoveTexturesLeft, "Move textures left (fine)", true));
425             createViewShortcut(KeyboardShortcut(WXK_LEFT, WXK_SHIFT), ActionContext_FaceSelection, Action(),
426                                Action(View::CommandIds::Actions::MoveTexturesLeft, "Move textures left (coarse)", true));
427             createViewShortcut(KeyboardShortcut(WXK_RIGHT), ActionContext_FaceSelection, Action(),
428                                Action(View::CommandIds::Actions::MoveTexturesRight, "Move textures right", true));
429             createViewShortcut(KeyboardShortcut(WXK_RIGHT, WXK_CONTROL), ActionContext_FaceSelection, Action(),
430                                Action(View::CommandIds::Actions::MoveTexturesRight, "Move textures right (fine)", true));
431             createViewShortcut(KeyboardShortcut(WXK_RIGHT, WXK_SHIFT), ActionContext_FaceSelection, Action(),
432                                Action(View::CommandIds::Actions::MoveTexturesRight, "Move textures right (coarse)", true));
433 
434             createViewShortcut(KeyboardShortcut(WXK_PAGEUP), ActionContext_FaceSelection, Action(),
435                                Action(View::CommandIds::Actions::RotateTexturesCW, "Rotate textures clockwise", true));
436             createViewShortcut(KeyboardShortcut(WXK_PAGEUP, WXK_CONTROL), ActionContext_FaceSelection, Action(),
437                                Action(View::CommandIds::Actions::RotateTexturesCW, "Rotate textures clockwise (fine)", true));
438             createViewShortcut(KeyboardShortcut(WXK_PAGEUP, WXK_SHIFT), ActionContext_FaceSelection, Action(),
439                                Action(View::CommandIds::Actions::RotateTexturesCW, "Rotate textures clockwise (coarse)", true));
440             createViewShortcut(KeyboardShortcut(WXK_PAGEDOWN), ActionContext_FaceSelection, Action(),
441                                Action(View::CommandIds::Actions::RotateTexturesCCW, "Rotate textures counter-clockwise", true));
442             createViewShortcut(KeyboardShortcut(WXK_PAGEDOWN, WXK_CONTROL), ActionContext_FaceSelection, Action(),
443                                Action(View::CommandIds::Actions::RotateTexturesCCW, "Rotate textures counter-clockwise (fine)", true));
444             createViewShortcut(KeyboardShortcut(WXK_PAGEDOWN, WXK_SHIFT), ActionContext_FaceSelection, Action(),
445                                Action(View::CommandIds::Actions::RotateTexturesCCW, "Rotate textures counter-clockwise (coarse)", true));
446 
447             createViewShortcut(KeyboardShortcut(WXK_SPACE), ActionContext_Any,
448                                Action(View::CommandIds::Actions::CycleMapViews, "Cycle map view", true));
449 
450             createViewShortcut(KeyboardShortcut(WXK_ESCAPE), ActionContext_Any,
451                                Action(View::CommandIds::Actions::Cancel, "Cancel", true));
452             createViewShortcut(KeyboardShortcut(WXK_ESCAPE, WXK_CONTROL), ActionContext_Any,
453                                Action(View::CommandIds::Actions::DeactivateTool, "Deactivate current tool", true));
454         }
455 
createViewShortcut(const KeyboardShortcut & shortcut,const int context,const Action & action2D,const Action & action3D)456         void ActionManager::createViewShortcut(const KeyboardShortcut& shortcut, const int context, const Action& action2D, const Action& action3D) {
457             m_viewShortcuts.push_back(ViewShortcut(shortcut, context, action2D, action3D));
458         }
459 
createViewShortcut(const KeyboardShortcut & shortcut,const int context,const Action & action)460         void ActionManager::createViewShortcut(const KeyboardShortcut& shortcut, const int context, const Action& action) {
461             m_viewShortcuts.push_back(ViewShortcut(shortcut, context, action));
462         }
463     }
464 }
465