From 0fc082e1ee3af5bb6a4b52f85756d24dc02b230f Mon Sep 17 00:00:00 2001
From: Jamie Greunbaum <jamie.greunbaum@battybovine.com>
Date: Tue, 2 Apr 2024 03:26:10 -0400
Subject: Add CollisionShape3D custom debug colours

This allows changing the display colour of a CollisionShape3D node on a per-shape basis.
It also adds the ability to display a solid coloured preview of a CollisionShape3D.

Closes https://github.com/godotengine/godot-proposals/issues/906
---
 .../gizmos/collision_shape_3d_gizmo_plugin.cpp     | 75 +++++++++++++++++-----
 .../gizmos/collision_shape_3d_gizmo_plugin.h       |  2 +
 editor/plugins/node_3d_editor_gizmos.cpp           |  7 +-
 3 files changed, 62 insertions(+), 22 deletions(-)

(limited to 'editor')

diff --git a/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp b/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp
index 573c686d57..b92abbcf79 100644
--- a/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp
+++ b/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp
@@ -49,17 +49,47 @@
 
 CollisionShape3DGizmoPlugin::CollisionShape3DGizmoPlugin() {
 	helper.instantiate();
-	const Color gizmo_color = SceneTree::get_singleton()->get_debug_collisions_color();
-	create_material("shape_material", gizmo_color);
-	const float gizmo_value = gizmo_color.get_v();
-	const Color gizmo_color_disabled = Color(gizmo_value, gizmo_value, gizmo_value, 0.65);
-	create_material("shape_material_disabled", gizmo_color_disabled);
+
+	create_collision_material("shape_material", 2.0);
+	create_collision_material("shape_material_arraymesh", 0.0625);
+
+	create_collision_material("shape_material_disabled", 0.0625);
+	create_collision_material("shape_material_arraymesh_disabled", 0.015625);
+
 	create_handle_material("handles");
 }
 
 CollisionShape3DGizmoPlugin::~CollisionShape3DGizmoPlugin() {
 }
 
+void CollisionShape3DGizmoPlugin::create_collision_material(const String &p_name, float p_alpha) {
+	Vector<Ref<StandardMaterial3D>> mats;
+
+	const Color collision_color(1.0, 1.0, 1.0, p_alpha);
+
+	for (int i = 0; i < 4; i++) {
+		bool instantiated = i < 2;
+
+		Ref<StandardMaterial3D> material = memnew(StandardMaterial3D);
+
+		Color color = collision_color;
+		color.a *= instantiated ? 0.25 : 1.0;
+
+		material->set_albedo(color);
+		material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+		material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
+		material->set_render_priority(StandardMaterial3D::RENDER_PRIORITY_MIN + 1);
+		material->set_cull_mode(StandardMaterial3D::CULL_BACK);
+		material->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true);
+		material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
+		material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
+
+		mats.push_back(material);
+	}
+
+	materials[p_name] = mats;
+}
+
 bool CollisionShape3DGizmoPlugin::has_gizmo(Node3D *p_spatial) {
 	return Object::cast_to<CollisionShape3D>(p_spatial) != nullptr;
 }
@@ -311,9 +341,20 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 		return;
 	}
 
-	const Ref<Material> material =
+	const Ref<StandardMaterial3D> material =
 			get_material(!cs->is_disabled() ? "shape_material" : "shape_material_disabled", p_gizmo);
-	Ref<Material> handles_material = get_material("handles");
+	const Ref<StandardMaterial3D> material_arraymesh =
+			get_material(!cs->is_disabled() ? "shape_material_arraymesh" : "shape_material_arraymesh_disabled", p_gizmo);
+	const Ref<Material> handles_material = get_material("handles");
+
+	const Color collision_color = cs->is_disabled() ? Color(1.0, 1.0, 1.0, 0.75) : cs->get_debug_color();
+
+	if (cs->get_debug_fill_enabled()) {
+		Ref<ArrayMesh> array_mesh = s->get_debug_arraymesh_faces(collision_color);
+		if (array_mesh.is_valid()) {
+			p_gizmo->add_mesh(array_mesh, material_arraymesh);
+		}
+	}
 
 	if (Object::cast_to<SphereShape3D>(*s)) {
 		Ref<SphereShape3D> sp = s;
@@ -351,7 +392,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 			collision_segments.push_back(Vector3(b.x, b.y, 0));
 		}
 
-		p_gizmo->add_lines(points, material);
+		p_gizmo->add_lines(points, material, false, collision_color);
 		p_gizmo->add_collision_segments(collision_segments);
 		Vector<Vector3> handles;
 		handles.push_back(Vector3(r, 0, 0));
