From f2aaad004830e91ce8a075b774de708529a28228 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 3 Jun 2025 14:50:47 +0200 Subject: [PATCH] Add viewport icons scale relative to the distance and editor control over it #2944 #2644 --- Source/Editor/SceneGraph/ActorNodeWithIcon.cs | 3 ++- .../Utilities/ViewportIconsRenderer.cpp | 22 ++++++++++++++----- .../Editor/Utilities/ViewportIconsRenderer.h | 13 +++++++++++ Source/Editor/Viewport/EditorViewport.cs | 12 ++++++++++ 4 files changed, 43 insertions(+), 7 deletions(-) diff --git a/Source/Editor/SceneGraph/ActorNodeWithIcon.cs b/Source/Editor/SceneGraph/ActorNodeWithIcon.cs index 9e66f5d5a..f9820bb55 100644 --- a/Source/Editor/SceneGraph/ActorNodeWithIcon.cs +++ b/Source/Editor/SceneGraph/ActorNodeWithIcon.cs @@ -35,7 +35,8 @@ namespace FlaxEditor.SceneGraph return false; } - BoundingSphere sphere = new BoundingSphere(Transform.Translation, 7.0f); + var center = _actor.Transform.Translation; + ViewportIconsRenderer.GetBounds(ref center, ref ray.Ray.Position, out var sphere); return CollisionsHelper.RayIntersectsSphere(ref ray.Ray, ref sphere, out distance); } } diff --git a/Source/Editor/Utilities/ViewportIconsRenderer.cpp b/Source/Editor/Utilities/ViewportIconsRenderer.cpp index 2562c9bf5..ccfa876bd 100644 --- a/Source/Editor/Utilities/ViewportIconsRenderer.cpp +++ b/Source/Editor/Utilities/ViewportIconsRenderer.cpp @@ -23,8 +23,6 @@ #include "Engine/Level/Actors/SpotLight.h" #include "Engine/Video/VideoPlayer.h" -#define ICON_RADIUS 7.0f - enum class IconTypes { PointLight, @@ -66,6 +64,16 @@ public: }; ViewportIconsRendererService ViewportIconsRendererServiceInstance; +float ViewportIconsRenderer::Scale = 1.0f; + +void ViewportIconsRenderer::GetBounds(const Vector3& position, const Vector3& viewPosition, BoundingSphere& bounds) +{ + constexpr float minSize = 7.0f; + constexpr float maxSize = 30.0f; + Real scale = Math::Square(Vector3::Distance(position, viewPosition) / 1000.0f); + Real radius = minSize + Math::Min(scale, 1.0f) * (maxSize - minSize); + bounds = BoundingSphere(position, radius * Scale); +} void ViewportIconsRenderer::DrawIcons(RenderContext& renderContext, Actor* actor) { @@ -133,7 +141,8 @@ void ViewportIconsRendererService::DrawIcons(RenderContext& renderContext, Scene AssetReference texture; for (Actor* icon : icons) { - BoundingSphere sphere(icon->GetPosition() - renderContext.View.Origin, ICON_RADIUS); + BoundingSphere sphere; + ViewportIconsRenderer::GetBounds(icon->GetPosition() - renderContext.View.Origin, renderContext.View.Position, sphere); if (!frustum.Intersects(sphere)) continue; IconTypes iconType; @@ -173,7 +182,7 @@ void ViewportIconsRendererService::DrawIcons(RenderContext& renderContext, Scene if (draw.Buffer) { // Create world matrix - Matrix::Scaling(ICON_RADIUS * 2.0f, m2); + Matrix::Scaling(sphere.Radius * 2.0f, m2); Matrix::RotationY(PI, world); Matrix::Multiply(m2, world, m1); Matrix::Billboard(sphere.Center, view.Position, Vector3::Up, view.Direction, m2); @@ -193,14 +202,15 @@ void ViewportIconsRendererService::DrawIcons(RenderContext& renderContext, Actor auto& view = renderContext.View; const BoundingFrustum frustum = view.Frustum; Matrix m1, m2, world; - BoundingSphere sphere(actor->GetPosition() - renderContext.View.Origin, ICON_RADIUS); + BoundingSphere sphere; + ViewportIconsRenderer::GetBounds(actor->GetPosition() - renderContext.View.Origin, renderContext.View.Position, sphere); IconTypes iconType; AssetReference texture; if (frustum.Intersects(sphere) && ActorTypeToIconType.TryGet(actor->GetTypeHandle(), iconType)) { // Create world matrix - Matrix::Scaling(ICON_RADIUS * 2.0f, m2); + Matrix::Scaling(sphere.Radius * 2.0f, m2); Matrix::RotationY(PI, world); Matrix::Multiply(m2, world, m1); Matrix::Billboard(sphere.Center, view.Position, Vector3::Up, view.Direction, m2); diff --git a/Source/Editor/Utilities/ViewportIconsRenderer.h b/Source/Editor/Utilities/ViewportIconsRenderer.h index 8dab1bbf4..c7bf7e1c3 100644 --- a/Source/Editor/Utilities/ViewportIconsRenderer.h +++ b/Source/Editor/Utilities/ViewportIconsRenderer.h @@ -17,6 +17,19 @@ API_CLASS(Static, Namespace="FlaxEditor") class FLAXENGINE_API ViewportIconsRend DECLARE_SCRIPTING_TYPE_NO_SPAWN(ViewportIconsRenderer); public: + /// + /// Global scale of the icons. + /// + API_FIELD() static float Scale; + + /// + /// Draws the icons for the actors in the given scene (or actor tree). + /// + /// The icon position. + /// The viewer position. + /// The computed bounds for the icon. + API_FUNCTION() static void GetBounds(API_PARAM(Ref) const Vector3& position, API_PARAM(Ref) const Vector3& viewPosition, API_PARAM(Out) BoundingSphere& bounds); + /// /// Draws the icons for the actors in the given scene (or actor tree). /// diff --git a/Source/Editor/Viewport/EditorViewport.cs b/Source/Editor/Viewport/EditorViewport.cs index b2bf0f64e..b4af43281 100644 --- a/Source/Editor/Viewport/EditorViewport.cs +++ b/Source/Editor/Viewport/EditorViewport.cs @@ -1002,6 +1002,18 @@ namespace FlaxEditor.Viewport ViewWidgetButtonMenu.VisibleChanged += control => resolutionValue.Value = ResolutionScale; } + // Icons Scale + { + var icons = ViewWidgetButtonMenu.AddButton("Icons"); + icons.CloseMenuOnClick = false; + var iconsValue = new FloatValueBox(ViewportIconsRenderer.Scale, xLocationForExtras, 2, 70.0f, 0.01f, 100.0f, 0.001f) + { + Parent = icons + }; + iconsValue.ValueChanged += () => ViewportIconsRenderer.Scale = iconsValue.Value; + ViewWidgetButtonMenu.VisibleChanged += control => iconsValue.Value = ViewportIconsRenderer.Scale; + } + #endregion View mode widget }