Skip to content

Commit 0e939de

Browse files
committed
basic entity multi-grab
1 parent afe1afa commit 0e939de

File tree

2 files changed

+61
-24
lines changed

2 files changed

+61
-24
lines changed

Game/source/editor.jai

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,9 @@ Editor: struct {
9595
mouse_tile_index: int;
9696

9797
grab: struct {
98-
entity_index: int;
99-
offset: Vector2; // position of mouse relative to origin of grabbed element, at time when grab begins
98+
entity_index: int;
99+
offset: Vector2; // position of mouse relative to origin of grabbed element, at time when grab begins
100+
elements_selected: int;
100101
};
101102

102103
brush: struct {
@@ -158,6 +159,25 @@ Editor: struct {
158159
tile_unit := 32.0;
159160
};
160161

162+
editor_toggle_grab_selection :: (entity: *Entity) {
163+
entity.flags ^= .SELECTED_IN_EDITOR;
164+
Editor.grab.elements_selected += ifx entity.flags & .SELECTED_IN_EDITOR then 1 else -1;
165+
}
166+
167+
editor_set_grab_selection :: (entity: *Entity) {
168+
editor_clear_grab_selection();
169+
entity.flags |= .SELECTED_IN_EDITOR;
170+
Editor.grab.elements_selected = 1;
171+
}
172+
173+
editor_clear_grab_selection :: () {
174+
Editor.grab.elements_selected = 0;
175+
176+
for *Editor.level.entities {
177+
it.flags &= ~.SELECTED_IN_EDITOR;
178+
}
179+
}
180+
161181
edit_level_with_id :: (id: string) -> bool {
162182
found, source_layout := table_find_new(*Game.loaded_level_layouts, id);
163183
if !found {

Game/source/editor_ui.jai

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,16 @@
1717
TODO: rename all of the functions to be a little more namespaced
1818
they are currently way too generic-sounding and could easily conflict later
1919
20+
21+
TODO:
22+
can probably remove the active holding focus thing entirely and just use mouse state
23+
no reason for us to be be able to set a new hot item while the mouse is down, methinks
24+
only valid reason I can think of is to support some kind of drag and drop between nodes
25+
but then in that case we would already be holding some other active element anyhow
26+
this would simplify some logic and should make multi-selection logic easier to follow
27+
28+
29+
2030
*/
2131

2232
#if EDITOR_ENABLED {
@@ -358,6 +368,7 @@ ui_begin_frame :: () {
358368

359369
if (hot == null && mouse_left() == .PRESSED) || !(flags & .ACTIVE_VISITED_THIS_FRAME) {
360370
ui_clear_active();
371+
editor_clear_grab_selection();
361372
}
362373

363374
if !(flags & .HOT_VISITED_THIS_FRAME) {
@@ -620,26 +631,12 @@ notify_parent_of_active_hot_state :: (node: *UI_Node) {
620631
}
621632

622633
// NOTE: performed on the ui_state.current_node
623-
update_active_hot_state :: (hovered: bool, want_focus_held: Handle_Focus_Type) -> Handle_Focus_Type {
634+
update_active_hot_state :: (hovered: bool, want_focus_held: Handle_Focus_Type, treat_as_if_active := false) -> Handle_Focus_Type {
624635
mouse := get_mouse();
625636
node := ui_state.current_node;
626637

627638
reset_transient_flags(node);
628639

629-
// if hovered {
630-
// if !ui_state.active_holding_focus && (node == ui_state.hot) {
631-
// if mouse.left == .PRESSED {
632-
// ui_set_active(node, want_focus_held & .L);
633-
// }
634-
// if mouse.right == .PRESSED {
635-
// ui_set_active(node, want_focus_held & .R);
636-
// }
637-
// }
638-
// ui_try_set_hot(node);
639-
// } else if node == ui_state.hot {
640-
// ui_state.hot == null;
641-
// }
642-
643640
if node == ui_state.hot {
644641
if hovered {
645642
node.flags |= .HOT;
@@ -665,7 +662,7 @@ update_active_hot_state :: (hovered: bool, want_focus_held: Handle_Focus_Type) -
665662
notify_parent_of_active_hot_state(node);
666663

667664
focus_held := Handle_Focus_Type.NONE;
668-
if node == ui_state.active {
665+
if node == ui_state.active || treat_as_if_active {
669666
node.flags |= .ACTIVE;
670667
ui_state.flags |= .ACTIVE_VISITED_THIS_FRAME;
671668

@@ -799,27 +796,47 @@ ui_entity_handle :: (index: int) {
799796
offset_ptr := *entity.init_position;
800797
size := get_size(entity);
801798

802-
// get entity handle rect
803799
rect := Rectf.{
804800
position = offset_ptr.* - size / 2,
805801
size = size,
806802
};
807803

808804
hovered := is_point_within_frect(Editor.mouse_tile_position, rect);
809-
focus := update_active_hot_state(hovered, .L);
805+
is_selected := (entity.flags & .SELECTED_IN_EDITOR).(bool);
806+
807+
focus := update_active_hot_state(hovered, .L, is_selected);
810808

811809
if focus == {
812810
case .L;
813-
if mouse.left == .RELEASED {
814-
offset_ptr.* = snap_to_nearest_unit(offset_ptr.*, 0.5);
815-
} else {
811+
if mouse.left == {
812+
case .PRESSED;
813+
if hovered {
814+
if key_modifier_state & .CTRL {
815+
editor_toggle_grab_selection(entity);
816+
if !(entity.flags & .SELECTED_IN_EDITOR) && node == ui_state.active then ui_clear_active();
817+
} else {
818+
if !(entity.flags & .SELECTED_IN_EDITOR) {
819+
editor_set_grab_selection(entity);
820+
Editor.details_panel_subject = entity.*;
821+
}
822+
}
823+
}
824+
825+
case .DOWN;
816826
offset_ptr.* += to_Vec2f(mouse.velocity) / Editor.tile_unit;
827+
828+
case .RELEASED;
829+
offset_ptr.* = snap_to_nearest_unit(offset_ptr.*, 0.5);
817830
}
818-
Editor.details_panel_subject = entity.*;
819831
}
820832

821833
update_node(node, offset_ptr.*);
822834

835+
// NOTE: this will only affect visuals, not ui function
836+
if is_selected {
837+
node.flags |= .ACTIVE;
838+
}
839+
823840
color := get_render_color(node, base_color, hot_color, active_color);
824841

825842
render_rect := rect;

0 commit comments

Comments
 (0)