2
0
Эх сурвалжийг харах

Merge pull request #113915 from ydeltastar/game-view-node-lock

Prevent locked and child nodes of selection groups from being selected in the Game view
Thaddeus Crews 1 өдөр өмнө
parent
commit
08e6cd181f

+ 72 - 0
editor/run/game_view_plugin.cpp

@@ -95,6 +95,12 @@ void GameViewDebugger::_session_started(Ref<EditorDebuggerSession> p_session) {
 	Array mode;
 	mode.append(select_mode);
 	p_session->send_message("scene:runtime_node_select_set_mode", mode);
+	Array avoid_locked;
+	avoid_locked.append(selection_avoid_locked);
+	p_session->send_message("scene:runtime_node_select_set_avoid_locked", avoid_locked);
+	Array prefer_group;
+	prefer_group.append(selection_prefer_group);
+	p_session->send_message("scene:runtime_node_select_set_prefer_group", prefer_group);
 	Array mute_audio_data;
 	mute_audio_data.append(mute_audio);
 	p_session->send_message("scene:debug_mute_audio", mute_audio_data);
@@ -183,6 +189,32 @@ void GameViewDebugger::set_selection_visible(bool p_visible) {
 	}
 }
 
+void GameViewDebugger::set_selection_avoid_locked(bool p_enabled) {
+	selection_avoid_locked = p_enabled;
+
+	Array message;
+	message.append(p_enabled);
+
+	for (Ref<EditorDebuggerSession> &I : sessions) {
+		if (I->is_active()) {
+			I->send_message("scene:runtime_node_select_set_avoid_locked", message);
+		}
+	}
+}
+
+void GameViewDebugger::set_selection_prefer_group(bool p_enabled) {
+	selection_prefer_group = p_enabled;
+
+	Array message;
+	message.append(p_enabled);
+
+	for (Ref<EditorDebuggerSession> &I : sessions) {
+		if (I->is_active()) {
+			I->send_message("scene:runtime_node_select_set_prefer_group", message);
+		}
+	}
+}
+
 void GameViewDebugger::set_select_mode(int p_mode) {
 	select_mode = p_mode;
 
@@ -596,6 +628,25 @@ void GameView::_select_mode_pressed(int p_option) {
 	EditorSettings::get_singleton()->set_project_metadata("game_view", "select_mode", mode);
 }
 
+void GameView::_selection_options_menu_id_pressed(int p_id) {
+	switch (p_id) {
+		case SELECTION_AVOID_LOCKED: {
+			selection_avoid_locked = !selection_avoid_locked;
+			debugger->set_selection_avoid_locked(selection_avoid_locked);
+			EditorSettings::get_singleton()->set_project_metadata("game_view", "selection_avoid_locked", selection_avoid_locked);
+		} break;
+		case SELECTION_PREFER_GROUP: {
+			selection_prefer_group = !selection_prefer_group;
+			debugger->set_selection_prefer_group(selection_prefer_group);
+			EditorSettings::get_singleton()->set_project_metadata("game_view", "selection_prefer_group", selection_prefer_group);
+		} break;
+	}
+
+	PopupMenu *menu = selection_options_menu->get_popup();
+	menu->set_item_checked(menu->get_item_index(SELECTION_AVOID_LOCKED), selection_avoid_locked);
+	menu->set_item_checked(menu->get_item_index(SELECTION_PREFER_GROUP), selection_prefer_group);
+}
+
 void GameView::_embed_options_menu_menu_id_pressed(int p_id) {
 	switch (p_id) {
 		case EMBED_RUN_GAME_EMBEDDED: {
@@ -880,6 +931,7 @@ void GameView::_notification(int p_what) {
 			select_mode_button[RuntimeNodeSelect::SELECT_MODE_LIST]->set_button_icon(get_editor_theme_icon(SNAME("ListSelect")));
 
 			hide_selection->set_button_icon(get_editor_theme_icon(hide_selection->is_pressed() ? SNAME("GuiVisibilityHidden") : SNAME("GuiVisibilityVisible")));
+			selection_options_menu->set_button_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl")));
 			embed_options_menu->set_button_icon(get_editor_theme_icon(SNAME("KeepAspect")));
 
 			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
 	}
 	hide_selection->connect(SceneStringName(toggled), callable_mp(this, &GameView::_hide_selection_toggled));
 
+	selection_options_menu = memnew(MenuButton);
+	selection_hb->add_child(selection_options_menu);
+	selection_options_menu->set_flat(false);
+	selection_options_menu->set_theme_type_variation("FlatMenuButton");
+	selection_options_menu->set_h_size_flags(SIZE_SHRINK_END);
+	selection_options_menu->set_tooltip_text(TTRC("Selection Options"));
+
+	PopupMenu *selection_menu = selection_options_menu->get_popup();
+	selection_menu->connect(SceneStringName(id_pressed), callable_mp(this, &GameView::_selection_options_menu_id_pressed));
+	selection_menu->add_check_item(TTRC("Don't Select Locked Nodes"), SELECTION_AVOID_LOCKED);
+	selection_menu->add_check_item(TTRC("Select Group Over Children"), SELECTION_PREFER_GROUP);
+
+	selection_avoid_locked = EditorSettings::get_singleton()->get_project_metadata("game_view", "selection_avoid_locked", false);
+	selection_prefer_group = EditorSettings::get_singleton()->get_project_metadata("game_view", "selection_prefer_group", false);
+	selection_menu->set_item_checked(selection_menu->get_item_index(SELECTION_AVOID_LOCKED), selection_avoid_locked);
+	selection_menu->set_item_checked(selection_menu->get_item_index(SELECTION_PREFER_GROUP), selection_prefer_group);
+
+	debugger->set_selection_avoid_locked(selection_avoid_locked);
+	debugger->set_selection_prefer_group(selection_prefer_group);
+
 	selection_hb->add_child(memnew(VSeparator));
 
 	HBoxContainer *audio_hb = memnew(HBoxContainer);

+ 13 - 0
editor/run/game_view_plugin.h

@@ -55,6 +55,9 @@ private:
 	bool mute_audio = false;
 	EditorDebuggerNode::CameraOverride camera_override_mode = EditorDebuggerNode::OVERRIDE_INGAME;
 
+	bool selection_avoid_locked = false;
+	bool selection_prefer_group = false;
+
 	void _session_started(Ref<EditorDebuggerSession> p_session);
 	void _session_stopped();
 
@@ -90,6 +93,9 @@ public:
 
 	void set_selection_visible(bool p_visible);
 
+	void set_selection_avoid_locked(bool p_enabled);
+	void set_selection_prefer_group(bool p_enabled);
+
 	void set_debug_mute_audio(bool p_enabled);
 
 	void set_camera_override(bool p_enabled);
@@ -113,6 +119,8 @@ class GameView : public VBoxContainer {
 		CAMERA_MODE_EDITORS,
 		EMBED_RUN_GAME_EMBEDDED,
 		EMBED_MAKE_FLOATING_ON_PLAY,
+		SELECTION_AVOID_LOCKED,
+		SELECTION_PREFER_GROUP,
 	};
 
 	enum EmbedSizeMode {
@@ -153,6 +161,9 @@ class GameView : public VBoxContainer {
 
 	bool debug_mute_audio = false;
 
+	bool selection_avoid_locked = false;
+	bool selection_prefer_group = false;
+
 	Button *suspend_button = nullptr;
 	Button *next_frame_button = nullptr;
 
@@ -160,6 +171,7 @@ class GameView : public VBoxContainer {
 	Button *select_mode_button[RuntimeNodeSelect::SELECT_MODE_MAX];
 
 	Button *hide_selection = nullptr;
+	MenuButton *selection_options_menu = nullptr;
 
 	Button *debug_mute_audio_button = nullptr;
 
@@ -191,6 +203,7 @@ class GameView : public VBoxContainer {
 
 	void _node_type_pressed(int p_option);
 	void _select_mode_pressed(int p_option);
+	void _selection_options_menu_id_pressed(int p_id);
 	void _embed_options_menu_menu_id_pressed(int p_id);
 
 	void _reset_time_scales();

+ 98 - 13
scene/debugger/scene_debugger.cpp

@@ -415,6 +415,20 @@ Error SceneDebugger::_msg_runtime_node_select_set_visible(const Array &p_args) {
 	return OK;
 }
 
+Error SceneDebugger::_msg_runtime_node_select_set_avoid_locked(const Array &p_args) {
+	ERR_FAIL_COND_V(p_args.is_empty(), ERR_INVALID_DATA);
+	bool avoid_locked = p_args[0];
+	RuntimeNodeSelect::get_singleton()->_set_avoid_locked(avoid_locked);
+	return OK;
+}
+
+Error SceneDebugger::_msg_runtime_node_select_set_prefer_group(const Array &p_args) {
+	ERR_FAIL_COND_V(p_args.is_empty(), ERR_INVALID_DATA);
+	bool prefer_group = p_args[0];
+	RuntimeNodeSelect::get_singleton()->_set_prefer_group(prefer_group);
+	return OK;
+}
+
 Error SceneDebugger::_msg_runtime_node_select_reset_camera_2d(const Array &p_args) {
 	RuntimeNodeSelect::get_singleton()->_reset_camera_2d();
 	return OK;
@@ -567,6 +581,8 @@ void SceneDebugger::_init_message_handlers() {
 	message_handlers["runtime_node_select_set_type"] = _msg_runtime_node_select_set_type;
 	message_handlers["runtime_node_select_set_mode"] = _msg_runtime_node_select_set_mode;
 	message_handlers["runtime_node_select_set_visible"] = _msg_runtime_node_select_set_visible;
+	message_handlers["runtime_node_select_set_avoid_locked"] = _msg_runtime_node_select_set_avoid_locked;
+	message_handlers["runtime_node_select_set_prefer_group"] = _msg_runtime_node_select_set_prefer_group;
 	message_handlers["runtime_node_select_reset_camera_2d"] = _msg_runtime_node_select_reset_camera_2d;
 #ifndef _3D_DISABLED
 	message_handlers["runtime_node_select_reset_camera_3d"] = _msg_runtime_node_select_reset_camera_3d;
@@ -1859,18 +1875,6 @@ void RuntimeNodeSelect::_physics_frame() {
 			}
 		}
 
-		// Remove possible duplicates.
-		for (int i = 0; i < items.size(); i++) {
-			Node *item = items[i].item;
-			for (int j = 0; j < i; j++) {
-				if (items[j].item == item) {
-					items.remove_at(i);
-					i--;
-
-					break;
-				}
-			}
-		}
 #ifndef _3D_DISABLED
 	} else if (node_select_type == NODE_TYPE_3D) {
 		if (selection_drag_valid) {
@@ -1881,6 +1885,57 @@ void RuntimeNodeSelect::_physics_frame() {
 #endif // _3D_DISABLED
 	}
 
+	if ((prefer_group_selection || avoid_locked_nodes) && !list_shortcut_pressed && node_select_mode == SELECT_MODE_SINGLE) {
+		for (int i = 0; i < items.size(); i++) {
+			Node *node = items[i].item;
+			Node *final_node = node;
+			real_t order = items[i].order;
+
+			// Replace the node by the group if grouped.
+			if (prefer_group_selection) {
+				while (node && node != root) {
+					if (node->has_meta("_edit_group_")) {
+						final_node = node;
+
+						if (Object::cast_to<CanvasItem>(final_node)) {
+							CanvasItem *ci_tmp = Object::cast_to<CanvasItem>(final_node);
+							order = ci_tmp->get_effective_z_index() + ci_tmp->get_canvas_layer();
+						} else if (Object::cast_to<Node3D>(final_node)) {
+							Node3D *node3d_tmp = Object::cast_to<Node3D>(final_node);
+							Camera3D *camera = root->get_camera_3d();
+							Vector3 pos = camera->project_ray_origin(selection_position);
+							order = -pos.distance_to(node3d_tmp->get_global_transform().origin);
+						}
+					}
+					node = node->get_parent();
+				}
+			}
+
+			// Filter out locked nodes.
+			if (avoid_locked_nodes && final_node->get_meta("_edit_lock_", false)) {
+				items.remove_at(i);
+				i--;
+				continue;
+			}
+
+			items.write[i].item = final_node;
+			items.write[i].order = order;
+		}
+	}
+
+	// Remove possible duplicates.
+	for (int i = 0; i < items.size(); i++) {
+		Node *item = items[i].item;
+		for (int j = 0; j < i; j++) {
+			if (items[j].item == item) {
+				items.remove_at(i);
+				i--;
+
+				break;
+			}
+		}
+	}
+
 	items.sort();
 
 	switch (selection_drag_state) {
@@ -2334,7 +2389,29 @@ void RuntimeNodeSelect::_open_selection_list(const Vector<SelectResult> &p_items
 	root->add_child(selection_list);
 
 	for (const SelectResult &I : p_items) {
-		selection_list->add_item(I.item->get_name());
+		int locked = 0;
+		if (I.item->get_meta("_edit_lock_", false)) {
+			locked = 1;
+		} else {
+			Node *scene = SceneTree::get_singleton()->get_root();
+			Node *node = I.item;
+
+			while (node && node != scene->get_parent()) {
+				if (node->has_meta("_edit_group_")) {
+					locked = 2;
+				}
+				node = node->get_parent();
+			}
+		}
+
+		String suffix;
+		if (locked == 1) {
+			suffix = " (" + RTR("Locked") + ")";
+		} else if (locked == 2) {
+			suffix = " (" + RTR("Grouped") + ")";
+		}
+
+		selection_list->add_item((String)I.item->get_name() + suffix);
 		selection_list->set_item_metadata(-1, I.item);
 	}
 
@@ -2358,6 +2435,14 @@ void RuntimeNodeSelect::_set_selection_visible(bool p_visible) {
 	}
 }
 
+void RuntimeNodeSelect::_set_avoid_locked(bool p_enabled) {
+	avoid_locked_nodes = p_enabled;
+}
+
+void RuntimeNodeSelect::_set_prefer_group(bool p_enabled) {
+	prefer_group_selection = p_enabled;
+}
+
 // Copied and trimmed from the CanvasItemEditor implementation.
 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) {
 	if (!p_node || Object::cast_to<Viewport>(p_node)) {

+ 7 - 0
scene/debugger/scene_debugger.h

@@ -115,6 +115,8 @@ private:
 	static Error _msg_runtime_node_select_set_type(const Array &p_args);
 	static Error _msg_runtime_node_select_set_mode(const Array &p_args);
 	static Error _msg_runtime_node_select_set_visible(const Array &p_args);
+	static Error _msg_runtime_node_select_set_avoid_locked(const Array &p_args);
+	static Error _msg_runtime_node_select_set_prefer_group(const Array &p_args);
 	static Error _msg_rq_screenshot(const Array &p_args);
 
 	static Error _msg_runtime_node_select_reset_camera_2d(const Array &p_args);
@@ -280,6 +282,9 @@ private:
 	bool selection_visible = true;
 	bool selection_update_queued = false;
 
+	bool avoid_locked_nodes = false;
+	bool prefer_group_selection = false;
+
 	bool multi_shortcut_pressed = false;
 	bool list_shortcut_pressed = false;
 	RID draw_canvas;
@@ -396,6 +401,8 @@ private:
 	void _clear_selection();
 	void _update_selection_drag(const Point2 &p_end_pos = Point2());
 	void _set_selection_visible(bool p_visible);
+	void _set_avoid_locked(bool p_enabled);
+	void _set_prefer_group(bool p_enabled);
 
 	void _open_selection_list(const Vector<SelectResult> &p_items, const Point2 &p_pos);
 	void _close_selection_list();