A game about forced loneliness, made by TACStudios
1using System; 2using System.Reflection; 3 4using UnityEditor; 5using UnityEngine; 6 7namespace Unity.PlasticSCM.Editor.UI 8{ 9 internal static class RunModal 10 { 11 static RunModal() 12 { 13 InitializeInfo(); 14 } 15 16 internal static bool IsAvailable() 17 { 18 return mShowWithModeMethod != null 19 && mCreateSavedGUIState != null 20 && mApplyAndForgetMethod != null 21 && mParentField != null 22 && mParentWindowProp != null 23 && mMakeModalMethod != null; 24 } 25 26 internal static void Dialog(EditorWindow window) 27 { 28 ShowAsUtility(window); 29 30 object savedGUIState = CreateSavedGUIState(); 31 PushDispatcherContext(window); 32 33 MakeModal(window); 34 35 PopDispatcherContext(window); 36 ApplySavedGUIState(savedGUIState); 37 } 38 39 static void MakeModal(EditorWindow window) 40 { 41 // MakeModal(m_Parent.window); 42 var hostView = mParentField.GetValue(window); 43 var parentWindow = mParentWindowProp.GetValue(hostView, null); 44 45 mMakeModalMethod.Invoke( 46 mMakeModalMethod.IsStatic ? null : window, 47 new object[] { parentWindow }); 48 } 49 50 static void ShowAsUtility(EditorWindow window) 51 { 52 // ShowWithMode(ShowMode.Utility); 53 mShowWithModeMethod.Invoke(window, new object[] { 2 }); 54 } 55 56 static object CreateSavedGUIState() 57 { 58 // SavedGUIState guiState = SavedGUIState.Create(); 59 return mCreateSavedGUIState.Invoke(null, null); 60 } 61 62 static void ApplySavedGUIState(object savedGUIState) 63 { 64 // guiState.ApplyAndForget(); 65 mApplyAndForgetMethod.Invoke(savedGUIState, null); 66 } 67 68 static void PopDispatcherContext(EditorWindow window) 69 { 70 //UnityEngine.UIElements.EventDispatcher.editorDispatcher.PopDispatcherContext(); 71 72 object editorDispatcher = mEditorDispatcherProp2020.GetValue(null); 73 mPopContextMethod2020.Invoke(editorDispatcher, null); 74 } 75 76 static void PushDispatcherContext(EditorWindow window) 77 { 78 //UnityEngine.UIElements.EventDispatcher.editorDispatcher.PushDispatcherContext(); 79 80 object editorDispatcher = mEditorDispatcherProp2020.GetValue(null); 81 mPushContextMethod2020.Invoke(editorDispatcher, null); 82 } 83 84 static object GetDispatcher(EditorWindow window) 85 { 86 object dispatcher = null; 87 if (MayHaveDispatcher()) 88 { 89 var parent = mParentField.GetValue(window); 90 if (parent != null) 91 { 92 var visualTree = mVisualTreeProp.GetValue(parent, null); 93 if (visualTree != null) 94 { 95 var panel = mPanelProp.GetValue(visualTree, null); 96 if (panel != null) 97 { 98 dispatcher = mDispatcherProp.GetValue(panel, null); 99 } 100 } 101 } 102 } 103 104 return dispatcher; 105 } 106 107 static bool MayHaveDispatcher() 108 { 109 return mDispatcherType != null 110 && mPushContextMethod != null 111 && mPopContextMethod != null; 112 } 113 114 static void InitializeInfo() 115 { 116 var flags = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static; 117 mMakeModalMethod = BuildMakeModalMethodInfo(flags); 118 mShowWithModeMethod = typeof(EditorWindow).GetMethod("ShowWithMode", flags); 119 mParentField = typeof(EditorWindow).GetField("m_Parent", flags); 120 var hostViewType = mParentField.FieldType; 121 mParentWindowProp = hostViewType.GetProperty("window", flags); 122 123 var savedGUIStateType = typeof(EditorWindow).Assembly.GetType("UnityEditor.SavedGUIState"); 124 mCreateSavedGUIState = savedGUIStateType.GetMethod("Create", flags); 125 mApplyAndForgetMethod = savedGUIStateType.GetMethod("ApplyAndForget", flags); 126 127 mEditorDispatcherProp2020 = typeof(UnityEngine.UIElements.EventDispatcher).GetProperty("editorDispatcher", flags); 128 mPushContextMethod2020 = mEditorDispatcherProp2020.PropertyType.GetMethod("PushDispatcherContext", flags); 129 mPopContextMethod2020 = mEditorDispatcherProp2020.PropertyType.GetMethod("PopDispatcherContext", flags); 130 131 flags = BindingFlags.NonPublic 132 | BindingFlags.Instance 133 | BindingFlags.Public; 134 135 mParentField = typeof(EditorWindow).GetField("m_Parent", flags); 136 if (mParentField != null) 137 hostViewType = mParentField.FieldType; 138 if (hostViewType != null) 139 mVisualTreeProp = hostViewType.GetProperty("visualTree"); 140 if (mVisualTreeProp != null) 141 { 142 var visualTreeType = mVisualTreeProp.PropertyType; 143 if (visualTreeType != null) 144 { 145 mPanelProp = visualTreeType.GetProperty("panel"); 146 if (mPanelProp != null) 147 { 148 var panelType = mPanelProp.PropertyType; 149 if (panelType != null) 150 { 151 mDispatcherProp = panelType.GetProperty("dispatcher"); 152 if (mDispatcherProp != null) 153 { 154 mDispatcherType = mDispatcherProp.PropertyType; 155 if (mDispatcherType != null) 156 { 157 mPushContextMethod = mDispatcherType.GetMethod("PushDispatcherContext", flags); 158 mPopContextMethod = mDispatcherType.GetMethod("PopDispatcherContext", flags); 159 } 160 } 161 } 162 } 163 } 164 } 165 } 166 167 static MethodInfo BuildMakeModalMethodInfo(BindingFlags flags) 168 { 169 return typeof(EditorWindow).GetMethod("Internal_MakeModal", flags); 170 } 171 172 static FieldInfo mParentField; 173 static PropertyInfo mParentWindowProp; 174 static MethodInfo mMakeModalMethod; 175 static MethodInfo mShowWithModeMethod; 176 static MethodInfo mCreateSavedGUIState; 177 static MethodInfo mApplyAndForgetMethod; 178 static PropertyInfo mVisualTreeProp; 179 static Type mDispatcherType; 180 static MethodInfo mPushContextMethod; 181 static MethodInfo mPopContextMethod; 182 static PropertyInfo mPanelProp; 183 static PropertyInfo mDispatcherProp; 184 185 static PropertyInfo mEditorDispatcherProp2020; 186 static MethodInfo mPushContextMethod2020; 187 static MethodInfo mPopContextMethod2020; 188 189 // // How ContainerWindows are visualized. Used with ContainerWindow.Show 190 // internal enum ShowMode 191 // { 192 // // Show as a normal window with max, min & close buttons. 193 // NormalWindow = 0, 194 // // Used for a popup menu. On mac this means light shadow and no titlebar. 195 // PopupMenu = 1, 196 // // Utility window - floats above the app. Disappears when app loses focus. 197 // Utility = 2, 198 // // Window has no shadow or decorations. Used internally for dragging stuff around. 199 // NoShadow = 3, 200 // // The Unity main window. On mac, this is the same as NormalWindow, except window doesn't have a close button. 201 // MainWindow = 4, 202 // // Aux windows. The ones that close the moment you move the mouse out of them. 203 // AuxWindow = 5, 204 // // Like PopupMenu, but without keyboard focus 205 // cm-help.es.txtTooltip = 6 206 // } 207 } 208}