Close and restore Prefab windows during scripting reload

This commit is contained in:
2024-04-22 23:58:27 +03:00
committed by Ari Vuollet
parent 989a5441f3
commit 47b95f5650
3 changed files with 138 additions and 42 deletions

View File

@@ -5,10 +5,12 @@ using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Xml; using System.Xml;
using FlaxEditor.Content; using FlaxEditor.Content;
using FlaxEditor.GUI.Dialogs; using FlaxEditor.GUI.Dialogs;
using FlaxEditor.GUI.Docking;
using FlaxEditor.Windows; using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets; using FlaxEditor.Windows.Assets;
using FlaxEditor.Windows.Profiler; using FlaxEditor.Windows.Profiler;
@@ -39,6 +41,7 @@ namespace FlaxEditor.Modules
public DockState DockState; public DockState DockState;
public DockPanel DockedTo; public DockPanel DockedTo;
public int DockedTabIndex;
public float? SplitterValue = null; public float? SplitterValue = null;
public bool SelectOnShow = false; public bool SelectOnShow = false;
@@ -48,6 +51,9 @@ namespace FlaxEditor.Modules
public Float2 FloatSize; public Float2 FloatSize;
public Float2 FloatPosition; public Float2 FloatPosition;
public AssetItem Item;
public AssetItem Item2;
// Constructor, to allow for default values // Constructor, to allow for default values
public WindowRestoreData() public WindowRestoreData()
{ {
@@ -807,6 +813,56 @@ namespace FlaxEditor.Modules
Editor.StateMachine.StateChanged += OnEditorStateChanged; Editor.StateMachine.StateChanged += OnEditorStateChanged;
} }
internal void AddToRestore(PrefabWindow win)
{
var type = win.GetType();
var winData = new WindowRestoreData();
var panel = win.ParentDockPanel;
// Ensure that this window is only selected following recompilation
// if it was the active tab in its dock panel. Otherwise, there is a
// risk of interrupting the user's workflow by potentially selecting
// background tabs.
var window = win.RootWindow?.Window;
winData.SelectOnShow = panel.SelectedTab == win;
winData.DockedTabIndex = 0;
if (panel is FloatWindowDockPanel && window != null && panel.TabsCount == 1)
{
winData.DockState = DockState.Float;
winData.FloatPosition = window.Position;
winData.FloatSize = window.ClientSize;
winData.Maximize = window.IsMaximized;
winData.Minimize = window.IsMinimized;
winData.DockedTo = panel;
}
else
{
for (int i = 0; i < panel.Tabs.Count; i++)
{
if (panel.Tabs[i] == win)
{
winData.DockedTabIndex = i;
break;
}
}
if (panel.TabsCount > 1)
{
winData.DockState = DockState.DockFill;
winData.DockedTo = panel;
}
else
{
winData.DockState = panel.TryGetDockState(out var splitterValue);
winData.DockedTo = panel.ParentDockPanel;
winData.SplitterValue = splitterValue;
}
}
winData.AssemblyName = type.Assembly.GetName().Name;
winData.TypeName = type.FullName;
winData.Item = win.Item;
_restoreWindows.Add(winData);
}
internal void AddToRestore(CustomEditorWindow win) internal void AddToRestore(CustomEditorWindow win)
{ {
var type = win.GetType(); var type = win.GetType();
@@ -839,7 +895,8 @@ namespace FlaxEditor.Modules
{ {
winData.DockState = DockState.DockFill; winData.DockState = DockState.DockFill;
winData.DockedTo = panel; winData.DockedTo = panel;
}else }
else
{ {
winData.DockState = panel.TryGetDockState(out var splitterValue); winData.DockState = panel.TryGetDockState(out var splitterValue);
winData.DockedTo = panel.ParentDockPanel; winData.DockedTo = panel.ParentDockPanel;
@@ -853,36 +910,89 @@ namespace FlaxEditor.Modules
private void OnScriptsReloadEnd() private void OnScriptsReloadEnd()
{ {
for (int i = 0; i < _restoreWindows.Count; i++) // Go in reverse order to create floating Prefab windows first before docked windows
for (int i = _restoreWindows.Count - 1; i >= 0; i--)
{ {
var winData = _restoreWindows[i]; var winData = _restoreWindows[i];
try try
{ {
var assembly = Utils.GetAssemblyByName(winData.AssemblyName); var assembly = Utils.GetAssemblyByName(winData.AssemblyName);
if (assembly != null) if (assembly == null)
continue;
var type = assembly.GetType(winData.TypeName);
if (type == null)
continue;
if (type == typeof(PrefabWindow))
{ {
var type = assembly.GetType(winData.TypeName); var win = new PrefabWindow(Editor.Instance, winData.Item);
if (type != null) win.Show(winData.DockState, winData.DockState != DockState.Float ? winData.DockedTo : null, winData.SelectOnShow, winData.SplitterValue);
if (winData.DockState == DockState.Float)
{ {
var win = (CustomEditorWindow)Activator.CreateInstance(type); var window = win.RootWindow.Window;
win.Show(winData.DockState, winData.DockedTo, winData.SelectOnShow, winData.SplitterValue); window.Position = winData.FloatPosition;
if (winData.DockState == DockState.Float) if (winData.Maximize)
{ {
var window = win.Window.RootWindow.Window; window.Maximize();
window.Position = winData.FloatPosition; }
if (winData.Maximize) else if (winData.Minimize)
{ {
window.Maximize(); window.Minimize();
} }
else if (winData.Minimize) else
{ {
window.Minimize(); window.ClientSize = winData.FloatSize;
} }
else
{ // Update panel reference in other windows docked to this panel
window.ClientSize = winData.FloatSize; foreach (ref var otherData in CollectionsMarshal.AsSpan(_restoreWindows))
} {
if (otherData.DockedTo == winData.DockedTo)
otherData.DockedTo = win.ParentDockPanel;
}
}
var panel = win.ParentDockPanel;
int currentTabIndex = 0;
for (int pi = 0; pi < panel.TabsCount; pi++)
{
if (panel.Tabs[pi] == win)
{
currentTabIndex = pi;
break;
}
}
while (currentTabIndex > winData.DockedTabIndex)
{
win.ParentDockPanel.MoveTabLeft(currentTabIndex);
currentTabIndex--;
}
while (currentTabIndex < winData.DockedTabIndex)
{
win.ParentDockPanel.MoveTabRight(currentTabIndex);
currentTabIndex++;
}
}
else
{
var win = (CustomEditorWindow)Activator.CreateInstance(type);
win.Show(winData.DockState, winData.DockedTo, winData.SelectOnShow, winData.SplitterValue);
if (winData.DockState == DockState.Float)
{
var window = win.Window.RootWindow.Window;
window.Position = winData.FloatPosition;
if (winData.Maximize)
{
window.Maximize();
}
else if (winData.Minimize)
{
window.Minimize();
}
else
{
window.ClientSize = winData.FloatSize;
} }
} }
} }

View File

@@ -194,7 +194,6 @@ namespace FlaxEditor.Windows.Assets
Editor.Prefabs.PrefabApplied += OnPrefabApplied; Editor.Prefabs.PrefabApplied += OnPrefabApplied;
ScriptsBuilder.ScriptsReloadBegin += OnScriptsReloadBegin; ScriptsBuilder.ScriptsReloadBegin += OnScriptsReloadBegin;
ScriptsBuilder.ScriptsReloadEnd += OnScriptsReloadEnd;
// Setup input actions // Setup input actions
InputActions.Add(options => options.Undo, () => InputActions.Add(options => options.Undo, () =>
@@ -311,24 +310,18 @@ namespace FlaxEditor.Windows.Assets
} }
} }
if (!IsHidden)
{
Editor.Instance.Windows.AddToRestore(this);
}
// Cleanup // Cleanup
Deselect(); Deselect();
Graph.MainActor = null; Graph.MainActor = null;
_viewport.Prefab = null; _viewport.Prefab = null;
_undo?.Clear(); // TODO: maybe don't clear undo? _undo?.Clear(); // TODO: maybe don't clear undo?
}
private void OnScriptsReloadEnd() Close();
{
_isScriptsReloading = false;
if (_asset == null || !_asset.IsLoaded)
return;
// Restore
OnPrefabOpened();
_undo.Clear();
ClearEditedFlag();
} }
private void OnUndoEvent(IUndoAction action) private void OnUndoEvent(IUndoAction action)
@@ -547,7 +540,6 @@ namespace FlaxEditor.Windows.Assets
{ {
Editor.Prefabs.PrefabApplied -= OnPrefabApplied; Editor.Prefabs.PrefabApplied -= OnPrefabApplied;
ScriptsBuilder.ScriptsReloadBegin -= OnScriptsReloadBegin; ScriptsBuilder.ScriptsReloadBegin -= OnScriptsReloadBegin;
ScriptsBuilder.ScriptsReloadEnd -= OnScriptsReloadEnd;
_undo.Dispose(); _undo.Dispose();
Graph.Dispose(); Graph.Dispose();

View File

@@ -1146,12 +1146,6 @@ namespace FlaxEngine.Interop
MethodInfo clearCacheMethod = TypeDescriptionProviderType?.Assembly.GetType("System.ComponentModel.ReflectionCachesUpdateHandler")?.GetMethod("ClearCache"); MethodInfo clearCacheMethod = TypeDescriptionProviderType?.Assembly.GetType("System.ComponentModel.ReflectionCachesUpdateHandler")?.GetMethod("ClearCache");
if (clearCacheMethod != null) if (clearCacheMethod != null)
clearCacheMethod.Invoke(null, new object[] { null }); clearCacheMethod.Invoke(null, new object[] { null });
else
{
MethodInfo beforeUpdateMethod = TypeDescriptionProviderType?.Assembly.GetType("System.ComponentModel.ReflectionCachesUpdateHandler")?.GetMethod("BeforeUpdate");
if (beforeUpdateMethod != null)
beforeUpdateMethod.Invoke(null, new object[] { null });
}
Type TypeDescriptorType = typeof(System.ComponentModel.TypeDescriptor); Type TypeDescriptorType = typeof(System.ComponentModel.TypeDescriptor);