From 0d4b4dc82663ed51c3a4ba19fbbecb70d79ef732 Mon Sep 17 00:00:00 2001
From: sinaioutlander <49360850+sinaioutlander@users.noreply.github.com>
Date: Sat, 24 Oct 2020 20:18:42 +1100
Subject: [PATCH] Debug console basically finished and working (using TMP now)
---
src/Explorer.csproj | 22 +++
src/ExplorerCore.cs | 14 +-
src/UI/ForceUnlockCursor.cs | 14 +-
src/UI/Main/DebugConsole.cs | 133 ++++++++++++++++++
src/UI/Main/MainMenu.cs | 15 +-
src/UI/UIFactory.cs | 107 ++++++++++++--
src/UI/UIManager.cs | 6 +
.../ColorUtility/ColorUtilityUnstrip.cs | 23 +++
8 files changed, 311 insertions(+), 23 deletions(-)
create mode 100644 src/UI/Main/DebugConsole.cs
create mode 100644 src/Unstrip/ColorUtility/ColorUtilityUnstrip.cs
diff --git a/src/Explorer.csproj b/src/Explorer.csproj
index f7bc8ae..d452a9e 100644
--- a/src/Explorer.csproj
+++ b/src/Explorer.csproj
@@ -87,6 +87,10 @@
..\lib\UnityEngine.dll
False
+
+ ..\lib\Unity.TextMeshPro.dll
+ False
+
@@ -124,6 +128,10 @@
$(MLCppGameFolder)\MelonLoader\Managed\Il2CppSystem.Core.dll
False
+
+ $(MLCppGameFolder)\MelonLoader\Managed\Unity.TextMeshPro.dll
+ False
+
$(MLCppGameFolder)\MelonLoader\Managed\UnityEngine.dll
False
@@ -136,6 +144,10 @@
$(MLCppGameFolder)\MelonLoader\Managed\UnityEngine.PhysicsModule.dll
False
+
+ $(MLCppGameFolder)\MelonLoader\Managed\UnityEngine.TextCoreModule.dll
+ False
+
$(MLCppGameFolder)\MelonLoader\Managed\UnityEngine.TextRenderingModule.dll
False
@@ -179,6 +191,10 @@
$(BIECppGameFolder)\BepInEx\unhollowed\Il2CppSystem.Core.dll
False
+
+ $(BIECppGameFolder)\BepInEx\unhollowed\Unity.TextMeshPro.dll
+ False
+
$(BIECppGameFolder)\BepInEx\unhollowed\UnityEngine.dll
False
@@ -191,6 +207,10 @@
$(BIECppGameFolder)\BepInEx\unhollowed\UnityEngine.PhysicsModule.dll
False
+
+ $(BIECppGameFolder)\BepInEx\unhollowed\UnityEngine.TextCoreModule.dll
+ False
+
$(BIECppGameFolder)\BepInEx\unhollowed\UnityEngine.TextRenderingModule.dll
False
@@ -232,6 +252,7 @@
+
@@ -243,6 +264,7 @@
+
diff --git a/src/ExplorerCore.cs b/src/ExplorerCore.cs
index e8b716e..0995ad1 100644
--- a/src/ExplorerCore.cs
+++ b/src/ExplorerCore.cs
@@ -4,6 +4,7 @@ using System.Linq;
using ExplorerBeta.Config;
using ExplorerBeta.Input;
using ExplorerBeta.UI;
+using ExplorerBeta.UI.Main;
using UnityEngine;
namespace ExplorerBeta
@@ -58,7 +59,7 @@ namespace ExplorerBeta
ShowMenu = true;
Log($"{NAME} initialized.");
- }
+ }
private static void SetShowMenu(bool show)
{
@@ -96,6 +97,10 @@ namespace ExplorerBeta
m_doneUIInit = true;
}
}
+ else
+ {
+ UIManager.Update();
+ }
if (InputManager.GetKeyDown(ModConfig.Instance.Main_Menu_Toggle))
{
@@ -105,11 +110,7 @@ namespace ExplorerBeta
if (ShowMenu)
{
ForceUnlockCursor.Update();
-
UIManager.Update();
-
- //// TODO:
- //InspectUnderMouse.Update();
}
}
@@ -120,6 +121,7 @@ namespace ExplorerBeta
public static void Log(object message)
{
+ DebugConsole.Log(message?.ToString());
#if ML
MelonLoader.MelonLogger.Log(message?.ToString());
#else
@@ -129,6 +131,7 @@ namespace ExplorerBeta
public static void LogWarning(object message)
{
+ DebugConsole.Log(message?.ToString(), "FFFF00");
#if ML
MelonLoader.MelonLogger.LogWarning(message?.ToString());
#else
@@ -138,6 +141,7 @@ namespace ExplorerBeta
public static void LogError(object message)
{
+ DebugConsole.Log(message?.ToString(), "FF0000");
#if ML
MelonLoader.MelonLogger.LogError(message?.ToString());
#else
diff --git a/src/UI/ForceUnlockCursor.cs b/src/UI/ForceUnlockCursor.cs
index 9a619c8..bf66234 100644
--- a/src/UI/ForceUnlockCursor.cs
+++ b/src/UI/ForceUnlockCursor.cs
@@ -4,6 +4,7 @@ using ExplorerBeta.Helpers;
using UnityEngine.EventSystems;
using ExplorerBeta.UI;
using ExplorerBeta.Input;
+using BF = System.Reflection.BindingFlags;
#if ML
using Harmony;
#else
@@ -49,8 +50,17 @@ namespace ExplorerBeta.UI
}
// Get current cursor state and enable cursor
- m_lastLockMode = Cursor.lockState;
- m_lastVisibleState = Cursor.visible;
+ try
+ {
+ //m_lastLockMode = Cursor.lockState;
+ m_lastLockMode = (CursorLockMode?)typeof(Cursor).GetProperty("lockState", BF.Public | BF.Static)?.GetValue(null, null)
+ ?? CursorLockMode.None;
+
+ //m_lastVisibleState = Cursor.visible;
+ m_lastVisibleState = (bool?)typeof(Cursor).GetProperty("visible", BF.Public | BF.Static)?.GetValue(null, null)
+ ?? false;
+ }
+ catch { }
// Setup Harmony Patches
TryPatch(typeof(EventSystem), "current", new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_EventSystem_set_current))), true);
diff --git a/src/UI/Main/DebugConsole.cs b/src/UI/Main/DebugConsole.cs
new file mode 100644
index 0000000..38d8c7a
--- /dev/null
+++ b/src/UI/Main/DebugConsole.cs
@@ -0,0 +1,133 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Explorer.Unstrip.ColorUtility;
+using ExplorerBeta.Input;
+using ExplorerBeta.Unstrip.Resources;
+using TMPro;
+using UnhollowerRuntimeLib;
+using UnityEngine;
+using UnityEngine.UI;
+
+namespace ExplorerBeta.UI.Main
+{
+ // TODO:
+ // - Maybe hook into Unity's debug logs
+ // - Buttons for clear, save to file, etc..?
+
+ public class DebugConsole
+ {
+ public static DebugConsole Instance { get; private set; }
+
+ public static GameObject CanvasRoot;
+ //private static GameObject Panel;
+
+ public readonly List AllMessages;
+ public readonly List MessageHolders;
+
+ private TMP_InputField m_textInput;
+
+ // todo probably put this in UImanager, use for C# console too
+ //internal static Font m_consoleFont;
+ //private const int MAX_MESSAGES = 100;
+
+ public DebugConsole(GameObject parent)
+ {
+ Instance = this;
+
+ AllMessages = new List();
+ MessageHolders = new List();
+
+ try
+ {
+ ConstructUI(parent);
+ }
+ catch (Exception e)
+ {
+ ExplorerCore.Log(e);
+ }
+ }
+
+ // todo: get scrollbar working with inputfield somehow
+
+ public void ConstructUI(GameObject parent)
+ {
+ var obj = UIFactory.CreateHorizontalGroup(parent, new Color(0.1f, 0.1f, 0.1f, 1.0f));
+ var mainGroup = obj.GetComponent();
+ mainGroup.childControlHeight = true;
+ mainGroup.childControlWidth = true;
+ mainGroup.childForceExpandHeight = true;
+ mainGroup.childForceExpandWidth = true;
+
+ var mainImage = obj.GetComponent();
+ mainImage.maskable = true;
+
+ var mask = obj.AddComponent();
+ mask.showMaskGraphic = true;
+
+ var mainLayout = obj.AddComponent();
+ mainLayout.preferredHeight = 230;
+ mainLayout.flexibleHeight = 0;
+
+ var input = UIFactory.CreateTMPInput(obj);
+
+ var inputLayout = input.AddComponent();
+ inputLayout.preferredWidth = 500;
+ inputLayout.flexibleWidth = 9999;
+
+ var scroll = UIFactory.CreateScrollbar(obj);
+
+ var scrollLayout = scroll.AddComponent();
+ scrollLayout.preferredWidth = 25;
+ scrollLayout.flexibleWidth = 0;
+
+ var scroller = scroll.GetComponent();
+ scroller.direction = Scrollbar.Direction.TopToBottom;
+ var scrollColors = scroller.colors;
+ scrollColors.normalColor = new Color(0.5f, 0.5f, 0.5f, 1.0f);
+ //try { scrollColors.selectedColor = scrollColors.normalColor; } catch { }
+ scroller.colors = scrollColors;
+
+ var tmpInput = input.GetComponent();
+ tmpInput.scrollSensitivity = 15;
+ tmpInput.verticalScrollbar = scroller;
+
+ m_textInput = input.GetComponent();
+
+ for (int i = 0; i < 100; i++)
+ {
+ Log("hello " + i);
+ }
+
+ Log("hello", Color.red);
+ Log("hello", Color.yellow);
+ }
+
+ public static void Log(string message)
+ {
+ Log(message, null);
+ }
+
+ public static void Log(string message, Color color)
+ {
+ Log(message, color.ToHex());
+ }
+
+ public static void Log(string message, string hexColor)
+ {
+ if (Instance == null)
+ return;
+
+ Instance.AllMessages.Add(message);
+
+ if (Instance.m_textInput)
+ {
+ if (hexColor != null)
+ message = $"{message}";
+
+ Instance.m_textInput.text = $"{message}\n{Instance.m_textInput.text}";
+ }
+ }
+ }
+}
diff --git a/src/UI/Main/MainMenu.cs b/src/UI/Main/MainMenu.cs
index a328d41..c3e1c33 100644
--- a/src/UI/Main/MainMenu.cs
+++ b/src/UI/Main/MainMenu.cs
@@ -75,14 +75,14 @@ namespace ExplorerBeta.UI.Main
var colors = button.colors;
colors.normalColor = m_navButtonSelected;
- colors.selectedColor = m_navButtonSelected;
+ //try { colors.selectedColor = m_navButtonSelected; } catch { }
button.colors = colors;
if (m_lastNavButtonPressed && m_lastNavButtonPressed != button)
{
var oldColors = m_lastNavButtonPressed.colors;
oldColors.normalColor = m_navButtonNormal;
- oldColors.selectedColor = m_navButtonNormal;
+ //try { oldColors.selectedColor = m_navButtonNormal; } catch { }
m_lastNavButtonPressed.colors = oldColors;
}
@@ -110,6 +110,13 @@ namespace ExplorerBeta.UI.Main
ConstructNavbar(content);
ConstructMainViewport(content);
+
+ ConstructDebugConsole(content);
+ }
+
+ private void ConstructDebugConsole(GameObject content)
+ {
+ new DebugConsole(content);
}
private void ConstructTitleBar(GameObject content)
@@ -176,8 +183,6 @@ namespace ExplorerBeta.UI.Main
private void ConstructNavbar(GameObject content)
{
- // Todo add pages programatically
-
var navbarObj = UIFactory.CreateHorizontalGroup(content);
var navGroup = navbarObj.GetComponent();
@@ -210,7 +215,7 @@ namespace ExplorerBeta.UI.Main
// Set button colors
var colorBlock = btn.colors;
colorBlock.normalColor = m_navButtonNormal;
- colorBlock.selectedColor = colorBlock.normalColor;
+ //try { colorBlock.selectedColor = colorBlock.normalColor; } catch { }
colorBlock.highlightedColor = m_navButtonHighlight;
colorBlock.pressedColor = m_navButtonSelected;
btn.colors = colorBlock;
diff --git a/src/UI/UIFactory.cs b/src/UI/UIFactory.cs
index f857a8a..de9b2a4 100644
--- a/src/UI/UIFactory.cs
+++ b/src/UI/UIFactory.cs
@@ -2,12 +2,13 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace ExplorerBeta.UI
{
- public static class UIFactory
+ public static class UIFactory
{
private static Vector2 s_ThickElementSize = new Vector2(160f, 30f);
private static Vector2 s_ThinElementSize = new Vector2(160f, 20f);
@@ -35,7 +36,7 @@ namespace ExplorerBeta.UI
var rect = obj.AddComponent();
if (size != default)
- {
+ {
rect.sizeDelta = size;
}
@@ -72,7 +73,7 @@ namespace ExplorerBeta.UI
SetLayerRecursively(child);
}
- private static void SetLayerRecursively(GameObject go)
+ public static void SetLayerRecursively(GameObject go)
{
go.layer = 5;
Transform transform = go.transform;
@@ -145,7 +146,7 @@ namespace ExplorerBeta.UI
}
public static GameObject CreateHorizontalGroup(GameObject parent, Color color = default)
- {
+ {
var groupObj = CreateUIObject("HorizontalLayout", parent);
var horiGroup = groupObj.AddComponent();
@@ -162,15 +163,16 @@ namespace ExplorerBeta.UI
}
public static GameObject CreateLabel(GameObject parent, TextAnchor alignment)
- {
+ {
GameObject labelObj = CreateUIObject("Label", parent, s_ThinElementSize);
var text = labelObj.AddComponent();
SetDefaultTextValues(text);
text.alignment = alignment;
+ text.supportRichText = true;
return labelObj;
- }
+ }
public static GameObject CreateButton(GameObject parent)
{
@@ -333,6 +335,86 @@ namespace ExplorerBeta.UI
return toggleObj;
}
+ public static GameObject CreateTMPInput(GameObject parent)
+ {
+ GameObject mainObj = CreateUIObject("InputField (TMP)", parent);
+
+ Image mainImage = mainObj.AddComponent();
+ mainImage.type = Image.Type.Sliced;
+ mainImage.color = new Color(38f / 255f, 38f / 255f, 38f / 255f, 1.0f);
+
+ var mainInput = mainObj.AddComponent();
+ mainInput.navigation.mode = Navigation.Mode.None;
+ mainInput.richText = true;
+ mainInput.isRichTextEditingAllowed = true;
+ mainInput.lineType = TMP_InputField.LineType.MultiLineNewline;
+ mainInput.interactable = true;
+ mainInput.transition = Selectable.Transition.ColorTint;
+ mainInput.onFocusSelectAll = false;
+
+ var mainColors = mainInput.colors;
+ mainColors.normalColor = new Color(1, 1, 1, 1);
+ mainColors.highlightedColor = new Color(245f / 255f, 245f / 255f, 245f / 255f, 1.0f);
+ mainColors.pressedColor = new Color(200f / 255f, 200f / 255f, 200f / 255f, 1.0f);
+ mainColors.highlightedColor = new Color(245f / 255f, 245f / 255f, 245f / 255f, 1.0f);
+ mainInput.colors = mainColors;
+
+ var mainGroup = mainObj.AddComponent();
+ mainGroup.childControlHeight = true;
+ mainGroup.childControlWidth = true;
+ mainGroup.childForceExpandWidth = true;
+ mainGroup.childForceExpandHeight = true;
+
+ var textArea = CreateUIObject("Text Area", mainObj);
+ textArea.AddComponent();
+
+ var textAreaRect = textArea.GetComponent();
+ textAreaRect.anchorMin = new Vector2(0, 0);
+ textAreaRect.anchorMax = new Vector2(1, 1);
+ textAreaRect.offsetMin = new Vector2(10, 7);
+ textAreaRect.offsetMax = new Vector2(10, 6);
+
+ mainInput.textViewport = textArea.GetComponent();
+
+ var placeHolderObj = CreateUIObject("Placeholder", textArea);
+ var placeholderText = placeHolderObj.AddComponent();
+ placeholderText.fontSize = 16;
+ placeholderText.text = "Nothing logged yet...";
+ placeholderText.color = new Color(0.5f, 0.5f, 0.5f, 1.0f);
+
+ var placeHolderRect = placeHolderObj.GetComponent();
+ placeHolderRect.anchorMin = Vector2.zero;
+ placeHolderRect.anchorMax = Vector2.one;
+ placeHolderRect.offsetMin = Vector2.zero;
+ placeHolderRect.offsetMax = Vector2.zero;
+
+ var placeholderLayout = placeHolderObj.AddComponent();
+ placeholderLayout.preferredWidth = 990;
+ placeholderLayout.flexibleWidth = 500;
+
+ mainInput.placeholder = placeholderText;
+
+ var inputTextObj = CreateUIObject("Text", textArea);
+ var inputText = inputTextObj.AddComponent();
+ inputText.fontSize = 16;
+ inputText.text = "";
+ inputText.color = new Color(1f, 1f, 1f, 1f);
+
+ var inputTextRect = inputTextObj.GetComponent();
+ inputTextRect.anchorMin = Vector2.zero;
+ inputTextRect.anchorMax = Vector2.one;
+ inputTextRect.offsetMin = Vector2.zero;
+ inputTextRect.offsetMax = Vector2.zero;
+
+ var test = inputTextObj.AddComponent();
+ test.preferredWidth = 990;
+ test.flexibleWidth = 500;
+
+ mainInput.textComponent = inputText;
+
+ return mainObj;
+ }
+
public static GameObject CreateInputField(GameObject parent)
{
GameObject inputObj = CreateUIObject("InputField", parent, s_ThickElementSize);
@@ -528,7 +610,7 @@ namespace ExplorerBeta.UI
return dropdownObj;
}
- public static GameObject CreateScrollView(GameObject parent, out GameObject content)
+ public static GameObject CreateScrollView(GameObject parent, out GameObject content, Color color = default)
{
GameObject scrollObj = CreateUIObject("Scroll View", parent);
@@ -602,14 +684,17 @@ namespace ExplorerBeta.UI
scrollRect.scrollSensitivity = 25;
Image scrollImage = scrollObj.AddComponent();
- scrollImage.sprite = UIResources.background;
- scrollImage.type = Image.Type.Sliced;
- scrollImage.color = s_PanelColor;
- viewportObj.AddComponent().showMaskGraphic = false;
+ scrollImage.type = Image.Type.Filled;
+
+ scrollImage.color = (color == default) ? new Color(0.3f, 0.3f, 0.3f, 1f) : color;
Image viewportImage = viewportObj.AddComponent();
viewportImage.sprite = UIResources.mask;
viewportImage.type = Image.Type.Sliced;
+ viewportImage.color = new Color(1, 1, 1, 1);
+
+ var mask = viewportObj.AddComponent();
+ mask.showMaskGraphic = false;
return scrollObj;
}
diff --git a/src/UI/UIManager.cs b/src/UI/UIManager.cs
index 80d2776..be63109 100644
--- a/src/UI/UIManager.cs
+++ b/src/UI/UIManager.cs
@@ -28,6 +28,12 @@ namespace ExplorerBeta.UI
// Create submodules
new MainMenu();
+
+ // Force refresh of anchors (?)
+ Canvas.ForceUpdateCanvases();
+
+ CanvasRoot.SetActive(false);
+ CanvasRoot.SetActive(true);
}
public static void SetEventSystem()
diff --git a/src/Unstrip/ColorUtility/ColorUtilityUnstrip.cs b/src/Unstrip/ColorUtility/ColorUtilityUnstrip.cs
new file mode 100644
index 0000000..8611c9a
--- /dev/null
+++ b/src/Unstrip/ColorUtility/ColorUtilityUnstrip.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using UnityEngine;
+
+namespace Explorer.Unstrip.ColorUtility
+{
+ public static class ColorUtilityUnstrip
+ {
+ public static string ToHex(this Color color)
+ {
+ var color32 = new Color32(
+ (byte)Mathf.Clamp(Mathf.RoundToInt(color.r * 255f), 0, 255),
+ (byte)Mathf.Clamp(Mathf.RoundToInt(color.g * 255f), 0, 255),
+ (byte)Mathf.Clamp(Mathf.RoundToInt(color.b * 255f), 0, 255),
+ 1
+ );
+
+ return string.Format("{0:X2}{1:X2}{2:X2}", color32.r, color32.g, color32.b);
+ }
+ }
+}