@@ -374,7 +415,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 
 		const Vector<Vector3> handles = helper->box_get_handles(bs->get_size());
 
-		p_gizmo->add_lines(lines, material);
+		p_gizmo->add_lines(lines, material, false, collision_color);
 		p_gizmo->add_collision_segments(lines);
 		p_gizmo->add_handles(handles, handles_material);
 	}
@@ -412,7 +453,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 			points.push_back(Vector3(b.y, b.x, 0) + dud);
 		}
 
-		p_gizmo->add_lines(points, material);
+		p_gizmo->add_lines(points, material, false, collision_color);
 
 		Vector<Vector3> collision_segments;
 
@@ -476,7 +517,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 			}
 		}
 
-		p_gizmo->add_lines(points, material);
+		p_gizmo->add_lines(points, material, false, collision_color);
 
 		Vector<Vector3> collision_segments;
 
@@ -531,7 +572,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 			p.normal * p.d + p.normal * 3
 		};
 
-		p_gizmo->add_lines(points, material);
+		p_gizmo->add_lines(points, material, false, collision_color);
 		p_gizmo->add_collision_segments(points);
 	}
 
@@ -549,7 +590,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 					lines.write[i * 2 + 0] = md.vertices[md.edges[i].vertex_a];
 					lines.write[i * 2 + 1] = md.vertices[md.edges[i].vertex_b];
 				}
-				p_gizmo->add_lines(lines, material);
+				p_gizmo->add_lines(lines, material, false, collision_color);
 				p_gizmo->add_collision_segments(lines);
 			}
 		}
@@ -558,7 +599,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 	if (Object::cast_to<ConcavePolygonShape3D>(*s)) {
 		Ref<ConcavePolygonShape3D> cs2 = s;
 		Ref<ArrayMesh> mesh = cs2->get_debug_mesh();
-		p_gizmo->add_mesh(mesh, material);
+		p_gizmo->add_lines(cs2->get_debug_mesh_lines(), material, false, collision_color);
 		p_gizmo->add_collision_segments(cs2->get_debug_mesh_lines());
 	}
 
@@ -569,7 +610,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 			Vector3(),
 			Vector3(0, 0, rs->get_length())
 		};
-		p_gizmo->add_lines(points, material);
+		p_gizmo->add_lines(points, material, false, collision_color);
 		p_gizmo->add_collision_segments(points);
 		Vector<Vector3> handles;
 		handles.push_back(Vector3(0, 0, rs->get_length()));
@@ -579,7 +620,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 	if (Object::cast_to<HeightMapShape3D>(*s)) {
 		Ref<HeightMapShape3D> hms = s;
 
-		Ref<ArrayMesh> mesh = hms->get_debug_mesh();
-		p_gizmo->add_mesh(mesh, material);
+		Vector<Vector3> lines = hms->get_debug_mesh_lines();
+		p_gizmo->add_lines(lines, material, false, collision_color);
 	}
 }
diff --git a/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.h b/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.h
index 464012acf9..09590fba58 100644
--- a/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.h
+++ b/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.h
@@ -38,6 +38,8 @@ class Gizmo3DHelper;
 class CollisionShape3DGizmoPlugin : public EditorNode3DGizmoPlugin {
 	GDCLASS(CollisionShape3DGizmoPlugin, EditorNode3DGizmoPlugin);
 
+	void create_collision_material(const String &p_name, float p_alpha);
+
 	Ref<Gizmo3DHelper> helper;
 
 public:
diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp
index 8aff3c9aec..b716e925cb 100644
--- a/editor/plugins/node_3d_editor_gizmos.cpp
+++ b/editor/plugins/node_3d_editor_gizmos.cpp
@@ -292,14 +292,11 @@ void EditorNode3DGizmo::add_vertices(const Vector<Vector3> &p_vertices, const Re
 
 	Vector<Color> color;
 	color.resize(p_vertices.size());
+	const Color vertex_color = (is_selected() ? Color(1, 1, 1, 0.8) : Color(1, 1, 1, 0.2)) * p_modulate;
 	{
 		Color *w = color.ptrw();
 		for (int i = 0; i < p_vertices.size(); i++) {
-			if (is_selected()) {
-				w[i] = Color(1, 1, 1, 0.8) * p_modulate;
-			} else {
-				w[i] = Color(1, 1, 1, 0.2) * p_modulate;
-			}
+			w[i] = vertex_color;
 		}
 	}
 
-- 
cgit v1.2.3