using System; using System.Collections.Generic; using System.Linq; using UnityEditor; using UnityEngine; using UnityObject = UnityEngine.Object; using HostView = UnityEngine.ScriptableObject; using View = UnityEngine.ScriptableObject; using ContainerWindow = UnityEngine.ScriptableObject; namespace FullscreenEditor { /// Manages the WindowContainers, Views and Windows that will be fullscreened. public abstract partial class FullscreenContainer : ScriptableObject { [SerializeField] private int m_ourIndex = -1; [SerializeField] private bool m_old = false; public Action didPresent = () => Logger.Debug("'Did Present' called"); private static int CurrentIndex { get { return EditorPrefs.GetInt("FullscreenIdx", 0); } set { EditorPrefs.SetInt("FullscreenIdx", value); } } /// The true view pyramid of this fullscreen container. public ViewPyramid ActualViewPyramid { get { return new ViewPyramid(m_dst.Container); } } /// The view that is currently fullscreened. public View FullscreenedView { get { return ActualViewPyramid.View; } } /// Position and size of the WindowContainer created for this fullscreen. public Rect Rect { get { return m_dst.Container ? m_dst.Container.GetPropertyValue("position") : new Rect(); } set { if (m_dst.Container) { m_dst.Container.InvokeMethod("SetMinMaxSizes", value.size, value.size); m_dst.Container.SetPropertyValue("position", value); Logger.Debug("Set {0} rect to {1}", this.name, value); } else Logger.Debug("No container on {0}, rect will not be set", this.name); } } private void Update() { if (!m_dst.Container) Close(); // Forcefully closed } protected virtual void OnEnable() { if (m_ourIndex == -1) { m_ourIndex = CurrentIndex++; name = string.Format("Fullscreen #{0}", m_ourIndex); hideFlags = HideFlags.HideAndDontSave; } #if UNITY_2018_1_OR_NEWER EditorApplication.wantsToQuit += WantsToQuit; #endif if (m_old && !m_dst.Container) { Logger.Warning("{0} wasn't properly closed", name); // After 1 frame to prevent OnDisable and OnDestroy from being called before this methods returns After.Frames(1, () => DestroyImmediate(this, true)); } m_old = true; EditorApplication.update += Update; } protected virtual void OnDisable() { EditorApplication.update -= Update; #if UNITY_2018_1_OR_NEWER EditorApplication.wantsToQuit += WantsToQuit; #endif } protected virtual void OnDestroy() { Logger.Debug(name + " destroyed"); if (m_dst.Container) { m_dst.Container.InvokeMethod("Close"); Logger.Warning("Destroying {0} which has open containers, always close the fullscreen before destroying it", name); } FullscreenCallbacks.afterFullscreenClose(this); } /// Destroy this container and exit fullscreen. public virtual void Close() { FullscreenCallbacks.beforeFullscreenClose(this); if (!m_dst.Window && m_dst.Container) Logger.Error("Placeholder window has been closed, Fullscreen Editor won't be able to restore window position"); if (m_dst.Container) // Container may have been destroyed by Alt+F4 m_dst.Container.InvokeMethod("Close"); // Closes the container, all its views and the windows DestroyImmediate(this, true); } /// Focus the view of this fullscreen. public virtual void Focus() { if (FullscreenedView && FullscreenedView.IsOfType(Types.GUIView)) FullscreenUtility.FocusView(FullscreenedView); } /// Gets wheter the view of this fullscreen is focused or not. public virtual bool IsFocused() { return FullscreenUtility.IsViewFocused(FullscreenedView); } #if UNITY_2018_1_OR_NEWER private bool WantsToQuit() { // Close the fullscreen before closing the editor, this way we have a better // ensurance that the fullscreen container will not be saved to the layout. // ContainerWindow.m_DontSaveToLayout is set to true, so in Unity < 2018.1 the // fullscreen will behave the same as if it was closed by Alt+F4. Close(); return true; } #endif } }