From 68eeee353e3d97c5568853183cd5237a383f0de1 Mon Sep 17 00:00:00 2001 From: sinaioutlander <49360850+sinaioutlander@users.noreply.github.com> Date: Sun, 30 Aug 2020 01:08:48 +1000 Subject: [PATCH] 1.4.5 (pre-release) - Implement Tab View * Implemented Tab View --- src/CachedObjects/CacheMethod.cs | 67 +++++++++++++++++++++-- src/CppExplorer.cs | 54 +++++++++---------- src/CppExplorer.csproj | 1 + src/MainMenu/MainMenu.cs | 2 + src/Windows/GameObjectWindow.cs | 35 +++++++----- src/Windows/ReflectionWindow.cs | 63 ++++++++++++++-------- src/Windows/ResizeDrag.cs | 9 ++++ src/Windows/TabViewWindow.cs | 91 ++++++++++++++++++++++++++++++++ src/Windows/UIWindow.cs | 21 +++++--- src/Windows/WindowManager.cs | 44 ++++++++++++--- 10 files changed, 303 insertions(+), 84 deletions(-) create mode 100644 src/Windows/TabViewWindow.cs diff --git a/src/CachedObjects/CacheMethod.cs b/src/CachedObjects/CacheMethod.cs index 30d4518..14659e6 100644 --- a/src/CachedObjects/CacheMethod.cs +++ b/src/CachedObjects/CacheMethod.cs @@ -9,30 +9,71 @@ using MelonLoader; namespace Explorer { + // TODO implement methods with primitive arguments + public class CacheMethod : CacheObjectBase { private bool m_evaluated = false; private CacheObjectBase m_cachedReturnValue; + public bool HasParameters + { + get + { + if (m_hasParams == null) + { + m_hasParams = (MemberInfo as MethodInfo).GetParameters().Length > 0; + } + return (bool)m_hasParams; + } + } + private bool? m_hasParams; + + // ======= TODO ======= + private bool m_isEvaluating; + private string[] m_argumentNames; + private Type[] m_argumentTypes; + private string[] m_argumentInput; + // ===================== + public static bool CanEvaluate(MethodInfo mi) { - if (mi.GetParameters().Length > 0 || mi.GetGenericArguments().Length > 0) + // generic type args not supported yet + if (mi.GetGenericArguments().Length > 0) { - // Currently methods with arguments are not supported (no good way to input them). return false; } + // TODO primitive params (commented out impl below) + if (mi.GetParameters().Length > 0) + { + return false; + } + + //// only primitive and string args supported + //foreach (var param in mi.GetParameters()) + //{ + // if (!param.ParameterType.IsPrimitive && param.ParameterType != typeof(string)) + // { + // return false; + // } + //} + return true; } public override void Init() { base.Init(); + + // TODO cache params } public override void UpdateValue() { base.UpdateValue(); + + // TODO update params (?) } private void Evaluate() @@ -40,7 +81,18 @@ namespace Explorer m_evaluated = true; var mi = MemberInfo as MethodInfo; - var ret = mi.Invoke(mi.IsStatic ? null : DeclaringInstance, new object[0]); + + object ret; + + if (!HasParameters) + { + ret = mi.Invoke(mi.IsStatic ? null : DeclaringInstance, new object[0]); + } + else + { + // TODO parse params, invoke if valid + throw new NotImplementedException("TODO"); + } if (ret != null) { @@ -65,7 +117,14 @@ namespace Explorer GUILayout.BeginHorizontal(null); if (GUILayout.Button("Evaluate", new GUILayoutOption[] { GUILayout.Width(70) })) { - Evaluate(); + if (HasParameters) + { + throw new NotImplementedException("TODO"); + } + else + { + Evaluate(); + } } GUI.skin.label.wordWrap = false; GUILayout.Label($"{ValueType}", null); diff --git a/src/CppExplorer.cs b/src/CppExplorer.cs index bd66eb3..fa24cc6 100644 --- a/src/CppExplorer.cs +++ b/src/CppExplorer.cs @@ -99,8 +99,6 @@ namespace Explorer public override void OnGUI() { - base.OnGUI(); - MainMenu.Instance.OnGUI(); WindowManager.Instance.OnGUI(); InspectUnderMouse.OnGUI(); @@ -170,34 +168,32 @@ namespace Explorer } } - // Temporarily disabled this because I don't think it's actually useful, and may in fact cause problems instead + // Make it appear as though UnlockMouse is disabled to the rest of the application. - //// Make it appear as though UnlockMouse is disabled to the rest of the application. + [HarmonyPatch(typeof(Cursor), nameof(Cursor.visible), MethodType.Getter)] + public class Cursor_get_visible + { + [HarmonyPostfix] + public static void Postfix(ref bool __result) + { + if (ShouldForceMouse) + { + __result = m_lastVisibleState; + } + } + } - //[HarmonyPatch(typeof(Cursor), nameof(Cursor.visible), MethodType.Getter)] - //public class Cursor_get_visible - //{ - // [HarmonyPostfix] - // public static void Postfix(ref bool __result) - // { - // if (ShouldForceMouse) - // { - // __result = m_lastVisibleState; - // } - // } - //} - - //[HarmonyPatch(typeof(Cursor), nameof(Cursor.lockState), MethodType.Getter)] - //public class Cursor_get_lockState - //{ - // [HarmonyPostfix] - // public static void Postfix(ref CursorLockMode __result) - // { - // if (ShouldForceMouse) - // { - // __result = m_lastLockMode; - // } - // } - //} + [HarmonyPatch(typeof(Cursor), nameof(Cursor.lockState), MethodType.Getter)] + public class Cursor_get_lockState + { + [HarmonyPostfix] + public static void Postfix(ref CursorLockMode __result) + { + if (ShouldForceMouse) + { + __result = m_lastLockMode; + } + } + } } } diff --git a/src/CppExplorer.csproj b/src/CppExplorer.csproj index 4b446cd..d8784ad 100644 --- a/src/CppExplorer.csproj +++ b/src/CppExplorer.csproj @@ -136,6 +136,7 @@ + diff --git a/src/MainMenu/MainMenu.cs b/src/MainMenu/MainMenu.cs index 68c1609..5081f67 100644 --- a/src/MainMenu/MainMenu.cs +++ b/src/MainMenu/MainMenu.cs @@ -110,6 +110,8 @@ namespace Explorer bool mouseState = CppExplorer.ForceUnlockMouse; bool setMouse = GUILayout.Toggle(mouseState, "Force Unlock Mouse (Left Alt)", null); if (setMouse != mouseState) CppExplorer.ForceUnlockMouse = setMouse; + + WindowManager.TabView = GUILayout.Toggle(WindowManager.TabView, "Tab View", null); GUILayout.EndHorizontal(); GUILayout.Space(10); diff --git a/src/Windows/GameObjectWindow.cs b/src/Windows/GameObjectWindow.cs index b70f8c9..40043bd 100644 --- a/src/Windows/GameObjectWindow.cs +++ b/src/Windows/GameObjectWindow.cs @@ -11,7 +11,9 @@ namespace Explorer { public class GameObjectWindow : UIWindow { - public override string Name { get => $"GameObject Inspector ({m_object.name})"; } + public override string Title => WindowManager.TabView + ? m_object.name + : $"GameObject Inspector ({m_object.name})"; public GameObject m_object; @@ -144,9 +146,13 @@ namespace Explorer { try { - Header(); + var rect = WindowManager.TabView ? TabViewWindow.Instance.m_rect : this.m_rect; - GUILayout.BeginArea(new Rect(5, 25, m_rect.width - 10, m_rect.height - 35), GUI.skin.box); + if (!WindowManager.TabView) + { + Header(); + GUILayout.BeginArea(new Rect(5, 25, rect.width - 10, rect.height - 35), GUI.skin.box); + } scroll = GUILayout.BeginScrollView(scroll, GUI.skin.scrollView); @@ -183,12 +189,12 @@ namespace Explorer // --- Horizontal Columns section --- GUILayout.BeginHorizontal(null); - GUILayout.BeginVertical(new GUILayoutOption[] { GUILayout.Width(m_rect.width / 2 - 17) }); - TransformList(); + GUILayout.BeginVertical(new GUILayoutOption[] { GUILayout.Width(rect.width / 2 - 17) }); + TransformList(rect); GUILayout.EndVertical(); - GUILayout.BeginVertical(new GUILayoutOption[] { GUILayout.Width(m_rect.width / 2 - 17) }); - ComponentList(); + GUILayout.BeginVertical(new GUILayoutOption[] { GUILayout.Width(rect.width / 2 - 17) }); + ComponentList(rect); GUILayout.EndVertical(); GUILayout.EndHorizontal(); // end horiz columns @@ -197,9 +203,12 @@ namespace Explorer GUILayout.EndScrollView(); - m_rect = ResizeDrag.ResizeWindow(m_rect, windowID); + if (!WindowManager.TabView) + { + m_rect = ResizeDrag.ResizeWindow(rect, windowID); - GUILayout.EndArea(); + GUILayout.EndArea(); + } } catch (Exception e) { @@ -207,7 +216,7 @@ namespace Explorer } } - private void TransformList() + private void TransformList(Rect m_rect) { GUILayout.BeginVertical(GUI.skin.box, null); // new GUILayoutOption[] { GUILayout.Height(250) }); m_transformScroll = GUILayout.BeginScrollView(m_transformScroll, GUI.skin.scrollView); @@ -222,7 +231,7 @@ namespace Explorer GUILayout.Label("null", null); continue; } - UIHelpers.GameobjButton(obj.gameObject, InspectGameObject, false, this.m_rect.width / 2 - 60); + UIHelpers.GameobjButton(obj.gameObject, InspectGameObject, false, m_rect.width / 2 - 60); } foreach (var obj in m_children.Where(x => x.childCount == 0)) { @@ -231,7 +240,7 @@ namespace Explorer GUILayout.Label("null", null); continue; } - UIHelpers.GameobjButton(obj.gameObject, InspectGameObject, false, this.m_rect.width / 2 - 60); + UIHelpers.GameobjButton(obj.gameObject, InspectGameObject, false, m_rect.width / 2 - 60); } } else @@ -244,7 +253,7 @@ namespace Explorer } - private void ComponentList() + private void ComponentList(Rect m_rect) { GUILayout.BeginVertical(GUI.skin.box, null); // new GUILayoutOption[] { GUILayout.Height(250) }); m_compScroll = GUILayout.BeginScrollView(m_compScroll, GUI.skin.scrollView); diff --git a/src/Windows/ReflectionWindow.cs b/src/Windows/ReflectionWindow.cs index 76f9c33..30bef67 100644 --- a/src/Windows/ReflectionWindow.cs +++ b/src/Windows/ReflectionWindow.cs @@ -12,7 +12,9 @@ namespace Explorer { public class ReflectionWindow : UIWindow { - public override string Name { get => $"Reflection Inspector ({ObjectType.Name})"; } + public override string Title => WindowManager.TabView + ? ObjectType.Name + : $"Reflection Inspector ({ObjectType.Name})"; public Type ObjectType; @@ -172,12 +174,16 @@ namespace Explorer { try { - Header(); + var rect = WindowManager.TabView ? TabViewWindow.Instance.m_rect : this.m_rect; - GUILayout.BeginArea(new Rect(5, 25, m_rect.width - 10, m_rect.height - 35), GUI.skin.box); + if (!WindowManager.TabView) + { + Header(); + GUILayout.BeginArea(new Rect(5, 25, rect.width - 10, rect.height - 35), GUI.skin.box); + } GUILayout.BeginHorizontal(null); - GUILayout.Label("Type: " + ObjectType.FullName + "", null); + GUILayout.Label("Type: " + ObjectType.FullName + "", new GUILayoutOption[] { GUILayout.Width(245f) }); if (m_uObj) { GUILayout.Label("Name: " + m_uObj.name, null); @@ -192,8 +198,11 @@ namespace Explorer if (m_component && m_component.gameObject is GameObject obj) { GUI.skin.label.alignment = TextAnchor.MiddleRight; - GUILayout.Label("GameObject:", null); - if (GUILayout.Button("" + obj.name + "", new GUILayoutOption[] { GUILayout.MaxWidth(m_rect.width - 350) })) + GUILayout.Label("GameObject:", new GUILayoutOption[] { GUILayout.Width(135) }); + var charWidth = obj.name.Length * 15; + var maxWidth = rect.width - 350; + var labelWidth = charWidth < maxWidth ? charWidth : maxWidth; + if (GUILayout.Button("" + obj.name + "", new GUILayoutOption[] { GUILayout.Width(labelWidth) })) { WindowManager.InspectObject(obj, out bool _); } @@ -206,14 +215,7 @@ namespace Explorer GUILayout.BeginHorizontal(null); GUILayout.Label("Search:", new GUILayoutOption[] { GUILayout.Width(75) }); - m_search = GUILayout.TextField(m_search, null); - GUILayout.Label("Limit per page:", new GUILayoutOption[] { GUILayout.Width(125) }); - var limitString = m_limitPerPage.ToString(); - limitString = GUILayout.TextField(limitString, new GUILayoutOption[] { GUILayout.Width(60) }); - if (int.TryParse(limitString, out int i)) - { - m_limitPerPage = i; - } + m_search = GUILayout.TextField(m_search, null); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(null); @@ -239,28 +241,38 @@ namespace Explorer GUILayout.Space(10); - int count = m_cachedMemberFiltered.Length; + // prev/next page buttons + GUILayout.BeginHorizontal(null); + GUILayout.Label("Limit per page:", new GUILayoutOption[] { GUILayout.Width(125) }); + var limitString = m_limitPerPage.ToString(); + limitString = GUILayout.TextField(limitString, new GUILayoutOption[] { GUILayout.Width(60) }); + if (int.TryParse(limitString, out int i)) + { + m_limitPerPage = i; + } + + int count = m_cachedMemberFiltered.Length; if (count > m_limitPerPage) { - // prev/next page buttons - GUILayout.BeginHorizontal(null); int maxOffset = (int)Mathf.Ceil((float)(count / (decimal)m_limitPerPage)) - 1; - if (GUILayout.Button("< Prev", null)) + if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) })) { if (m_pageOffset > 0) m_pageOffset--; scroll = Vector2.zero; } + GUI.skin.label.alignment = TextAnchor.MiddleCenter; GUILayout.Label($"Page {m_pageOffset + 1}/{maxOffset + 1}", new GUILayoutOption[] { GUILayout.Width(80) }); + GUI.skin.label.alignment = TextAnchor.UpperLeft; - if (GUILayout.Button("Next >", null)) + if (GUILayout.Button("Next >", new GUILayoutOption[] { GUILayout.Width(80) })) { if (m_pageOffset < maxOffset) m_pageOffset++; scroll = Vector2.zero; } - GUILayout.EndHorizontal(); } + GUILayout.EndHorizontal(); scroll = GUILayout.BeginScrollView(scroll, GUI.skin.scrollView); @@ -270,9 +282,12 @@ namespace Explorer GUILayout.EndScrollView(); - m_rect = ResizeDrag.ResizeWindow(m_rect, windowID); + if (!WindowManager.TabView) + { + m_rect = ResizeDrag.ResizeWindow(rect, windowID); - GUILayout.EndArea(); + GUILayout.EndArea(); + } } catch (Exception e) { @@ -299,6 +314,8 @@ namespace Explorer return; } + var rect = WindowManager.TabView ? TabViewWindow.Instance.m_rect : this.m_rect; + UIStyles.HorizontalLine(Color.grey); GUILayout.Label($"{title}", null); @@ -320,7 +337,7 @@ namespace Explorer GUILayout.BeginHorizontal(new GUILayoutOption[] { GUILayout.Height(25) }); try { - holder.Draw(this.m_rect, 180f); + holder.Draw(rect, 180f); } catch // (Exception e) { diff --git a/src/Windows/ResizeDrag.cs b/src/Windows/ResizeDrag.cs index 7b8e3d0..e1d0f7d 100644 --- a/src/Windows/ResizeDrag.cs +++ b/src/Windows/ResizeDrag.cs @@ -5,6 +5,7 @@ using System.Text; using System.Threading.Tasks; using UnityEngine; using MelonLoader; +using UnhollowerBaseLib; namespace Explorer { @@ -21,6 +22,8 @@ namespace Explorer { if (RESIZE_FAILED) return _rect; + var origRect = _rect; + try { GUILayout.BeginHorizontal(GUI.skin.box, null); @@ -53,10 +56,16 @@ namespace Explorer GUILayout.EndHorizontal(); } + catch (Il2CppException e) when (e.Message.StartsWith("System.ArgumentException")) + { + // suppress + return origRect; + } catch (Exception e) { RESIZE_FAILED = true; MelonLogger.Log("Exception on GuiResize: " + e.GetType() + ", " + e.Message); + return origRect; } GUI.skin.label.alignment = TextAnchor.UpperLeft; diff --git a/src/Windows/TabViewWindow.cs b/src/Windows/TabViewWindow.cs new file mode 100644 index 0000000..7008f6d --- /dev/null +++ b/src/Windows/TabViewWindow.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace Explorer +{ + public class TabViewWindow : UIWindow + { + public override string Title => "Tab View"; + + public static TabViewWindow Instance => m_instance ?? (m_instance = new TabViewWindow()); + private static TabViewWindow m_instance; + + public int TargetTabID = 0; + + public override bool IsTabViewWindow => true; + + public TabViewWindow() + { + m_rect = new Rect(570, 0, 550, 700); + } + + public override void Init() { } + public override void Update() { } + + public override void WindowFunction(int windowID) + { + try + { + Header(); + + GUILayout.BeginArea(new Rect(5, 25, m_rect.width - 10, m_rect.height - 35), GUI.skin.box); + + GUILayout.BeginVertical(GUI.skin.box, null); + GUILayout.BeginHorizontal(null); + GUI.skin.button.alignment = TextAnchor.MiddleLeft; + int tabPerRow = Mathf.FloorToInt((float)((decimal)m_rect.width / 238)); + int rowCount = 0; + for (int i = 0; i < WindowManager.Windows.Count; i++) + { + if (rowCount >= tabPerRow) + { + rowCount = 0; + GUILayout.EndHorizontal(); + GUILayout.BeginHorizontal(null); + } + rowCount++; + + bool focused = i == TargetTabID; + string color = focused ? "" : ""; + + var window = WindowManager.Windows[i]; + if (GUILayout.Button(color + window.Title + "", new GUILayoutOption[] { GUILayout.Width(200) })) + { + TargetTabID = i; + } + if (GUILayout.Button("X", new GUILayoutOption[] { GUILayout.Width(22) })) + { + window.DestroyWindow(); + } + } + GUILayout.EndHorizontal(); + GUILayout.EndVertical(); + GUI.skin.button.alignment = TextAnchor.MiddleCenter; + + while (TargetTabID >= WindowManager.Windows.Count) + { + TargetTabID--; + } + + if (TargetTabID >= 0) + { + var window = WindowManager.Windows[TargetTabID]; + window.WindowFunction(window.windowID); + } + + try + { + m_rect = ResizeDrag.ResizeWindow(m_rect, windowID); + } + catch { } + + GUILayout.EndArea(); + } + catch { } + } + } +} diff --git a/src/Windows/UIWindow.cs b/src/Windows/UIWindow.cs index e6df846..9bc6cc0 100644 --- a/src/Windows/UIWindow.cs +++ b/src/Windows/UIWindow.cs @@ -14,7 +14,7 @@ namespace Explorer { public abstract class UIWindow { - public abstract string Name { get; } + public abstract string Title { get; } public object Target; @@ -23,6 +23,8 @@ namespace Explorer public Vector2 scroll = Vector2.zero; + public virtual bool IsTabViewWindow => false; + public abstract void Init(); public abstract void WindowFunction(int windowID); public abstract void Update(); @@ -62,7 +64,7 @@ namespace Explorer var origSkin = GUI.skin; GUI.skin = UIStyles.WindowSkin; - m_rect = GUI.Window(windowID, m_rect, (GUI.WindowFunction)WindowFunction, Name); + m_rect = GUI.Window(windowID, m_rect, (GUI.WindowFunction)WindowFunction, Title); GUI.skin = origSkin; } @@ -70,12 +72,17 @@ namespace Explorer public void Header() { - GUI.DragWindow(new Rect(0, 0, m_rect.width - 90, 20)); - - if (GUI.Button(new Rect(m_rect.width - 90, 2, 80, 20), "X")) + if (!WindowManager.TabView || IsTabViewWindow) { - DestroyWindow(); - return; + GUI.DragWindow(new Rect(0, 0, m_rect.width - 90, 20)); + } + if (!WindowManager.TabView) + { + if (GUI.Button(new Rect(m_rect.width - 90, 2, 80, 20), "X")) + { + DestroyWindow(); + return; + } } } } diff --git a/src/Windows/WindowManager.cs b/src/Windows/WindowManager.cs index 4f215d1..0afc67c 100644 --- a/src/Windows/WindowManager.cs +++ b/src/Windows/WindowManager.cs @@ -16,6 +16,8 @@ namespace Explorer { public static WindowManager Instance; + public static bool TabView = true; + public static List Windows = new List(); public static int CurrentWindowID { get; set; } = 500000; private static Rect m_lastWindowRect; @@ -27,17 +29,31 @@ namespace Explorer public void Update() { - foreach (var window in Windows) + for (int i = 0; i < Windows.Count; i++) { - window.Update(); + var window = Windows[i]; + if (window != null) + { + window.Update(); + } } } public void OnGUI() { - foreach (var window in Windows) + if (TabView) { - window.OnGUI(); + if (Windows.Count > 0) + { + TabViewWindow.Instance.OnGUI(); + } + } + else + { + foreach (var window in Windows) + { + window.OnGUI(); + } } } @@ -119,8 +135,7 @@ namespace Explorer if (equals) { - GUI.BringWindowToFront(window.windowID); - GUI.FocusWindow(window.windowID); + FocusWindow(window); return window; } } @@ -136,10 +151,23 @@ namespace Explorer } } + private static void FocusWindow(UIWindow window) + { + if (!TabView) + { + GUI.BringWindowToFront(window.windowID); + GUI.FocusWindow(window.windowID); + } + else + { + TabViewWindow.Instance.TargetTabID = Windows.IndexOf(window); + } + } + private static UIWindow InspectGameObject(GameObject obj) { var new_window = UIWindow.CreateWindow(obj); - GUI.FocusWindow(new_window.windowID); + FocusWindow(new_window); return new_window; } @@ -147,7 +175,7 @@ namespace Explorer public static UIWindow InspectReflection(object obj) { var new_window = UIWindow.CreateWindow(obj); - GUI.FocusWindow(new_window.windowID); + FocusWindow(new_window); return new_window; }