Skip to content

Commit 08e6cd1

Browse files
committed
Merge pull request godotengine#113915 from ydeltastar/game-view-node-lock
Prevent locked and child nodes of selection groups from being selected in the Game view
2 parents 9bdae42 + a92851c commit 08e6cd1

4 files changed

Lines changed: 190 additions & 13 deletions

File tree

editor/run/game_view_plugin.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,12 @@ void GameViewDebugger::_session_started(Ref<EditorDebuggerSession> p_session) {
9595
Array mode;
9696
mode.append(select_mode);
9797
p_session->send_message("scene:runtime_node_select_set_mode", mode);
98+
Array avoid_locked;
99+
avoid_locked.append(selection_avoid_locked);
100+
p_session->send_message("scene:runtime_node_select_set_avoid_locked", avoid_locked);
101+
Array prefer_group;
102+
prefer_group.append(selection_prefer_group);
103+
p_session->send_message("scene:runtime_node_select_set_prefer_group", prefer_group);
98104
Array mute_audio_data;
99105
mute_audio_data.append(mute_audio);
100106
p_session->send_message("scene:debug_mute_audio", mute_audio_data);
@@ -183,6 +189,32 @@ void GameViewDebugger::set_selection_visible(bool p_visible) {
183189
}
184190
}
185191

