diff --git a/Source/Editor/Viewport/Previews/AnimatedModelPreview.cs b/Source/Editor/Viewport/Previews/AnimatedModelPreview.cs index 2310668b6..4a1c57757 100644 --- a/Source/Editor/Viewport/Previews/AnimatedModelPreview.cs +++ b/Source/Editor/Viewport/Previews/AnimatedModelPreview.cs @@ -3,8 +3,6 @@ using System; using FlaxEditor.GUI.ContextMenu; using FlaxEngine; -using FlaxEditor.GUI.Input; -using FlaxEngine.GUI; using Object = FlaxEngine.Object; namespace FlaxEditor.Viewport.Previews @@ -15,11 +13,10 @@ namespace FlaxEditor.Viewport.Previews /// public class AnimatedModelPreview : AssetPreview { + public AnimatedModel _previewModel; private ContextMenuButton _showNodesButton, _showBoundsButton, _showFloorButton, _showNodesNamesButton; - private bool _showNodes, _showBounds, _showFloor, _showCurrentLOD, _showNodesNames; - private AnimatedModel _previewModel; + private bool _showNodes, _showBounds, _showFloor, _showNodesNames; private StaticModel _floorModel; - private ContextMenuButton _showCurrentLODButton; private bool _playAnimation, _playAnimationOnce; private float _playSpeed = 1.0f; @@ -207,26 +204,6 @@ namespace FlaxEditor.Viewport.Previews // Show Floor _showFloorButton = ViewWidgetShowMenu.AddButton("Floor", button => ShowFloor = !ShowFloor); _showFloorButton.IndexInParent = 1; - - // Show Current LOD - _showCurrentLODButton = ViewWidgetShowMenu.AddButton("Current LOD", button => - { - _showCurrentLOD = !_showCurrentLOD; - _showCurrentLODButton.Icon = _showCurrentLOD ? Style.Current.CheckBoxTick : SpriteHandle.Invalid; - }); - _showCurrentLODButton.IndexInParent = 2; - - // Preview LOD - { - var previewLOD = ViewWidgetButtonMenu.AddButton("Preview LOD"); - previewLOD.CloseMenuOnClick = false; - var previewLODValue = new IntValueBox(-1, 90, 2, 70.0f, -1, 10, 0.02f) - { - Parent = previewLOD - }; - previewLODValue.ValueChanged += () => _previewModel.ForcedLOD = previewLODValue.Value; - ViewWidgetButtonMenu.VisibleChanged += control => previewLODValue.Value = _previewModel.ForcedLOD; - } } // Enable shadows @@ -339,44 +316,6 @@ namespace FlaxEditor.Viewport.Previews _previewModel.ResetAnimation(); } - private int ComputeLODIndex(SkinnedModel model) - { - if (PreviewActor.ForcedLOD != -1) - return PreviewActor.ForcedLOD; - - // Based on RenderTools::ComputeModelLOD - CreateProjectionMatrix(out var projectionMatrix); - float screenMultiple = 0.5f * Mathf.Max(projectionMatrix.M11, projectionMatrix.M22); - var sphere = PreviewActor.Sphere; - var viewOrigin = ViewPosition; - var distSqr = Vector3.DistanceSquared(ref sphere.Center, ref viewOrigin); - var screenRadiusSquared = Mathf.Square(screenMultiple * sphere.Radius) / Mathf.Max(1.0f, distSqr); - - // Check if model is being culled - if (Mathf.Square(model.MinScreenSize * 0.5f) > screenRadiusSquared) - return -1; - - // Skip if no need to calculate LOD - if (model.LoadedLODs == 0) - return -1; - var lods = model.LODs; - if (lods.Length == 0) - return -1; - if (lods.Length == 1) - return 0; - - // Iterate backwards and return the first matching LOD - for (int lodIndex = lods.Length - 1; lodIndex >= 0; lodIndex--) - { - if (Mathf.Square(lods[lodIndex].ScreenSize * 0.5f) >= screenRadiusSquared) - { - return lodIndex + PreviewActor.LODBias; - } - } - - return 0; - } - /// protected override void OnDebugDraw(GPUContext context, ref RenderContext renderContext) { @@ -440,45 +379,6 @@ namespace FlaxEditor.Viewport.Previews } } - /// - public override void Draw() - { - base.Draw(); - - var skinnedModel = _previewModel.SkinnedModel; - if (skinnedModel == null || !skinnedModel.IsLoaded) - return; - var lods = skinnedModel.LODs; - if (lods.Length == 0) - { - // Force show skeleton for models without geometry - ShowNodes = true; - return; - } - if (_showCurrentLOD) - { - var lodIndex = ComputeLODIndex(skinnedModel); - string text = string.Format("Current LOD: {0}", lodIndex); - if (lodIndex != -1) - { - lodIndex = Mathf.Clamp(lodIndex + PreviewActor.LODBias, 0, lods.Length - 1); - var lod = lods[lodIndex]; - int triangleCount = 0, vertexCount = 0; - for (int meshIndex = 0; meshIndex < lod.Meshes.Length; meshIndex++) - { - var mesh = lod.Meshes[meshIndex]; - triangleCount += mesh.TriangleCount; - vertexCount += mesh.VertexCount; - } - text += string.Format("\nTriangles: {0:N0}\nVertices: {1:N0}", triangleCount, vertexCount); - } - var font = Style.Current.FontMedium; - var pos = new Float2(10, 50); - Render2D.DrawText(font, text, new Rectangle(pos + Float2.One, Size), Color.Black); - Render2D.DrawText(font, text, new Rectangle(pos, Size), Color.White); - } - } - /// public override void Update(float deltaTime) { @@ -498,14 +398,21 @@ namespace FlaxEditor.Viewport.Previews } } + /// + /// Resets the camera to focus on a object. + /// + public void ResetCamera() + { + ViewportCamera.SetArcBallView(_previewModel.Box); + } + /// public override bool OnKeyDown(KeyboardKeys key) { switch (key) { case KeyboardKeys.F: - // Pay respect.. - ViewportCamera.SetArcBallView(_previewModel.Box); + ResetCamera(); return true; case KeyboardKeys.Spacebar: PlayAnimation = !PlayAnimation; @@ -525,7 +432,6 @@ namespace FlaxEditor.Viewport.Previews _showNodesButton = null; _showBoundsButton = null; _showFloorButton = null; - _showCurrentLODButton = null; _showNodesNamesButton = null; base.OnDestroy(); diff --git a/Source/Editor/Viewport/Previews/MaterialPreview.cs b/Source/Editor/Viewport/Previews/MaterialPreview.cs index 632ec199e..5520d6c4c 100644 --- a/Source/Editor/Viewport/Previews/MaterialPreview.cs +++ b/Source/Editor/Viewport/Previews/MaterialPreview.cs @@ -4,6 +4,8 @@ using System; using FlaxEditor.Surface; using FlaxEngine; using FlaxEngine.GUI; +using FlaxEditor.Viewport.Widgets; +using FlaxEditor.GUI.ContextMenu; using Object = FlaxEngine.Object; namespace FlaxEditor.Viewport.Previews @@ -46,6 +48,7 @@ namespace FlaxEditor.Viewport.Previews private int _selectedModelIndex; private Image _guiMaterialControl; private readonly MaterialBase[] _postFxMaterialsCache = new MaterialBase[1]; + private ContextMenu _modelWidgetButtonMenu; /// /// Gets or sets the material asset to preview. It can be or . @@ -95,20 +98,33 @@ namespace FlaxEditor.Viewport.Previews Task.AddCustomActor(_previewModel); // Create context menu for primitive switching - if (useWidgets && ViewWidgetButtonMenu != null) + if (useWidgets) { - ViewWidgetButtonMenu.AddSeparator(); - var modelSelect = ViewWidgetButtonMenu.AddChildMenu("Model").ContextMenu; - - // Fill out all models - for (int i = 0; i < Models.Length; i++) + // Model mode widget + var modelMode = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight); + _modelWidgetButtonMenu = new ContextMenu(); + _modelWidgetButtonMenu.VisibleChanged += control => { - var button = modelSelect.AddButton(Models[i]); - button.Tag = i; - } + if (!control.Visible) + return; + _modelWidgetButtonMenu.ItemsContainer.DisposeChildren(); - // Link the action - modelSelect.ButtonClicked += (button) => SelectedModelIndex = (int)button.Tag; + // Fill out all models + for (int i = 0; i < Models.Length; i++) + { + var index = i; + var button = _modelWidgetButtonMenu.AddButton(Models[index]); + button.ButtonClicked += _ => SelectedModelIndex = index; + button.Checked = SelectedModelIndex == index; + button.Tag = index; + } + }; + new ViewportWidgetButton("Model", SpriteHandle.Invalid, _modelWidgetButtonMenu) + { + TooltipText = "Change material model", + Parent = modelMode, + }; + modelMode.Parent = this; } } diff --git a/Source/Editor/Viewport/Previews/ModelBasePreview.cs b/Source/Editor/Viewport/Previews/ModelBasePreview.cs index ffba23094..e4f1109d4 100644 --- a/Source/Editor/Viewport/Previews/ModelBasePreview.cs +++ b/Source/Editor/Viewport/Previews/ModelBasePreview.cs @@ -1,6 +1,5 @@ // Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. -using FlaxEditor.GUI.Input; using FlaxEngine; using Object = FlaxEngine.Object; @@ -56,25 +55,14 @@ namespace FlaxEditor.Viewport.Previews // Link actors for rendering Task.AddCustomActor(StaticModel); Task.AddCustomActor(AnimatedModel); + } - if (useWidgets) - { - // Preview LOD - { - var previewLOD = ViewWidgetButtonMenu.AddButton("Preview LOD"); - previewLOD.CloseMenuOnClick = false; - var previewLODValue = new IntValueBox(-1, 90, 2, 70.0f, -1, 10, 0.02f) - { - Parent = previewLOD - }; - previewLODValue.ValueChanged += () => - { - StaticModel.ForcedLOD = previewLODValue.Value; - AnimatedModel.ForcedLOD = previewLODValue.Value; - }; - ViewWidgetButtonMenu.VisibleChanged += control => previewLODValue.Value = StaticModel.ForcedLOD; - } - } + /// + /// Resets the camera to focus on a object. + /// + public void ResetCamera() + { + ViewportCamera.SetArcBallView(StaticModel.Model != null ? StaticModel.Box : AnimatedModel.Box); } private void OnBegin(RenderTask task, GPUContext context) @@ -103,8 +91,7 @@ namespace FlaxEditor.Viewport.Previews switch (key) { case KeyboardKeys.F: - // Pay respect.. - ViewportCamera.SetArcBallView(StaticModel.Model != null ? StaticModel.Box : AnimatedModel.Box); + ResetCamera(); break; } return base.OnKeyDown(key); diff --git a/Source/Editor/Viewport/Previews/ModelPreview.cs b/Source/Editor/Viewport/Previews/ModelPreview.cs index 9193b6d40..a0b6d0ca0 100644 --- a/Source/Editor/Viewport/Previews/ModelPreview.cs +++ b/Source/Editor/Viewport/Previews/ModelPreview.cs @@ -1,10 +1,10 @@ // Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. using FlaxEditor.GUI.ContextMenu; -using FlaxEditor.GUI.Input; using FlaxEngine; using FlaxEngine.GUI; using FlaxEngine.Utilities; +using FlaxEditor.Viewport.Widgets; using Object = FlaxEngine.Object; namespace FlaxEditor.Viewport.Previews @@ -16,10 +16,27 @@ namespace FlaxEditor.Viewport.Previews public class ModelPreview : AssetPreview { private ContextMenuButton _showBoundsButton, _showCurrentLODButton, _showNormalsButton, _showTangentsButton, _showBitangentsButton, _showFloorButton; + private ContextMenu _previewLODsWidgetButtonMenu; private StaticModel _previewModel, _floorModel; private bool _showBounds, _showCurrentLOD, _showNormals, _showTangents, _showBitangents, _showFloor; private MeshDataCache _meshDatas; + /// + /// Gets or sets a value that shows LOD statistics + /// + public bool ShowCurrentLOD + { + get => _showCurrentLOD; + set + { + if (_showCurrentLOD == value) + return; + _showCurrentLOD = value; + if (_showCurrentLODButton != null) + _showCurrentLODButton.Checked = value; + } + } + /// /// Gets or sets the model asset to preview. /// @@ -198,17 +215,36 @@ namespace FlaxEditor.Viewport.Previews }); _showCurrentLODButton.IndexInParent = 2; - // Preview LOD + // Preview LODs mode widget + var PreviewLODsMode = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight); + _previewLODsWidgetButtonMenu = new ContextMenu(); + _previewLODsWidgetButtonMenu.VisibleChanged += control => { - var previewLOD = ViewWidgetButtonMenu.AddButton("Preview LOD"); - previewLOD.CloseMenuOnClick = false; - var previewLODValue = new IntValueBox(-1, 90, 2, 70.0f, -1, 10, 0.02f) + if (!control.Visible) + return; + var model = _previewModel.Model; + if (model && !model.WaitForLoaded()) { - Parent = previewLOD - }; - previewLODValue.ValueChanged += () => _previewModel.ForcedLOD = previewLODValue.Value; - ViewWidgetButtonMenu.VisibleChanged += control => previewLODValue.Value = _previewModel.ForcedLOD; - } + _previewLODsWidgetButtonMenu.ItemsContainer.DisposeChildren(); + var lods = model.LODs.Length; + for (int i = -1; i < lods; i++) + { + var index = i; + var button = _previewLODsWidgetButtonMenu.AddButton("LOD " + (index == -1 ? "Auto" : index)); + button.ButtonClicked += _ => _previewModel.ForcedLOD = index; + button.Checked = _previewModel.ForcedLOD == index; + button.Tag = index; + if (lods <= 1) + break; + } + } + }; + new ViewportWidgetButton("Preview LOD", SpriteHandle.Invalid, _previewLODsWidgetButtonMenu) + { + TooltipText = "Preview LOD properties", + Parent = PreviewLODsMode, + }; + PreviewLODsMode.Parent = this; } } @@ -312,7 +348,7 @@ namespace FlaxEditor.Viewport.Previews var distSqr = Vector3.DistanceSquared(ref sphere.Center, ref viewOrigin); var screenRadiusSquared = Mathf.Square(screenMultiple * sphere.Radius) / Mathf.Max(1.0f, distSqr); screenSize = Mathf.Sqrt((float)screenRadiusSquared) * 2.0f; - + // Check if model is being culled if (Mathf.Square(model.MinScreenSize * 0.5f) > screenRadiusSquared) return -1; @@ -346,8 +382,11 @@ namespace FlaxEditor.Viewport.Previews if (_showCurrentLOD) { var asset = Model; - var lodIndex = ComputeLODIndex(asset, out var screenSize); - string text = string.Format("Current LOD: {0}\nScreen Size: {1:F2}", lodIndex, screenSize); + var lodIndex = ComputeLODIndex(asset, out var screenSize); + var auto = _previewModel.ForcedLOD == -1; + string text = auto ? "LOD Automatic" : ""; + text += auto ? string.Format("\nScreen Size: {0:F2}", screenSize) : ""; + text += string.Format("\nCurrent LOD: {0}", lodIndex); if (lodIndex != -1) { var lods = asset.LODs; @@ -369,14 +408,21 @@ namespace FlaxEditor.Viewport.Previews } } + /// + /// Resets the camera to focus on a object. + /// + public void ResetCamera() + { + ViewportCamera.SetArcBallView(_previewModel.Box); + } + /// public override bool OnKeyDown(KeyboardKeys key) { switch (key) { case KeyboardKeys.F: - // Pay respect.. - ViewportCamera.SetArcBallView(_previewModel.Box); + ResetCamera(); break; } return base.OnKeyDown(key); @@ -389,6 +435,7 @@ namespace FlaxEditor.Viewport.Previews Object.Destroy(ref _previewModel); _showBoundsButton = null; _showCurrentLODButton = null; + _previewLODsWidgetButtonMenu = null; _showNormalsButton = null; _showTangentsButton = null; _showBitangentsButton = null; diff --git a/Source/Editor/Viewport/Previews/SkinnedModelPreview.cs b/Source/Editor/Viewport/Previews/SkinnedModelPreview.cs new file mode 100644 index 000000000..c11ea9ea4 --- /dev/null +++ b/Source/Editor/Viewport/Previews/SkinnedModelPreview.cs @@ -0,0 +1,177 @@ +// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. + +using FlaxEditor.GUI.ContextMenu; +using FlaxEngine; +using FlaxEngine.GUI; +using FlaxEditor.Viewport.Widgets; + +namespace FlaxEditor.Viewport.Previews +{ + /// + /// Animation asset preview editor viewport. + /// + /// + public class SkinnedModelPreview : AnimatedModelPreview + { + private bool _showCurrentLOD; + private ContextMenuButton _showCurrentLODButton; + private ContextMenu _previewLODsWidgetButtonMenu; + + /// + /// Gets or sets a value that shows LOD statistics + /// + public bool ShowCurrentLOD + { + get => _showCurrentLOD; + set + { + if (_showCurrentLOD == value) + return; + _showCurrentLOD = value; + if (_showCurrentLODButton != null) + _showCurrentLODButton.Checked = value; + } + } + + /// + /// Initializes a new instance of the class. + /// + /// if set to true use widgets. + public SkinnedModelPreview(bool useWidgets) + : base(useWidgets) + { + if (useWidgets) + { + // Show Current LOD + _showCurrentLODButton = ViewWidgetShowMenu.AddButton("Current LOD", button => + { + _showCurrentLOD = !_showCurrentLOD; + _showCurrentLODButton.Icon = _showCurrentLOD ? Style.Current.CheckBoxTick : SpriteHandle.Invalid; + }); + _showCurrentLODButton.IndexInParent = 2; + + // PreviewLODS mode widget + var PreviewLODSMode = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight); + _previewLODsWidgetButtonMenu = new ContextMenu(); + _previewLODsWidgetButtonMenu.VisibleChanged += control => + { + if (!control.Visible) + return; + var skinned = _previewModel.SkinnedModel; + if (skinned && !skinned.WaitForLoaded()) + { + _previewLODsWidgetButtonMenu.ItemsContainer.DisposeChildren(); + var lods = skinned.LODs.Length; + for (int i = -1; i < lods; i++) + { + var index = i; + var button = _previewLODsWidgetButtonMenu.AddButton("LOD " + (index == -1 ? "Auto" : index)); + button.ButtonClicked += (button) => _previewModel.ForcedLOD = index; + button.Checked = _previewModel.ForcedLOD == index; + button.Tag = index; + if (lods <= 1) + break; + } + } + }; + new ViewportWidgetButton("Preview LOD", SpriteHandle.Invalid, _previewLODsWidgetButtonMenu) + { + TooltipText = "Preview LOD properties", + Parent = PreviewLODSMode, + }; + PreviewLODSMode.Parent = this; + } + } + + private int ComputeLODIndex(SkinnedModel model, out float screenSize) + { + screenSize = 1.0f; + if (PreviewActor.ForcedLOD != -1) + return PreviewActor.ForcedLOD; + + // Based on RenderTools::ComputeModelLOD + CreateProjectionMatrix(out var projectionMatrix); + float screenMultiple = 0.5f * Mathf.Max(projectionMatrix.M11, projectionMatrix.M22); + var sphere = PreviewActor.Sphere; + var viewOrigin = ViewPosition; + var distSqr = Vector3.DistanceSquared(ref sphere.Center, ref viewOrigin); + var screenRadiusSquared = Mathf.Square(screenMultiple * sphere.Radius) / Mathf.Max(1.0f, distSqr); + screenSize = Mathf.Sqrt((float)screenRadiusSquared) * 2.0f; + + // Check if model is being culled + if (Mathf.Square(model.MinScreenSize * 0.5f) > screenRadiusSquared) + return -1; + + // Skip if no need to calculate LOD + if (model.LoadedLODs == 0) + return -1; + var lods = model.LODs; + if (lods.Length == 0) + return -1; + if (lods.Length == 1) + return 0; + + // Iterate backwards and return the first matching LOD + for (int lodIndex = lods.Length - 1; lodIndex >= 0; lodIndex--) + { + if (Mathf.Square(lods[lodIndex].ScreenSize * 0.5f) >= screenRadiusSquared) + { + return lodIndex + PreviewActor.LODBias; + } + } + + return 0; + } + + /// + public override void Draw() + { + base.Draw(); + + var skinnedModel = _previewModel.SkinnedModel; + if (skinnedModel == null || !skinnedModel.IsLoaded) + return; + var lods = skinnedModel.LODs; + if (lods.Length == 0) + { + // Force show skeleton for models without geometry + ShowNodes = true; + return; + } + if (_showCurrentLOD) + { + var lodIndex = ComputeLODIndex(skinnedModel, out var screenSize); + var auto = _previewModel.ForcedLOD == -1; + string text = auto ? "LOD Automatic" : ""; + text += auto ? string.Format("\nScreen Size: {0:F2}", screenSize) : ""; + text += string.Format("\nCurrent LOD: {0}", lodIndex); + if (lodIndex != -1) + { + lodIndex = Mathf.Clamp(lodIndex + PreviewActor.LODBias, 0, lods.Length - 1); + var lod = lods[lodIndex]; + int triangleCount = 0, vertexCount = 0; + for (int meshIndex = 0; meshIndex < lod.Meshes.Length; meshIndex++) + { + var mesh = lod.Meshes[meshIndex]; + triangleCount += mesh.TriangleCount; + vertexCount += mesh.VertexCount; + } + text += string.Format("\nTriangles: {0:N0}\nVertices: {1:N0}", triangleCount, vertexCount); + } + var font = Style.Current.FontMedium; + var pos = new Float2(10, 50); + Render2D.DrawText(font, text, new Rectangle(pos + Float2.One, Size), Color.Black); + Render2D.DrawText(font, text, new Rectangle(pos, Size), Color.White); + } + } + + /// + public override void OnDestroy() + { + _showCurrentLODButton = null; + _previewLODsWidgetButtonMenu = null; + + base.OnDestroy(); + } + } +} diff --git a/Source/Editor/Windows/Assets/CollisionDataWindow.cs b/Source/Editor/Windows/Assets/CollisionDataWindow.cs index 9ce4c8765..cc1daa45b 100644 --- a/Source/Editor/Windows/Assets/CollisionDataWindow.cs +++ b/Source/Editor/Windows/Assets/CollisionDataWindow.cs @@ -182,6 +182,7 @@ namespace FlaxEditor.Windows.Assets { // Toolstrip _toolstrip.AddSeparator(); + _toolstrip.AddButton(editor.Icons.CenterView64, () => _preview.ResetCamera()).LinkTooltip("Show whole collision"); _toolstrip.AddButton(editor.Icons.Docs64, () => Platform.OpenUrl(Utilities.Constants.DocsUrl + "manual/physics/colliders/collision-data.html")).LinkTooltip("See documentation to learn more"); // Split Panel diff --git a/Source/Editor/Windows/Assets/ModelWindow.cs b/Source/Editor/Windows/Assets/ModelWindow.cs index e44882b73..f70f6a3b5 100644 --- a/Source/Editor/Windows/Assets/ModelWindow.cs +++ b/Source/Editor/Windows/Assets/ModelWindow.cs @@ -779,6 +779,7 @@ namespace FlaxEditor.Windows.Assets private MeshDataCache _meshData; private ModelImportSettings _importSettings = new ModelImportSettings(); private float _backfacesThreshold = 0.6f; + private ToolStripButton _showCurrentLODButton; /// public ModelWindow(Editor editor, AssetItem item) @@ -786,6 +787,9 @@ namespace FlaxEditor.Windows.Assets { // Toolstrip _toolstrip.AddSeparator(); + _showCurrentLODButton = (ToolStripButton)_toolstrip.AddButton(editor.Icons.Info64, () => _preview.ShowCurrentLOD = !_preview.ShowCurrentLOD).LinkTooltip("Show LOD statistics"); + _toolstrip.AddButton(editor.Icons.CenterView64, () => _preview.ResetCamera()).LinkTooltip("Show whole model"); + _toolstrip.AddSeparator(); _toolstrip.AddButton(editor.Icons.Docs64, () => Platform.OpenUrl(Utilities.Constants.DocsUrl + "manual/graphics/models/index.html")).LinkTooltip("See documentation to learn more"); // Model preview @@ -869,6 +873,8 @@ namespace FlaxEditor.Windows.Assets } } + _showCurrentLODButton.Checked = _preview.ShowCurrentLOD; + base.Update(deltaTime); } @@ -946,6 +952,7 @@ namespace FlaxEditor.Windows.Assets base.OnDestroy(); Object.Destroy(ref _highlightActor); + _showCurrentLODButton = null; } } } diff --git a/Source/Editor/Windows/Assets/SkinnedModelWindow.cs b/Source/Editor/Windows/Assets/SkinnedModelWindow.cs index d18593549..a7ee6e767 100644 --- a/Source/Editor/Windows/Assets/SkinnedModelWindow.cs +++ b/Source/Editor/Windows/Assets/SkinnedModelWindow.cs @@ -31,7 +31,7 @@ namespace FlaxEditor.Windows.Assets /// public sealed class SkinnedModelWindow : ModelBaseWindow { - private sealed class Preview : AnimatedModelPreview + private sealed class Preview : SkinnedModelPreview { private readonly SkinnedModelWindow _window; @@ -1105,6 +1105,7 @@ namespace FlaxEditor.Windows.Assets private Preview _preview; private AnimatedModel _highlightActor; private ToolStripButton _showNodesButton; + private ToolStripButton _showCurrentLODButton; private MeshData[][] _meshDatas; private bool _meshDatasInProgress; @@ -1116,7 +1117,9 @@ namespace FlaxEditor.Windows.Assets { // Toolstrip _toolstrip.AddSeparator(); + _showCurrentLODButton = (ToolStripButton)_toolstrip.AddButton(editor.Icons.Info64, () => _preview.ShowCurrentLOD = !_preview.ShowCurrentLOD).LinkTooltip("Show LOD statistics"); _showNodesButton = (ToolStripButton)_toolstrip.AddButton(editor.Icons.Bone64, () => _preview.ShowNodes = !_preview.ShowNodes).LinkTooltip("Show animated model nodes debug view"); + _toolstrip.AddButton(editor.Icons.CenterView64, () => _preview.ResetCamera()).LinkTooltip("Show whole model"); _toolstrip.AddSeparator(); _toolstrip.AddButton(editor.Icons.Docs64, () => Platform.OpenUrl(Utilities.Constants.DocsUrl + "manual/animation/skinned-model/index.html")).LinkTooltip("See documentation to learn more"); @@ -1265,6 +1268,7 @@ namespace FlaxEditor.Windows.Assets } } + _showCurrentLODButton.Checked = _preview.ShowCurrentLOD; _showNodesButton.Checked = _preview.ShowNodes; base.Update(deltaTime); @@ -1349,6 +1353,7 @@ namespace FlaxEditor.Windows.Assets Object.Destroy(ref _highlightActor); _preview = null; _showNodesButton = null; + _showCurrentLODButton = null; } } }