1// This file can be included several times.
2
3#ifndef REGISTER_QUICK_ACTION
4// This helps IDEs properly syntax highlight the uses of the macro below.
5#define REGISTER_QUICK_ACTION(name, text, callback, disabled, active, button_color, description)
6#endif
7
8#define ALWAYS_FALSE []() -> bool { return false; }
9#define DEFAULT_BTN []() -> int { return -1; }
10
11REGISTER_QUICK_ACTION(
12 ShowHelp,
13 "Show help",
14 [&]() { ShowHelp(); },
15 ALWAYS_FALSE,
16 ALWAYS_FALSE,
17 DEFAULT_BTN,
18 "[F1] Open the DDNet Wiki page for the map editor in a web browser.")
19REGISTER_QUICK_ACTION(
20 Exit,
21 "Exit",
22 [&]() { Exit(); },
23 ALWAYS_FALSE,
24 ALWAYS_FALSE,
25 DEFAULT_BTN,
26 "[Escape] Exit from the editor.")
27REGISTER_QUICK_ACTION(
28 BrushPicker,
29 "Brush picker",
30 [&]() { m_ShowPickerToggle = !m_ShowPickerToggle; },
31 [&]() -> bool {
32 return m_Mode != MODE_LAYERS ||
33 Map()->m_vSelectedLayers.size() != 1 ||
34 Map()->SelectedLayer(0) == nullptr ||
35 (Map()->SelectedLayer(0)->m_Type != LAYERTYPE_TILES && Map()->SelectedLayer(0)->m_Type != LAYERTYPE_QUADS);
36 },
37 [&]() -> bool { return m_ShowPickerToggle; },
38 DEFAULT_BTN,
39 "[Ctrl+Space, Hold Space] Toggle brush picker.")
40REGISTER_QUICK_ACTION(
41 ToggleGrid,
42 "Toggle grid",
43 [&]() { MapView()->MapGrid()->Toggle(); },
44 ALWAYS_FALSE,
45 [&]() -> bool { return MapView()->MapGrid()->IsEnabled(); },
46 DEFAULT_BTN,
47 "[Ctrl+G] Toggle grid.")
48REGISTER_QUICK_ACTION(
49 GameTilesAir,
50 "Game tiles: Air",
51 [&]() { FillGameTiles(EGameTileOp::AIR); },
52 [&]() -> bool { return !CanFillGameTiles(); },
53 ALWAYS_FALSE,
54 DEFAULT_BTN,
55 "Construct game tiles from this layer.")
56REGISTER_QUICK_ACTION(
57 GameTilesHookable,
58 "Game tiles: Hookable",
59 [&]() { FillGameTiles(EGameTileOp::HOOKABLE); },
60 [&]() -> bool { return !CanFillGameTiles(); },
61 ALWAYS_FALSE,
62 DEFAULT_BTN,
63 "Construct game tiles from this layer.")
64REGISTER_QUICK_ACTION(
65 GameTilesDeath,
66 "Game tiles: Death",
67 [&]() { FillGameTiles(EGameTileOp::DEATH); },
68 [&]() -> bool { return !CanFillGameTiles(); },
69 ALWAYS_FALSE,
70 DEFAULT_BTN,
71 "Construct game tiles from this layer.")
72REGISTER_QUICK_ACTION(
73 GameTilesUnhookable,
74 "Game tiles: Unhookable",
75 [&]() { FillGameTiles(EGameTileOp::UNHOOKABLE); },
76 [&]() -> bool { return !CanFillGameTiles(); },
77 ALWAYS_FALSE,
78 DEFAULT_BTN,
79 "Construct game tiles from this layer.")
80REGISTER_QUICK_ACTION(
81 GameTilesHookthrough,
82 "Game tiles: Hookthrough",
83 [&]() { FillGameTiles(EGameTileOp::HOOKTHROUGH); },
84 [&]() -> bool { return !CanFillGameTiles(); },
85 ALWAYS_FALSE,
86 DEFAULT_BTN,
87 "Construct game tiles from this layer.")
88REGISTER_QUICK_ACTION(
89 GameTilesFreeze,
90 "Game tiles: Freeze",
91 [&]() { FillGameTiles(EGameTileOp::FREEZE); },
92 [&]() -> bool { return !CanFillGameTiles(); },
93 ALWAYS_FALSE,
94 DEFAULT_BTN,
95 "Construct game tiles from this layer.")
96REGISTER_QUICK_ACTION(
97 GameTilesUnfreeze,
98 "Game tiles: Unfreeze",
99 [&]() { FillGameTiles(EGameTileOp::UNFREEZE); },
100 [&]() -> bool { return !CanFillGameTiles(); },
101 ALWAYS_FALSE,
102 DEFAULT_BTN,
103 "Construct game tiles from this layer.")
104REGISTER_QUICK_ACTION(
105 GameTilesDeepFreeze,
106 "Game tiles: Deep Freeze",
107 [&]() { FillGameTiles(EGameTileOp::DEEP_FREEZE); },
108 [&]() -> bool { return !CanFillGameTiles(); },
109 ALWAYS_FALSE,
110 DEFAULT_BTN,
111 "Construct game tiles from this layer.")
112REGISTER_QUICK_ACTION(
113 GameTilesDeepUnfreeze,
114 "Game tiles: Deep Unfreeze",
115 [&]() { FillGameTiles(EGameTileOp::DEEP_UNFREEZE); },
116 [&]() -> bool { return !CanFillGameTiles(); },
117 ALWAYS_FALSE,
118 DEFAULT_BTN,
119 "Construct game tiles from this layer.")
120REGISTER_QUICK_ACTION(
121 GameTilesBlueCheckTele,
122 "Game tiles: Blue Check Tele",
123 [&]() { FillGameTiles(EGameTileOp::BLUE_CHECK_TELE); },
124 [&]() -> bool { return !CanFillGameTiles(); },
125 ALWAYS_FALSE,
126 DEFAULT_BTN,
127 "Construct game tiles from this layer.")
128REGISTER_QUICK_ACTION(
129 GameTilesRedCheckTele,
130 "Game tiles: Red Check Tele",
131 [&]() { FillGameTiles(EGameTileOp::RED_CHECK_TELE); },
132 [&]() -> bool { return !CanFillGameTiles(); },
133 ALWAYS_FALSE,
134 DEFAULT_BTN,
135 "Construct game tiles from this layer.")
136REGISTER_QUICK_ACTION(
137 GameTilesLiveFreeze,
138 "Game tiles: Live Freeze",
139 [&]() { FillGameTiles(EGameTileOp::LIVE_FREEZE); },
140 [&]() -> bool { return !CanFillGameTiles(); },
141 ALWAYS_FALSE,
142 DEFAULT_BTN,
143 "Construct game tiles from this layer.")
144REGISTER_QUICK_ACTION(
145 GameTilesLiveUnfreeze,
146 "Game tiles: Live Unfreeze",
147 [&]() { FillGameTiles(EGameTileOp::LIVE_UNFREEZE); },
148 [&]() -> bool { return !CanFillGameTiles(); },
149 ALWAYS_FALSE,
150 DEFAULT_BTN,
151 "Construct game tiles from this layer.")
152REGISTER_QUICK_ACTION(
153 AddGroup,
154 "Add group",
155 [&]() { AddGroup(); },
156 ALWAYS_FALSE,
157 ALWAYS_FALSE,
158 DEFAULT_BTN,
159 "Add a new group.")
160REGISTER_QUICK_ACTION(
161 ResetZoom,
162 "Reset zoom",
163 [&]() { MapView()->ResetZoom(); },
164 ALWAYS_FALSE,
165 ALWAYS_FALSE,
166 DEFAULT_BTN,
167 "[Numpad*] Zoom to normal and remove editor offset.")
168REGISTER_QUICK_ACTION(
169 ZoomOut,
170 "Zoom out",
171 [&]() { MapView()->Zoom()->ScaleValue(1.331f); },
172 ALWAYS_FALSE,
173 ALWAYS_FALSE,
174 DEFAULT_BTN,
175 "[Numpad-] Zoom out.")
176REGISTER_QUICK_ACTION(
177 ZoomIn,
178 "Zoom in",
179 [&]() { MapView()->Zoom()->ScaleValue(1.0f / 1.331f); },
180 ALWAYS_FALSE,
181 ALWAYS_FALSE,
182 DEFAULT_BTN,
183 "[Numpad+] Zoom in.")
184REGISTER_QUICK_ACTION(
185 Refocus,
186 "Refocus",
187 [&]() { MapView()->Focus(); },
188 ALWAYS_FALSE,
189 ALWAYS_FALSE,
190 DEFAULT_BTN,
191 "[Home] Restore map focus.")
192REGISTER_QUICK_ACTION(
193 GotoPosition,
194 "Goto position",
195 [&]() { GotoPosition(); },
196 ALWAYS_FALSE,
197 ALWAYS_FALSE,
198 DEFAULT_BTN,
199 "Go to a specified coordinate point on the map.")
200REGISTER_QUICK_ACTION(
201 Proof,
202 "Proof",
203 [&]() { MapView()->ProofMode()->Toggle(); },
204 ALWAYS_FALSE,
205 [&]() -> bool { return MapView()->ProofMode()->IsEnabled(); },
206 DEFAULT_BTN,
207 "Toggle proof borders. These borders represent the area that a player can see with default zoom.")
208REGISTER_QUICK_ACTION(
209 AddTileLayer, "Add tile layer", [&]() { AddTileLayer(); }, ALWAYS_FALSE, ALWAYS_FALSE, DEFAULT_BTN, "Create a new tile layer.")
210REGISTER_QUICK_ACTION(
211 AddSwitchLayer,
212 "Add switch layer",
213 [&]() { AddSwitchLayer(); },
214 [&]() -> bool { return !Map()->SelectedGroup()->m_GameGroup || Map()->m_pSwitchLayer; },
215 ALWAYS_FALSE,
216 DEFAULT_BTN,
217 "Create a new switch layer.")
218REGISTER_QUICK_ACTION(
219 AddTuneLayer,
220 "Add tune layer",
221 [&]() { AddTuneLayer(); },
222 [&]() -> bool { return !Map()->SelectedGroup()->m_GameGroup || Map()->m_pTuneLayer; },
223 ALWAYS_FALSE,
224 DEFAULT_BTN,
225 "Create a new tuning layer.")
226REGISTER_QUICK_ACTION(
227 AddSpeedupLayer,
228 "Add speedup layer",
229 [&]() { AddSpeedupLayer(); },
230 [&]() -> bool { return !Map()->SelectedGroup()->m_GameGroup || Map()->m_pSpeedupLayer; },
231 ALWAYS_FALSE,
232 DEFAULT_BTN,
233 "Create a new speedup layer.")
234REGISTER_QUICK_ACTION(
235 AddTeleLayer,
236 "Add tele layer",
237 [&]() { AddTeleLayer(); },
238 [&]() -> bool { return !Map()->SelectedGroup()->m_GameGroup || Map()->m_pTeleLayer; },
239 ALWAYS_FALSE,
240 DEFAULT_BTN,
241 "Create a new tele layer.")
242REGISTER_QUICK_ACTION(
243 AddFrontLayer,
244 "Add front layer",
245 [&]() { AddFrontLayer(); },
246 [&]() -> bool { return !Map()->SelectedGroup()->m_GameGroup || Map()->m_pFrontLayer; },
247 ALWAYS_FALSE,
248 DEFAULT_BTN,
249 "Create a new item layer.")
250REGISTER_QUICK_ACTION(
251 AddQuadsLayer, "Add quads layer", [&]() { AddQuadsLayer(); }, ALWAYS_FALSE, ALWAYS_FALSE, DEFAULT_BTN, "Create a new quads layer.")
252REGISTER_QUICK_ACTION(
253 AddSoundLayer, "Add sound layer", [&]() { AddSoundLayer(); }, ALWAYS_FALSE, ALWAYS_FALSE, DEFAULT_BTN, "Create a new sound layer.")
254REGISTER_QUICK_ACTION(
255 NewMap,
256 "New map",
257 [&]() {
258 Reset();
259 AddDefaultMap();
260 },
261 ALWAYS_FALSE,
262 ALWAYS_FALSE,
263 DEFAULT_BTN,
264 "[Ctrl+N] Create a new map.")
265REGISTER_QUICK_ACTION(
266 Save,
267 "Save",
268 [&]() {
269 if(Map()->m_aFilename[0] != '\0' && Map()->m_ValidSaveFilename)
270 {
271 CallbackSaveMap(Map()->m_aFilename, IStorage::TYPE_SAVE, this);
272 }
273 else
274 {
275 m_FileBrowser.ShowFileDialog(IStorage::TYPE_SAVE, CFileBrowser::EFileType::MAP, "Save map", "Save", "maps", "", CallbackSaveMap, this);
276 }
277 },
278 ALWAYS_FALSE,
279 ALWAYS_FALSE,
280 DEFAULT_BTN,
281 "[Ctrl+S] Save the current map.")
282REGISTER_QUICK_ACTION(
283 SaveAs,
284 "Save as",
285 [&]() {
286 m_FileBrowser.ShowFileDialog(IStorage::TYPE_SAVE, CFileBrowser::EFileType::MAP, "Save map", "Save as", "maps", Map()->m_aAutosaveName, CallbackSaveMap, this);
287 },
288 ALWAYS_FALSE,
289 ALWAYS_FALSE,
290 DEFAULT_BTN,
291 "[Ctrl+Shift+S] Save the current map under a new name.")
292REGISTER_QUICK_ACTION(
293 SaveCopy,
294 "Save copy",
295 [&]() {
296 m_FileBrowser.ShowFileDialog(IStorage::TYPE_SAVE, CFileBrowser::EFileType::MAP, "Save map", "Save copy", "maps", Map()->m_aAutosaveName, CallbackSaveCopyMap, this);
297 },
298 ALWAYS_FALSE,
299 ALWAYS_FALSE,
300 DEFAULT_BTN,
301 "[Ctrl+Shift+Alt+S] Save a copy of the current map under a new name.")
302REGISTER_QUICK_ACTION(
303 LoadMap,
304 "Load map",
305 [&]() {
306 m_FileBrowser.ShowFileDialog(IStorage::TYPE_ALL, CFileBrowser::EFileType::MAP, "Load map", "Load", "maps", "", CallbackOpenMap, this);
307 },
308 ALWAYS_FALSE,
309 ALWAYS_FALSE,
310 DEFAULT_BTN,
311 "[Ctrl+L] Open a map for editing.")
312REGISTER_QUICK_ACTION(
313 LoadIngameMap,
314 "Load ingame map",
315 [&]() {
316 LoadIngameMap();
317 },
318 [&]() -> bool { return Client()->State() != IClient::STATE_ONLINE && Client()->State() != IClient::STATE_DEMOPLAYBACK; },
319 ALWAYS_FALSE,
320 DEFAULT_BTN,
321 "[Ctrl+Shift+L] Open the current ingame map for editing.")
322REGISTER_QUICK_ACTION(
323 AppendMap,
324 "Append map",
325 [&]() {
326 m_FileBrowser.ShowFileDialog(IStorage::TYPE_ALL, CFileBrowser::EFileType::MAP, "Append map", "Append", "maps", "", CallbackAppendMap, this);
327 },
328 ALWAYS_FALSE,
329 ALWAYS_FALSE,
330 DEFAULT_BTN,
331 "[Ctrl+A] Open a map and add everything from that map to the current map.")
332REGISTER_QUICK_ACTION(
333 CloseMap,
334 "Close map",
335 [&]() { CloseMap(m_SelectedMap, true); },
336 ALWAYS_FALSE,
337 ALWAYS_FALSE,
338 DEFAULT_BTN,
339 "[Ctrl+F4] Close the current map.")
340REGISTER_QUICK_ACTION(
341 Envelopes,
342 "Envelopes",
343 [&]() { m_ActiveExtraEditor = m_ActiveExtraEditor == EXTRAEDITOR_ENVELOPES ? EXTRAEDITOR_NONE : EXTRAEDITOR_ENVELOPES; },
344 ALWAYS_FALSE,
345 ALWAYS_FALSE,
346 [&]() -> int { return m_ShowPicker ? -1 : m_ActiveExtraEditor == EXTRAEDITOR_ENVELOPES; },
347 "Toggle the envelope editor.")
348REGISTER_QUICK_ACTION(
349 ServerSettings,
350 "Server settings",
351 [&]() { m_ActiveExtraEditor = m_ActiveExtraEditor == EXTRAEDITOR_SERVER_SETTINGS ? EXTRAEDITOR_NONE : EXTRAEDITOR_SERVER_SETTINGS; },
352 ALWAYS_FALSE,
353 ALWAYS_FALSE,
354 [&]() -> int { return m_ShowPicker ? -1 : m_ActiveExtraEditor == EXTRAEDITOR_SERVER_SETTINGS; },
355 "Toggle the server settings editor.")
356REGISTER_QUICK_ACTION(
357 History,
358 "History",
359 [&]() { m_ActiveExtraEditor = m_ActiveExtraEditor == EXTRAEDITOR_HISTORY ? EXTRAEDITOR_NONE : EXTRAEDITOR_HISTORY; },
360 ALWAYS_FALSE,
361 ALWAYS_FALSE,
362 [&]() -> int { return m_ShowPicker ? -1 : m_ActiveExtraEditor == EXTRAEDITOR_HISTORY; },
363 "Toggle the editor history view.")
364REGISTER_QUICK_ACTION(
365 AddImage,
366 "Add image",
367 [&]() { m_FileBrowser.ShowFileDialog(IStorage::TYPE_ALL, CFileBrowser::EFileType::IMAGE, "Add image", "Add", "mapres", "", AddImage, this); },
368 ALWAYS_FALSE,
369 ALWAYS_FALSE,
370 DEFAULT_BTN,
371 "Load a new image to use in the map.")
372REGISTER_QUICK_ACTION(
373 LayerPropAddImage,
374 "Layer: add image",
375 [&]() { LayerSelectImage(); },
376 [&]() -> bool { return !IsNonGameTileLayerSelected(); },
377 ALWAYS_FALSE,
378 DEFAULT_BTN,
379 "Pick mapres image for currently selected layer.")
380REGISTER_QUICK_ACTION(
381 ShowInfoOff,
382 "Show info: Off",
383 [&]() {
384 m_ShowTileInfo = SHOW_TILE_OFF;
385 },
386 ALWAYS_FALSE,
387 [&]() -> bool { return m_ShowTileInfo == SHOW_TILE_OFF; },
388 DEFAULT_BTN,
389 "Do not show tile information.")
390REGISTER_QUICK_ACTION(
391 ShowInfoDec,
392 "Show info: Dec",
393 [&]() {
394 m_ShowTileInfo = SHOW_TILE_DECIMAL;
395 },
396 ALWAYS_FALSE,
397 [&]() -> bool { return m_ShowTileInfo == SHOW_TILE_DECIMAL; },
398 DEFAULT_BTN,
399 "[Ctrl+I] Show tile information.")
400REGISTER_QUICK_ACTION(
401 ShowInfoHex,
402 "Show info: Hex",
403 [&]() {
404 m_ShowTileInfo = SHOW_TILE_HEXADECIMAL;
405 },
406 ALWAYS_FALSE,
407 [&]() -> bool { return m_ShowTileInfo == SHOW_TILE_HEXADECIMAL; },
408 DEFAULT_BTN,
409 "[Ctrl+Shift+I] Show tile information in hexadecimal.")
410REGISTER_QUICK_ACTION(
411 PreviewQuadEnvelopes,
412 "Preview quad envelopes",
413 [&]() {
414 m_ShowEnvelopePreview = !m_ShowEnvelopePreview;
415 m_ActiveEnvelopePreview = EEnvelopePreview::NONE;
416 },
417 ALWAYS_FALSE,
418 [&]() -> bool { return m_ShowEnvelopePreview; },
419 DEFAULT_BTN,
420 "Toggle previewing the paths of quads with a position envelope when a quad layer is selected.")
421REGISTER_QUICK_ACTION(
422 DeleteLayer,
423 "Delete layer",
424 [&]() { DeleteSelectedLayer(); },
425 [&]() -> bool {
426 std::shared_ptr<CLayer> pCurrentLayer = Map()->SelectedLayer(0);
427 if(!pCurrentLayer)
428 return true;
429 return Map()->m_pGameLayer == pCurrentLayer;
430 },
431 ALWAYS_FALSE,
432 DEFAULT_BTN,
433 "Delete the layer.")
434REGISTER_QUICK_ACTION(
435 Pipette,
436 "Pipette",
437 [&]() { m_ColorPipetteActive = !m_ColorPipetteActive; },
438 ALWAYS_FALSE,
439 [&]() -> bool { return m_ColorPipetteActive; },
440 DEFAULT_BTN,
441 "[Ctrl+Shift+C] Color pipette. Pick a color from the screen by clicking on it.")
442REGISTER_QUICK_ACTION(
443 MapDetails,
444 "Map details",
445 [&]() { MapDetails(); },
446 ALWAYS_FALSE,
447 ALWAYS_FALSE,
448 DEFAULT_BTN,
449 "Adjust the map details of the current map.")
450REGISTER_QUICK_ACTION(
451 AddQuad,
452 "Add quad",
453 [&]() { AddQuadOrSound(); },
454 [&]() -> bool {
455 std::shared_ptr<CLayer> pLayer = Map()->SelectedLayer(0);
456 if(!pLayer)
457 return false;
458 return pLayer->m_Type != LAYERTYPE_QUADS;
459 },
460 ALWAYS_FALSE,
461 DEFAULT_BTN,
462 "[Ctrl+Q] Add a new quad.")
463REGISTER_QUICK_ACTION(
464 AddSoundSource,
465 "Add sound source",
466 [&]() { AddQuadOrSound(); },
467 [&]() -> bool {
468 std::shared_ptr<CLayer> pLayer = Map()->SelectedLayer(0);
469 if(!pLayer)
470 return false;
471 return pLayer->m_Type != LAYERTYPE_SOUNDS;
472 },
473 ALWAYS_FALSE,
474 DEFAULT_BTN,
475 "[Ctrl+Q] Add a new sound source.")
476REGISTER_QUICK_ACTION(
477 TestMapLocally,
478 "Test map locally",
479 [&]() { TestMapLocally(); },
480 ALWAYS_FALSE,
481 ALWAYS_FALSE,
482 DEFAULT_BTN,
483 "Run a local server with the current map and connect you to it.")
484
485#undef ALWAYS_FALSE
486#undef DEFAULT_BTN
487