You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
234 lines
8.7 KiB
234 lines
8.7 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using ContainerWindow = UnityEngine.ScriptableObject;
|
|
using HostView = UnityEngine.ScriptableObject;
|
|
using View = UnityEngine.ScriptableObject;
|
|
|
|
namespace FullscreenEditor {
|
|
public class FullscreenWindow : FullscreenContainer {
|
|
|
|
[SerializeField] private RectOffset m_rectOffset;
|
|
[SerializeField] private RectOffset m_toolbarOffset;
|
|
[SerializeField] private bool m_createdByFullscreenOnPlay;
|
|
|
|
public RectOffset ClipOffset {
|
|
get { return m_rectOffset; }
|
|
set {
|
|
if(m_dst.View) {
|
|
m_rectOffset = value;
|
|
m_dst.View.InvokeMethod("SetPosition", value.Add(new Rect(Vector2.zero, Rect.size)));
|
|
}
|
|
}
|
|
}
|
|
|
|
internal bool CreatedByFullscreenOnPlay {
|
|
get { return m_createdByFullscreenOnPlay; }
|
|
set { m_createdByFullscreenOnPlay = value; }
|
|
}
|
|
|
|
public bool HasToolbarOffset { get { return ToolbarOffset != null; } }
|
|
|
|
public virtual RectOffset ToolbarOffset {
|
|
get {
|
|
if(m_toolbarOffset == null)
|
|
m_toolbarOffset = new RectOffset(0, 0, (int)FullscreenUtility.GetToolbarHeight(), 0);
|
|
return m_toolbarOffset;
|
|
}
|
|
}
|
|
|
|
private void SwapWindows(EditorWindow a, EditorWindow b) {
|
|
var parentA = a.GetFieldValue<View>("m_Parent");
|
|
var parentB = b.GetFieldValue<View>("m_Parent");
|
|
|
|
var containerA = parentA.GetPropertyValue<ContainerWindow>("window");
|
|
var containerB = parentB.GetPropertyValue<ContainerWindow>("window");
|
|
|
|
var selectedPaneA = parentA.GetPropertyValue<EditorWindow>("actualView");
|
|
var selectedPaneB = parentB.GetPropertyValue<EditorWindow>("actualView");
|
|
|
|
SetFreezeContainer(containerA, true);
|
|
SetFreezeContainer(containerB, true);
|
|
|
|
Logger.Debug("Swapping windows {0} and {1} @ {2} and {3}", a, b, parentA, parentB);
|
|
|
|
parentA.SetPropertyValue("actualView", b);
|
|
parentB.SetPropertyValue("actualView", a);
|
|
|
|
ReplaceDockAreaPane(parentA, a, b);
|
|
ReplaceDockAreaPane(parentB, b, a);
|
|
|
|
a.InvokeMethod("MakeParentsSettingsMatchMe");
|
|
b.InvokeMethod("MakeParentsSettingsMatchMe");
|
|
|
|
if(selectedPaneA != a)
|
|
parentA.SetPropertyValue("actualView", selectedPaneA);
|
|
if(selectedPaneB != b)
|
|
parentB.SetPropertyValue("actualView", selectedPaneB);
|
|
|
|
SetFreezeContainer(containerA, false);
|
|
SetFreezeContainer(containerB, false);
|
|
}
|
|
|
|
protected void ReplaceDockAreaPane(View dockArea, EditorWindow originalPane, EditorWindow newPane) {
|
|
if(dockArea.HasField("m_Panes")) {
|
|
var dockedPanes = dockArea.GetFieldValue<List<EditorWindow>>("m_Panes");
|
|
var dockIndex = dockedPanes.IndexOf(originalPane);
|
|
dockedPanes[dockIndex] = newPane;
|
|
}
|
|
}
|
|
|
|
public void SetToolbarStatus(bool toolbarVisible) {
|
|
if(!HasToolbarOffset)
|
|
return;
|
|
|
|
if(FullscreenPreferences.UseGlobalToolbarHiding)
|
|
return;
|
|
|
|
ClipOffset = toolbarVisible ? new RectOffset() : ToolbarOffset;
|
|
}
|
|
|
|
public override void Focus() {
|
|
var window = ActualViewPyramid.Window;
|
|
|
|
if(window)
|
|
window.Focus();
|
|
else
|
|
base.Focus();
|
|
}
|
|
|
|
public override bool IsFocused() {
|
|
return EditorWindow.focusedWindow && EditorWindow.focusedWindow == ActualViewPyramid.Window;
|
|
}
|
|
|
|
protected override void AfterOpening() {
|
|
base.AfterOpening();
|
|
|
|
Focus();
|
|
|
|
if(m_src.Window)
|
|
m_dst.Window.titleContent = m_src.Window.titleContent; // Copy the title of the window to the placeholder
|
|
|
|
SetToolbarStatus(FullscreenPreferences.ToolbarVisible); // Hide/show the toolbar
|
|
// macOS doesn't like fast things, so we'll wait a bit and do it again
|
|
// Looks like Linux does not like it too
|
|
After.Milliseconds(100d, () => SetToolbarStatus(FullscreenPreferences.ToolbarVisible));
|
|
|
|
var notificationWindow = ActualViewPyramid.Window;
|
|
|
|
After.Milliseconds(50d, () => {
|
|
if(!notificationWindow) // Might have been closed
|
|
return;
|
|
|
|
var menuItemPath = string.Empty;
|
|
if(notificationWindow.IsOfType(Types.GameView)) {
|
|
menuItemPath = Fullscreen
|
|
.GetAllFullscreen()
|
|
.Where(fs => fs.ActualViewPyramid.Window && fs.ActualViewPyramid.Window.IsOfType(Types.GameView))
|
|
.Count() > 1 ?
|
|
Shortcut.MOSAIC_PATH :
|
|
Shortcut.GAME_VIEW_PATH;
|
|
} else if(notificationWindow is SceneView)
|
|
menuItemPath = Shortcut.SCENE_VIEW_PATH;
|
|
else
|
|
menuItemPath = Shortcut.CURRENT_VIEW_PATH;
|
|
|
|
FullscreenUtility.ShowFullscreenExitNotification(notificationWindow, menuItemPath);
|
|
});
|
|
|
|
}
|
|
|
|
protected override void OnEnable() {
|
|
base.OnEnable();
|
|
FullscreenPreferences.ToolbarVisible.OnValueSaved += SetToolbarStatus;
|
|
}
|
|
|
|
protected override void OnDisable() {
|
|
base.OnDisable();
|
|
FullscreenPreferences.ToolbarVisible.OnValueSaved -= SetToolbarStatus;
|
|
}
|
|
|
|
internal void OpenWindow<T>(Rect rect, T window = null) where T : EditorWindow {
|
|
OpenWindow(rect, typeof(T), window);
|
|
}
|
|
|
|
internal void OpenWindow(Rect rect, Type type, EditorWindow window = null, bool disposableWindow = false) {
|
|
if(type == null)
|
|
throw new ArgumentNullException("type");
|
|
|
|
if(!type.IsOfType(typeof(EditorWindow)))
|
|
throw new ArgumentException("Type must be inherited from UnityEditor.EditorWindow", "type");
|
|
|
|
if(window is PlaceholderWindow) {
|
|
FullscreenUtility.ShowFullscreenNotification(window, "Wanna fullscreen the placeholder?\nSorry, not possible");
|
|
Logger.Debug("Tried to fullscreen a placeholder window");
|
|
return;
|
|
}
|
|
|
|
if(Fullscreen.GetFullscreenFromView(window)) {
|
|
FullscreenUtility.ShowFullscreenNotification(window, "You can't fullscreen a window already in fullscreen");
|
|
Logger.Debug("Tried to fullscreen a view already in fullscreen");
|
|
return;
|
|
}
|
|
|
|
if(window && window.HasProperty("isFullscreen") && window.GetPropertyValue<bool>("isFullscreen")) {
|
|
Logger.Debug("Tried to fullscreen a view already using Unity's built-in fullscreen");
|
|
window.ShowNotification(new GUIContent("This is a built-in fullscreen and not a Fullscreen Editor instance. Use Ctrl+Shift+F7 or Alt-F4 to close it."));
|
|
return;
|
|
}
|
|
|
|
BeforeOpening();
|
|
|
|
if(window)
|
|
m_src = new ViewPyramid(window);
|
|
|
|
var childWindow = window ?
|
|
(EditorWindow)CreateInstance<PlaceholderWindow>() :
|
|
(EditorWindow)CreateInstance(type); // Instantiate a new window for this fullscreen
|
|
|
|
m_dst = CreateFullscreenViewPyramid(rect, childWindow);
|
|
|
|
if(window) // We can't swap the src window if we didn't create a placeholder window
|
|
SwapWindows(m_src.Window, m_dst.Window);
|
|
|
|
Rect = rect;
|
|
|
|
if(disposableWindow && childWindow is PlaceholderWindow) {
|
|
childWindow.Close(); // Close the pyramid we created because disposable views are not restore later
|
|
m_dst.Window = m_src.Window;
|
|
}
|
|
|
|
AfterOpening();
|
|
}
|
|
|
|
internal bool IsPlaceholderVisible() {
|
|
if(!(m_dst.Window is PlaceholderWindow))
|
|
return false;
|
|
|
|
var pyramid = new ViewPyramid(m_dst.Window);
|
|
|
|
if(!pyramid.View || !pyramid.View.IsOfType(Types.HostView))
|
|
return false;
|
|
|
|
var actualView = pyramid.View.GetPropertyValue<View>("actualView");
|
|
|
|
return actualView == m_dst.Window;
|
|
}
|
|
|
|
public override void Close() {
|
|
|
|
var shouldRefocus = IsFocused() && IsPlaceholderVisible();
|
|
|
|
if(m_src.Window && m_dst.Window)
|
|
SwapWindows(m_src.Window, m_dst.Window); // Swap back the source window
|
|
|
|
base.Close();
|
|
|
|
if(shouldRefocus && m_src.Window)
|
|
m_src.Window.Focus();
|
|
}
|
|
|
|
}
|
|
}
|
|
|