Add support for UICanvas preview in Prefab Viewport

Fixes #157
This commit is contained in:
2021-02-05 21:11:35 +01:00
parent 3661b19d6c
commit 78e4ba2f17
2 changed files with 116 additions and 29 deletions
@@ -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));
}
}
/// <summary>
/// Initializes a new instance of the <see cref="PrefabPreview"/> class.
/// </summary>
+90 -7
View File
@@ -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<CanvasRenderer>();
_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
}
}