diff --git a/Source/Editor/Tools/Foliage/EditFoliageGizmoMode.cs b/Source/Editor/Tools/Foliage/EditFoliageGizmoMode.cs index 181bc1d17..e9102fb12 100644 --- a/Source/Editor/Tools/Foliage/EditFoliageGizmoMode.cs +++ b/Source/Editor/Tools/Foliage/EditFoliageGizmoMode.cs @@ -17,7 +17,7 @@ namespace FlaxEditor.Tools.Foliage private int _selectedInstanceIndex = -1; /// - /// The foliage painting gizmo. + /// The foliage editing gizmo. /// public EditFoliageGizmo Gizmo; @@ -66,8 +66,6 @@ namespace FlaxEditor.Tools.Foliage base.Init(owner); Gizmo = new EditFoliageGizmo(owner, this); - SelectionOutline = FlaxEngine.Object.New(); - SelectionOutline.GizmoMode = this; } /// @@ -84,6 +82,11 @@ namespace FlaxEditor.Tools.Foliage base.OnActivated(); Owner.Gizmos.Active = Gizmo; + if (SelectionOutline == null) + { + SelectionOutline = FlaxEngine.Object.New(); + SelectionOutline.GizmoMode = this; + } ((MainEditorGizmoViewport)Owner).OverrideSelectionOutline(SelectionOutline); SelectedInstanceIndex = -1; } diff --git a/Source/Editor/Tools/Foliage/EditFoliageSelectionOutline.cs b/Source/Editor/Tools/Foliage/EditFoliageSelectionOutline.cs index 309b62ed3..ee078ea4e 100644 --- a/Source/Editor/Tools/Foliage/EditFoliageSelectionOutline.cs +++ b/Source/Editor/Tools/Foliage/EditFoliageSelectionOutline.cs @@ -6,7 +6,7 @@ using FlaxEngine; namespace FlaxEditor.Tools.Foliage { /// - /// The custom outline for drawing the selected foliage instances outlines. + /// The custom outline for drawing the selected foliage instance. /// /// [HideInEditor] diff --git a/Source/Editor/Tools/Foliage/FoliageTab.cs b/Source/Editor/Tools/Foliage/FoliageTab.cs index f893049ae..da5142070 100644 --- a/Source/Editor/Tools/Foliage/FoliageTab.cs +++ b/Source/Editor/Tools/Foliage/FoliageTab.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using FlaxEditor.GUI.Tabs; using FlaxEditor.Modules; using FlaxEditor.SceneGraph.Actors; -using FlaxEditor.Viewport.Modes; using FlaxEngine; using FlaxEngine.GUI; @@ -214,7 +213,7 @@ namespace FlaxEditor.Tools.Foliage private void InitSculptMode() { - var tab = _modes.AddTab(FoliageTypes = new FoliageTypesTab(this)); + var tab = _modes.AddTab(FoliageTypes = new FoliageTypesTab(this, Editor.Windows.EditWin.Viewport.EditFoliageTypesGizmo)); tab.Selected += OnTabSelected; } @@ -251,7 +250,7 @@ namespace FlaxEditor.Tools.Foliage switch (_modes.SelectedTabIndex) { case 0: - Editor.Windows.EditWin.Viewport.Gizmos.SetActiveMode(); + Editor.Windows.EditWin.Viewport.Gizmos.SetActiveMode(); break; case 1: Editor.Windows.EditWin.Viewport.Gizmos.SetActiveMode(); diff --git a/Source/Editor/Tools/Foliage/FoliageTypesGizmo.cs b/Source/Editor/Tools/Foliage/FoliageTypesGizmo.cs new file mode 100644 index 000000000..a4d95e388 --- /dev/null +++ b/Source/Editor/Tools/Foliage/FoliageTypesGizmo.cs @@ -0,0 +1,44 @@ +// Copyright (c) Wojciech Figat. All rights reserved. + +using FlaxEditor.Gizmo; + +namespace FlaxEditor.Tools.Foliage +{ + /// + /// Gizmo for editing foliage types. + /// + public sealed class FoliageTypesGizmo : GizmoBase + { + /// + /// The parent mode. + /// + public readonly FoliageTypesGizmoMode GizmoMode; + + /// + /// Initializes a new instance of the class. + /// + /// The owner. + /// The mode. + public FoliageTypesGizmo(IGizmoOwner owner, FoliageTypesGizmoMode mode) + : base(owner) + { + GizmoMode = mode; + } + + /// + public override void Pick() + { + // Get mouse ray and try to hit foliage instance + var foliage = GizmoMode.SelectedFoliage; + if (!foliage) + return; + var ray = Owner.MouseRay; + if (foliage.Intersects(ref ray, out _, out _, out var instanceIndex)) + { + // Select hit instance type + var instance = foliage.GetInstance(instanceIndex); + GizmoMode.SelectedTypeIndex = instance.Type; + } + } + } +} diff --git a/Source/Editor/Tools/Foliage/FoliageTypesGizmoMode.cs b/Source/Editor/Tools/Foliage/FoliageTypesGizmoMode.cs new file mode 100644 index 000000000..0fed59181 --- /dev/null +++ b/Source/Editor/Tools/Foliage/FoliageTypesGizmoMode.cs @@ -0,0 +1,86 @@ +// Copyright (c) Wojciech Figat. All rights reserved. + +using FlaxEditor.Gizmo; +using FlaxEditor.SceneGraph.Actors; +using FlaxEditor.Viewport; +using FlaxEditor.Viewport.Modes; + +namespace FlaxEditor.Tools.Foliage +{ + /// + /// Foliage types editing mode. + /// + /// + public class FoliageTypesGizmoMode : EditorGizmoMode + { + /// + /// The foliage types gizmo. + /// + public FoliageTypesGizmo Gizmo; + + /// + /// The foliage type editing selection outline. + /// + public FoliageTypesOutline SelectionOutline; + + /// + /// The selected foliage type index. + /// + public int SelectedTypeIndex + { + get => Editor.Instance.Windows.ToolboxWin.Foliage.SelectedFoliageTypeIndex; + set => Editor.Instance.Windows.ToolboxWin.Foliage.SelectedFoliageTypeIndex = value; + } + + /// + /// Gets the selected foliage actor (see ). + /// + public FlaxEngine.Foliage SelectedFoliage + { + get + { + var sceneEditing = Editor.Instance.SceneEditing; + var foliageNode = sceneEditing.SelectionCount == 1 ? sceneEditing.Selection[0] as FoliageNode : null; + return (FlaxEngine.Foliage)foliageNode?.Actor; + } + } + + /// + public override void Init(IGizmoOwner owner) + { + base.Init(owner); + + Gizmo = new FoliageTypesGizmo(owner, this); + } + + /// + public override void Dispose() + { + FlaxEngine.Object.Destroy(ref SelectionOutline); + + base.Dispose(); + } + + /// + public override void OnActivated() + { + base.OnActivated(); + + Owner.Gizmos.Active = Gizmo; + if (SelectionOutline == null) + { + SelectionOutline = FlaxEngine.Object.New(); + SelectionOutline.GizmoMode = this; + } + ((MainEditorGizmoViewport)Owner).OverrideSelectionOutline(SelectionOutline); + } + + /// + public override void OnDeactivated() + { + ((MainEditorGizmoViewport)Owner).OverrideSelectionOutline(null); + + base.OnDeactivated(); + } + } +} diff --git a/Source/Editor/Tools/Foliage/FoliageTypesOutline.cs b/Source/Editor/Tools/Foliage/FoliageTypesOutline.cs new file mode 100644 index 000000000..dfd773e58 --- /dev/null +++ b/Source/Editor/Tools/Foliage/FoliageTypesOutline.cs @@ -0,0 +1,62 @@ +// Copyright (c) Wojciech Figat. All rights reserved. + +using FlaxEditor.Gizmo; +using FlaxEngine; + +namespace FlaxEditor.Tools.Foliage +{ + /// + /// The custom outline for drawing the selected foliage type. + /// + /// + [HideInEditor] + public class FoliageTypesOutline : SelectionOutline + { + /// + /// The parent mode. + /// + public FoliageTypesGizmoMode GizmoMode; + + /// + public override bool CanRender() + { + if (!HasDataReady) + return false; + + var foliage = GizmoMode.SelectedFoliage; + if (!foliage) + return false; + var typeIndex = GizmoMode.SelectedTypeIndex; + if (typeIndex < 0 || typeIndex >= foliage.FoliageTypesCount) + return false; + return true; + } + + /// + public override void Render(GPUContext context, ref RenderContext renderContext, GPUTexture input, GPUTexture output) + { + base.Render(context, ref renderContext, input, output); + + // Restore debug option + var foliage = GizmoMode.SelectedFoliage; + if (foliage) + foliage._drawFoliageType = -1; + } + + /// + protected override void DrawSelectionDepth(GPUContext context, SceneRenderTask task, GPUTexture customDepth) + { + var foliage = GizmoMode.SelectedFoliage; + if (!foliage) + return; + var typeIndex = GizmoMode.SelectedTypeIndex; + if (typeIndex < 0 || typeIndex >= foliage.FoliageTypesCount) + return; + + // Draw instances of the given type + foliage._drawFoliageType = typeIndex; + _actors.Add(foliage); + Renderer.DrawSceneDepth(context, task, customDepth, _actors); + } + } +} diff --git a/Source/Editor/Tools/Foliage/FoliageTypesTab.cs b/Source/Editor/Tools/Foliage/FoliageTypesTab.cs index 33c3c1fb5..18dc948cd 100644 --- a/Source/Editor/Tools/Foliage/FoliageTypesTab.cs +++ b/Source/Editor/Tools/Foliage/FoliageTypesTab.cs @@ -334,7 +334,8 @@ namespace FlaxEditor.Tools.Foliage /// Initializes a new instance of the class. /// /// The parent tab. - public FoliageTypesTab(FoliageTab tab) + /// The gizmo mode. + public FoliageTypesTab(FoliageTab tab, FoliageTypesGizmoMode mode) : base("Foliage Types") { Tab = tab; diff --git a/Source/Editor/Viewport/MainEditorGizmoViewport.cs b/Source/Editor/Viewport/MainEditorGizmoViewport.cs index a9eab5ceb..debec1a14 100644 --- a/Source/Editor/Viewport/MainEditorGizmoViewport.cs +++ b/Source/Editor/Viewport/MainEditorGizmoViewport.cs @@ -179,12 +179,17 @@ namespace FlaxEditor.Viewport public Tools.Terrain.EditTerrainGizmoMode EditTerrainGizmo; /// - /// The paint foliage gizmo. + /// The edit foliage types gizmo. + /// + public Tools.Foliage.FoliageTypesGizmoMode EditFoliageTypesGizmo; + + /// + /// The paint foliage instances gizmo. /// public Tools.Foliage.PaintFoliageGizmoMode PaintFoliageGizmo; /// - /// The edit foliage gizmo. + /// The edit foliage instances gizmo. /// public Tools.Foliage.EditFoliageGizmoMode EditFoliageGizmo; @@ -276,6 +281,7 @@ namespace FlaxEditor.Viewport Gizmos.AddMode(SculptTerrainGizmo = new Tools.Terrain.SculptTerrainGizmoMode()); Gizmos.AddMode(PaintTerrainGizmo = new Tools.Terrain.PaintTerrainGizmoMode()); Gizmos.AddMode(EditTerrainGizmo = new Tools.Terrain.EditTerrainGizmoMode()); + Gizmos.AddMode(EditFoliageTypesGizmo = new Tools.Foliage.FoliageTypesGizmoMode()); Gizmos.AddMode(PaintFoliageGizmo = new Tools.Foliage.PaintFoliageGizmoMode()); Gizmos.AddMode(EditFoliageGizmo = new Tools.Foliage.EditFoliageGizmoMode()); @@ -343,10 +349,12 @@ namespace FlaxEditor.Viewport /// The custom selection outline or null if use default one. public void OverrideSelectionOutline(SelectionOutline customSelectionOutline) { + if (Task == null) + return; + if (_customSelectionOutline != null) { Task.RemoveCustomPostFx(_customSelectionOutline); - Object.Destroy(ref _customSelectionOutline); Task.AddCustomPostFx(customSelectionOutline ? customSelectionOutline : SelectionOutline); } else if (customSelectionOutline != null) @@ -857,8 +865,8 @@ namespace FlaxEditor.Viewport if (_task != null) { // Release if task is not used to save screenshot for project icon + ReleaseTaskResources(); Object.Destroy(ref _task); - ReleaseResources(); } base.OnDestroy(); @@ -874,6 +882,7 @@ namespace FlaxEditor.Viewport _savedTask = _task; _savedBackBuffer = _backBuffer; + ReleaseTaskResources(); _task = null; _backBuffer = null; } @@ -884,20 +893,20 @@ namespace FlaxEditor.Viewport { _savedTask.Enabled = false; Object.Destroy(_savedTask); - ReleaseResources(); + ReleaseTaskResources(); _savedTask = null; } Object.Destroy(ref _savedBackBuffer); } - private void ReleaseResources() + private void ReleaseTaskResources() { - if (Task) + if (_task) { - Task.RemoveCustomPostFx(SelectionOutline); - Task.RemoveCustomPostFx(EditorPrimitives); - Task.RemoveCustomPostFx(_editorSpritesRenderer); - Task.RemoveCustomPostFx(_customSelectionOutline); + _task.RemoveCustomPostFx(SelectionOutline); + _task.RemoveCustomPostFx(EditorPrimitives); + _task.RemoveCustomPostFx(_editorSpritesRenderer); + _task.RemoveCustomPostFx(_customSelectionOutline); } Object.Destroy(ref SelectionOutline); Object.Destroy(ref EditorPrimitives); diff --git a/Source/Engine/Foliage/Foliage.cpp b/Source/Engine/Foliage/Foliage.cpp index c9e18ac9f..9b97e0e95 100644 --- a/Source/Engine/Foliage/Foliage.cpp +++ b/Source/Engine/Foliage/Foliage.cpp @@ -29,7 +29,7 @@ #include #define FOLIAGE_GET_DRAW_MODES(renderContext, type) (type._drawModes & renderContext.View.Pass & renderContext.View.GetShadowsDrawPassMask(type.ShadowsMode)) -#define FOLIAGE_CAN_DRAW(renderContext, type) (type.IsReady() && FOLIAGE_GET_DRAW_MODES(renderContext, type) != DrawPass::None && type.Model->CanBeRendered()) +#define FOLIAGE_CAN_DRAW(renderContext, type) (type.IsReady() && type._canDraw && FOLIAGE_GET_DRAW_MODES(renderContext, type) != DrawPass::None && type.Model->CanBeRendered()) Foliage::Foliage(const SpawnParams& params) : Actor(params) @@ -620,14 +620,18 @@ void Foliage::PreDraw(const RenderView& view) } // Cache data per foliage instance type - for (FoliageType& type : FoliageTypes) - InitType(view, type); + for (int32 i = 0; i < FoliageTypes.Count(); i++) + InitType(view, i); } -void Foliage::InitType(const RenderView& view, FoliageType& type) +void Foliage::InitType(const RenderView& view, int32 typeIndex) { + FoliageType& type = FoliageTypes[typeIndex]; const DrawPass drawModes = type._drawModes & view.Pass & view.GetShadowsDrawPassMask(type.ShadowsMode); type._canDraw = type.IsReady() && drawModes != DrawPass::None && type.Model && type.Model->CanBeRendered(); +#if USE_EDITOR + type._canDraw &= _drawFoliageType == -1 || _drawFoliageType == typeIndex; +#endif bool drawModesDirty = false; for (int32 j = 0; j < type.Entries.Count(); j++) { @@ -1286,7 +1290,7 @@ void Foliage::Draw(RenderContext& renderContext) // Draw single foliage instance projection into Global Surface Atlas auto& instance = *(FoliageInstance*)GlobalSurfaceAtlasPass::Instance()->GetCurrentActorObject(); auto& type = FoliageTypes[instance.Type]; - InitType(renderContext.View, type); + InitType(renderContext.View, instance.Type); Matrix world; const Transform transform = _transform.LocalToWorld(instance.Transform); renderContext.View.GetWorldMatrix(transform, world); diff --git a/Source/Engine/Foliage/Foliage.h b/Source/Engine/Foliage/Foliage.h index 948504736..b428ad356 100644 --- a/Source/Engine/Foliage/Foliage.h +++ b/Source/Engine/Foliage/Foliage.h @@ -217,7 +217,7 @@ private: #endif void PreDraw(const RenderView& view); - void InitType(const RenderView& view, FoliageType& type); + void InitType(const RenderView& view, int32 typeIndex); void UpdateBounds(); public: @@ -231,6 +231,12 @@ public: /// True whether the two objects intersected, otherwise false. API_FUNCTION() bool Intersects(API_PARAM(Ref) const Ray& ray, API_PARAM(Out) Real& distance, API_PARAM(Out) Vector3& normal, API_PARAM(Out) int32& instanceIndex); +private: +#if USE_EDITOR + // Debug filter to draw only specific foliage type (in editor). + API_FIELD(Internal) int32 _drawFoliageType = -1; +#endif + public: // [Actor] void Draw(RenderContext& renderContext) override;