diff --git a/Source/Editor/Viewport/Previews/PrefabPreview.cs b/Source/Editor/Viewport/Previews/PrefabPreview.cs index aa04a41fd..066e98456 100644 --- a/Source/Editor/Viewport/Previews/PrefabPreview.cs +++ b/Source/Editor/Viewport/Previews/PrefabPreview.cs @@ -31,44 +31,34 @@ namespace FlaxEditor.Viewport.Previews if (_prefab == value) return; + // Unset and cleanup spawned instance if (_instance) { - // Unlink UI control - if (customControlLinked) - { - if (customControlLinked.Control?.Parent == this) - customControlLinked.Control.Parent = null; - customControlLinked = null; - } - - // Remove for preview - Task.RemoveCustomActor(_instance); - - // Delete - Object.Destroy(_instance); + var instance = _instance; + Instance = null; + Object.Destroy(instance); } _prefab = value; if (_prefab) { + // Load prefab _prefab.WaitForLoaded(); + // Spawn prefab var prevPreview = LoadingPreview; LoadingPreview = this; - - _instance = PrefabManager.SpawnPrefab(_prefab, null); - + var instance = PrefabManager.SpawnPrefab(_prefab, null); LoadingPreview = prevPreview; - - if (_instance == null) + if (instance == null) { _prefab = null; throw new FlaxException("Failed to spawn a prefab for the preview."); } - // Add to preview - Task.AddCustomActor(_instance); + // Set instance + Instance = instance; } } } @@ -94,7 +84,7 @@ namespace FlaxEditor.Viewport.Previews customControlLinked = null; } - // Remove for preview + // Remove for the preview Task.RemoveCustomActor(_instance); } @@ -102,12 +92,26 @@ namespace FlaxEditor.Viewport.Previews if (_instance) { - // Add to preview + // Add to the preview Task.AddCustomActor(_instance); + + // Link UI canvases to the preview + LinkCanvas(_instance); } } } + private void LinkCanvas(Actor actor) + { + if (actor is UICanvas uiCanvas) + uiCanvas.EditorOverride(Task, this); + var children = actor.ChildrenCount; + for (int i = 0; i < children; i++) + { + LinkCanvas(actor.GetChild(i)); + } + } + /// /// Initializes a new instance of the class. /// diff --git a/Source/Engine/UI/UICanvas.cs b/Source/Engine/UI/UICanvas.cs index e0b6425de..65956293b 100644 --- a/Source/Engine/UI/UICanvas.cs +++ b/Source/Engine/UI/UICanvas.cs @@ -1,5 +1,6 @@ // Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. +using System; using System.Globalization; using System.IO; using System.Text; @@ -279,16 +280,41 @@ namespace FlaxEngine else if (_renderMode == CanvasRenderMode.CameraSpace) { Matrix tmp1, tmp2; + Vector3 viewPos, viewUp, viewForward, pos; + Quaternion viewRot; // Use default camera is not specified var camera = RenderCamera ?? Camera.MainCamera; +#if FLAX_EDITOR + if (_editorTask) + { + // Use editor viewport task to override Camera Space placement + var view = _editorTask.View; + var frustum = view.Frustum; + if (!frustum.IsOrthographic) + _guiRoot.Size = new Vector2(frustum.GetWidthAtDepth(Distance), frustum.GetHeightAtDepth(Distance)); + else + _guiRoot.Size = _editorTask.Viewport.Size; + Matrix.Translation(_guiRoot.Width / -2.0f, _guiRoot.Height / -2.0f, 0, out world); + Matrix.RotationYawPitchRoll(Mathf.Pi, Mathf.Pi, 0, out tmp2); + Matrix.Multiply(ref world, ref tmp2, out tmp1); + viewPos = view.Position; + viewRot = view.Direction != Vector3.Up ? Quaternion.LookRotation(view.Direction, Vector3.Up) : Quaternion.LookRotation(view.Direction, Vector3.Right); + viewUp = Vector3.Up * viewRot; + viewForward = view.Direction; + pos = view.Position + view.Direction * Distance; + Matrix.Billboard(ref pos, ref viewPos, ref viewUp, ref viewForward, out tmp2); + Matrix.Multiply(ref tmp1, ref tmp2, out world); + return; + } +#endif + // Adjust GUI size to the viewport size at the given distance form the camera var viewport = camera.Viewport; if (camera.UsePerspective) { - Matrix tmp3; - camera.GetMatrices(out tmp1, out tmp3, ref viewport); + camera.GetMatrices(out tmp1, out var tmp3, ref viewport); Matrix.Multiply(ref tmp1, ref tmp3, out tmp2); var frustum = new BoundingFrustum(tmp2); _guiRoot.Size = new Vector2(frustum.GetWidthAtDepth(Distance), frustum.GetHeightAtDepth(Distance)); @@ -304,11 +330,11 @@ namespace FlaxEngine Matrix.Multiply(ref world, ref tmp2, out tmp1); // In front of the camera - var viewPos = camera.Position; - var viewRot = camera.Orientation; - var viewUp = Vector3.Up * viewRot; - var viewForward = Vector3.Forward * viewRot; - var pos = viewPos + viewForward * Distance; + viewPos = camera.Position; + viewRot = camera.Orientation; + viewUp = Vector3.Up * viewRot; + viewForward = Vector3.Forward * viewRot; + pos = viewPos + viewForward * Distance; Matrix.Billboard(ref pos, ref viewPos, ref viewUp, ref viewForward, out tmp2); Matrix.Multiply(ref tmp1, ref tmp2, out world); @@ -334,11 +360,18 @@ namespace FlaxEngine _guiRoot.Offsets = Margin.Zero; if (_renderer) { +#if FLAX_EDITOR + _editorTask?.CustomPostFx.Remove(_renderer); +#endif SceneRenderTask.GlobalCustomPostFx.Remove(_renderer); _renderer.Canvas = null; Destroy(_renderer); _renderer = null; } +#if FLAX_EDITOR + if (_editorRoot) + _guiRoot.Parent = _editorRoot; +#endif break; } case CanvasRenderMode.CameraSpace: @@ -346,12 +379,31 @@ namespace FlaxEngine { // Render canvas manually _guiRoot.AnchorPreset = AnchorPresets.TopLeft; +#if FLAX_EDITOR + if (_editorRoot != null && _guiRoot != null) + _guiRoot.Parent = null; +#endif if (_renderer == null) { _renderer = New(); _renderer.Canvas = this; if (IsActiveInHierarchy && Scene) + { +#if FLAX_EDITOR + if (_editorTask != null) + { + _editorTask.CustomPostFx.Add(_renderer); + break; + } +#endif SceneRenderTask.GlobalCustomPostFx.Add(_renderer); + } +#if FLAX_EDITOR + else if (_editorTask != null && IsActiveInHierarchy) + { + _editorTask.CustomPostFx.Add(_renderer); + } +#endif } break; } @@ -490,10 +542,21 @@ namespace FlaxEngine internal void OnEnable() { +#if FLAX_EDITOR + _guiRoot.Parent = _editorRoot ?? RootControl.CanvasRoot; +#else _guiRoot.Parent = RootControl.CanvasRoot; +#endif if (_renderer) { +#if FLAX_EDITOR + if (_editorTask != null) + { + _editorTask.CustomPostFx.Add(_renderer); + return; + } +#endif SceneRenderTask.GlobalCustomPostFx.Add(_renderer); } } @@ -518,5 +581,25 @@ namespace FlaxEngine _renderer = null; } } + +#if FLAX_EDITOR + private SceneRenderTask _editorTask; + private ContainerControl _editorRoot; + + internal void EditorOverride(SceneRenderTask task, ContainerControl root) + { + if (_editorTask != null && _renderer != null) + _editorTask.CustomPostFx.Remove(_renderer); + if (_editorRoot != null && _guiRoot != null) + _guiRoot.Parent = null; + + _editorTask = task; + _editorRoot = root; + Setup(); + + if (RenderMode == CanvasRenderMode.ScreenSpace && _editorRoot != null && _guiRoot != null) + _guiRoot.Parent = _editorRoot; + } +#endif } }