From b655b1bd9338306f36b9b7e3be5ee5ab43ba52f4 Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Wed, 20 May 2026 18:02:14 +0200 Subject: [PATCH] Improve decal gizmo in the 3D editor - Only show gizmo lines when the node is selected, similar to other visual-oriented 3D nodes. - Draw a directional arrow at the decal's outer bound, similar to DirectionalLight3D. --- editor/scene/3d/gizmos/decal_gizmo_plugin.cpp | 87 +++++++++++++------ .../scene/3d/gizmos/light_3d_gizmo_plugin.cpp | 8 +- 2 files changed, 64 insertions(+), 31 deletions(-) diff --git a/editor/scene/3d/gizmos/decal_gizmo_plugin.cpp b/editor/scene/3d/gizmos/decal_gizmo_plugin.cpp index f0597fbfa3..24ed0e915a 100644 --- a/editor/scene/3d/gizmos/decal_gizmo_plugin.cpp +++ b/editor/scene/3d/gizmos/decal_gizmo_plugin.cpp @@ -94,38 +94,71 @@ void DecalGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { p_gizmo->clear(); - Vector lines; - Vector3 size = decal->get_size(); + if (p_gizmo->is_selected()) { + Vector lines; + Vector3 size = decal->get_size(); - AABB aabb; - aabb.position = -size / 2; - aabb.size = size; + AABB aabb; + aabb.position = -size / 2; + aabb.size = size; - for (int i = 0; i < 12; i++) { - Vector3 a, b; - aabb.get_edge(i, a, b); - if (a.y == b.y) { - lines.push_back(a); - lines.push_back(b); - } else { - Vector3 ah = a.lerp(b, 0.2); - lines.push_back(a); - lines.push_back(ah); - Vector3 bh = b.lerp(a, 0.2); - lines.push_back(b); - lines.push_back(bh); + // Draw the decal's AABB with lines. + for (int i = 0; i < 12; i++) { + Vector3 a, b; + aabb.get_edge(i, a, b); + if (a.y == b.y) { + lines.push_back(a); + lines.push_back(b); + } else { + Vector3 ah = a.lerp(b, 0.2); + lines.push_back(a); + lines.push_back(ah); + Vector3 bh = b.lerp(a, 0.2); + lines.push_back(b); + lines.push_back(bh); + } } + + // Draw a directional arrow at the decal's origin. + constexpr int arrow_points = 7; + const float arrow_length = size.y * 0.5; + + const Vector3 arrow[arrow_points] = { + Vector3(0, 0, -1), + Vector3(0, 0.8, 0), + Vector3(0, 0.3, 0), + Vector3(0, 0.3, arrow_length), + Vector3(0, -0.3, arrow_length), + Vector3(0, -0.3, 0), + Vector3(0, -0.8, 0) + }; + + constexpr int arrow_sides = 2; + + for (int i = 0; i < arrow_sides; i++) { + for (int j = 0; j < arrow_points; j++) { + // Rotate by 90 degrees on the X axis to match the decal orientation. + const Basis rotation = Basis(Vector3(1, 0, 0), -Math::PI * 0.5) * Basis(Vector3(0, 0, 1), Math::PI * i / arrow_sides); + const Basis scale = Basis::from_scale(size * 0.125); + // Move the arrow to start at the top of the decal (when the decal points downwards). + // This ensures the arrow is not within surface geometry, since decals are sometimes placed inside surfaces. + const Transform3D transform = Transform3D(scale * rotation, Vector3(0, size.y * 0.5, 0)); + + Vector3 v1 = arrow[j] - Vector3(0, 0, arrow_length); + Vector3 v2 = arrow[(j + 1) % arrow_points] - Vector3(0, 0, arrow_length); + + lines.push_back(transform.xform(v1)); + lines.push_back(transform.xform(v2)); + } + } + + Vector handles = helper->box_get_handles(decal->get_size()); + Ref material = get_material("decal_material", p_gizmo); + + p_gizmo->add_lines(lines, material); + p_gizmo->add_handles(handles, get_material("handles")); } - float half_size_y = size.y / 2; - lines.push_back(Vector3(0, half_size_y, 0)); - lines.push_back(Vector3(0, half_size_y * 1.2, 0)); - - Vector handles = helper->box_get_handles(decal->get_size()); - Ref material = get_material("decal_material", p_gizmo); const Ref icon = get_material("decal_icon", p_gizmo); - - p_gizmo->add_lines(lines, material); p_gizmo->add_unscaled_billboard(icon, 0.05); - p_gizmo->add_handles(handles, get_material("handles")); } diff --git a/editor/scene/3d/gizmos/light_3d_gizmo_plugin.cpp b/editor/scene/3d/gizmos/light_3d_gizmo_plugin.cpp index 4408a2dd67..3cd0f4d632 100644 --- a/editor/scene/3d/gizmos/light_3d_gizmo_plugin.cpp +++ b/editor/scene/3d/gizmos/light_3d_gizmo_plugin.cpp @@ -256,10 +256,10 @@ void Light3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { if (p_gizmo->is_selected()) { Ref material = get_material("lines_primary", p_gizmo); - const int arrow_points = 7; - const float arrow_length = 1.5; + constexpr int arrow_points = 7; + constexpr float arrow_length = 1.5; - Vector3 arrow[arrow_points] = { + const Vector3 arrow[arrow_points] = { Vector3(0, 0, -1), Vector3(0, 0.8, 0), Vector3(0, 0.3, 0), @@ -269,7 +269,7 @@ void Light3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Vector3(0, -0.8, 0) }; - int arrow_sides = 2; + constexpr int arrow_sides = 2; Vector lines;