diff --git a/Source/Editor/Utilities/ViewportIconsRenderer.cpp b/Source/Editor/Utilities/ViewportIconsRenderer.cpp index 889d94052..68e53c0ff 100644 --- a/Source/Editor/Utilities/ViewportIconsRenderer.cpp +++ b/Source/Editor/Utilities/ViewportIconsRenderer.cpp @@ -57,30 +57,46 @@ public: ViewportIconsRendererService ViewportIconsRendererServiceInstance; -void ViewportIconsRenderer::DrawIcons(RenderContext& renderContext, Scene* scene) +namespace { - auto& view = renderContext.View; - if ((view.Flags & ViewFlags::EditorSprites) == 0 || QuadModel == nullptr || !QuadModel->IsLoaded()) - return; - - const BoundingFrustum frustum = view.Frustum; - auto& icons = scene->GetSceneRendering()->ViewportIcons; - Matrix m1, m2, world; - Mesh::DrawInfo draw; - draw.Lightmap = nullptr; - draw.LightmapUVs = nullptr; - draw.Flags = StaticFlags::Transform; - draw.DrawModes = DrawPass::Forward; - draw.PerInstanceRandom = 0; - draw.LODBias = 0; - draw.ForcedLOD = -1; - draw.VertexColors = nullptr; - - for (Actor* icon : icons) + void DrawIcons(RenderContext& renderContext, Scene* scene, Mesh::DrawInfo& draw) { - BoundingSphere sphere(icon->GetPosition(), ICON_RADIUS); + auto& view = renderContext.View; + const BoundingFrustum frustum = view.Frustum; + auto& icons = scene->GetSceneRendering()->ViewportIcons; + Matrix m1, m2, world; + for (Actor* icon : icons) + { + BoundingSphere sphere(icon->GetPosition(), ICON_RADIUS); + IconTypes iconType; + if (frustum.Intersects(sphere) && ActorTypeToIconType.TryGet(icon->GetTypeHandle(), iconType)) + { + // Create world matrix + Matrix::Scaling(ICON_RADIUS * 2.0f, m2); + Matrix::RotationY(PI, world); + Matrix::Multiply(m2, world, m1); + Matrix::Billboard(sphere.Center, view.Position, Vector3::Up, view.Direction, m2); + Matrix::Multiply(m1, m2, world); + + // Draw icon + GeometryDrawStateData drawState; + draw.DrawState = &drawState; + draw.Buffer = &InstanceBuffers[static_cast(iconType)]; + draw.World = &world; + draw.Bounds = sphere; + QuadModel->Draw(renderContext, draw); + } + } + } + + void DrawIcons(RenderContext& renderContext, Actor* actor, Mesh::DrawInfo& draw) + { + auto& view = renderContext.View; + const BoundingFrustum frustum = view.Frustum; + Matrix m1, m2, world; + BoundingSphere sphere(actor->GetPosition(), ICON_RADIUS); IconTypes iconType; - if (frustum.Intersects(sphere) && ActorTypeToIconType.TryGet(icon->GetTypeHandle(), iconType)) + if (frustum.Intersects(sphere) && ActorTypeToIconType.TryGet(actor->GetTypeHandle(), iconType)) { // Create world matrix Matrix::Scaling(ICON_RADIUS * 2.0f, m2); @@ -97,6 +113,35 @@ void ViewportIconsRenderer::DrawIcons(RenderContext& renderContext, Scene* scene draw.Bounds = sphere; QuadModel->Draw(renderContext, draw); } + + for (auto child : actor->Children) + DrawIcons(renderContext, child, draw); + } +} + +void ViewportIconsRenderer::DrawIcons(RenderContext& renderContext, Actor* actor) +{ + auto& view = renderContext.View; + if ((view.Flags & ViewFlags::EditorSprites) == 0 || QuadModel == nullptr || !QuadModel->IsLoaded()) + return; + + Mesh::DrawInfo draw; + draw.Lightmap = nullptr; + draw.LightmapUVs = nullptr; + draw.Flags = StaticFlags::Transform; + draw.DrawModes = DrawPass::Forward; + draw.PerInstanceRandom = 0; + draw.LODBias = 0; + draw.ForcedLOD = -1; + draw.VertexColors = nullptr; + + if (const auto scene = SceneObject::Cast(actor)) + { + ::DrawIcons(renderContext, scene, draw); + } + else + { + ::DrawIcons(renderContext, actor, draw); } } diff --git a/Source/Editor/Utilities/ViewportIconsRenderer.h b/Source/Editor/Utilities/ViewportIconsRenderer.h index 8aacbe76b..0a19443a5 100644 --- a/Source/Editor/Utilities/ViewportIconsRenderer.h +++ b/Source/Editor/Utilities/ViewportIconsRenderer.h @@ -6,7 +6,7 @@ struct RenderContext; class SceneRenderTask; -class Scene; +class Actor; /// /// Editor viewports icons rendering service. @@ -17,9 +17,9 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(ViewportIconsRenderer); public: /// - /// Draws the icons for the actors in the given scene. + /// Draws the icons for the actors in the given scene (or actor tree). /// /// The rendering context. - /// The scene. - API_FUNCTION() static void DrawIcons(API_PARAM(Ref) RenderContext& renderContext, Scene* scene); + /// The actor (use scene for faster rendering). + API_FUNCTION() static void DrawIcons(API_PARAM(Ref) RenderContext& renderContext, Actor* actor); }; diff --git a/Source/Editor/Viewport/MainEditorGizmoViewport.cs b/Source/Editor/Viewport/MainEditorGizmoViewport.cs index 3d44ff477..80bbe2214 100644 --- a/Source/Editor/Viewport/MainEditorGizmoViewport.cs +++ b/Source/Editor/Viewport/MainEditorGizmoViewport.cs @@ -62,7 +62,7 @@ namespace FlaxEditor.Viewport /// /// [HideInEditor] - public sealed class EditorSpritesRenderer : PostProcessEffect + public class EditorSpritesRenderer : PostProcessEffect { /// /// The rendering task. @@ -100,11 +100,7 @@ namespace FlaxEditor.Viewport context.SetRenderTarget(depthBufferHandle, input.View()); // Collect draw calls - for (int i = 0; i < Level.ScenesCount; i++) - { - var scene = Level.GetScene(i); - ViewportIconsRenderer.DrawIcons(ref renderContext, scene); - } + Draw(ref renderContext); // Sort draw calls renderList.SortDrawCalls(ref renderContext, true, DrawCallsListType.Forward); @@ -118,6 +114,18 @@ namespace FlaxEditor.Viewport Profiler.EndEventGPU(); } + + /// + /// Draws the icons. + /// + protected virtual void Draw(ref RenderContext renderContext) + { + for (int i = 0; i < Level.ScenesCount; i++) + { + var scene = Level.GetScene(i); + ViewportIconsRenderer.DrawIcons(ref renderContext, scene); + } + } } private readonly ViewportDebugDrawData _debugDrawData = new ViewportDebugDrawData(32); diff --git a/Source/Editor/Viewport/PrefabWindowViewport.cs b/Source/Editor/Viewport/PrefabWindowViewport.cs index 0e6af06fd..2261882fa 100644 --- a/Source/Editor/Viewport/PrefabWindowViewport.cs +++ b/Source/Editor/Viewport/PrefabWindowViewport.cs @@ -26,6 +26,18 @@ namespace FlaxEditor.Viewport /// public class PrefabWindowViewport : PrefabPreview, IEditorPrimitivesOwner { + private sealed class PrefabSpritesRenderer : MainEditorGizmoViewport.EditorSpritesRenderer + { + public PrefabWindowViewport Viewport; + + public override bool CanRender => (Task.View.Flags & ViewFlags.EditorSprites) == ViewFlags.EditorSprites && Enabled; + + protected override void Draw(ref RenderContext renderContext) + { + ViewportIconsRenderer.DrawIcons(ref renderContext, Viewport.Instance); + } + } + private readonly PrefabWindow _window; private UpdateDelegate _update; @@ -39,6 +51,7 @@ namespace FlaxEditor.Viewport private readonly ViewportDebugDrawData _debugDrawData = new ViewportDebugDrawData(32); private IntPtr _debugDrawContext; + private PrefabSpritesRenderer _spritesRenderer; private readonly DragAssets _dragAssets = new DragAssets(ValidateDragItem); private readonly DragActorType _dragActorType = new DragActorType(ValidateDragActorType); private readonly DragHandlers _dragHandlers = new DragHandlers(); @@ -78,7 +91,7 @@ namespace FlaxEditor.Viewport // Prepare rendering task Task.ActorsSource = ActorsSources.CustomActors; - Task.ViewFlags = ViewFlags.DefaultEditor & ~ViewFlags.EditorSprites; + Task.ViewFlags = ViewFlags.DefaultEditor; Task.Begin += OnBegin; Task.CollectDrawCalls += OnCollectDrawCalls; Task.PostRender += OnPostRender; @@ -90,6 +103,10 @@ namespace FlaxEditor.Viewport EditorPrimitives = FlaxEngine.Object.New(); EditorPrimitives.Viewport = this; Task.CustomPostFx.Add(EditorPrimitives); + _spritesRenderer = FlaxEngine.Object.New(); + _spritesRenderer.Task = Task; + _spritesRenderer.Viewport = this; + Task.CustomPostFx.Add(_spritesRenderer); // Add transformation gizmo TransformGizmo = new TransformGizmo(this); @@ -258,6 +275,12 @@ namespace FlaxEditor.Viewport EditorPrimitives.Render(context, ref renderContext, task.Output, task.Output); } + // Render editor sprites + if (_spritesRenderer && _spritesRenderer.CanRender) + { + _spritesRenderer.Render(context, ref renderContext, task.Output, task.Output); + } + // Render selection outline if (SelectionOutline && SelectionOutline.CanRender) { @@ -855,6 +878,7 @@ namespace FlaxEditor.Viewport } FlaxEngine.Object.Destroy(ref SelectionOutline); FlaxEngine.Object.Destroy(ref EditorPrimitives); + FlaxEngine.Object.Destroy(ref _spritesRenderer); base.OnDestroy(); }