using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace FullscreenEditor {
/// The window that will be shown in the place of the original view when creating a fullscreen container.
public class PlaceholderWindow : EditorWindow {
private const float PREVIEW_FRAMERATE = 24f;
private static class Styles {
public static readonly GUIStyle textStyle = new GUIStyle("BoldLabel");
public static readonly GUIStyle backgroundShadow = new GUIStyle("InnerShadowBg");
public static readonly GUIStyle buttonStyle = new GUIStyle("LargeButton");
static Styles() {
textStyle.wordWrap = true;
textStyle.alignment = TextAnchor.MiddleCenter;
}
}
[SerializeField] private Vector2 m_scroll;
[SerializeField] private FullscreenContainer m_fullscreenContainer;
[SerializeField] private bool m_containerForcefullyClosed;
private double m_nextUpdate;
private RenderTexture m_previewRT;
private FullscreenContainer FullscreenContainer {
get {
if (m_containerForcefullyClosed)
return null;
if (!m_fullscreenContainer)
m_fullscreenContainer = FullscreenUtility.GetRef(name);
if (!m_fullscreenContainer)
m_containerForcefullyClosed = true;
return m_fullscreenContainer;
}
set { m_fullscreenContainer = value; }
}
private bool PreviewSupported {
get {
return FullscreenContainer &&
!FullscreenContainer.Rect.Overlaps(position) &&
FullscreenContainer.m_dst.View &&
FullscreenContainer.m_src.Window &&
FullscreenContainer.m_dst.View.HasMethod("GrabPixels");
}
}
private void Update() {
if (EditorApplication.timeSinceStartup < m_nextUpdate)
return;
m_nextUpdate = EditorApplication.timeSinceStartup + (1f / PREVIEW_FRAMERATE);
RenderTexture.ReleaseTemporary(m_previewRT);
m_previewRT = null;
if (!PreviewSupported || m_containerForcefullyClosed)
return;
var view = FullscreenContainer ? FullscreenContainer.m_dst.View : null;
var width = (int)FullscreenContainer.Rect.width;
var height = (int)FullscreenContainer.Rect.height;
if (!view || width < 10 || height < 10)
return;
m_previewRT = RenderTexture.GetTemporary(width, height, 0);
view.InvokeMethod("GrabPixels", m_previewRT, new Rect(0f, 0f, width, height));
Repaint();
}
private void OnDisable() {
RenderTexture.ReleaseTemporary(m_previewRT);
}
private void OnGUI() {
using(var scrollScope = new EditorGUILayout.ScrollViewScope(m_scroll))
using(var mainScope = new EditorGUILayout.VerticalScope(Styles.backgroundShadow)) {
m_scroll = scrollScope.scrollPosition;
using(new GUIColor(Color.white, 0.1f))
if (m_previewRT) {
var rtRect = SystemInfo.graphicsUVStartsAtTop ?
Rect.MinMaxRect(0f, 1f, 1f, 0f) : // Direct3D like
Rect.MinMaxRect(0f, 0f, 1f, 1f); // OpenGL like
GUI.DrawTextureWithTexCoords(mainScope.rect, m_previewRT, rtRect);
}
using(new GUIColor(Styles.textStyle.normal.textColor * 0.05f))
GUI.DrawTexture(mainScope.rect, FullscreenUtility.FullscreenIcon, ScaleMode.ScaleAndCrop);
GUILayout.FlexibleSpace();
using(new EditorGUILayout.HorizontalScope()) {
GUILayout.FlexibleSpace();
using(new GUIContentColor(Styles.textStyle.normal.textColor))
GUILayout.Label(FullscreenUtility.FullscreenIcon, Styles.textStyle);
using(new EditorGUILayout.VerticalScope()) {
if (FullscreenContainer && FullscreenContainer.ActualViewPyramid.Container) {
GUILayout.Label("The view that lives here is in fullscreen mode", Styles.textStyle);
GUILayout.Label("Don't close this placeholder", Styles.textStyle);
} else {
GUILayout.Label("The view that lived here was forcefully closed while in fullscreen, restore is not available", Styles.textStyle);
GUILayout.Label("Consider using the shortcuts to exit fullscreen", Styles.textStyle);
GUILayout.Label("You may close this placeholder", Styles.textStyle);
}
}
GUILayout.FlexibleSpace();
}
using(new EditorGUILayout.HorizontalScope()) {
GUILayout.FlexibleSpace();
if (FullscreenContainer && FullscreenContainer.ActualViewPyramid.Container) {
if (GUILayout.Button("Restore View", Styles.buttonStyle))
FullscreenContainer.Close();
} else if (GUILayout.Button("Close Placeholder", Styles.buttonStyle))
Close();
GUILayout.FlexibleSpace();
}
GUILayout.FlexibleSpace();
// This GUI may be called after "this" has been destroyed, that causes a NullReference for the "name" getter
// Not sure why this happens tho
EditorGUILayout.LabelField(SafeObjToString(() => name));
EditorGUILayout.Space();
if (FullscreenUtility.DebugModeEnabled) {
EditorGUILayout.LabelField("Forcefully Closed", SafeObjToString(() => m_containerForcefullyClosed));
EditorGUILayout.LabelField("Container", SafeObjToString(() => FullscreenContainer));
EditorGUILayout.LabelField("Rect", SafeObjToString(() => FullscreenContainer.Rect));
EditorGUILayout.LabelField("SRC Window", SafeObjToString(() => FullscreenContainer.m_src.Window));
EditorGUILayout.LabelField("SRC View", SafeObjToString(() => FullscreenContainer.m_src.View));
EditorGUILayout.LabelField("SRC Container", SafeObjToString(() => FullscreenContainer.m_src.Container));
EditorGUILayout.LabelField("DST Window", SafeObjToString(() => FullscreenContainer.m_dst.Window));
EditorGUILayout.LabelField("DST View", SafeObjToString(() => FullscreenContainer.m_dst.View));
EditorGUILayout.LabelField("DST Container", SafeObjToString(() => FullscreenContainer.m_dst.Container));
EditorGUILayout.Space();
}
}
}
private string SafeObjToString(Func obj) {
try {
var i = obj();
return i == null? "null": i.ToString();
} catch {
return "invalid";
}
}
}
}