From 21cac2ad6e96cb73eed729a3380dcf652bc959eb Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 20 Apr 2026 13:17:04 +0200 Subject: [PATCH] Various improvements to model previews in editor --- Source/Editor/Content/Proxy/ModelProxy.cs | 1 + Source/Editor/Content/Proxy/PrefabProxy.cs | 2 +- .../Viewport/Previews/AnimatedModelPreview.cs | 9 +++++- .../Editor/Viewport/Previews/ModelPreview.cs | 28 +++++++++++++++---- .../Viewport/Previews/SkinnedModelPreview.cs | 8 +++--- 5 files changed, 37 insertions(+), 11 deletions(-) diff --git a/Source/Editor/Content/Proxy/ModelProxy.cs b/Source/Editor/Content/Proxy/ModelProxy.cs index 8b20073d8..a57ddbf61 100644 --- a/Source/Editor/Content/Proxy/ModelProxy.cs +++ b/Source/Editor/Content/Proxy/ModelProxy.cs @@ -95,6 +95,7 @@ namespace FlaxEditor.Content var bounds = _preview.Model.GetBox(); var maxSize = Math.Max(0.001f, (float)bounds.Size.MaxValue); _preview.ViewportCamera.SetArcBallView(bounds); + _preview.NearPlane = Mathf.Min(10.0f, maxSize * 0.5f); _preview.FarPlane = Mathf.Max(1000.0f, maxSize * 2 + 100.0f); _preview.Task.OnDraw(); diff --git a/Source/Editor/Content/Proxy/PrefabProxy.cs b/Source/Editor/Content/Proxy/PrefabProxy.cs index 0fb247605..410df23b0 100644 --- a/Source/Editor/Content/Proxy/PrefabProxy.cs +++ b/Source/Editor/Content/Proxy/PrefabProxy.cs @@ -188,7 +188,7 @@ namespace FlaxEditor.Content if (bounds != BoundingBox.Empty) { float targetSize = 38.0f; - var maxSize = Math.Max(0.001f, (float)bounds.Size.MaxValue); + float maxSize = Math.Max(0.001f, (float)bounds.Size.MaxValue); float scale = targetSize / maxSize; _preview.Instance.Scale = new Float3(scale); _preview.Instance.Position = -bounds.Center * scale; diff --git a/Source/Editor/Viewport/Previews/AnimatedModelPreview.cs b/Source/Editor/Viewport/Previews/AnimatedModelPreview.cs index a678e868a..10dcdf671 100644 --- a/Source/Editor/Viewport/Previews/AnimatedModelPreview.cs +++ b/Source/Editor/Viewport/Previews/AnimatedModelPreview.cs @@ -17,7 +17,7 @@ namespace FlaxEditor.Viewport.Previews private ContextMenuButton _showNodesButton, _showBoundsButton, _showFloorButton, _showNodesNamesButton; private bool _showNodes, _showBounds, _showFloor, _showNodesNames; private StaticModel _floorModel; - private bool _playAnimation, _playAnimationOnce; + private bool _playAnimation, _playAnimationOnce, _autoAdjustCamera = true; private float _playSpeed = 1.0f; /// @@ -291,6 +291,13 @@ namespace FlaxEditor.Viewport.Previews private void OnBegin(RenderTask task, GPUContext context) { + if (_autoAdjustCamera && SkinnedModel && SkinnedModel.IsLoaded) + { + // Control camera's near/far planes to properly cover object + _autoAdjustCamera = false; + ModelPreview.AdjustCamera(this, SkinnedModel.GetBox()); + } + if (!ScaleToFit) { if (_snapToOrigin) diff --git a/Source/Editor/Viewport/Previews/ModelPreview.cs b/Source/Editor/Viewport/Previews/ModelPreview.cs index ae0424da3..55f5a4592 100644 --- a/Source/Editor/Viewport/Previews/ModelPreview.cs +++ b/Source/Editor/Viewport/Previews/ModelPreview.cs @@ -18,7 +18,7 @@ namespace FlaxEditor.Viewport.Previews private ContextMenuButton _showBoundsButton, _showCurrentLODButton, _showNormalsButton, _showTangentsButton, _showBitangentsButton, _showFloorButton; private ContextMenu _previewLODsWidgetButtonMenu; private StaticModel _previewModel, _floorModel; - private bool _showBounds, _showCurrentLOD, _showNormals, _showTangents, _showBitangents, _showFloor; + private bool _showBounds, _showCurrentLOD, _showNormals, _showTangents, _showBitangents, _showFloor, _autoAdjustCamera = true; private MeshDataCache _meshDatas; /// @@ -221,8 +221,8 @@ namespace FlaxEditor.Viewport.Previews _showCurrentLODButton.IndexInParent = 2; _showCurrentLODButton.CloseMenuOnClick = false; - // Preview LODs mode widget - var PreviewLODsMode = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight); + // Preview LOD mode widget + var previewLODsMode = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight); _previewLODsWidgetButtonMenu = new ContextMenu(); _previewLODsWidgetButtonMenu.VisibleChanged += control => { @@ -248,14 +248,32 @@ namespace FlaxEditor.Viewport.Previews new ViewportWidgetButton("Preview LOD", SpriteHandle.Invalid, _previewLODsWidgetButtonMenu) { TooltipText = "Preview LOD properties", - Parent = PreviewLODsMode, + Parent = previewLODsMode, }; - PreviewLODsMode.Parent = this; + previewLODsMode.Parent = this; + } + } + + internal static void AdjustCamera(AssetPreview preview, BoundingBox box) + { + if (box.Size.MaxValue < preview.NearPlane) + { + // Very small object + preview.NearPlane = Mathf.Min(preview.NearPlane, box.Size.MaxValue * 0.5f + 0.01f); + preview.FarPlane *= 0.5f; + preview.MovementSpeed = 0.1f; } } private void OnBegin(RenderTask task, GPUContext context) { + if (_autoAdjustCamera && Model && Model.IsLoaded) + { + // Control camera's near/far planes to properly cover object + _autoAdjustCamera = false; + AdjustCamera(this, Model.GetBox()); + } + if (!ScaleToFit) { _previewModel.Scale = Float3.One; diff --git a/Source/Editor/Viewport/Previews/SkinnedModelPreview.cs b/Source/Editor/Viewport/Previews/SkinnedModelPreview.cs index 3048d0c78..d394190ce 100644 --- a/Source/Editor/Viewport/Previews/SkinnedModelPreview.cs +++ b/Source/Editor/Viewport/Previews/SkinnedModelPreview.cs @@ -51,8 +51,8 @@ namespace FlaxEditor.Viewport.Previews _showCurrentLODButton.IndexInParent = 2; _showCurrentLODButton.CloseMenuOnClick = false; - // PreviewLODS mode widget - var PreviewLODSMode = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight); + // Preview LOD mode widget + var previewLODMode = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight); _previewLODsWidgetButtonMenu = new ContextMenu(); _previewLODsWidgetButtonMenu.VisibleChanged += control => { @@ -78,9 +78,9 @@ namespace FlaxEditor.Viewport.Previews new ViewportWidgetButton("Preview LOD", SpriteHandle.Invalid, _previewLODsWidgetButtonMenu) { TooltipText = "Preview LOD properties", - Parent = PreviewLODSMode, + Parent = previewLODMode, }; - PreviewLODSMode.Parent = this; + previewLODMode.Parent = this; } }