Browse Source

Merge pull request #62084 from smix8/path_debug_options_4.x

Add Path2D/3D debug options
Rémi Verschelde 3 years ago
parent
commit
a7e589df38

+ 6 - 0
doc/classes/ProjectSettings.xml

@@ -494,6 +494,12 @@
 		<member name="debug/shapes/navigation/geometry_color" type="Color" setter="" getter="" default="Color(0.1, 1, 0.7, 0.4)">
 			Color of the navigation geometry, visible when "Visible Navigation" is enabled in the Debug menu.
 		</member>
+		<member name="debug/shapes/paths/geometry_color" type="Color" setter="" getter="" default="Color(0.1, 1, 0.7, 0.4)">
+			Color of the curve path geometry, visible when "Visible Paths" is enabled in the Debug menu.
+		</member>
+		<member name="debug/shapes/paths/geometry_width" type="float" setter="" getter="" default="2.0">
+			Line width of the curve path geometry, visible when "Visible Paths" is enabled in the Debug menu.
+		</member>
 		<member name="display/mouse_cursor/custom_image" type="String" setter="" getter="" default="&quot;&quot;">
 			Custom image for the mouse cursor (limited to 256×256).
 		</member>

+ 3 - 0
doc/classes/SceneTree.xml

@@ -221,6 +221,9 @@
 		<member name="debug_navigation_hint" type="bool" setter="set_debug_navigation_hint" getter="is_debugging_navigation_hint" default="false">
 			If [code]true[/code], navigation polygons will be visible when running the game from the editor for debugging purposes.
 		</member>
+		<member name="debug_paths_hint" type="bool" setter="set_debug_paths_hint" getter="is_debugging_paths_hint" default="false">
+			If [code]true[/code], curves from [Path2D] and [Path3D] nodes will be visible when running the game from the editor for debugging purposes.
+		</member>
 		<member name="edited_scene_root" type="Node" setter="set_edited_scene_root" getter="get_edited_scene_root">
 			The root of the edited scene.
 		</member>

+ 5 - 0
editor/editor_run.cpp

