diff --git a/Source/Editor/Viewport/Previews/AnimatedModelPreview.cs b/Source/Editor/Viewport/Previews/AnimatedModelPreview.cs index 2310668b6..aae48fe11 100644 --- a/Source/Editor/Viewport/Previews/AnimatedModelPreview.cs +++ b/Source/Editor/Viewport/Previews/AnimatedModelPreview.cs @@ -15,11 +15,13 @@ 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 +209,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 +321,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 +384,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,6 +403,14 @@ namespace FlaxEditor.Viewport.Previews } } + /// + /// Calls SetArcBallView from ViewportCamera + /// + public void CallSetArcBallView() + { + ViewportCamera.SetArcBallView(_previewModel.Box); + } + /// public override bool OnKeyDown(KeyboardKeys key) { @@ -505,7 +418,7 @@ namespace FlaxEditor.Viewport.Previews { case KeyboardKeys.F: // Pay respect.. - ViewportCamera.SetArcBallView(_previewModel.Box); + CallSetArcBallView(); return true; case KeyboardKeys.Spacebar: PlayAnimation = !PlayAnimation; @@ -525,7 +438,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..3dfab1cff 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 @@ -63,6 +65,11 @@ namespace FlaxEditor.Viewport.Previews } } + /// + /// The "Model" widget button context menu. + /// + private ContextMenu modelWidgetButtonMenu; + /// /// Gets or sets the selected preview model index. /// @@ -80,6 +87,27 @@ namespace FlaxEditor.Viewport.Previews } } + /// + /// Fill out all models + /// + /// + private void ModelWidgetMenuOnVisibleChanged(Control control) + { + if (!control.Visible) return; + + modelWidgetButtonMenu.ItemsContainer.DisposeChildren(); + + // Fill out all models + for (int i = 0; i < Models.Length; i++) + { + var index = i; + var button = modelWidgetButtonMenu.AddButton(Models[index]); + button.ButtonClicked += (button) => SelectedModelIndex = index; + button.Checked = SelectedModelIndex == index; + button.Tag = index; + } + } + /// /// Initializes a new instance of the class. /// @@ -95,20 +123,18 @@ 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 += ModelWidgetMenuOnVisibleChanged; + var previewLODSModeButton = new ViewportWidgetButton("Model", SpriteHandle.Invalid, modelWidgetButtonMenu) { - var button = modelSelect.AddButton(Models[i]); - button.Tag = i; - } - - // Link the action - modelSelect.ButtonClicked += (button) => SelectedModelIndex = (int)button.Tag; + 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..e5834edc9 100644 --- a/Source/Editor/Viewport/Previews/ModelBasePreview.cs +++ b/Source/Editor/Viewport/Previews/ModelBasePreview.cs @@ -56,25 +56,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; - } - } + /// + /// Calls SetArcBallView from ViewportCamera + /// + public void CallSetArcBallView() + { + ViewportCamera.SetArcBallView(StaticModel.Model != null ? StaticModel.Box : AnimatedModel.Box); } private void OnBegin(RenderTask task, GPUContext context) @@ -104,7 +93,7 @@ namespace FlaxEditor.Viewport.Previews { case KeyboardKeys.F: // Pay respect.. - ViewportCamera.SetArcBallView(StaticModel.Model != null ? StaticModel.Box : AnimatedModel.Box); + CallSetArcBallView(); break; } return base.OnKeyDown(key); diff --git a/Source/Editor/Viewport/Previews/ModelPreview.cs b/Source/Editor/Viewport/Previews/ModelPreview.cs index 9193b6d40..dc0de37da 100644 --- a/Source/Editor/Viewport/Previews/ModelPreview.cs +++ b/Source/Editor/Viewport/Previews/ModelPreview.cs @@ -5,6 +5,7 @@ using FlaxEditor.GUI.Input; using FlaxEngine; using FlaxEngine.GUI; using FlaxEngine.Utilities; +using FlaxEditor.Viewport.Widgets; using Object = FlaxEngine.Object; namespace FlaxEditor.Viewport.Previews @@ -20,6 +21,29 @@ namespace FlaxEditor.Viewport.Previews private bool _showBounds, _showCurrentLOD, _showNormals, _showTangents, _showBitangents, _showFloor; private MeshDataCache _meshDatas; + /// + /// The "PreviewLODS" widget button context menu. + /// + 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 (value) + ShowDebugDraw = true; + if (_showCurrentLODButton != null) + _showCurrentLODButton.Checked = value; + } + } + /// /// Gets or sets the model asset to preview. /// @@ -198,16 +222,41 @@ namespace FlaxEditor.Viewport.Previews }); _showCurrentLODButton.IndexInParent = 2; - // Preview LOD + // PreviewLODS mode widget + var PreviewLODSMode = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight); + previewLODSWidgetButtonMenu = new ContextMenu(); + previewLODSWidgetButtonMenu.VisibleChanged += PreviewLODSWidgetMenuOnVisibleChanged; + var previewLODSModeButton = new ViewportWidgetButton("Preview LOD", SpriteHandle.Invalid, previewLODSWidgetButtonMenu) { - 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; + TooltipText = "Preview LOD properties", + Parent = PreviewLODSMode, + }; + PreviewLODSMode.Parent = this; + } + } + + /// + /// Fill out all Model LODS + /// + /// + private void PreviewLODSWidgetMenuOnVisibleChanged(Control control) + { + if (!control.Visible) + return; + + var model = _previewModel.Model; + if (model && !model.WaitForLoaded() && model.IsLoaded) + { + 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 += (button) => _previewModel.ForcedLOD = index; + button.Checked = _previewModel.ForcedLOD == index; + button.Tag = index; + if (lods <= 1) return; } } } @@ -346,8 +395,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,6 +421,14 @@ namespace FlaxEditor.Viewport.Previews } } + /// + /// Calls SetArcBallView from ViewportCamera + /// + public void CallSetArcBallView() + { + ViewportCamera.SetArcBallView(_previewModel.Box); + } + /// public override bool OnKeyDown(KeyboardKeys key) { @@ -376,7 +436,7 @@ namespace FlaxEditor.Viewport.Previews { case KeyboardKeys.F: // Pay respect.. - ViewportCamera.SetArcBallView(_previewModel.Box); + CallSetArcBallView(); break; } return base.OnKeyDown(key); diff --git a/Source/Editor/Viewport/Previews/SkinnedModelPreview.cs b/Source/Editor/Viewport/Previews/SkinnedModelPreview.cs new file mode 100644 index 000000000..a8b98b423 --- /dev/null +++ b/Source/Editor/Viewport/Previews/SkinnedModelPreview.cs @@ -0,0 +1,188 @@ +using System; +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; + + /// + /// The "PreviewLODS" widget button context menu. + /// + 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 (value) + ShowDebugDraw = true; + 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 += PreviewLODSWidgetMenuOnVisibleChanged; + var previewLODSModeButton = new ViewportWidgetButton("Preview LOD", SpriteHandle.Invalid, previewLODSWidgetButtonMenu) + { + TooltipText = "Preview LOD properties", + Parent = PreviewLODSMode, + }; + PreviewLODSMode.Parent = this; + } + } + + /// + /// Fill out all SkinnedModel LODS + /// + /// + private void PreviewLODSWidgetMenuOnVisibleChanged(Control control) + { + if (!control.Visible) + return; + + var skinned = _previewModel.SkinnedModel; + if (skinned && !skinned.WaitForLoaded() && skinned.IsLoaded) + { + 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) return; + } + } + } + + /// + 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; + + base.OnDestroy(); + } + } +} diff --git a/Source/Editor/Windows/Assets/CollisionDataWindow.cs b/Source/Editor/Windows/Assets/CollisionDataWindow.cs index 9ce4c8765..82e0681fa 100644 --- a/Source/Editor/Windows/Assets/CollisionDataWindow.cs +++ b/Source/Editor/Windows/Assets/CollisionDataWindow.cs @@ -182,6 +182,9 @@ namespace FlaxEditor.Windows.Assets { // Toolstrip _toolstrip.AddSeparator(); + + _toolstrip.AddButton(editor.Icons.CenterView64, () => _preview.CallSetArcBallView()).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..cc7657fc7 100644 --- a/Source/Editor/Windows/Assets/ModelWindow.cs +++ b/Source/Editor/Windows/Assets/ModelWindow.cs @@ -779,12 +779,18 @@ 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) : base(editor, item) { // Toolstrip + _toolstrip.AddSeparator(); + _showCurrentLODButton = (ToolStripButton)_toolstrip.AddButton(editor.Icons.Info64, () => _preview.ShowCurrentLOD = !_preview.ShowCurrentLOD).LinkTooltip("Show LOD statistics"); + + _toolstrip.AddButton(editor.Icons.CenterView64, () => _preview.CallSetArcBallView()).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"); @@ -869,6 +875,8 @@ namespace FlaxEditor.Windows.Assets } } + _showCurrentLODButton.Checked = _preview.ShowCurrentLOD; + base.Update(deltaTime); } @@ -946,6 +954,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..367fc3a1a 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,13 @@ 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.CallSetArcBallView()).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 +1272,7 @@ namespace FlaxEditor.Windows.Assets } } + _showCurrentLODButton.Checked = _preview.ShowCurrentLOD; _showNodesButton.Checked = _preview.ShowNodes; base.Update(deltaTime); @@ -1349,6 +1357,7 @@ namespace FlaxEditor.Windows.Assets Object.Destroy(ref _highlightActor); _preview = null; _showNodesButton = null; + _showCurrentLODButton = null; } } }