192+
void GameViewDebugger::set_selection_avoid_locked(bool p_enabled) {
193+
selection_avoid_locked = p_enabled;
194+
195+
Array message;
196+
message.append(p_enabled);
197+
198+
for (Ref<EditorDebuggerSession> &I : sessions) {
199+
if (I->is_active()) {
200+
I->send_message("scene:runtime_node_select_set_avoid_locked", message);
201+
}
202+
}
203+
}
204+
205+
void GameViewDebugger::set_selection_prefer_group(bool p_enabled) {
206+
selection_prefer_group = p_enabled;
207+
208+
Array message;
209+
message.append(p_enabled);
210+
211+
for (Ref<EditorDebuggerSession> &I : sessions) {
212+
if (I->is_active()) {
213+
I->send_message("scene:runtime_node_select_set_prefer_group", message);
214+
}
215+
}
216+
}
217+
186218
void GameViewDebugger::set_select_mode(int p_mode) {
187219
select_mode = p_mode;
188220

@@ -596,6 +628,25 @@ void GameView::_select_mode_pressed(int p_option) {
596628
EditorSettings::get_singleton()->set_project_metadata("game_view", "select_mode", mode);
597629
}
598630

631+
void GameView::_selection_options_menu_id_pressed(int p_id) {
632+
switch (p_id) {
633+
case SELECTION_AVOID_LOCKED: {
634+
selection_avoid_locked = !selection_avoid_locked;
635+
debugger->set_selection_avoid_locked(selection_avoid_locked);
636+
EditorSettings::get_singleton()->set_project_metadata("game_view", "selection_avoid_locked", selection_avoid_locked);
637+
} break;
638+
case SELECTION_PREFER_GROUP: {
639+
selection_prefer_group = !selection_prefer_group;
640+
debugger->set_selection_prefer_group(selection_prefer_group);
641+
EditorSettings::get_singleton()->set_project_metadata("game_view", "selection_prefer_group", selection_prefer_group);
642+
} break;
643+
}
644+
645+
PopupMenu *menu = selection_options_menu->get_popup();
646+
menu->set_item_checked(menu->get_item_index(SELECTION_AVOID_LOCKED), selection_avoid_locked);
647+
menu->set_item_checked(menu->get_item_index(SELECTION_PREFER_GROUP), selection_prefer_group);
648+
}
649+
599650
void GameView::_embed_options_menu_menu_id_pressed(int p_id) {
600651
switch (p_id) {
601652
case EMBED_RUN_GAME_EMBEDDED: {
@@ -880,6 +931,7 @@ void GameView::_notification(int p_what) {
880931
select_mode_button[RuntimeNodeSelect::SELECT_MODE_LIST]->set_button_icon(get_editor_theme_icon(SNAME("ListSelect")));
881932

882933
hide_selection->set_button_icon(get_editor_theme_icon(hide_selection->is_pressed() ? SNAME("GuiVisibilityHidden") : SNAME("GuiVisibilityVisible")));
934+
selection_options_menu->set_button_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl")));
883935
embed_options_menu->set_button_icon(get_editor_theme_icon(SNAME("KeepAspect")));
884936

885937
debug_mute_audio_button->set_button_icon(get_editor_theme_icon(debug_mute_audio ? SNAME("AudioMute") : SNAME("AudioStreamPlayer")));
@@ -1272,6 +1324,26 @@ GameView::GameView(Ref<GameViewDebugger> p_debugger, EmbeddedProcessBase *p_embe
12721324
}
12731325
hide_selection->connect(SceneStringName(toggled), callable_mp(this, &GameView::_hide_selection_toggled));
12741326

1327+
selection_options_menu = memnew(MenuButton);
1328+
selection_hb->add_child(selection_options_menu);
1329+
selection_options_menu->set_flat(false);
1330+
selection_options_menu->set_theme_type_variation("FlatMenuButton");
1331+
selection_options_menu->set_h_size_flags(SIZE_SHRINK_END);
1332+
selection_options_menu->set_tooltip_text(TTRC("Selection Options"));
1333+
1334+
PopupMenu *selection_menu = selection_options_menu->get_popup();
1335+
selection_menu->connect(SceneStringName(id_pressed), callable_mp(this, &GameView::_selection_options_menu_id_pressed));
1336+
selection_menu->add_check_item(TTRC("Don't Select Locked Nodes"), SELECTION_AVOID_LOCKED);
1337+
selection_menu->add_check_item(TTRC("Select Group Over Children"), SELECTION_PREFER_GROUP);
1338+
1339+
selection_avoid_locked = EditorSettings::get_singleton()->get_project_metadata("game_view", "selection_avoid_locked", false);
1340+
selection_prefer_group = EditorSettings::get_singleton()->get_project_metadata("game_view", "selection_prefer_group", false);
1341+
selection_menu->set_item_checked(selection_menu->get_item_index(SELECTION_AVOID_LOCKED), selection_avoid_locked);
1342+
selection_menu->set_item_checked(selection_menu->get_item_index(SELECTION_PREFER_GROUP), selection_prefer_group);
1343+
1344+
debugger->set_selection_avoid_locked(selection_avoid_locked);
1345+
debugger->set_selection_prefer_group(selection_prefer_group);
1346+
12751347
selection_hb->add_child(memnew(VSeparator));
12761348

12771349
HBoxContainer *audio_hb = memnew(HBoxContainer);

editor/run/game_view_plugin.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ class GameViewDebugger : public EditorDebuggerPlugin {
5555
bool mute_audio = false;
5656
EditorDebuggerNode::CameraOverride camera_override_mode = EditorDebuggerNode::OVERRIDE_INGAME;
5757

58+
bool selection_avoid_locked = false;
59+
bool selection_prefer_group = false;
60+
5861
void _session_started(Ref<EditorDebuggerSession> p_session);
5962
void _session_stopped();
6063

@@ -90,6 +93,9 @@ class GameViewDebugger : public EditorDebuggerPlugin {
9093

9194
void set_selection_visible(bool p_visible);
9295

96+
void set_selection_avoid_locked(bool p_enabled);
97+
void set_selection_prefer_group(bool p_enabled);
98+
9399
void set_debug_mute_audio(bool p_enabled);
94100

95101
void set_camera_override(bool p_enabled);
@@ -113,6 +119,8 @@ class GameView : public VBoxContainer {
113119
CAMERA_MODE_EDITORS,
114120
EMBED_RUN_GAME_EMBEDDED,
115121
EMBED_MAKE_FLOATING_ON_PLAY,
122+
SELECTION_AVOID_LOCKED,
123+
SELECTION_PREFER_GROUP,
116124
};
117125

118126
enum EmbedSizeMode {
@@ -153,13 +161,17 @@ class GameView : public VBoxContainer {
153161

154162
bool debug_mute_audio = false;
155163

164+
bool selection_avoid_locked = false;
165+
bool selection_prefer_group = false;
166+
156167
Button *suspend_button = nullptr;
157168
Button *next_frame_button = nullptr;
158169

159170
Button *node_type_button[RuntimeNodeSelect::NODE_TYPE_MAX];
160171
Button *select_mode_button[RuntimeNodeSelect::SELECT_MODE_MAX];
161172

162173
Button *hide_selection = nullptr;
174+
MenuButton *selection_options_menu = nullptr;
163175

164176
Button *debug_mute_audio_button = nullptr;
165177

@@ -191,6 +203,7 @@ class GameView : public VBoxContainer {
191203

192204
void _node_type_pressed(int p_option);
193205
void _select_mode_pressed(int p_option);
206+
void _selection_options_menu_id_pressed(int p_id);
194207
void _embed_options_menu_menu_id_pressed(int p_id);
195208

196209
void _reset_time_scales();

scene/debugger/scene_debugger.cpp

Lines changed: 98 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,20 @@ Error SceneDebugger::_msg_runtime_node_select_set_visible(const Array &p_args) {
415415
return OK;
416416
}
417417

418+
Error SceneDebugger::_msg_runtime_node_select_set_avoid_locked(const Array &p_args) {
419+
ERR_FAIL_COND_V(p_args.is_empty(), ERR_INVALID_DATA);
420+
bool avoid_locked = p_args[0];
421+
RuntimeNodeSelect::get_singleton()->_set_avoid_locked(avoid_locked);
422+
return OK;
423+
}
424+
425+
Error SceneDebugger::_msg_runtime_node_select_set_prefer_group(const Array &p_args) {
426+
ERR_FAIL_COND_V(p_args.is_empty(), ERR_INVALID_DATA);
427+
bool prefer_group = p_args[0];
428+
RuntimeNodeSelect::get_singleton()->_set_prefer_group(prefer_group);
429+
return OK;
430+
}
431+
418432
Error SceneDebugger::_msg_runtime_node_select_reset_camera_2d(const Array &p_args) {
419433
RuntimeNodeSelect::get_singleton()->_reset_camera_2d();
420434
return OK;
@@ -567,6 +581,8 @@ void SceneDebugger::_init_message_handlers() {
567581
message_handlers["runtime_node_select_set_type"] = _msg_runtime_node_select_set_type;
568582
message_handlers["runtime_node_select_set_mode"] = _msg_runtime_node_select_set_mode;
569583
message_handlers["runtime_node_select_set_visible"] = _msg_runtime_node_select_set_visible;
584+
message_handlers["runtime_node_select_set_avoid_locked"] = _msg_runtime_node_select_set_avoid_locked;
585+
message_handlers["runtime_node_select_set_prefer_group"] = _msg_runtime_node_select_set_prefer_group;
570586
message_handlers["runtime_node_select_reset_camera_2d"] = _msg_runtime_node_select_reset_camera_2d;
571587
#ifndef _3D_DISABLED
572588
message_handlers["runtime_node_select_reset_camera_3d"] = _msg_runtime_node_select_reset_camera_3d;
@@ -1859,18 +1875,6 @@ void RuntimeNodeSelect::_physics_frame() {
18591875
}
18601876
}
18611877

1862-
// Remove possible duplicates.
1863-
for (int i = 0; i < items.size(); i++) {
1864-
Node *item = items[i].item;
1865-
for (int j = 0; j < i; j++) {
1866-
if (items[j].item == item) {
1867-
items.remove_at(i);
1868-
i--;
1869-
1870-
break;
1871-
}
1872-
}
1873-
}
18741878
#ifndef _3D_DISABLED
18751879
} else if (node_select_type == NODE_TYPE_3D) {
18761880
if (selection_drag_valid) {
@@ -1881,6 +1885,57 @@ void RuntimeNodeSelect::_physics_frame() {
18811885
#endif // _3D_DISABLED
18821886
}
18831887

1888+
if ((prefer_group_selection || avoid_locked_nodes) && !list_shortcut_pressed && node_select_mode == SELECT_MODE_SINGLE) {
1889+
for (int i = 0; i < items.size(); i++) {
1890+
Node *node = items[i].item;
1891+
Node *final_node = node;
1892+
real_t order = items[i].order;
1893+
1894+
// Replace the node by the group if grouped.
1895+
if (prefer_group_selection) {
1896+
while (node && node != root) {
1897+
if (node->has_meta("_edit_group_")) {
1898+
final_node = node;
1899+
1900+
if (Object::cast_to<CanvasItem>(final_node)) {
1901+
CanvasItem *ci_tmp = Object::cast_to<CanvasItem>(final_node);
1902+
order = ci_tmp->get_effective_z_index() + ci_tmp->get_canvas_layer();
1903+
} else if (Object::cast_to<Node3D>(final_node)) {
1904+
Node3D *node3d_tmp = Object::cast_to<Node3D>(final_node);
1905+
Camera3D *camera = root->get_camera_3d();
1906+
Vector3 pos = camera->project_ray_origin(selection_position);
1907+
order = -pos.distance_to(node3d_tmp->get_global_transform().origin);
1908+
}
1909+
}
1910+
node = node->get_parent();
1911+
}
1912+
}
1913+
1914+
// Filter out locked nodes.
1915+
if (avoid_locked_nodes && final_node->get_meta("_edit_lock_", false)) {
1916+
items.remove_at(i);
1917+
i--;
1918+
continue;
1919+
}
1920+
1921+
items.write[i].item = final_node;
1922+
items.write[i].order = order;
1923+
}
1924+
}
1925+
1926+
// Remove possible duplicates.
1927+
for (int i = 0; i < items.size(); i++) {
1928+
Node *item = items[i].item;
1929+
for (int j = 0; j < i; j++) {
1930+
if (items[j].item == item) {
1931+
items.remove_at(i);
1932+
i--;
1933+
1934+
break;
1935+
}
1936+
}
1937+
}
1938+
18841939
items.sort();
18851940

18861941
switch (selection_drag_state) {
@@ -2334,7 +2389,29 @@ void RuntimeNodeSelect::_open_selection_list(const Vector<SelectResult> &p_items
23342389
root->add_child(selection_list);
23352390

23362391
for (const SelectResult &I : p_items) {
2337-
selection_list->add_item(I.item->get_name());
2392+
int locked = 0;
2393+
if (I.item->get_meta("_edit_lock_", false)) {
2394+
locked = 1;
2395+
} else {
2396+
Node *scene = SceneTree::get_singleton()->get_root();
2397+
Node *node = I.item;
2398+
2399+
while (node && node != scene->get_parent()) {
2400+
if (node->has_meta("_edit_group_")) {
2401+
locked = 2;
2402+
}
2403+
node = node->get_parent();
2404+
}
2405+
}
2406+
2407+
String suffix;
2408+
if (locked == 1) {
2409+
suffix = " (" + RTR("Locked") + ")";
2410+
} else if (locked == 2) {
2411+
suffix = " (" + RTR("Grouped") + ")";
2412+
}
2413+
2414+
selection_list->add_item((String)I.item->get_name() + suffix);
23382415
selection_list->set_item_metadata(-1, I.item);
23392416
}
23402417

@@ -2358,6 +2435,14 @@ void RuntimeNodeSelect::_set_selection_visible(bool p_visible) {
23582435
}
23592436
}
23602437

2438+
void RuntimeNodeSelect::_set_avoid_locked(bool p_enabled) {
2439+
avoid_locked_nodes = p_enabled;
2440+
}
2441+
2442+
void RuntimeNodeSelect::_set_prefer_group(bool p_enabled) {
2443+
prefer_group_selection = p_enabled;
2444+
}
2445+
23612446
// Copied and trimmed from the CanvasItemEditor implementation.
23622447
void RuntimeNodeSelect::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, Vector<SelectResult> &r_items, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) {
23632448
if (!p_node || Object::cast_to<Viewport>(p_node)) {

scene/debugger/scene_debugger.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ class SceneDebugger {
115115
static Error _msg_runtime_node_select_set_type(const Array &p_args);
116116
static Error _msg_runtime_node_select_set_mode(const Array &p_args);
117117
static Error _msg_runtime_node_select_set_visible(const Array &p_args);
118+
static Error _msg_runtime_node_select_set_avoid_locked(const Array &p_args);
119+
static Error _msg_runtime_node_select_set_prefer_group(const Array &p_args);
118120
static Error _msg_rq_screenshot(const Array &p_args);
119121

120122
static Error _msg_runtime_node_select_reset_camera_2d(const Array &p_args);
@@ -280,6 +282,9 @@ class RuntimeNodeSelect : public Object {
280282
bool selection_visible = true;
281283
bool selection_update_queued = false;
282284

285+
bool avoid_locked_nodes = false;
286+
bool prefer_group_selection = false;
287+
283288
bool multi_shortcut_pressed = false;
284289
bool list_shortcut_pressed = false;
285290
RID draw_canvas;
@@ -396,6 +401,8 @@ class RuntimeNodeSelect : public Object {
396401
void _clear_selection();
397402
void _update_selection_drag(const Point2 &p_end_pos = Point2());
398403
void _set_selection_visible(bool p_visible);
404+
void _set_avoid_locked(bool p_enabled);
405+
void _set_prefer_group(bool p_enabled);
399406

400407
void _open_selection_list(const Vector<SelectResult> &p_items, const Point2 &p_pos);
401408
void _close_selection_list();

0 commit comments

Comments
 (0)