@@ -59,11 +59,16 @@ Error EditorRun::run(const String &p_scene, const String &p_write_movie) {
 	args.push_back(itos(OS::get_singleton()->get_process_id()));
 
 	bool debug_collisions = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_debug_collisons", false);
+	bool debug_paths = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_debug_paths", false);
 	bool debug_navigation = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_debug_navigation", false);
 	if (debug_collisions) {
 		args.push_back("--debug-collisions");
 	}
 
+	if (debug_paths) {
+		args.push_back("--debug-paths");
+	}
+
 	if (debug_navigation) {
 		args.push_back("--debug-navigation");
 	}

+ 13 - 0
editor/plugins/debugger_editor_plugin.cpp

@@ -72,6 +72,9 @@ DebuggerEditorPlugin::DebuggerEditorPlugin(MenuButton *p_debug_menu) {
 	p->add_check_shortcut(ED_SHORTCUT("editor/visible_collision_shapes", TTR("Visible Collision Shapes")), RUN_DEBUG_COLLISONS);
 	p->set_item_tooltip(-1,
 			TTR("When this option is enabled, collision shapes and raycast nodes (for 2D and 3D) will be visible in the running project."));
+	p->add_check_shortcut(ED_SHORTCUT("editor/visible_paths", TTR("Visible Paths")), RUN_DEBUG_PATHS);
+	p->set_item_tooltip(-1,
+			TTR("When this option is enabled, curve resources used by path nodes will be visible in the running project."));
 	p->add_check_shortcut(ED_SHORTCUT("editor/visible_navigation", TTR("Visible Navigation")), RUN_DEBUG_NAVIGATION);
 	p->set_item_tooltip(-1,
 			TTR("When this option is enabled, navigation meshes and polygons will be visible in the running project."));
@@ -152,6 +155,12 @@ void DebuggerEditorPlugin::_menu_option(int p_option) {
 			debug_menu->get_popup()->set_item_checked(debug_menu->get_popup()->get_item_index(RUN_DEBUG_COLLISONS), !ischecked);
 			EditorSettings::get_singleton()->set_project_metadata("debug_options", "run_debug_collisons", !ischecked);
 
+		} break;
+		case RUN_DEBUG_PATHS: {
+			bool ischecked = debug_menu->get_popup()->is_item_checked(debug_menu->get_popup()->get_item_index(RUN_DEBUG_PATHS));
+			debug_menu->get_popup()->set_item_checked(debug_menu->get_popup()->get_item_index(RUN_DEBUG_PATHS), !ischecked);
+			EditorSettings::get_singleton()->set_project_metadata("debug_options", "run_debug_paths", !ischecked);
+
 		} break;
 		case RUN_DEBUG_NAVIGATION: {
 			bool ischecked = debug_menu->get_popup()->is_item_checked(debug_menu->get_popup()->get_item_index(RUN_DEBUG_NAVIGATION));
@@ -182,6 +191,7 @@ void DebuggerEditorPlugin::_update_debug_options() {
 	bool check_deploy_remote = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_deploy_remote_debug", false);
 	bool check_file_server = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_file_server", false);
 	bool check_debug_collisions = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_debug_collisons", false);
+	bool check_debug_paths = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_debug_paths", false);
 	bool check_debug_navigation = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_debug_navigation", false);
 	bool check_live_debug = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_live_debug", true);
 	bool check_reload_scripts = EditorSettings::get_singleton()->get_project_metadata("debug_options", "run_reload_scripts", true);
@@ -196,6 +206,9 @@ void DebuggerEditorPlugin::_update_debug_options() {
 	if (check_debug_collisions) {
 		_menu_option(RUN_DEBUG_COLLISONS);
 	}
+	if (check_debug_paths) {
+		_menu_option(RUN_DEBUG_PATHS);
+	}
 	if (check_debug_navigation) {
 		_menu_option(RUN_DEBUG_NAVIGATION);
 	}

+ 1 - 0
editor/plugins/debugger_editor_plugin.h

@@ -49,6 +49,7 @@ private:
 		RUN_FILE_SERVER,
 		RUN_LIVE_DEBUG,
 		RUN_DEBUG_COLLISONS,
+		RUN_DEBUG_PATHS,
 		RUN_DEBUG_NAVIGATION,
 		RUN_DEPLOY_REMOTE_DEBUG,
 		RUN_RELOAD_SCRIPTS,

+ 7 - 0
main/main.cpp

@@ -175,6 +175,7 @@ static Vector2 init_custom_pos;
 static bool use_debug_profiler = false;
 #ifdef DEBUG_ENABLED
 static bool debug_collisions = false;
+static bool debug_paths = false;
 static bool debug_navigation = false;
 #endif
 static int frame_delay = 0;
@@ -357,6 +358,7 @@ void Main::print_help(const char *p_binary) {
 	OS::get_singleton()->print("  --remote-debug <uri>                         Remote debug (<protocol>://<host/IP>[:<port>], e.g. tcp://127.0.0.1:6007).\n");
 #if defined(DEBUG_ENABLED)
 	OS::get_singleton()->print("  --debug-collisions                           Show collision shapes when running the scene.\n");
+	OS::get_singleton()->print("  --debug-paths                                Show path lines when running the scene.\n");
 	OS::get_singleton()->print("  --debug-navigation                           Show navigation polygons when running the scene.\n");
 	OS::get_singleton()->print("  --debug-stringnames                          Print all StringName allocations to stdout when the engine quits.\n");
 #endif
@@ -1107,6 +1109,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 #if defined(DEBUG_ENABLED)
 		} else if (I->get() == "--debug-collisions") {
 			debug_collisions = true;
+		} else if (I->get() == "--debug-paths") {
+			debug_paths = true;
 		} else if (I->get() == "--debug-navigation") {
 			debug_navigation = true;
 		} else if (I->get() == "--debug-stringnames") {
@@ -2375,6 +2379,9 @@ bool Main::start() {
 		if (debug_collisions) {
 			sml->set_debug_collisions_hint(true);
 		}
+		if (debug_paths) {
+			sml->set_debug_paths_hint(true);
+		}
 		if (debug_navigation) {
 			sml->set_debug_navigation_hint(true);
 		}

+ 6 - 8
scene/2d/path_2d.cpp

@@ -87,13 +87,13 @@ bool Path2D::_edit_is_selected_on_click(const Point2 &p_point, double p_toleranc
 
 void Path2D::_notification(int p_what) {
 	switch (p_what) {
-		// Draw the curve if navigation debugging is enabled.
+		// Draw the curve if path debugging is enabled.
 		case NOTIFICATION_DRAW: {
 			if (!curve.is_valid()) {
 				break;
 			}
 
-			if (!Engine::get_singleton()->is_editor_hint() && !get_tree()->is_debugging_navigation_hint()) {
+			if (!Engine::get_singleton()->is_editor_hint() && !get_tree()->is_debugging_paths_hint()) {
 				return;
 			}
 
@@ -102,12 +102,10 @@ void Path2D::_notification(int p_what) {
 			}
 
 #ifdef TOOLS_ENABLED
-			const real_t line_width = 2 * EDSCALE;
+			const real_t line_width = get_tree()->get_debug_paths_width() * EDSCALE;
 #else
-			const real_t line_width = 2;
+			const real_t line_width = get_tree()->get_debug_paths_width();
 #endif
-			const Color color = Color(0.5, 0.6, 1.0, 0.7);
-
 			_cached_draw_pts.resize(curve->get_point_count() * 8);
 			int count = 0;
 
@@ -119,7 +117,7 @@ void Path2D::_notification(int p_what) {
 				}
 			}
 
-			draw_polyline(_cached_draw_pts, color, line_width, true);
+			draw_polyline(_cached_draw_pts, get_tree()->get_debug_paths_color(), line_width, true);
 		} break;
 	}
 }
@@ -129,7 +127,7 @@ void Path2D::_curve_changed() {
 		return;
 	}
 
-	if (!Engine::get_singleton()->is_editor_hint() && !get_tree()->is_debugging_navigation_hint()) {
+	if (!Engine::get_singleton()->is_editor_hint() && !get_tree()->is_debugging_paths_hint()) {
 		return;
 	}
 

+ 90 - 0
scene/3d/path_3d.cpp

@@ -30,6 +30,92 @@
 
 #include "path_3d.h"
 
+Path3D::Path3D() {
+	SceneTree *st = SceneTree::get_singleton();
+	if (st && st->is_debugging_paths_hint()) {
+		debug_instance = RS::get_singleton()->instance_create();
+		set_notify_transform(true);
+		_update_debug_mesh();
+	}
+}
+
+Path3D::~Path3D() {
+	if (debug_instance.is_valid()) {
+		RS::get_singleton()->free(debug_instance);
+	}
+	if (debug_mesh.is_valid()) {
+		RS::get_singleton()->free(debug_mesh->get_rid());
+	}
+}
+
+void Path3D::_notification(int p_what) {
+	switch (p_what) {
+		case NOTIFICATION_ENTER_TREE: {
+			SceneTree *st = SceneTree::get_singleton();
+			if (st && st->is_debugging_paths_hint()) {
+				_update_debug_mesh();
+			}
+		} break;
+
+		case NOTIFICATION_EXIT_TREE: {
+			SceneTree *st = SceneTree::get_singleton();
+			if (st && st->is_debugging_paths_hint()) {
+				RS::get_singleton()->instance_set_visible(debug_instance, false);
+			}
+		} break;
+
+		case NOTIFICATION_TRANSFORM_CHANGED: {
+			if (is_inside_tree() && debug_instance.is_valid()) {
+				RS::get_singleton()->instance_set_transform(debug_instance, get_global_transform());
+			}
+		} break;
+	}
+}
+
+void Path3D::_update_debug_mesh() {
+	SceneTree *st = SceneTree::get_singleton();
+	if (!(st && st->is_debugging_paths_hint())) {
+		return;
+	}
+
+	if (!debug_mesh.is_valid()) {
+		debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh));
+	}
+
+	if (!(curve.is_valid())) {
+		RS::get_singleton()->instance_set_visible(debug_instance, false);
+		return;
+	}
+	if (curve->get_point_count() < 2) {
+		RS::get_singleton()->instance_set_visible(debug_instance, false);
+		return;
+	}
+
+	Vector<Vector3> vertex_array;
+
+	for (int i = 1; i < curve->get_point_count(); i++) {
+		Vector3 line_end = curve->get_point_position(i);
+		Vector3 line_start = curve->get_point_position(i - 1);
+		vertex_array.push_back(line_start);
+		vertex_array.push_back(line_end);
+	}
+
+	Array mesh_array;
+	mesh_array.resize(Mesh::ARRAY_MAX);
+	mesh_array[Mesh::ARRAY_VERTEX] = vertex_array;
+
+	debug_mesh->clear_surfaces();
+	debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, mesh_array);
+
+	RS::get_singleton()->instance_set_base(debug_instance, debug_mesh->get_rid());
+	RS::get_singleton()->mesh_surface_set_material(debug_mesh->get_rid(), 0, st->get_debug_paths_material()->get_rid());
+	if (is_inside_tree()) {
+		RS::get_singleton()->instance_set_scenario(debug_instance, get_world_3d()->get_scenario());
+		RS::get_singleton()->instance_set_transform(debug_instance, get_global_transform());
+		RS::get_singleton()->instance_set_visible(debug_instance, is_visible_in_tree());
+	}
+}
+
 void Path3D::_curve_changed() {
 	if (is_inside_tree() && Engine::get_singleton()->is_editor_hint()) {
 		update_gizmos();
@@ -48,6 +134,10 @@ void Path3D::_curve_changed() {
 			}
 		}
 	}
+	SceneTree *st = SceneTree::get_singleton();
+	if (st && st->is_debugging_paths_hint()) {
+		_update_debug_mesh();
+	}
 }
 
 void Path3D::set_curve(const Ref<Curve3D> &p_curve) {

+ 10 - 1
scene/3d/path_3d.h

@@ -41,14 +41,23 @@ class Path3D : public Node3D {
 
 	void _curve_changed();
 
+	RID debug_instance;
+	Ref<ArrayMesh> debug_mesh;
+
+private:
+	void _update_debug_mesh();
+
 protected:
+	void _notification(int p_what);
+
 	static void _bind_methods();
 
 public:
 	void set_curve(const Ref<Curve3D> &p_curve);
 	Ref<Curve3D> get_curve() const;
 
-	Path3D() {}
+	Path3D();
+	~Path3D();
 };
 
 class PathFollow3D : public Node3D {

+ 46 - 0
scene/main/scene_tree.cpp

@@ -659,6 +659,14 @@ bool SceneTree::is_debugging_collisions_hint() const {
 	return debug_collisions_hint;
 }
 
+void SceneTree::set_debug_paths_hint(bool p_enabled) {
+	debug_paths_hint = p_enabled;
+}
+
+bool SceneTree::is_debugging_paths_hint() const {
+	return debug_paths_hint;
+}
+
 void SceneTree::set_debug_navigation_hint(bool p_enabled) {
 	debug_navigation_hint = p_enabled;
 }
@@ -684,6 +692,22 @@ Color SceneTree::get_debug_collision_contact_color() const {
 	return debug_collision_contact_color;
 }
 
+void SceneTree::set_debug_paths_color(const Color &p_color) {
+	debug_paths_color = p_color;
+}
+
+Color SceneTree::get_debug_paths_color() const {
+	return debug_paths_color;
+}
+
+void SceneTree::set_debug_paths_width(float p_width) {
+	debug_paths_width = p_width;
+}
+
+float SceneTree::get_debug_paths_width() const {
+	return debug_paths_width;
+}
+
 void SceneTree::set_debug_navigation_color(const Color &p_color) {
 	debug_navigation_color = p_color;
 }
@@ -700,6 +724,23 @@ Color SceneTree::get_debug_navigation_disabled_color() const {
 	return debug_navigation_disabled_color;
 }
 
+Ref<Material> SceneTree::get_debug_paths_material() {
+	if (debug_paths_material.is_valid()) {
+		return debug_paths_material;
+	}
+
+	Ref<StandardMaterial3D> _debug_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
+	_debug_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+	_debug_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
+	_debug_material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
+	_debug_material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
+	_debug_material->set_albedo(get_debug_paths_color());
+
+	debug_paths_material = _debug_material;
+
+	return debug_paths_material;
+}
+
 Ref<Material> SceneTree::get_debug_navigation_material() {
 	if (navigation_material.is_valid()) {
 		return navigation_material;
@@ -1207,6 +1248,8 @@ void SceneTree::_bind_methods() {
 
 	ClassDB::bind_method(D_METHOD("set_debug_collisions_hint", "enable"), &SceneTree::set_debug_collisions_hint);
 	ClassDB::bind_method(D_METHOD("is_debugging_collisions_hint"), &SceneTree::is_debugging_collisions_hint);
+	ClassDB::bind_method(D_METHOD("set_debug_paths_hint", "enable"), &SceneTree::set_debug_paths_hint);
+	ClassDB::bind_method(D_METHOD("is_debugging_paths_hint"), &SceneTree::is_debugging_paths_hint);
 	ClassDB::bind_method(D_METHOD("set_debug_navigation_hint", "enable"), &SceneTree::set_debug_navigation_hint);
 	ClassDB::bind_method(D_METHOD("is_debugging_navigation_hint"), &SceneTree::is_debugging_navigation_hint);
 
@@ -1268,6 +1311,7 @@ void SceneTree::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_accept_quit"), "set_auto_accept_quit", "is_auto_accept_quit");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "quit_on_go_back"), "set_quit_on_go_back", "is_quit_on_go_back");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_collisions_hint"), "set_debug_collisions_hint", "is_debugging_collisions_hint");
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_paths_hint"), "set_debug_paths_hint", "is_debugging_paths_hint");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_navigation_hint"), "set_debug_navigation_hint", "is_debugging_navigation_hint");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "paused"), "set_pause", "is_paused");
 	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "edited_scene_root", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_edited_scene_root", "get_edited_scene_root");
@@ -1344,6 +1388,8 @@ SceneTree::SceneTree() {
 	}
 	debug_collisions_color = GLOBAL_DEF("debug/shapes/collision/shape_color", Color(0.0, 0.6, 0.7, 0.42));
 	debug_collision_contact_color = GLOBAL_DEF("debug/shapes/collision/contact_color", Color(1.0, 0.2, 0.1, 0.8));
+	debug_paths_color = GLOBAL_DEF("debug/shapes/paths/geometry_color", Color(0.1, 1.0, 0.7, 0.4));
+	debug_paths_width = GLOBAL_DEF("debug/shapes/paths/geometry_width", 2.0);
 	debug_navigation_color = GLOBAL_DEF("debug/shapes/navigation/geometry_color", Color(0.1, 1.0, 0.7, 0.4));
 	debug_navigation_disabled_color = GLOBAL_DEF("debug/shapes/navigation/disabled_geometry_color", Color(1.0, 0.7, 0.1, 0.4));
 	collision_debug_contacts = GLOBAL_DEF("debug/shapes/collision/max_contacts_displayed", 10000);

+ 17 - 0
scene/main/scene_tree.h

@@ -97,6 +97,7 @@ private:
 
 #ifdef DEBUG_ENABLED
 	bool debug_collisions_hint = false;
+	bool debug_paths_hint = false;
 	bool debug_navigation_hint = false;
 #endif
 	bool paused = false;
@@ -146,9 +147,12 @@ private:
 
 	Color debug_collisions_color;
 	Color debug_collision_contact_color;
+	Color debug_paths_color;
+	float debug_paths_width = 1.0f;
 	Color debug_navigation_color;
 	Color debug_navigation_disabled_color;
 	Ref<ArrayMesh> debug_contact_mesh;
+	Ref<Material> debug_paths_material;
 	Ref<Material> navigation_material;
 	Ref<Material> navigation_disabled_material;
 	Ref<Material> collision_material;
@@ -297,12 +301,18 @@ public:
 	void set_debug_collisions_hint(bool p_enabled);
 	bool is_debugging_collisions_hint() const;
 
+	void set_debug_paths_hint(bool p_enabled);
+	bool is_debugging_paths_hint() const;
+
 	void set_debug_navigation_hint(bool p_enabled);
 	bool is_debugging_navigation_hint() const;
 #else
 	void set_debug_collisions_hint(bool p_enabled) {}
 	bool is_debugging_collisions_hint() const { return false; }
 
+	void set_debug_paths_hint(bool p_enabled) {}
+	bool is_debugging_paths_hint() const { return false; }
+
 	void set_debug_navigation_hint(bool p_enabled) {}
 	bool is_debugging_navigation_hint() const { return false; }
 #endif
@@ -313,12 +323,19 @@ public:
 	void set_debug_collision_contact_color(const Color &p_color);
 	Color get_debug_collision_contact_color() const;
 
+	void set_debug_paths_color(const Color &p_color);
+	Color get_debug_paths_color() const;
+
+	void set_debug_paths_width(float p_width);
+	float get_debug_paths_width() const;
+
 	void set_debug_navigation_color(const Color &p_color);
 	Color get_debug_navigation_color() const;
 
 	void set_debug_navigation_disabled_color(const Color &p_color);
 	Color get_debug_navigation_disabled_color() const;
 
+	Ref<Material> get_debug_paths_material();
 	Ref<Material> get_debug_navigation_material();
 	Ref<Material> get_debug_navigation_disabled_material();
 	Ref<Material> get_debug_collision_material();