// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. using FlaxEditor.GUI.ContextMenu; using FlaxEditor.GUI.Input; using FlaxEngine; using Object = FlaxEngine.Object; namespace FlaxEditor.Viewport.Previews { /// /// Model asset preview editor viewport. /// /// public class ModelPreview : AssetPreview { private ContextMenuButton _showBoundsButton; private StaticModel _previewModel; private bool _showBounds; /// /// Gets or sets the model asset to preview. /// public Model Model { get => _previewModel.Model; set => _previewModel.Model = value; } /// /// Gets the model actor used to preview selected asset. /// public StaticModel PreviewActor => _previewModel; /// /// Gets or sets a value indicating whether show animated model bounding box debug view. /// public bool ShowBounds { get => _showBounds; set { _showBounds = value; if (value) ShowDebugDraw = true; if (_showBoundsButton != null) _showBoundsButton.Checked = value; } } /// /// Gets or sets a value indicating whether scale the model to the normalized bounds. /// public bool ScaleToFit { get; set; } = true; /// /// Initializes a new instance of the class. /// /// if set to true use widgets. public ModelPreview(bool useWidgets) : base(useWidgets) { Task.Begin += OnBegin; // Setup preview scene _previewModel = new StaticModel(); // Link actors for rendering Task.AddCustomActor(_previewModel); if (useWidgets) { // Show Bounds _showBoundsButton = ViewWidgetShowMenu.AddButton("Bounds", () => ShowBounds = !ShowBounds); // Preview LOD { var previewLOD = ViewWidgetButtonMenu.AddButton("Preview LOD"); 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; } } } private void OnBegin(RenderTask task, GPUContext context) { if (!ScaleToFit) { _previewModel.Scale = Vector3.One; _previewModel.Position = Vector3.Zero; return; } // Update preview model scale to fit the preview var model = Model; if (model && model.IsLoaded) { float targetSize = 50.0f; BoundingBox box = model.GetBox(); float maxSize = Mathf.Max(0.001f, box.Size.MaxValue); float scale = targetSize / maxSize; _previewModel.Scale = new Vector3(scale); _previewModel.Position = box.Center * (-0.5f * scale) + new Vector3(0, -10, 0); } } /// protected override void OnDebugDraw(GPUContext context, ref RenderContext renderContext) { base.OnDebugDraw(context, ref renderContext); // Draw bounds if (_showBounds) { DebugDraw.DrawWireBox(_previewModel.Box, Color.Violet.RGBMultiplied(0.8f), 0, false); } } /// public override bool OnKeyDown(KeyboardKeys key) { switch (key) { case KeyboardKeys.F: // Pay respect.. ViewportCamera.SetArcBallView(_previewModel.Box); break; } return base.OnKeyDown(key); } /// public override void OnDestroy() { // Ensure to cleanup created actor objects Object.Destroy(ref _previewModel); base.OnDestroy(); } } }