1 //------------------------------------------------------------------------
2 // COMMAND FUNCTIONS
3 //------------------------------------------------------------------------
4 //
5 // Eureka DOOM Editor
6 //
7 // Copyright (C) 2001-2018 Andrew Apted
8 // Copyright (C) 1997-2003 Andr� Majorel et al
9 //
10 // This program is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU General Public License
12 // as published by the Free Software Foundation; either version 2
13 // of the License, or (at your option) any later version.
14 //
15 // This program is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 //------------------------------------------------------------------------
21 //
22 // Based on Yadex which incorporated code from DEU 5.21 that was put
23 // in the public domain in 1994 by Rapha�l Quinet and Brendon Wyber.
24 //
25 //------------------------------------------------------------------------
26
27 #include "main.h"
28
29 #include "e_checks.h"
30 #include "e_cutpaste.h"
31 #include "e_hover.h"
32 #include "r_grid.h"
33 #include "e_linedef.h"
34 #include "e_main.h"
35 #include "e_objects.h"
36 #include "e_sector.h"
37 #include "e_path.h"
38 #include "e_vertex.h"
39 #include "m_config.h"
40 #include "m_editlump.h"
41 #include "m_events.h"
42 #include "m_loadsave.h"
43 #include "m_nodes.h"
44 #include "r_render.h"
45 #include "r_subdiv.h"
46 #include "ui_window.h"
47 #include "ui_about.h"
48 #include "ui_misc.h"
49 #include "ui_prefs.h"
50
51
52 // config items
53 int minimum_drag_pixels = 5;
54
55
CMD_Nothing()56 void CMD_Nothing()
57 {
58 /* hey jude, don't make it bad */
59 }
60
61
CMD_MetaKey()62 void CMD_MetaKey()
63 {
64 if (edit.sticky_mod)
65 {
66 ClearStickyMod();
67 return;
68 }
69
70 Status_Set("META...");
71
72 edit.sticky_mod = MOD_META;
73 }
74
75
CMD_EditMode()76 void CMD_EditMode()
77 {
78 char mode = tolower(EXEC_Param[0][0]);
79
80 if (! mode || ! strchr("lstvr", mode))
81 {
82 Beep("Bad parameter for EditMode: '%s'", EXEC_Param[0]);
83 return;
84 }
85
86 Editor_ChangeMode(mode);
87 }
88
89
CMD_Select()90 void CMD_Select()
91 {
92 if (edit.render3d)
93 return;
94
95 // FIXME : action in effect?
96
97 // FIXME : split_line in effect?
98
99 if (edit.highlight.is_nil())
100 {
101 Beep("Nothing under cursor");
102 return;
103 }
104
105 Selection_Toggle(edit.highlight);
106 RedrawMap();
107 }
108
109
CMD_SelectAll()110 void CMD_SelectAll()
111 {
112 Editor_ClearErrorMode();
113
114 int total = NumObjects(edit.mode);
115
116 Selection_Push();
117
118 edit.Selected->change_type(edit.mode);
119 edit.Selected->frob_range(0, total-1, BOP_ADD);
120
121 RedrawMap();
122 }
123
124
CMD_UnselectAll()125 void CMD_UnselectAll()
126 {
127 Editor_ClearErrorMode();
128
129 if (edit.action == ACT_DRAW_LINE ||
130 edit.action == ACT_TRANSFORM)
131 {
132 Editor_ClearAction();
133 }
134
135 Selection_Clear();
136
137 RedrawMap();
138 }
139
140
CMD_InvertSelection()141 void CMD_InvertSelection()
142 {
143 // do not clear selection when in error mode
144 edit.error_mode = false;
145
146 int total = NumObjects(edit.mode);
147
148 if (edit.Selected->what_type() != edit.mode)
149 {
150 // convert the selection
151 selection_c *prev_sel = edit.Selected;
152 edit.Selected = new selection_c(edit.mode, true /* extended */);
153
154 ConvertSelection(prev_sel, edit.Selected);
155 delete prev_sel;
156 }
157
158 edit.Selected->frob_range(0, total-1, BOP_TOGGLE);
159
160 RedrawMap();
161 }
162
163
CMD_Quit()164 void CMD_Quit()
165 {
166 Main_Quit();
167 }
168
169
CMD_Undo()170 void CMD_Undo()
171 {
172 if (! BA_Undo())
173 {
174 Beep("No operation to undo");
175 return;
176 }
177
178 RedrawMap();
179 main_win->UpdatePanelObj();
180 }
181
182
CMD_Redo()183 void CMD_Redo()
184 {
185 if (! BA_Redo())
186 {
187 Beep("No operation to redo");
188 return;
189 }
190
191 RedrawMap();
192 main_win->UpdatePanelObj();
193 }
194
195
SetGamma(int new_val)196 static void SetGamma(int new_val)
197 {
198 usegamma = CLAMP(0, new_val, 4);
199
200 W_UpdateGamma();
201
202 // for OpenGL, need to reload all images
203 if (main_win && main_win->canvas)
204 main_win->canvas->DeleteContext();
205
206 Status_Set("gamma level %d", usegamma);
207
208 RedrawMap();
209 }
210
211
CMD_SetVar()212 void CMD_SetVar()
213 {
214 const char *var_name = EXEC_Param[0];
215 const char *value = EXEC_Param[1];
216
217 if (! var_name[0])
218 {
219 Beep("Set: missing var name");
220 return;
221 }
222
223 if (! value[0])
224 {
225 Beep("Set: missing value");
226 return;
227 }
228
229 int int_val = atoi(value);
230 bool bool_val = (int_val > 0);
231
232
233 if (y_stricmp(var_name, "3d") == 0)
234 {
235 Render3D_Enable(bool_val);
236 }
237 else if (y_stricmp(var_name, "browser") == 0)
238 {
239 Editor_ClearAction();
240
241 int want_vis = bool_val ? 1 : 0;
242 int is_visible = main_win->browser->visible() ? 1 : 0;
243
244 if (want_vis != is_visible)
245 main_win->BrowserMode('/');
246 }
247 else if (y_stricmp(var_name, "grid") == 0)
248 {
249 grid.SetShown(bool_val);
250 }
251 else if (y_stricmp(var_name, "snap") == 0)
252 {
253 grid.SetSnap(bool_val);
254 }
255 else if (y_stricmp(var_name, "sprites") == 0)
256 {
257 edit.thing_render_mode = int_val;
258 RedrawMap();
259 }
260 else if (y_stricmp(var_name, "obj_nums") == 0)
261 {
262 edit.show_object_numbers = bool_val;
263 RedrawMap();
264 }
265 else if (y_stricmp(var_name, "gamma") == 0)
266 {
267 SetGamma(int_val);
268 }
269 else if (y_stricmp(var_name, "ratio") == 0)
270 {
271 grid.ratio = CLAMP(0, int_val, 7);
272 main_win->info_bar->UpdateRatio();
273 RedrawMap();
274 }
275 else if (y_stricmp(var_name, "sec_render") == 0)
276 {
277 int_val = CLAMP(0, int_val, (int)SREND_SoundProp);
278 edit.sector_render_mode = (sector_rendering_mode_e) int_val;
279
280 if (edit.render3d)
281 Render3D_Enable(false);
282
283 // need sectors mode for sound propagation display
284 if (edit.sector_render_mode == SREND_SoundProp && edit.mode != OBJ_SECTORS)
285 Editor_ChangeMode('s');
286
287 RedrawMap();
288 }
289 else
290 {
291 Beep("Set: unknown var: %s", var_name);
292 }
293 }
294
295
CMD_ToggleVar()296 void CMD_ToggleVar()
297 {
298 const char *var_name = EXEC_Param[0];
299
300 if (! var_name[0])
301 {
302 Beep("Toggle: missing var name");
303 return;
304 }
305
306 if (y_stricmp(var_name, "3d") == 0)
307 {
308 Render3D_Enable(! edit.render3d);
309 }
310 else if (y_stricmp(var_name, "browser") == 0)
311 {
312 Editor_ClearAction();
313
314 main_win->BrowserMode('/');
315 }
316 else if (y_stricmp(var_name, "recent") == 0)
317 {
318 main_win->browser->ToggleRecent();
319 }
320 else if (y_stricmp(var_name, "grid") == 0)
321 {
322 grid.ToggleShown();
323 }
324 else if (y_stricmp(var_name, "snap") == 0)
325 {
326 grid.ToggleSnap();
327 }
328 else if (y_stricmp(var_name, "sprites") == 0)
329 {
330 edit.thing_render_mode = ! edit.thing_render_mode;
331 RedrawMap();
332 }
333 else if (y_stricmp(var_name, "obj_nums") == 0)
334 {
335 edit.show_object_numbers = ! edit.show_object_numbers;
336 RedrawMap();
337 }
338 else if (y_stricmp(var_name, "gamma") == 0)
339 {
340 SetGamma((usegamma >= 4) ? 0 : usegamma + 1);
341 }
342 else if (y_stricmp(var_name, "ratio") == 0)
343 {
344 if (grid.ratio >= 7)
345 grid.ratio = 0;
346 else
347 grid.ratio++;
348
349 main_win->info_bar->UpdateRatio();
350 RedrawMap();
351 }
352 else if (y_stricmp(var_name, "sec_render") == 0)
353 {
354 if (edit.sector_render_mode >= SREND_SoundProp)
355 edit.sector_render_mode = SREND_Nothing;
356 else
357 edit.sector_render_mode = (sector_rendering_mode_e)(1 + (int)edit.sector_render_mode);
358 RedrawMap();
359 }
360 else
361 {
362 Beep("Toggle: unknown var: %s", var_name);
363 }
364 }
365
366
CMD_BrowserMode()367 void CMD_BrowserMode()
368 {
369 if (! EXEC_Param[0][0])
370 {
371 Beep("BrowserMode: missing mode");
372 return;
373 }
374
375 char mode = toupper(EXEC_Param[0][0]);
376
377 if (! (mode == 'L' || mode == 'S' || mode == 'O' ||
378 mode == 'T' || mode == 'F' || mode == 'G'))
379 {
380 Beep("Unknown browser mode: %s", EXEC_Param[0]);
381 return;
382 }
383
384 // if that browser is already open, close it now
385 if (main_win->browser->visible() &&
386 main_win->browser->GetMode() == mode &&
387 ! Exec_HasFlag("/force") &&
388 ! Exec_HasFlag("/recent"))
389 {
390 main_win->BrowserMode(0);
391 return;
392 }
393
394 main_win->BrowserMode(mode);
395
396 if (Exec_HasFlag("/recent"))
397 {
398 main_win->browser->ToggleRecent(true /* force */);
399 }
400 }
401
402
CMD_Scroll()403 void CMD_Scroll()
404 {
405 // these are percentages
406 float delta_x = atof(EXEC_Param[0]);
407 float delta_y = atof(EXEC_Param[1]);
408
409 if (delta_x == 0 && delta_y == 0)
410 {
411 Beep("Bad parameter to Scroll: '%s' %s'", EXEC_Param[0], EXEC_Param[1]);
412 return;
413 }
414
415 int base_size = (main_win->canvas->w() + main_win->canvas->h()) / 2;
416
417 delta_x = delta_x * base_size / 100.0 / grid.Scale;
418 delta_y = delta_y * base_size / 100.0 / grid.Scale;
419
420 grid.Scroll(delta_x, delta_y);
421 }
422
423
NAV_Scroll_Left_release(void)424 static void NAV_Scroll_Left_release(void)
425 {
426 edit.nav_left = 0;
427 }
428
CMD_NAV_Scroll_Left()429 void CMD_NAV_Scroll_Left()
430 {
431 if (! EXEC_CurKey)
432 return;
433
434 if (! edit.is_navigating)
435 Editor_ClearNav();
436
437 float perc = atof(EXEC_Param[0]);
438 int base_size = (main_win->canvas->w() + main_win->canvas->h()) / 2;
439 edit.nav_left = perc * base_size / 100.0 / grid.Scale;
440
441 Nav_SetKey(EXEC_CurKey, &NAV_Scroll_Left_release);
442 }
443
444
NAV_Scroll_Right_release(void)445 static void NAV_Scroll_Right_release(void)
446 {
447 edit.nav_right = 0;
448 }
449
CMD_NAV_Scroll_Right()450 void CMD_NAV_Scroll_Right()
451 {
452 if (! EXEC_CurKey)
453 return;
454
455 if (! edit.is_navigating)
456 Editor_ClearNav();
457
458 float perc = atof(EXEC_Param[0]);
459 int base_size = (main_win->canvas->w() + main_win->canvas->h()) / 2;
460 edit.nav_right = perc * base_size / 100.0 / grid.Scale;
461
462 Nav_SetKey(EXEC_CurKey, &NAV_Scroll_Right_release);
463 }
464
465
NAV_Scroll_Up_release(void)466 static void NAV_Scroll_Up_release(void)
467 {
468 edit.nav_up = 0;
469 }
470
CMD_NAV_Scroll_Up()471 void CMD_NAV_Scroll_Up()
472 {
473 if (! EXEC_CurKey)
474 return;
475
476 if (! edit.is_navigating)
477 Editor_ClearNav();
478
479 float perc = atof(EXEC_Param[0]);
480 int base_size = (main_win->canvas->w() + main_win->canvas->h()) / 2;
481 edit.nav_up = perc * base_size / 100.0 / grid.Scale;
482
483 Nav_SetKey(EXEC_CurKey, &NAV_Scroll_Up_release);
484 }
485
486
NAV_Scroll_Down_release(void)487 static void NAV_Scroll_Down_release(void)
488 {
489 edit.nav_down = 0;
490 }
491
CMD_NAV_Scroll_Down()492 void CMD_NAV_Scroll_Down()
493 {
494 if (! EXEC_CurKey)
495 return;
496
497 if (! edit.is_navigating)
498 Editor_ClearNav();
499
500 float perc = atof(EXEC_Param[0]);
501 int base_size = (main_win->canvas->w() + main_win->canvas->h()) / 2;
502 edit.nav_down = perc * base_size / 100.0 / grid.Scale;
503
504 Nav_SetKey(EXEC_CurKey, &NAV_Scroll_Down_release);
505 }
506
507
NAV_MouseScroll_release(void)508 static void NAV_MouseScroll_release(void)
509 {
510 Editor_ScrollMap(+1);
511 }
512
CMD_NAV_MouseScroll()513 void CMD_NAV_MouseScroll()
514 {
515 if (! EXEC_CurKey)
516 return;
517
518 edit.panning_speed = atof(EXEC_Param[0]);
519 edit.panning_lax = Exec_HasFlag("/LAX");
520
521 if (! edit.is_navigating)
522 Editor_ClearNav();
523
524 if (Nav_SetKey(EXEC_CurKey, &NAV_MouseScroll_release))
525 {
526 // begin
527 Editor_ScrollMap(-1);
528 }
529 }
530
531
532 static void DoBeginDrag();
533
534
CheckBeginDrag()535 void CheckBeginDrag()
536 {
537 if (! edit.clicked.valid())
538 return;
539
540 if (! edit.click_check_drag)
541 return;
542
543 // can drag things and sector planes in 3D mode
544 if (edit.render3d && !(edit.mode == OBJ_THINGS || edit.mode == OBJ_SECTORS))
545 return;
546
547 int pixel_dx = Fl::event_x() - edit.click_screen_x;
548 int pixel_dy = Fl::event_y() - edit.click_screen_y;
549
550 if (MAX(abs(pixel_dx), abs(pixel_dy)) < minimum_drag_pixels)
551 return;
552
553 // if highlighted object is in selection, we drag the selection,
554 // otherwise we drag just this one object.
555
556 if (edit.click_force_single || !edit.Selected->get(edit.clicked.num))
557 edit.dragged = edit.clicked;
558 else
559 edit.dragged.clear();
560
561 DoBeginDrag();
562 }
563
DoBeginDrag()564 static void DoBeginDrag()
565 {
566 edit.drag_start_x = edit.drag_cur_x = edit.click_map_x;
567 edit.drag_start_y = edit.drag_cur_y = edit.click_map_y;
568 edit.drag_start_z = edit.drag_cur_z = edit.click_map_z;
569
570 edit.drag_screen_dx = edit.drag_screen_dy = 0;
571 edit.drag_thing_num = -1;
572 edit.drag_other_vert = -1;
573
574 // the focus is only used when grid snapping is on
575 GetDragFocus(&edit.drag_focus_x, &edit.drag_focus_y, edit.click_map_x, edit.click_map_y);
576
577 if (edit.render3d)
578 {
579 if (edit.mode == OBJ_SECTORS)
580 edit.drag_sector_dz = 0;
581
582 if (edit.mode == OBJ_THINGS)
583 {
584 edit.drag_thing_num = edit.clicked.num;
585 edit.drag_thing_floorh = edit.drag_start_z;
586 edit.drag_thing_up_down = (Level_format != MAPF_Doom && !grid.snap);
587
588 // get thing's floor
589 if (edit.drag_thing_num >= 0)
590 {
591 const Thing *T = Things[edit.drag_thing_num];
592
593 Objid sec;
594 GetNearObject(sec, OBJ_SECTORS, T->x(), T->y());
595
596 if (sec.valid())
597 edit.drag_thing_floorh = Sectors[sec.num]->floorh;
598 }
599 }
600 }
601
602 // in vertex mode, show all the connected lines too
603 if (edit.drag_lines)
604 {
605 delete edit.drag_lines;
606 edit.drag_lines = NULL;
607 }
608
609 if (edit.mode == OBJ_VERTICES)
610 {
611 edit.drag_lines = new selection_c(OBJ_LINEDEFS);
612 ConvertSelection(edit.Selected, edit.drag_lines);
613
614 // find opposite end-point when dragging a single vertex
615 if (edit.dragged.valid())
616 edit.drag_other_vert = Vertex_FindDragOther(edit.dragged.num);
617 }
618
619 edit.clicked.clear();
620
621 Editor_SetAction(ACT_DRAG);
622
623 main_win->canvas->redraw();
624 }
625
626
ACT_SelectBox_release(void)627 static void ACT_SelectBox_release(void)
628 {
629 // check if cancelled or overridden
630 if (edit.action != ACT_SELBOX)
631 return;
632
633 Editor_ClearAction();
634 Editor_ClearErrorMode();
635
636 // a mere click and release will unselect everything
637 double x1 = 0, y1 = 0, x2 = 0, y2 = 0;
638 if (! main_win->canvas->SelboxGet(x1, y1, x2, y2))
639 {
640 ExecuteCommand("UnselectAll");
641 return;
642 }
643
644 SelectObjectsInBox(edit.Selected, edit.mode, x1, y1, x2, y2);
645 RedrawMap();
646 }
647
648
ACT_Drag_release(void)649 static void ACT_Drag_release(void)
650 {
651 // check if cancelled or overridden
652 if (edit.action != ACT_DRAG)
653 {
654 edit.dragged.clear();
655 return;
656 }
657
658 if (edit.render3d)
659 {
660 if (edit.mode == OBJ_THINGS)
661 Render3D_DragThings();
662
663 if (edit.mode == OBJ_SECTORS)
664 Render3D_DragSectors();
665 }
666
667 // note: DragDelta needs edit.dragged
668 double dx, dy;
669 main_win->canvas->DragDelta(&dx, &dy);
670
671 Objid dragged(edit.dragged);
672 edit.dragged.clear();
673
674 if (edit.drag_lines)
675 edit.drag_lines->clear_all();
676
677 if (! edit.render3d && (dx || dy))
678 {
679 if (dragged.valid())
680 DragSingleObject(dragged, dx, dy);
681 else
682 MoveObjects(edit.Selected, dx, dy);
683 }
684
685 Editor_ClearAction();
686
687 RedrawMap();
688 }
689
690
ACT_Click_release(void)691 static void ACT_Click_release(void)
692 {
693 Objid click_obj(edit.clicked);
694 edit.clicked.clear();
695
696 edit.click_check_drag = false;
697
698
699 if (edit.action == ACT_SELBOX)
700 {
701 ACT_SelectBox_release();
702 return;
703 }
704 else if (edit.action == ACT_DRAG)
705 {
706 ACT_Drag_release();
707 return;
708 }
709
710 // check if cancelled or overridden
711 if (edit.action != ACT_CLICK)
712 return;
713
714 if (edit.click_check_select && click_obj.valid())
715 {
716 // only toggle selection if it's the same object as before
717 Objid near_obj;
718 if (edit.render3d)
719 near_obj = edit.highlight;
720 else
721 GetNearObject(near_obj, edit.mode, edit.map_x, edit.map_y);
722
723 if (near_obj.num == click_obj.num)
724 Selection_Toggle(click_obj);
725 }
726
727 Editor_ClearAction();
728 Editor_ClearErrorMode();
729
730 RedrawMap();
731 }
732
CMD_ACT_Click()733 void CMD_ACT_Click()
734 {
735 if (! EXEC_CurKey)
736 return;
737
738 // require a highlighted object in 3D mode
739 if (edit.render3d && edit.highlight.is_nil())
740 return;
741
742 if (! Nav_ActionKey(EXEC_CurKey, &ACT_Click_release))
743 return;
744
745 edit.click_check_select = ! Exec_HasFlag("/noselect");
746 edit.click_check_drag = ! Exec_HasFlag("/nodrag");
747 edit.click_force_single = false;
748
749 // remember some state (for drag detection)
750 edit.click_screen_x = Fl::event_x();
751 edit.click_screen_y = Fl::event_y();
752
753 edit.click_map_x = edit.map_x;
754 edit.click_map_y = edit.map_y;
755 edit.click_map_z = edit.map_z;
756
757 // handle 3D mode, skip stuff below which only makes sense in 2D
758 if (edit.render3d)
759 {
760 if (edit.highlight.type == OBJ_THINGS)
761 {
762 const Thing *T = Things[edit.highlight.num];
763 edit.drag_point_dist = r_view.DistToViewPlane(T->x(), T->y());
764 }
765 else
766 {
767 edit.drag_point_dist = r_view.DistToViewPlane(edit.map_x, edit.map_y);
768 }
769
770 edit.clicked = edit.highlight;
771 Editor_SetAction(ACT_CLICK);
772 return;
773 }
774
775 // check for splitting a line, and ensure we can drag the vertex
776 if (! Exec_HasFlag("/nosplit") &&
777 edit.mode == OBJ_VERTICES &&
778 edit.split_line.valid() &&
779 edit.action != ACT_DRAW_LINE)
780 {
781 int split_ld = edit.split_line.num;
782
783 edit.click_force_single = true; // if drag vertex, force single-obj mode
784 edit.click_check_select = false; // do NOT select the new vertex
785
786 // check if both ends are in selection, if so (and only then)
787 // shall we select the new vertex
788 const LineDef *L = LineDefs[split_ld];
789
790 bool want_select = edit.Selected->get(L->start) && edit.Selected->get(L->end);
791
792 BA_Begin();
793 BA_Message("split linedef #%d", split_ld);
794
795 int new_vert = BA_New(OBJ_VERTICES);
796
797 Vertex *V = Vertices[new_vert];
798
799 V->SetRawXY(edit.split_x, edit.split_y);
800
801 SplitLineDefAtVertex(split_ld, new_vert);
802
803 BA_End();
804
805 if (want_select)
806 edit.Selected->set(new_vert);
807
808 edit.clicked = Objid(OBJ_VERTICES, new_vert);
809 Editor_SetAction(ACT_CLICK);
810
811 RedrawMap();
812 return;
813 }
814
815 // find the object under the pointer.
816 GetNearObject(edit.clicked, edit.mode, edit.map_x, edit.map_y);
817
818 // clicking on an empty space starts a new selection box
819 if (edit.click_check_select && edit.clicked.is_nil())
820 {
821 edit.selbox_x1 = edit.selbox_x2 = edit.map_x;
822 edit.selbox_y1 = edit.selbox_y2 = edit.map_y;
823
824 Editor_SetAction(ACT_SELBOX);
825 return;
826 }
827
828 Editor_SetAction(ACT_CLICK);
829 }
830
831
CMD_ACT_SelectBox()832 void CMD_ACT_SelectBox()
833 {
834 if (edit.render3d)
835 return;
836
837 if (! EXEC_CurKey)
838 return;
839
840 if (! Nav_ActionKey(EXEC_CurKey, &ACT_SelectBox_release))
841 return;
842
843 edit.selbox_x1 = edit.selbox_x2 = edit.map_x;
844 edit.selbox_y1 = edit.selbox_y2 = edit.map_y;
845
846 Editor_SetAction(ACT_SELBOX);
847 }
848
849
CMD_ACT_Drag()850 void CMD_ACT_Drag()
851 {
852 if (! EXEC_CurKey)
853 return;
854
855 if (edit.Selected->empty())
856 {
857 Beep("Nothing to drag");
858 return;
859 }
860
861 if (! Nav_ActionKey(EXEC_CurKey, &ACT_Drag_release))
862 return;
863
864 // we only drag the selection, never a single object
865 edit.dragged.clear();
866
867 DoBeginDrag();
868 }
869
870
Transform_Update()871 void Transform_Update()
872 {
873 double dx1 = edit.map_x - edit.trans_param.mid_x;
874 double dy1 = edit.map_y - edit.trans_param.mid_y;
875
876 double dx0 = edit.trans_start_x - edit.trans_param.mid_x;
877 double dy0 = edit.trans_start_y - edit.trans_param.mid_y;
878
879 edit.trans_param.scale_x = edit.trans_param.scale_y = 1;
880 edit.trans_param.skew_x = edit.trans_param.skew_y = 0;
881 edit.trans_param.rotate = 0;
882
883 if (edit.trans_mode == TRANS_K_Rotate || edit.trans_mode == TRANS_K_RotScale)
884 {
885 int angle1 = (int)ComputeAngle(dx1, dy1);
886 int angle0 = (int)ComputeAngle(dx0, dy0);
887
888 edit.trans_param.rotate = angle1 - angle0;
889
890 // fprintf(stderr, "angle diff : %1.2f\n", edit.trans_rotate * 360.0 / 65536.0);
891 }
892
893 switch (edit.trans_mode)
894 {
895 case TRANS_K_Scale:
896 case TRANS_K_RotScale:
897 dx1 = MAX(abs(dx1), abs(dy1));
898 dx0 = MAX(abs(dx0), abs(dy0));
899
900 if (dx0)
901 {
902 edit.trans_param.scale_x = dx1 / (float)dx0;
903 edit.trans_param.scale_y = edit.trans_param.scale_x;
904 }
905 break;
906
907 case TRANS_K_Stretch:
908 if (dx0) edit.trans_param.scale_x = dx1 / (float)dx0;
909 if (dy0) edit.trans_param.scale_y = dy1 / (float)dy0;
910 break;
911
912 case TRANS_K_Rotate:
913 // already done
914 break;
915
916 case TRANS_K_Skew:
917 if (abs(dx0) >= abs(dy0))
918 {
919 if (dx0) edit.trans_param.skew_y = (dy1 - dy0) / (float)dx0;
920 }
921 else
922 {
923 if (dy0) edit.trans_param.skew_x = (dx1 - dx0) / (float)dy0;
924 }
925 break;
926 }
927
928 main_win->canvas->redraw();
929 }
930
931
ACT_Transform_release(void)932 static void ACT_Transform_release(void)
933 {
934 // check if cancelled or overridden
935 if (edit.action != ACT_TRANSFORM)
936 return;
937
938 if (edit.trans_lines)
939 edit.trans_lines->clear_all();
940
941 TransformObjects(edit.trans_param);
942
943 Editor_ClearAction();
944
945 RedrawMap();
946 }
947
CMD_ACT_Transform()948 void CMD_ACT_Transform()
949 {
950 if (edit.render3d)
951 return;
952
953 if (! EXEC_CurKey)
954 return;
955
956 if (edit.Selected->empty())
957 {
958 Beep("Nothing to scale");
959 return;
960 }
961
962 const char *keyword = EXEC_Param[0];
963 transform_keyword_e mode;
964
965 if (! keyword[0])
966 {
967 Beep("ACT_Transform: missing keyword");
968 return;
969 }
970 else if (y_stricmp(keyword, "scale") == 0)
971 {
972 mode = TRANS_K_Scale;
973 }
974 else if (y_stricmp(keyword, "stretch") == 0)
975 {
976 mode = TRANS_K_Stretch;
977 }
978 else if (y_stricmp(keyword, "rotate") == 0)
979 {
980 mode = TRANS_K_Rotate;
981 }
982 else if (y_stricmp(keyword, "rotscale") == 0)
983 {
984 mode = TRANS_K_RotScale;
985 }
986 else if (y_stricmp(keyword, "skew") == 0)
987 {
988 mode = TRANS_K_Skew;
989 }
990 else
991 {
992 Beep("ACT_Transform: unknown keyword: %s", keyword);
993 return;
994 }
995
996
997 if (! Nav_ActionKey(EXEC_CurKey, &ACT_Transform_release))
998 return;
999
1000
1001 double middle_x, middle_y;
1002 Objs_CalcMiddle(edit.Selected, &middle_x, &middle_y);
1003
1004 edit.trans_mode = mode;
1005 edit.trans_start_x = edit.map_x;
1006 edit.trans_start_y = edit.map_y;
1007
1008 edit.trans_param.Clear();
1009 edit.trans_param.mid_x = middle_x;
1010 edit.trans_param.mid_y = middle_y;
1011
1012 if (edit.trans_lines)
1013 {
1014 delete edit.trans_lines;
1015 edit.trans_lines = NULL;
1016 }
1017
1018 if (edit.mode == OBJ_VERTICES)
1019 {
1020 edit.trans_lines = new selection_c(OBJ_LINEDEFS);
1021 ConvertSelection(edit.Selected, edit.trans_lines);
1022 }
1023
1024 Editor_SetAction(ACT_TRANSFORM);
1025 }
1026
1027
CMD_WHEEL_Scroll()1028 void CMD_WHEEL_Scroll()
1029 {
1030 float speed = atof(EXEC_Param[0]);
1031
1032 if (Exec_HasFlag("/LAX"))
1033 {
1034 keycode_t mod = Fl::event_state() & MOD_ALL_MASK;
1035
1036 if (mod & MOD_SHIFT)
1037 speed /= 3.0;
1038 else if (mod & MOD_COMMAND)
1039 speed *= 3.0;
1040 }
1041
1042 float delta_x = wheel_dx;
1043 float delta_y = 0 - wheel_dy;
1044
1045 int base_size = (main_win->canvas->w() + main_win->canvas->h()) / 2;
1046
1047 speed = speed * base_size / 100.0 / grid.Scale;
1048
1049 grid.Scroll(delta_x * speed, delta_y * speed);
1050 }
1051
1052
CMD_Merge()1053 void CMD_Merge()
1054 {
1055 switch (edit.mode)
1056 {
1057 case OBJ_VERTICES:
1058 CMD_VT_Merge();
1059 break;
1060
1061 case OBJ_LINEDEFS:
1062 CMD_LIN_MergeTwo();
1063 break;
1064
1065 case OBJ_SECTORS:
1066 CMD_SEC_Merge();
1067 break;
1068
1069 case OBJ_THINGS:
1070 CMD_TH_Merge();
1071 break;
1072
1073 default:
1074 Beep("Cannot merge that");
1075 break;
1076 }
1077 }
1078
1079
CMD_Disconnect()1080 void CMD_Disconnect()
1081 {
1082 switch (edit.mode)
1083 {
1084 case OBJ_VERTICES:
1085 CMD_VT_Disconnect();
1086 break;
1087
1088 case OBJ_LINEDEFS:
1089 CMD_LIN_Disconnect();
1090 break;
1091
1092 case OBJ_SECTORS:
1093 CMD_SEC_Disconnect();
1094 break;
1095
1096 case OBJ_THINGS:
1097 CMD_TH_Disconnect();
1098 break;
1099
1100 default:
1101 Beep("Cannot disconnect that");
1102 break;
1103 }
1104 }
1105
1106
CMD_Zoom()1107 void CMD_Zoom()
1108 {
1109 int delta = atoi(EXEC_Param[0]);
1110
1111 if (delta == 0)
1112 {
1113 Beep("Zoom: bad or missing value");
1114 return;
1115 }
1116
1117 int mid_x = edit.map_x;
1118 int mid_y = edit.map_y;
1119
1120 if (Exec_HasFlag("/center"))
1121 {
1122 mid_x = I_ROUND(grid.orig_x);
1123 mid_y = I_ROUND(grid.orig_y);
1124 }
1125
1126 Editor_Zoom(delta, mid_x, mid_y);
1127 }
1128
1129
CMD_ZoomWholeMap()1130 void CMD_ZoomWholeMap()
1131 {
1132 if (edit.render3d)
1133 Render3D_Enable(false);
1134
1135 ZoomWholeMap();
1136 }
1137
1138
CMD_ZoomSelection()1139 void CMD_ZoomSelection()
1140 {
1141 if (edit.Selected->empty())
1142 {
1143 Beep("No selection to zoom");
1144 return;
1145 }
1146
1147 GoToSelection();
1148 }
1149
1150
CMD_GoToCamera()1151 void CMD_GoToCamera()
1152 {
1153 if (edit.render3d)
1154 Render3D_Enable(false);
1155
1156 double x, y; float angle;
1157 Render3D_GetCameraPos(&x, &y, &angle);
1158
1159 grid.MoveTo(x, y);
1160
1161 RedrawMap();
1162 }
1163
1164
CMD_PlaceCamera()1165 void CMD_PlaceCamera()
1166 {
1167 if (edit.render3d)
1168 {
1169 Beep("Not supported in 3D view");
1170 return;
1171 }
1172
1173 if (! edit.pointer_in_window)
1174 {
1175 // IDEA: turn cursor into cross, wait for click in map window
1176
1177 Beep("Mouse is not over map");
1178 return;
1179 }
1180
1181 double x = edit.map_x;
1182 double y = edit.map_y;
1183
1184 Render3D_SetCameraPos(x, y);
1185
1186 if (Exec_HasFlag("/open3d"))
1187 {
1188 Render3D_Enable(true);
1189 }
1190
1191 RedrawMap();
1192 }
1193
1194
CMD_MoveObjects_Dialog()1195 void CMD_MoveObjects_Dialog()
1196 {
1197 soh_type_e unselect = Selection_Or_Highlight();
1198 if (unselect == SOH_Empty)
1199 {
1200 Beep("Nothing to move");
1201 return;
1202 }
1203
1204 bool want_dz = (edit.mode == OBJ_SECTORS);
1205 // can move things vertically in Hexen/UDMF formats
1206 if (edit.mode == OBJ_THINGS && Level_format != MAPF_Doom)
1207 want_dz = true;
1208
1209 UI_MoveDialog * dialog = new UI_MoveDialog(want_dz);
1210
1211 dialog->Run();
1212
1213 delete dialog;
1214
1215 if (unselect == SOH_Unselect)
1216 Selection_Clear(true /* nosave */);
1217 }
1218
1219
CMD_ScaleObjects_Dialog()1220 void CMD_ScaleObjects_Dialog()
1221 {
1222 soh_type_e unselect = Selection_Or_Highlight();
1223 if (unselect == SOH_Empty)
1224 {
1225 Beep("Nothing to scale");
1226 return;
1227 }
1228
1229 UI_ScaleDialog * dialog = new UI_ScaleDialog();
1230
1231 dialog->Run();
1232
1233 delete dialog;
1234
1235 if (unselect == SOH_Unselect)
1236 Selection_Clear(true /* nosave */);
1237 }
1238
1239
CMD_RotateObjects_Dialog()1240 void CMD_RotateObjects_Dialog()
1241 {
1242 soh_type_e unselect = Selection_Or_Highlight();
1243 if (unselect == SOH_Empty)
1244 {
1245 Beep("Nothing to rotate");
1246 return;
1247 }
1248
1249 UI_RotateDialog * dialog = new UI_RotateDialog();
1250
1251 dialog->Run();
1252
1253 delete dialog;
1254
1255 if (unselect == SOH_Unselect)
1256 Selection_Clear(true /* nosave */);
1257 }
1258
1259
CMD_GRID_Bump()1260 void CMD_GRID_Bump()
1261 {
1262 int delta = atoi(EXEC_Param[0]);
1263
1264 delta = (delta >= 0) ? +1 : -1;
1265
1266 grid.AdjustStep(delta);
1267 }
1268
1269
CMD_GRID_Set()1270 void CMD_GRID_Set()
1271 {
1272 int step = atoi(EXEC_Param[0]);
1273
1274 if (step < 2 || step > 4096)
1275 {
1276 Beep("Bad grid step");
1277 return;
1278 }
1279
1280 grid.ForceStep(step);
1281 }
1282
1283
CMD_GRID_Zoom()1284 void CMD_GRID_Zoom()
1285 {
1286 // target scale is positive for NN:1 and negative for 1:NN
1287
1288 double scale = atof(EXEC_Param[0]);
1289
1290 if (scale == 0)
1291 {
1292 Beep("Bad scale");
1293 return;
1294 }
1295
1296 if (scale < 0)
1297 scale = -1.0 / scale;
1298
1299 float S1 = grid.Scale;
1300
1301 grid.NearestScale(scale);
1302
1303 grid.RefocusZoom(edit.map_x, edit.map_y, S1);
1304 }
1305
1306
CMD_BR_CycleCategory()1307 void CMD_BR_CycleCategory()
1308 {
1309 if (! main_win->browser->visible())
1310 {
1311 Beep("Browser not open");
1312 return;
1313 }
1314
1315 int dir = (atoi(EXEC_Param[0]) >= 0) ? +1 : -1;
1316
1317 main_win->browser->CycleCategory(dir);
1318 }
1319
1320
CMD_BR_ClearSearch()1321 void CMD_BR_ClearSearch()
1322 {
1323 if (! main_win->browser->visible())
1324 {
1325 Beep("Browser not open");
1326 return;
1327 }
1328
1329 main_win->browser->ClearSearchBox();
1330 }
1331
1332
CMD_BR_Scroll()1333 void CMD_BR_Scroll()
1334 {
1335 if (! main_win->browser->visible())
1336 {
1337 Beep("Browser not open");
1338 return;
1339 }
1340
1341 if (! EXEC_Param[0][0])
1342 {
1343 Beep("BR_Scroll: missing value");
1344 return;
1345 }
1346
1347 int delta = atoi(EXEC_Param[0]);
1348
1349 main_win->browser->Scroll(delta);
1350 }
1351
1352
CMD_DefaultProps()1353 void CMD_DefaultProps()
1354 {
1355 main_win->ShowDefaultProps();
1356 }
1357
1358
CMD_FindDialog()1359 void CMD_FindDialog()
1360 {
1361 main_win->ShowFindAndReplace();
1362 }
1363
1364
CMD_FindNext()1365 void CMD_FindNext()
1366 {
1367 main_win->find_box->FindNext();
1368 }
1369
1370
CMD_RecalcSectors()1371 void CMD_RecalcSectors()
1372 {
1373 Subdiv_InvalidateAll();
1374 RedrawMap();
1375 }
1376
1377
CMD_LogViewer()1378 void CMD_LogViewer()
1379 {
1380 LogViewer_Open();
1381 }
1382
1383
CMD_OnlineDocs()1384 void CMD_OnlineDocs()
1385 {
1386 int rv = fl_open_uri("http://eureka-editor.sourceforge.net/?n=Docs.Index");
1387 if (rv == 1)
1388 Status_Set("Opened web browser");
1389 else
1390 Beep("Failed to open web browser");
1391 }
1392
1393
CMD_AboutDialog()1394 void CMD_AboutDialog()
1395 {
1396 DLG_AboutText();
1397 }
1398
1399
1400 //------------------------------------------------------------------------
1401
1402
1403 static editor_command_t command_table[] =
1404 {
1405 /* ---- miscellaneous / UI stuff ---- */
1406
1407 { "Nothing", "Misc",
1408 &CMD_Nothing
1409 },
1410
1411 { "Set", "Misc",
1412 &CMD_SetVar,
1413 /* flags */ NULL,
1414 /* keywords */ "3d browser gamma grid obj_nums ratio sec_render snap sprites"
1415 },
1416
1417 { "Toggle", "Misc",
1418 &CMD_ToggleVar,
1419 /* flags */ NULL,
1420 /* keywords */ "3d browser gamma grid obj_nums ratio sec_render snap recent sprites"
1421 },
1422
1423 { "MetaKey", "Misc",
1424 &CMD_MetaKey
1425 },
1426
1427 { "EditMode", "Misc",
1428 &CMD_EditMode,
1429 /* flags */ NULL,
1430 /* keywords */ "thing line sector vertex"
1431 },
1432
1433 { "OpMenu", "Misc",
1434 &CMD_OperationMenu
1435 },
1436
1437 { "MapCheck", "Misc",
1438 &CMD_MapCheck,
1439 /* flags */ NULL,
1440 /* keywords */ "all major vertices sectors linedefs things textures tags current"
1441 },
1442
1443
1444 /* ----- 2D canvas ----- */
1445
1446 { "Scroll", "2D View",
1447 &CMD_Scroll
1448 },
1449
1450 { "GRID_Bump", "2D View",
1451 &CMD_GRID_Bump
1452 },
1453
1454 { "GRID_Set", "2D View",
1455 &CMD_GRID_Set
1456 },
1457
1458 { "GRID_Zoom", "2D View",
1459 &CMD_GRID_Zoom
1460 },
1461
1462 { "ACT_SelectBox", "2D View",
1463 &CMD_ACT_SelectBox
1464 },
1465
1466 { "WHEEL_Scroll", "2D View",
1467 &CMD_WHEEL_Scroll
1468 },
1469
1470 { "NAV_Scroll_Left", "2D View",
1471 &CMD_NAV_Scroll_Left
1472 },
1473
1474 { "NAV_Scroll_Right", "2D View",
1475 &CMD_NAV_Scroll_Right
1476 },
1477
1478 { "NAV_Scroll_Up", "2D View",
1479 &CMD_NAV_Scroll_Up
1480 },
1481
1482 { "NAV_Scroll_Down", "2D View",
1483 &CMD_NAV_Scroll_Down
1484 },
1485
1486 { "NAV_MouseScroll", "2D View",
1487 &CMD_NAV_MouseScroll
1488 },
1489
1490
1491 /* ----- FILE menu ----- */
1492
1493 { "NewProject", "File",
1494 &CMD_NewProject
1495 },
1496
1497 { "ManageProject", "File",
1498 &CMD_ManageProject
1499 },
1500
1501 { "OpenMap", "File",
1502 &CMD_OpenMap
1503 },
1504
1505 { "GivenFile", "File",
1506 &CMD_GivenFile,
1507 /* flags */ NULL,
1508 /* keywords */ "next prev first last current"
1509 },
1510
1511 { "FlipMap", "File",
1512 &CMD_FlipMap,
1513 /* flags */ NULL,
1514 /* keywords */ "next prev first last"
1515 },
1516
1517 { "SaveMap", "File",
1518 &CMD_SaveMap
1519 },
1520
1521 { "ExportMap", "File",
1522 &CMD_ExportMap
1523 },
1524
1525 { "FreshMap", "File",
1526 &CMD_FreshMap
1527 },
1528
1529 { "CopyMap", "File",
1530 &CMD_CopyMap
1531 },
1532
1533 { "RenameMap", "File",
1534 &CMD_RenameMap
1535 },
1536
1537 { "DeleteMap", "File",
1538 &CMD_DeleteMap
1539 },
1540
1541 { "Quit", "File",
1542 &CMD_Quit
1543 },
1544
1545
1546 /* ----- EDIT menu ----- */
1547
1548 { "Undo", "Edit",
1549 &CMD_Undo
1550 },
1551
1552 { "Redo", "Edit",
1553 &CMD_Redo
1554 },
1555
1556 { "Insert", "Edit",
1557 &CMD_Insert,
1558 /* flags */ "/continue /nofill"
1559 },
1560
1561 { "Delete", "Edit",
1562 &CMD_Delete,
1563 /* flags */ "/keep"
1564 },
1565
1566 { "Clipboard_Cut", "Edit",
1567 &CMD_Clipboard_Cut
1568 },
1569
1570 { "Clipboard_Copy", "Edit",
1571 &CMD_Clipboard_Copy
1572 },
1573
1574 { "Clipboard_Paste", "Edit",
1575 &CMD_Clipboard_Paste
1576 },
1577
1578 { "Select", "Edit",
1579 &CMD_Select
1580 },
1581
1582 { "SelectAll", "Edit",
1583 &CMD_SelectAll
1584 },
1585
1586 { "UnselectAll", "Edit",
1587 &CMD_UnselectAll
1588 },
1589
1590 { "InvertSelection", "Edit",
1591 &CMD_InvertSelection
1592 },
1593
1594 { "LastSelection", "Edit",
1595 &CMD_LastSelection
1596 },
1597
1598 { "CopyAndPaste", "Edit",
1599 &CMD_CopyAndPaste
1600 },
1601
1602 { "CopyProperties", "Edit",
1603 &CMD_CopyProperties,
1604 /* flags */ "/reverse"
1605 },
1606
1607 { "PruneUnused", "Edit",
1608 &CMD_PruneUnused
1609 },
1610
1611 { "MoveObjectsDialog", "Edit",
1612 &CMD_MoveObjects_Dialog
1613 },
1614
1615 { "ScaleObjectsDialog", "Edit",
1616 &CMD_ScaleObjects_Dialog
1617 },
1618
1619 { "RotateObjectsDialog", "Edit",
1620 &CMD_RotateObjects_Dialog
1621 },
1622
1623
1624 /* ----- VIEW menu ----- */
1625
1626 { "Zoom", "View",
1627 &CMD_Zoom,
1628 /* flags */ "/center"
1629 },
1630
1631 { "ZoomWholeMap", "View",
1632 &CMD_ZoomWholeMap
1633 },
1634
1635 { "ZoomSelection", "View",
1636 &CMD_ZoomSelection
1637 },
1638
1639 { "DefaultProps", "View",
1640 &CMD_DefaultProps
1641 },
1642
1643 { "FindDialog", "View",
1644 &CMD_FindDialog
1645 },
1646
1647 { "FindNext", "View",
1648 &CMD_FindNext
1649 },
1650
1651 { "GoToCamera", "View",
1652 &CMD_GoToCamera
1653 },
1654
1655 { "PlaceCamera", "View",
1656 &CMD_PlaceCamera,
1657 /* flags */ "/open3d"
1658 },
1659
1660 { "JumpToObject", "View",
1661 &CMD_JumpToObject
1662 },
1663
1664
1665 /* ------ TOOLS menu ------ */
1666
1667 { "PreferenceDialog", "Tools",
1668 &CMD_Preferences
1669 },
1670
1671 { "TestMap", "Tools",
1672 &CMD_TestMap
1673 },
1674
1675 { "RecalcSectors", "Tools",
1676 &CMD_RecalcSectors
1677 },
1678
1679 { "BuildAllNodes", "Tools",
1680 &CMD_BuildAllNodes
1681 },
1682
1683 { "EditLump", "Tools",
1684 &CMD_EditLump,
1685 /* flags */ "/header /scripts"
1686 },
1687
1688 { "AddBehavior", "Tools",
1689 &CMD_AddBehaviorLump
1690 },
1691
1692 { "LogViewer", "Tools",
1693 &CMD_LogViewer
1694 },
1695
1696
1697 /* ------ HELP menu ------ */
1698
1699 { "OnlineDocs", "Help",
1700 &CMD_OnlineDocs
1701 },
1702
1703 { "AboutDialog", "Help",
1704 &CMD_AboutDialog
1705 },
1706
1707
1708 /* ----- general operations ----- */
1709
1710 { "Merge", "General",
1711 &CMD_Merge,
1712 /* flags */ "/keep"
1713 },
1714
1715 { "Disconnect", "General",
1716 &CMD_Disconnect
1717 },
1718
1719 { "Mirror", "General",
1720 &CMD_Mirror,
1721 /* flags */ NULL,
1722 /* keywords */ "horiz vert"
1723 },
1724
1725 { "Rotate90", "General",
1726 &CMD_Rotate90,
1727 /* flags */ NULL,
1728 /* keywords */ "cw acw"
1729 },
1730
1731 { "Enlarge", "General",
1732 &CMD_Enlarge
1733 },
1734
1735 { "Shrink", "General",
1736 &CMD_Shrink
1737 },
1738
1739 { "Quantize", "General",
1740 &CMD_Quantize
1741 },
1742
1743 { "ApplyTag", "General",
1744 &CMD_ApplyTag,
1745 /* flags */ NULL,
1746 /* keywords */ "fresh last"
1747 },
1748
1749 { "ACT_Click", "General",
1750 &CMD_ACT_Click,
1751 /* flags */ "/noselect /nodrag /nosplit"
1752 },
1753
1754 { "ACT_Drag", "General",
1755 &CMD_ACT_Drag
1756 },
1757
1758 { "ACT_Transform", "General",
1759 &CMD_ACT_Transform,
1760 /* flags */ NULL,
1761 /* keywords */ "scale stretch rotate rotscale skew"
1762 },
1763
1764
1765 /* ------ LineDef mode ------ */
1766
1767 { "LIN_Align", NULL,
1768 &CMD_LIN_Align,
1769 /* flags */ "/x /y /right /clear"
1770 },
1771
1772 { "LIN_Flip", NULL,
1773 &CMD_LIN_Flip,
1774 /* flags */ "/force"
1775 },
1776
1777 { "LIN_SwapSides", NULL,
1778 &CMD_LIN_SwapSides
1779 },
1780
1781 { "LIN_SplitHalf", NULL,
1782 &CMD_LIN_SplitHalf
1783 },
1784
1785 { "LIN_SelectPath", NULL,
1786 &CMD_LIN_SelectPath,
1787 /* flags */ "/fresh /onesided /sametex"
1788 },
1789
1790
1791 /* ------ Sector mode ------ */
1792
1793 { "SEC_Floor", NULL,
1794 &CMD_SEC_Floor
1795 },
1796
1797 { "SEC_Ceil", NULL,
1798 &CMD_SEC_Ceil
1799 },
1800
1801 { "SEC_Light", NULL,
1802 &CMD_SEC_Light
1803 },
1804
1805 { "SEC_SelectGroup", NULL,
1806 &CMD_SEC_SelectGroup,
1807 /* flags */ "/fresh /can_walk /doors /floor_h /floor_tex /ceil_h /ceil_tex /light /tag /special"
1808 },
1809
1810 { "SEC_SwapFlats", NULL,
1811 &CMD_SEC_SwapFlats
1812 },
1813
1814
1815 /* ------ Thing mode ------ */
1816
1817 { "TH_Spin", NULL,
1818 &CMD_TH_SpinThings
1819 },
1820
1821
1822 /* ------ Vertex mode ------ */
1823
1824 { "VT_ShapeLine", NULL,
1825 &CMD_VT_ShapeLine
1826 },
1827
1828 { "VT_ShapeArc", NULL,
1829 &CMD_VT_ShapeArc
1830 },
1831
1832
1833 /* -------- Browser -------- */
1834
1835 { "BrowserMode", "Browser",
1836 &CMD_BrowserMode,
1837 /* flags */ "/recent",
1838 /* keywords */ "obj tex flat line sec genline"
1839 },
1840
1841 { "BR_CycleCategory", "Browser",
1842 &CMD_BR_CycleCategory
1843 },
1844
1845 { "BR_ClearSearch", "Browser",
1846 &CMD_BR_ClearSearch
1847 },
1848
1849 { "BR_Scroll", "Browser",
1850 &CMD_BR_Scroll
1851 },
1852
1853 // end of command list
1854 { NULL, NULL, 0, NULL }
1855 };
1856
1857
Editor_RegisterCommands()1858 void Editor_RegisterCommands()
1859 {
1860 M_RegisterCommandList(command_table);
1861 }
1862
1863
1864 //--- editor settings ---
1865 // vi:ts=4:sw=4:noexpandtab
1866