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.
232 lines
8.6 KiB
232 lines
8.6 KiB
using System; |
|
using System.Reflection; |
|
|
|
using UnityEditor; |
|
using UnityEngine; |
|
|
|
namespace Unity.PlasticSCM.Editor.UI |
|
{ |
|
internal static class RunModal |
|
{ |
|
static RunModal() |
|
{ |
|
InitializeInfo(); |
|
} |
|
|
|
internal static bool IsAvailable() |
|
{ |
|
return mShowWithModeMethod != null |
|
&& mCreateSavedGUIState != null |
|
&& mApplyAndForgetMethod != null |
|
&& mParentField != null |
|
&& mParentWindowProp != null |
|
&& mMakeModalMethod != null; |
|
} |
|
|
|
internal static void Dialog(EditorWindow window) |
|
{ |
|
ShowAsUtility(window); |
|
|
|
object savedGUIState = CreateSavedGUIState(); |
|
PushDispatcherContext(window); |
|
|
|
MakeModal(window); |
|
|
|
PopDispatcherContext(window); |
|
ApplySavedGUIState(savedGUIState); |
|
} |
|
|
|
static void MakeModal(EditorWindow window) |
|
{ |
|
// MakeModal(m_Parent.window); |
|
var hostView = mParentField.GetValue(window); |
|
var parentWindow = mParentWindowProp.GetValue(hostView, null); |
|
|
|
mMakeModalMethod.Invoke( |
|
mMakeModalMethod.IsStatic ? null : window, |
|
new object[] { parentWindow }); |
|
} |
|
|
|
static void ShowAsUtility(EditorWindow window) |
|
{ |
|
// ShowWithMode(ShowMode.Utility); |
|
mShowWithModeMethod.Invoke(window, new object[] { 2 }); |
|
} |
|
|
|
static object CreateSavedGUIState() |
|
{ |
|
// SavedGUIState guiState = SavedGUIState.Create(); |
|
return mCreateSavedGUIState.Invoke(null, null); |
|
} |
|
|
|
static void ApplySavedGUIState(object savedGUIState) |
|
{ |
|
// guiState.ApplyAndForget(); |
|
mApplyAndForgetMethod.Invoke(savedGUIState, null); |
|
} |
|
|
|
static void PopDispatcherContext(EditorWindow window) |
|
{ |
|
#if UNITY_2020_1_OR_NEWER |
|
//UnityEngine.UIElements.EventDispatcher.editorDispatcher.PopDispatcherContext(); |
|
|
|
object editorDispatcher = mEditorDispatcherProp2020.GetValue(null); |
|
mPopContextMethod2020.Invoke(editorDispatcher, null); |
|
#else |
|
// m_Parent.visualTree.panel.dispatcher?.PopDispatcherContext(); |
|
|
|
object dispatcher = GetDispatcher(window); |
|
|
|
if (dispatcher != null) |
|
mPopContextMethod.Invoke(dispatcher, null); |
|
#endif |
|
} |
|
|
|
static void PushDispatcherContext(EditorWindow window) |
|
{ |
|
#if UNITY_2020_1_OR_NEWER |
|
//UnityEngine.UIElements.EventDispatcher.editorDispatcher.PushDispatcherContext(); |
|
|
|
object editorDispatcher = mEditorDispatcherProp2020.GetValue(null); |
|
mPushContextMethod2020.Invoke(editorDispatcher, null); |
|
#else |
|
// m_Parent.visualTree.panel.dispatcher?.PushDispatcherContext(); |
|
|
|
object dispatcher = GetDispatcher(window); |
|
|
|
if (dispatcher != null) |
|
mPushContextMethod.Invoke(dispatcher, null); |
|
#endif |
|
} |
|
|
|
static object GetDispatcher(EditorWindow window) |
|
{ |
|
object dispatcher = null; |
|
if (MayHaveDispatcher()) |
|
{ |
|
var parent = mParentField.GetValue(window); |
|
if (parent != null) |
|
{ |
|
var visualTree = mVisualTreeProp.GetValue(parent, null); |
|
if (visualTree != null) |
|
{ |
|
var panel = mPanelProp.GetValue(visualTree, null); |
|
if (panel != null) |
|
{ |
|
dispatcher = mDispatcherProp.GetValue(panel, null); |
|
} |
|
} |
|
} |
|
} |
|
|
|
return dispatcher; |
|
} |
|
|
|
static bool MayHaveDispatcher() |
|
{ |
|
return mDispatcherType != null |
|
&& mPushContextMethod != null |
|
&& mPopContextMethod != null; |
|
} |
|
|
|
static void InitializeInfo() |
|
{ |
|
var flags = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static; |
|
mMakeModalMethod = BuildMakeModalMethodInfo(flags); |
|
mShowWithModeMethod = typeof(EditorWindow).GetMethod("ShowWithMode", flags); |
|
mParentField = typeof(EditorWindow).GetField("m_Parent", flags); |
|
var hostViewType = mParentField.FieldType; |
|
mParentWindowProp = hostViewType.GetProperty("window", flags); |
|
|
|
var savedGUIStateType = typeof(EditorWindow).Assembly.GetType("UnityEditor.SavedGUIState"); |
|
mCreateSavedGUIState = savedGUIStateType.GetMethod("Create", flags); |
|
mApplyAndForgetMethod = savedGUIStateType.GetMethod("ApplyAndForget", flags); |
|
|
|
#if UNITY_2020_1_OR_NEWER |
|
mEditorDispatcherProp2020 = typeof(UnityEngine.UIElements.EventDispatcher).GetProperty("editorDispatcher", flags); |
|
mPushContextMethod2020 = mEditorDispatcherProp2020.PropertyType.GetMethod("PushDispatcherContext", flags); |
|
mPopContextMethod2020 = mEditorDispatcherProp2020.PropertyType.GetMethod("PopDispatcherContext", flags); |
|
#endif |
|
flags = BindingFlags.NonPublic |
|
| BindingFlags.Instance |
|
| BindingFlags.Public; |
|
|
|
mParentField = typeof(EditorWindow).GetField("m_Parent", flags); |
|
if (mParentField != null) |
|
hostViewType = mParentField.FieldType; |
|
if (hostViewType != null) |
|
mVisualTreeProp = hostViewType.GetProperty("visualTree"); |
|
if (mVisualTreeProp != null) |
|
{ |
|
var visualTreeType = mVisualTreeProp.PropertyType; |
|
if (visualTreeType != null) |
|
{ |
|
mPanelProp = visualTreeType.GetProperty("panel"); |
|
if (mPanelProp != null) |
|
{ |
|
var panelType = mPanelProp.PropertyType; |
|
if (panelType != null) |
|
{ |
|
mDispatcherProp = panelType.GetProperty("dispatcher"); |
|
if (mDispatcherProp != null) |
|
{ |
|
mDispatcherType = mDispatcherProp.PropertyType; |
|
if (mDispatcherType != null) |
|
{ |
|
mPushContextMethod = mDispatcherType.GetMethod("PushDispatcherContext", flags); |
|
mPopContextMethod = mDispatcherType.GetMethod("PopDispatcherContext", flags); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
static MethodInfo BuildMakeModalMethodInfo(BindingFlags flags) |
|
{ |
|
if (EditorVersion.IsCurrentEditorOlderThan("2019.3.10f1")) |
|
return typeof(EditorWindow).GetMethod("MakeModal", flags); |
|
|
|
return typeof(EditorWindow).GetMethod("Internal_MakeModal", flags); |
|
} |
|
|
|
static FieldInfo mParentField; |
|
static PropertyInfo mParentWindowProp; |
|
static MethodInfo mMakeModalMethod; |
|
static MethodInfo mShowWithModeMethod; |
|
static MethodInfo mCreateSavedGUIState; |
|
static MethodInfo mApplyAndForgetMethod; |
|
static PropertyInfo mVisualTreeProp; |
|
static Type mDispatcherType; |
|
static MethodInfo mPushContextMethod; |
|
static MethodInfo mPopContextMethod; |
|
static PropertyInfo mPanelProp; |
|
static PropertyInfo mDispatcherProp; |
|
|
|
#if UNITY_2020_1_OR_NEWER |
|
static PropertyInfo mEditorDispatcherProp2020; |
|
static MethodInfo mPushContextMethod2020; |
|
static MethodInfo mPopContextMethod2020; |
|
#endif |
|
|
|
// // How ContainerWindows are visualized. Used with ContainerWindow.Show |
|
// internal enum ShowMode |
|
// { |
|
// // Show as a normal window with max, min & close buttons. |
|
// NormalWindow = 0, |
|
// // Used for a popup menu. On mac this means light shadow and no titlebar. |
|
// PopupMenu = 1, |
|
// // Utility window - floats above the app. Disappears when app loses focus. |
|
// Utility = 2, |
|
// // Window has no shadow or decorations. Used internally for dragging stuff around. |
|
// NoShadow = 3, |
|
// // The Unity main window. On mac, this is the same as NormalWindow, except window doesn't have a close button. |
|
// MainWindow = 4, |
|
// // Aux windows. The ones that close the moment you move the mouse out of them. |
|
// AuxWindow = 5, |
|
// // Like PopupMenu, but without keyboard focus |
|
// Tooltip = 6 |
|
// } |
|
} |
|
}
|
|
|