Compare commits

..

63 Commits
4.7.0 ... 4.7.8

Author SHA1 Message Date
6f44a3376b Bump UniverseLib 2022-04-24 05:58:36 +10:00
3a6b573ac3 Bump version 2022-04-24 05:57:29 +10:00
cbe17927fb Ensure valid panel size after loading save data 2022-04-24 05:57:22 +10:00
15f3f37948 Clean up all objects in editor 2022-04-24 05:56:47 +10:00
de6760e427 Add more convenient editor config serialization 2022-04-24 05:56:36 +10:00
83edd1b9bb Bump editor package 2022-04-24 02:12:57 +10:00
613be34e95 Bump UniverseLib 2022-04-24 02:04:08 +10:00
58c65b9b8b Make TypeCompleter asynchronous 2022-04-24 02:02:34 +10:00
6fcf6a521c Bump version 2022-04-24 02:02:29 +10:00
81a174f865 Remove call to obsolete methods 2022-04-24 01:59:53 +10:00
b5e3cc2ea5 Use separate TypeCompleters for different contexts 2022-04-24 01:59:03 +10:00
14f46ade6a Cancel pending generic when edit button pressed 2022-04-24 01:58:27 +10:00
e92556805b Update BepInExConfigHandler.cs 2022-04-23 01:05:51 +10:00
8662742461 Bump version 2022-04-23 00:19:31 +10:00
63393a9d66 Update README.md 2022-04-22 22:31:36 +10:00
13986f95c1 Update UnityExplorer.STANDALONE.Mono.dll 2022-04-22 22:27:48 +10:00
b47bfa1e83 Remove Mono restriction on generic type eligibility 2022-04-22 22:27:43 +10:00
12c51248fe Update Editor package 2022-04-22 22:20:01 +10:00
9b9cb54a79 Fix a typo 2022-04-22 22:19:43 +10:00
6a28a93e3a Update for obsolete method 2022-04-22 22:11:24 +10:00
32e718faeb Bump UniverseLib 2022-04-22 21:31:30 +10:00
4d46b74d54 Fix references for rename 2022-04-22 21:04:50 +10:00
7e5246cead Recache types when borrowing 2022-04-22 21:04:23 +10:00
abf5267364 Fix HookCreator method filtering 2022-04-22 21:03:51 +10:00
3afee7254c Fix results TypeCompleter issues 2022-04-22 21:03:33 +10:00
1643d4b7dd Allow generic class construction for unbound types 2022-04-22 21:03:11 +10:00
cef8c12d20 Fix TryFocusActiveInspector for classes 2022-04-22 21:02:45 +10:00
5e07847356 Make current hooks view smaller in height 2022-04-22 21:02:08 +10:00
2dc6e386df Fix generated patch code for ref and subclasses 2022-04-22 21:01:47 +10:00
ff882296fd Fix for GenericConstructorWidget, adjust UI 2022-04-22 21:01:09 +10:00
ecc33927ee Make GenericConstructorWidget reusable 2022-04-22 21:00:18 +10:00
6e91f2a792 Hooks: Add support for generic classes and methods 2022-04-22 09:15:51 +10:00
97cb14d6fc HookInstance: Clean up generated patch code 2022-04-22 09:12:38 +10:00
8b861f7c77 Log Panel: Remove a todo 2022-04-22 09:12:22 +10:00
9379e0f813 Fix constraints on AddComponent TypeCompleter 2022-04-22 09:08:49 +10:00
bdda12a040 Remove redundant reference to EvaluateWidget 2022-04-22 09:08:17 +10:00
75bd654a94 TypeCompleter: Allow generics, support shorthand names 2022-04-22 09:07:51 +10:00
f174c7543a C# Console: Fix autocomplete caret deselection 2022-04-22 09:06:52 +10:00
08f2c6035e Bump version 2022-04-20 18:47:23 +10:00
475e24a66a Update editor package 2022-04-20 18:47:19 +10:00
c62b93535d Update position input when Reset button clicked 2022-04-20 18:47:12 +10:00
374d0b3bae Bump UniverseLib 2022-04-20 18:46:48 +10:00
1f87e89b97 Add some more functionality to Freecam
- Option to use Game's camera
- Button to reset position back to original cam pos
- Free cam position will be stored between stopping/starting free cam
2022-04-19 19:37:05 +10:00
495bc41a8d Bump Editor package 2022-04-19 18:06:16 +10:00
9cf62c3250 Bump UniverseLib, fix EventSystem issue 2022-04-19 18:05:55 +10:00
4c9b3115cd Update UnityEditorPackage 2022-04-19 01:23:11 +10:00
ebdce70418 Move instructions 2022-04-19 01:22:25 +10:00
7c0b37440b Update UnityEditorPackage 2022-04-19 01:19:04 +10:00
0d8ab8bf14 Allow FreeCam to run when menu closed 2022-04-19 01:12:33 +10:00
5a3cad9be2 Fix weird Behaviour inheritance issue 2022-04-19 00:57:13 +10:00
70d67f1dad Bump version 2022-04-18 21:39:50 +10:00
469484d129 Add FreeCam panel 2022-04-18 21:39:17 +10:00
c5e262d1c3 Fix UEPanel save data issue 2022-04-18 21:39:11 +10:00
53c8dfcb6d Bump UniverseLib 2022-04-18 21:38:49 +10:00
ae3ac21992 Add test for Il2CppSystem.Array 2022-04-18 19:12:42 +10:00
7765b64748 Make MouseInspector panel just a PanelBase 2022-04-18 19:12:21 +10:00
a5023d03f4 Update to UniverseLib 1.3.4 2022-04-18 19:11:39 +10:00
a5e6b65dee Add UniverseLib to C# Console default usings 2022-04-18 19:10:24 +10:00
c45cd8c1e1 Update editor package 2022-04-14 02:41:18 +10:00
e46e24e1af Fix typo 2022-04-14 02:32:01 +10:00
3d66493f9c Use UniverseLib PanelBase/PanelDragger 2022-04-14 01:25:59 +10:00
7e0f98ef91 Automatic code cleanup (no real changes)
- Use explicit type of var
- Use 'new()'
- Remove unnecessary usings
- Sort usings
- Apply formatting
2022-04-12 05:20:35 +10:00
693f5818be Remove duplicate UIManager.Update call 2022-04-12 04:46:04 +10:00
110 changed files with 2747 additions and 3420 deletions

View File

@ -115,7 +115,7 @@ The inspector is used to see detailed information on objects of any type and man
### Hook Manager ### Hook Manager
* The Hooks panel allows you to hook methods at the click of a button for debugging purposes. * The Hooks panel allows you to hook methods at the click of a button for debugging purposes.
* Simply enter any class (generic types not yet supported) and hook the methods you want from the menu. * Simply enter any class and hook the methods you want from the menu.
* You can edit the source code of the generated hook with the "Edit Hook Source" button. Accepted method names are `Prefix` (which can return `bool` or `void`), `Postfix`, `Finalizer` (which can return `Exception` or `void`), and `Transpiler` (which must return `IEnumerable<HarmonyLib.CodeInstruction>`). You can define multiple patches if you wish. * You can edit the source code of the generated hook with the "Edit Hook Source" button. Accepted method names are `Prefix` (which can return `bool` or `void`), `Postfix`, `Finalizer` (which can return `Exception` or `void`), and `Transpiler` (which must return `IEnumerable<HarmonyLib.CodeInstruction>`). You can define multiple patches if you wish.
### Mouse-Inspect ### Mouse-Inspect
@ -124,6 +124,13 @@ The inspector is used to see detailed information on objects of any type and man
* <b>World</b>: uses Physics.Raycast to look for Colliders * <b>World</b>: uses Physics.Raycast to look for Colliders
* <b>UI</b>: uses GraphicRaycasters to find UI objects * <b>UI</b>: uses GraphicRaycasters to find UI objects
### Freecam
* UnityExplorer provides a basic Free Camera which you can control with your keyboard and mouse.
* Unlike all other features of UnityExplorer, you can still use Freecam while UnityExplorer's menu is hidden.
* Supports using the game's main Camera or a separate custom Camera.
* See the Freecam panel for further instructions and details.
### Clipboard ### Clipboard
* The "Clipboard" panel allows you to see your current paste value, or clear it (resets it to `null`) * The "Clipboard" panel allows you to see your current paste value, or clear it (resets it to `null`)

View File

@ -62,9 +62,7 @@ The inspector is used to see detailed information on objects of any type and man
### Settings ### Settings
* You can change the settings via the "Options" tab of the menu, or directly from the config file. * You can change the settings via the "Options" tab of the menu, or directly from the config file.
* BepInEx: `BepInEx\config\com.sinai.unityexplorer.cfg` * <AssetsFolder>/sinai-dev-UnityExplorer~/config.cfg
* MelonLoader: `UserData\MelonPreferences.cfg`
* Standalone `{DLL_location}\UnityExplorer\config.cfg`
# Acknowledgments # Acknowledgments

View File

@ -1,6 +1,6 @@
{ {
"name": "com.sinai-dev.unityexplorer", "name": "com.sinai-dev.unityexplorer",
"version": "4.7.0", "version": "4.7.8",
"displayName": "UnityExplorer", "displayName": "UnityExplorer",
"description": "An in-game UI for exploring, debugging and modifying Unity games.", "description": "An in-game UI for exploring, debugging and modifying Unity games.",
"unity": "2017.1", "unity": "2017.1",

View File

@ -2,12 +2,10 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using UnityEngine;
using UnityExplorer.CSConsole.Lexers; using UnityExplorer.CSConsole.Lexers;
using UnityExplorer.UI; using UnityExplorer.UI.Panels;
using UnityExplorer.UI.Widgets.AutoComplete; using UnityExplorer.UI.Widgets.AutoComplete;
using UniverseLib; using UniverseLib;
using UniverseLib.UI;
using UniverseLib.UI.Models; using UniverseLib.UI.Models;
using UniverseLib.Utility; using UniverseLib.Utility;
@ -29,10 +27,23 @@ namespace UnityExplorer.CSConsole
private readonly HashSet<char> delimiters = new() private readonly HashSet<char> delimiters = new()
{ {
'{', '}', ',', ';', '<', '>', '(', ')', '[', ']', '=', '|', '&', '?' '{',
'}',
',',
';',
'<',
'>',
'(',
')',
'[',
']',
'=',
'|',
'&',
'?'
}; };
private readonly List<Suggestion> suggestions = new List<Suggestion>(); private readonly List<Suggestion> suggestions = new();
public void CheckAutocompletes() public void CheckAutocompletes()
{ {
@ -83,7 +94,7 @@ namespace UnityExplorer.CSConsole
// Get manual namespace completions // Get manual namespace completions
foreach (var ns in ReflectionUtility.AllNamespaces) foreach (string ns in ReflectionUtility.AllNamespaces)
{ {
if (ns.StartsWith(input)) if (ns.StartsWith(input))
{ {
@ -97,7 +108,7 @@ namespace UnityExplorer.CSConsole
// Get manual keyword completions // Get manual keyword completions
foreach (var kw in KeywordLexer.keywords) foreach (string kw in KeywordLexer.keywords)
{ {
if (kw.StartsWith(input))// && kw.Length > input.Length) if (kw.StartsWith(input))// && kw.Length > input.Length)
{ {
@ -121,11 +132,11 @@ namespace UnityExplorer.CSConsole
} }
private readonly Dictionary<string, string> namespaceHighlights = new Dictionary<string, string>(); private readonly Dictionary<string, string> namespaceHighlights = new();
private readonly Dictionary<string, string> keywordHighlights = new Dictionary<string, string>(); private readonly Dictionary<string, string> keywordHighlights = new();
private readonly StringBuilder highlightBuilder = new StringBuilder(); private readonly StringBuilder highlightBuilder = new();
private const string OPEN_HIGHLIGHT = "<color=cyan>"; private const string OPEN_HIGHLIGHT = "<color=cyan>";
private string GetHighlightString(string prefix, string completion) private string GetHighlightString(string prefix, string completion)

View File

@ -1,4 +1,6 @@
using System; using HarmonyLib;
using Mono.CSharp;
using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@ -8,18 +10,14 @@ using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.EventSystems; using UnityEngine.EventSystems;
using UnityEngine.UI; using UnityEngine.UI;
using UniverseLib.Input;
using UnityExplorer.CSConsole;
using UnityExplorer.UI; using UnityExplorer.UI;
using UnityExplorer.UI.Panels; using UnityExplorer.UI.Panels;
using UnityExplorer.UI.Widgets.AutoComplete; using UnityExplorer.UI.Widgets.AutoComplete;
using UniverseLib.UI;
using UniverseLib; using UniverseLib;
using UniverseLib.Input;
using UniverseLib.Runtime;
using UniverseLib.UI.Models; using UniverseLib.UI.Models;
using UniverseLib.Utility; using UniverseLib.Utility;
using HarmonyLib;
using UniverseLib.Runtime;
using Mono.CSharp;
namespace UnityExplorer.CSConsole namespace UnityExplorer.CSConsole
{ {
@ -54,6 +52,7 @@ namespace UnityExplorer.CSConsole
"System.Collections", "System.Collections",
"System.Collections.Generic", "System.Collections.Generic",
"UnityEngine", "UnityEngine",
"UniverseLib",
#if CPP #if CPP
"UnhollowerBaseLib", "UnhollowerBaseLib",
"UnhollowerRuntimeLib", "UnhollowerRuntimeLib",
@ -62,8 +61,6 @@ namespace UnityExplorer.CSConsole
public static void Init() public static void Init()
{ {
InitEventSystemPropertyHandlers();
// Make sure console is supported on this platform // Make sure console is supported on this platform
try try
{ {
@ -99,11 +96,11 @@ namespace UnityExplorer.CSConsole
if (!Directory.Exists(ScriptsFolder)) if (!Directory.Exists(ScriptsFolder))
Directory.CreateDirectory(ScriptsFolder); Directory.CreateDirectory(ScriptsFolder);
var startupPath = Path.Combine(ScriptsFolder, "startup.cs"); string startupPath = Path.Combine(ScriptsFolder, "startup.cs");
if (File.Exists(startupPath)) if (File.Exists(startupPath))
{ {
ExplorerCore.Log($"Executing startup script from '{startupPath}'..."); ExplorerCore.Log($"Executing startup script from '{startupPath}'...");
var text = File.ReadAllText(startupPath); string text = File.ReadAllText(startupPath);
Input.Text = text; Input.Text = text;
Evaluate(); Evaluate();
} }
@ -153,7 +150,7 @@ namespace UnityExplorer.CSConsole
if (Evaluator != null) if (Evaluator != null)
Evaluator.Dispose(); Evaluator.Dispose();
GenerateTextWriter(); GenerateTextWriter();
Evaluator = new ScriptEvaluator(evaluatorStringWriter) Evaluator = new ScriptEvaluator(evaluatorStringWriter)
{ {
@ -161,7 +158,7 @@ namespace UnityExplorer.CSConsole
}; };
usingDirectives = new HashSet<string>(); usingDirectives = new HashSet<string>();
foreach (var use in DefaultUsing) foreach (string use in DefaultUsing)
AddUsing(use); AddUsing(use);
if (logSuccess) if (logSuccess)
@ -200,7 +197,7 @@ namespace UnityExplorer.CSConsole
{ {
// Compile the code. If it returned a CompiledMethod, it is REPL. // Compile the code. If it returned a CompiledMethod, it is REPL.
CompiledMethod repl = Evaluator.Compile(input); CompiledMethod repl = Evaluator.Compile(input);
if (repl != null) if (repl != null)
{ {
// Valid REPL, we have a delegate to the evaluation. // Valid REPL, we have a delegate to the evaluation.
@ -208,7 +205,7 @@ namespace UnityExplorer.CSConsole
{ {
object ret = null; object ret = null;
repl.Invoke(ref ret); repl.Invoke(ref ret);
var result = ret?.ToString(); string result = ret?.ToString();
if (!string.IsNullOrEmpty(result)) if (!string.IsNullOrEmpty(result))
ExplorerCore.Log($"Invoked REPL, result: {ret}"); ExplorerCore.Log($"Invoked REPL, result: {ret}");
else else
@ -222,13 +219,13 @@ namespace UnityExplorer.CSConsole
else else
{ {
// The compiled code was not REPL, so it was a using directive or it defined classes. // The compiled code was not REPL, so it was a using directive or it defined classes.
string output = Evaluator._textWriter.ToString(); string output = Evaluator._textWriter.ToString();
var outputSplit = output.Split('\n'); string[] outputSplit = output.Split('\n');
if (outputSplit.Length >= 2) if (outputSplit.Length >= 2)
output = outputSplit[outputSplit.Length - 2]; output = outputSplit[outputSplit.Length - 2];
evaluatorOutput.Clear(); evaluatorOutput.Clear();
if (ScriptEvaluator._reportPrinter.ErrorsCount > 0) if (ScriptEvaluator._reportPrinter.ErrorsCount > 0)
throw new FormatException($"Unable to compile the code. Evaluator's last output was:\r\n{output}"); throw new FormatException($"Unable to compile the code. Evaluator's last output was:\r\n{output}");
else if (!supressLog) else if (!supressLog)
@ -286,7 +283,7 @@ namespace UnityExplorer.CSConsole
DoAutoIndent(); DoAutoIndent();
} }
var inStringOrComment = HighlightVisibleInput(); bool inStringOrComment = HighlightVisibleInput();
if (!settingCaretCoroutine) if (!settingCaretCoroutine)
{ {
@ -359,12 +356,12 @@ namespace UnityExplorer.CSConsole
// If caret moved, ensure caret is visible in the viewport // If caret moved, ensure caret is visible in the viewport
if (caretMoved) if (caretMoved)
{ {
var charInfo = Input.TextGenerator.characters[LastCaretPosition]; UICharInfo charInfo = Input.TextGenerator.characters[LastCaretPosition];
var charTop = charInfo.cursorPos.y; float charTop = charInfo.cursorPos.y;
var charBot = charTop - CSCONSOLE_LINEHEIGHT; float charBot = charTop - CSCONSOLE_LINEHEIGHT;
var viewportMin = Input.Transform.rect.height - Input.Transform.anchoredPosition.y - (Input.Transform.rect.height * 0.5f); float viewportMin = Input.Transform.rect.height - Input.Transform.anchoredPosition.y - (Input.Transform.rect.height * 0.5f);
var viewportMax = viewportMin - Panel.InputScroller.ViewportRect.rect.height; float viewportMax = viewportMin - Panel.InputScroller.ViewportRect.rect.height;
float diff = 0f; float diff = 0f;
if (charTop > viewportMin) if (charTop > viewportMin)
@ -374,7 +371,7 @@ namespace UnityExplorer.CSConsole
if (Math.Abs(diff) > 1) if (Math.Abs(diff) > 1)
{ {
var rect = Input.Transform; RectTransform rect = Input.Transform;
rect.anchoredPosition = new Vector2(rect.anchoredPosition.x, rect.anchoredPosition.y - diff); rect.anchoredPosition = new Vector2(rect.anchoredPosition.x, rect.anchoredPosition.y - diff);
} }
} }
@ -387,82 +384,17 @@ namespace UnityExplorer.CSConsole
RuntimeHelper.StartCoroutine(SetCaretCoroutine(caretPosition)); RuntimeHelper.StartCoroutine(SetCaretCoroutine(caretPosition));
} }
static void InitEventSystemPropertyHandlers()
{
try
{
foreach (var member in typeof(EventSystem).GetMembers(AccessTools.all))
{
if (member.Name == "m_CurrentSelected")
{
Type backingType;
if (member.MemberType == MemberTypes.Property)
backingType = (member as PropertyInfo).PropertyType;
else
backingType = (member as FieldInfo).FieldType;
usingEventSystemDictionaryMembers = ReflectionUtility.IsDictionary(backingType);
break;
}
}
}
catch (Exception ex)
{
ExplorerCore.LogWarning($"Exception checking EventSystem property backing type: {ex}");
}
}
static bool usingEventSystemDictionaryMembers;
static readonly AmbiguousMemberHandler<EventSystem, GameObject> m_CurrentSelected_Handler_Normal
= new(true, true, "m_CurrentSelected", "m_currentSelected");
static readonly AmbiguousMemberHandler<EventSystem, Dictionary<int, GameObject>> m_CurrentSelected_Handler_Dictionary
= new(true, true, "m_CurrentSelected", "m_currentSelected");
static readonly AmbiguousMemberHandler<EventSystem, bool> m_SelectionGuard_Handler_Normal
= new(true, true, "m_SelectionGuard", "m_selectionGuard");
static readonly AmbiguousMemberHandler<EventSystem, Dictionary<int, bool>> m_SelectionGuard_Handler_Dictionary
= new(true, true, "m_SelectionGuard", "m_selectionGuard");
static void SetCurrentSelectedGameObject(EventSystem instance, GameObject value)
{
instance.SetSelectedGameObject(value);
if (usingEventSystemDictionaryMembers)
m_CurrentSelected_Handler_Dictionary.GetValue(instance)[0] = value;
else
m_CurrentSelected_Handler_Normal.SetValue(instance, value);
}
static void SetSelectionGuard(EventSystem instance, bool value)
{
if (usingEventSystemDictionaryMembers)
m_SelectionGuard_Handler_Dictionary.GetValue(instance)[0] = value;
else
m_SelectionGuard_Handler_Normal.SetValue(instance, value);
}
private static IEnumerator SetCaretCoroutine(int caretPosition) private static IEnumerator SetCaretCoroutine(int caretPosition)
{ {
var color = Input.Component.selectionColor; Color color = Input.Component.selectionColor;
color.a = 0f; color.a = 0f;
Input.Component.selectionColor = color; Input.Component.selectionColor = color;
try { SetCurrentSelectedGameObject(CursorUnlocker.CurrentEventSystem, null); } EventSystemHelper.SetSelectionGuard(false);
catch (Exception ex) { ExplorerCore.Log($"Failed removing selected object: {ex}"); }
yield return null; // ~~~~~~~ YIELD FRAME ~~~~~~~~~
try { SetSelectionGuard(CursorUnlocker.CurrentEventSystem, false); }
catch (Exception ex) { ExplorerCore.Log($"Failed setting selection guard: {ex}"); }
try { SetCurrentSelectedGameObject(CursorUnlocker.CurrentEventSystem, Input.GameObject); }
catch (Exception ex) { ExplorerCore.Log($"Failed setting selected gameobject: {ex}"); }
yield return null; // ~~~~~~~ YIELD FRAME ~~~~~~~~~
Input.Component.Select(); Input.Component.Select();
yield return null; // ~~~~~~~ YIELD FRAME ~~~~~~~~~
Input.Component.caretPosition = caretPosition; Input.Component.caretPosition = caretPosition;
Input.Component.selectionFocusPosition = caretPosition; Input.Component.selectionFocusPosition = caretPosition;
LastCaretPosition = Input.Component.caretPosition; LastCaretPosition = Input.Component.caretPosition;
@ -495,12 +427,12 @@ namespace UnityExplorer.CSConsole
// the top and bottom position of the viewport in relation to the text height // the top and bottom position of the viewport in relation to the text height
// they need the half-height adjustment to normalize against the 'line.topY' value. // they need the half-height adjustment to normalize against the 'line.topY' value.
var viewportMin = Input.Transform.rect.height - Input.Transform.anchoredPosition.y - (Input.Transform.rect.height * 0.5f); float viewportMin = Input.Transform.rect.height - Input.Transform.anchoredPosition.y - (Input.Transform.rect.height * 0.5f);
var viewportMax = viewportMin - Panel.InputScroller.ViewportRect.rect.height; float viewportMax = viewportMin - Panel.InputScroller.ViewportRect.rect.height;
for (int i = 0; i < Input.TextGenerator.lineCount; i++) for (int i = 0; i < Input.TextGenerator.lineCount; i++)
{ {
var line = Input.TextGenerator.lines[i]; UILineInfo line = Input.TextGenerator.lines[i];
// if not set the top line yet, and top of line is below the viewport top // if not set the top line yet, and top of line is below the viewport top
if (topLine == -1 && line.topY <= viewportMin) if (topLine == -1 && line.topY <= viewportMin)
topLine = i; topLine = i;
@ -534,7 +466,7 @@ namespace UnityExplorer.CSConsole
realStartLine++; realStartLine++;
char lastPrev = '\n'; char lastPrev = '\n';
var sb = new StringBuilder(); StringBuilder sb = new();
// append leading new lines for spacing (no point rendering line numbers we cant see) // append leading new lines for spacing (no point rendering line numbers we cant see)
for (int i = 0; i < topLine; i++) for (int i = 0; i < topLine; i++)
@ -676,7 +608,7 @@ Doorstop example:
public static void SetupHelpInteraction() public static void SetupHelpInteraction()
{ {
var drop = Panel.HelpDropdown; Dropdown drop = Panel.HelpDropdown;
helpDict.Add("Help", ""); helpDict.Add("Help", "");
helpDict.Add("Usings", HELP_USINGS); helpDict.Add("Usings", HELP_USINGS);
@ -684,7 +616,7 @@ Doorstop example:
helpDict.Add("Classes", HELP_CLASSES); helpDict.Add("Classes", HELP_CLASSES);
helpDict.Add("Coroutines", HELP_COROUTINES); helpDict.Add("Coroutines", HELP_COROUTINES);
foreach (var opt in helpDict) foreach (KeyValuePair<string, string> opt in helpDict)
drop.options.Add(new Dropdown.OptionData(opt.Key)); drop.options.Add(new Dropdown.OptionData(opt.Key));
} }
@ -693,7 +625,7 @@ Doorstop example:
if (index == 0) if (index == 0)
return; return;
var helpText = helpDict.ElementAt(index); KeyValuePair<string, string> helpText = helpDict.ElementAt(index);
Input.Text = helpText.Value; Input.Text = helpText.Value;
@ -706,7 +638,7 @@ Doorstop example:
// It is recommended to use the Log panel (or a console log window) while using this tool. // It is recommended to use the Log panel (or a console log window) while using this tool.
// Use the Help dropdown to see detailed examples of how to use the console. // Use the Help dropdown to see detailed examples of how to use the console.
// To execute a script automatically on startup, put the script at 'UnityExplorer\Scripts\startup.cs'</color>"; // To execute a script automatically on startup, put the script at 'sinai-dev-UnityExplorer\Scripts\startup.cs'</color>";
internal const string HELP_USINGS = @"// You can add a using directive to any namespace, but you must compile for it to take effect. internal const string HELP_USINGS = @"// You can add a using directive to any namespace, but you must compile for it to take effect.
// It will remain in effect until you Reset the console. // It will remain in effect until you Reset the console.

View File

@ -1,12 +1,7 @@
using Mono.CSharp; using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text; using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.CSConsole.Lexers; using UnityExplorer.CSConsole.Lexers;
using UniverseLib;
using UniverseLib.Utility; using UniverseLib.Utility;
namespace UnityExplorer.CSConsole namespace UnityExplorer.CSConsole
@ -25,14 +20,14 @@ namespace UnityExplorer.CSConsole
#region Core and initialization #region Core and initialization
public const char WHITESPACE = ' '; public const char WHITESPACE = ' ';
public readonly HashSet<char> IndentOpenChars = new HashSet<char> { '{', '(' }; public readonly HashSet<char> IndentOpenChars = new() { '{', '(' };
public readonly HashSet<char> IndentCloseChars = new HashSet<char> { '}', ')' }; public readonly HashSet<char> IndentCloseChars = new() { '}', ')' };
private readonly Lexer[] lexers; private readonly Lexer[] lexers;
private readonly HashSet<char> delimiters = new HashSet<char>(); private readonly HashSet<char> delimiters = new();
private readonly StringLexer stringLexer = new StringLexer(); private readonly StringLexer stringLexer = new();
private readonly CommentLexer commentLexer = new CommentLexer(); private readonly CommentLexer commentLexer = new();
public LexerBuilder() public LexerBuilder()
{ {
@ -45,7 +40,7 @@ namespace UnityExplorer.CSConsole
new KeywordLexer(), new KeywordLexer(),
}; };
foreach (var matcher in lexers) foreach (Lexer matcher in lexers)
{ {
foreach (char c in matcher.Delimiters) foreach (char c in matcher.Delimiters)
{ {
@ -97,13 +92,13 @@ namespace UnityExplorer.CSConsole
currentStartIdx = startIdx; currentStartIdx = startIdx;
currentEndIdx = endIdx; currentEndIdx = endIdx;
var sb = new StringBuilder(); StringBuilder sb = new();
for (int i = 0; i < leadingLines; i++) for (int i = 0; i < leadingLines; i++)
sb.Append('\n'); sb.Append('\n');
int lastUnhighlighted = startIdx; int lastUnhighlighted = startIdx;
foreach (var match in GetMatches()) foreach (MatchInfo match in GetMatches())
{ {
// append non-highlighted text between last match and this // append non-highlighted text between last match and this
for (int i = lastUnhighlighted; i < match.startIndex; i++) for (int i = lastUnhighlighted; i < match.startIndex; i++)
@ -130,7 +125,7 @@ namespace UnityExplorer.CSConsole
} }
// check caretIdx to determine inStringOrComment state // check caretIdx to determine inStringOrComment state
if (caretIdx >= match.startIndex && (caretIdx <= (matchEndIdx+1) || (caretIdx >= input.Length && matchEndIdx >= input.Length - 1))) if (caretIdx >= match.startIndex && (caretIdx <= (matchEndIdx + 1) || (caretIdx >= input.Length && matchEndIdx >= input.Length - 1)))
caretInStringOrComment = match.isStringOrComment; caretInStringOrComment = match.isStringOrComment;
} }
@ -158,7 +153,7 @@ namespace UnityExplorer.CSConsole
bool anyMatch = false; bool anyMatch = false;
int startIndex = CommittedIndex + 1; int startIndex = CommittedIndex + 1;
foreach (var lexer in lexers) foreach (Lexer lexer in lexers)
{ {
if (lexer.TryMatchCurrent(this)) if (lexer.TryMatchCurrent(this))
{ {

View File

@ -1,6 +1,4 @@
using System.Collections.Generic; using UnityEngine;
using System.Linq;
using UnityEngine;
namespace UnityExplorer.CSConsole.Lexers namespace UnityExplorer.CSConsole.Lexers
{ {
@ -13,7 +11,7 @@ namespace UnityExplorer.CSConsole.Lexers
} }
// forest green // forest green
protected override Color HighlightColor => new Color(0.34f, 0.65f, 0.29f, 1.0f); protected override Color HighlightColor => new(0.34f, 0.65f, 0.29f, 1.0f);
public override bool TryMatchCurrent(LexerBuilder lexer) public override bool TryMatchCurrent(LexerBuilder lexer)
{ {

View File

@ -7,9 +7,9 @@ namespace UnityExplorer.CSConsole.Lexers
public class KeywordLexer : Lexer public class KeywordLexer : Lexer
{ {
// system blue // system blue
protected override Color HighlightColor => new Color(0.33f, 0.61f, 0.83f, 1.0f); protected override Color HighlightColor => new(0.33f, 0.61f, 0.83f, 1.0f);
public static readonly HashSet<string> keywords = new HashSet<string> public static readonly HashSet<string> keywords = new()
{ {
// reserved keywords // reserved keywords
"abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", "class", "const", "continue", "abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", "class", "const", "continue",
@ -28,15 +28,15 @@ namespace UnityExplorer.CSConsole.Lexers
public override bool TryMatchCurrent(LexerBuilder lexer) public override bool TryMatchCurrent(LexerBuilder lexer)
{ {
var prev = lexer.Previous; char prev = lexer.Previous;
var first = lexer.Current; char first = lexer.Current;
// check for keywords // check for keywords
if (lexer.IsDelimiter(prev, true) && char.IsLetter(first)) if (lexer.IsDelimiter(prev, true) && char.IsLetter(first))
{ {
// can be a keyword... // can be a keyword...
var sb = new StringBuilder(); StringBuilder sb = new();
sb.Append(lexer.Current); sb.Append(lexer.Current);
while (!lexer.EndOfInput && char.IsLetter(lexer.PeekNext())) while (!lexer.EndOfInput && char.IsLetter(lexer.PeekNext()))
sb.Append(lexer.Current); sb.Append(lexer.Current);

View File

@ -1,7 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using UnityEngine; using UnityEngine;
using UniverseLib;
using UniverseLib.Utility; using UniverseLib.Utility;
namespace UnityExplorer.CSConsole.Lexers namespace UnityExplorer.CSConsole.Lexers

View File

@ -5,7 +5,7 @@ namespace UnityExplorer.CSConsole.Lexers
public class NumberLexer : Lexer public class NumberLexer : Lexer
{ {
// Maroon // Maroon
protected override Color HighlightColor => new Color(0.58f, 0.33f, 0.33f, 1.0f); protected override Color HighlightColor => new(0.58f, 0.33f, 0.33f, 1.0f);
private bool IsNumeric(char c) => char.IsNumber(c) || c == '.'; private bool IsNumeric(char c) => char.IsNumber(c) || c == '.';

View File

@ -8,7 +8,7 @@ namespace UnityExplorer.CSConsole.Lexers
public override IEnumerable<char> Delimiters => new[] { '"', '\'', }; public override IEnumerable<char> Delimiters => new[] { '"', '\'', };
// orange // orange
protected override Color HighlightColor => new Color(0.79f, 0.52f, 0.32f, 1.0f); protected override Color HighlightColor => new(0.79f, 0.52f, 0.32f, 1.0f);
public override bool TryMatchCurrent(LexerBuilder lexer) public override bool TryMatchCurrent(LexerBuilder lexer)
{ {

View File

@ -1,6 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using UnityEngine; using UnityEngine;
namespace UnityExplorer.CSConsole.Lexers namespace UnityExplorer.CSConsole.Lexers
@ -8,14 +7,14 @@ namespace UnityExplorer.CSConsole.Lexers
public class SymbolLexer : Lexer public class SymbolLexer : Lexer
{ {
// silver // silver
protected override Color HighlightColor => new Color(0.6f, 0.6f, 0.6f); protected override Color HighlightColor => new(0.6f, 0.6f, 0.6f);
// all symbols are delimiters // all symbols are delimiters
public override IEnumerable<char> Delimiters => symbols.Where(it => it != '.'); // '.' is not a delimiter, only a separator. public override IEnumerable<char> Delimiters => symbols.Where(it => it != '.'); // '.' is not a delimiter, only a separator.
public static bool IsSymbol(char c) => symbols.Contains(c); public static bool IsSymbol(char c) => symbols.Contains(c);
public static readonly HashSet<char> symbols = new HashSet<char> public static readonly HashSet<char> symbols = new()
{ {
'[', '{', '(', // open '[', '{', '(', // open
']', '}', ')', // close ']', '}', ')', // close

View File

@ -3,7 +3,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Text;
// Thanks to ManlyMarco for this // Thanks to ManlyMarco for this
@ -13,7 +12,10 @@ namespace UnityExplorer.CSConsole
{ {
private static readonly HashSet<string> StdLib = new(StringComparer.InvariantCultureIgnoreCase) private static readonly HashSet<string> StdLib = new(StringComparer.InvariantCultureIgnoreCase)
{ {
"mscorlib", "System.Core", "System", "System.Xml" "mscorlib",
"System.Core",
"System",
"System.Xml"
}; };
internal TextWriter _textWriter; internal TextWriter _textWriter;
@ -45,7 +47,7 @@ namespace UnityExplorer.CSConsole
private void Reference(Assembly asm) private void Reference(Assembly asm)
{ {
var name = asm.GetName().Name; string name = asm.GetName().Name;
if (name == "completions") if (name == "completions")
return; return;
ReferenceAssembly(asm); ReferenceAssembly(asm);
@ -55,7 +57,7 @@ namespace UnityExplorer.CSConsole
{ {
_reportPrinter = new StreamReportPrinter(tw); _reportPrinter = new StreamReportPrinter(tw);
var settings = new CompilerSettings CompilerSettings settings = new()
{ {
Version = LanguageVersion.Experimental, Version = LanguageVersion.Experimental,
GenerateDebugInfo = false, GenerateDebugInfo = false,

View File

@ -2,11 +2,9 @@
using Mono.CSharp; using Mono.CSharp;
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using UnityEngine; using UnityEngine;
using UnityExplorer.Runtime;
using UnityExplorer.UI.Panels; using UnityExplorer.UI.Panels;
using UniverseLib; using UniverseLib;
@ -29,16 +27,16 @@ namespace UnityExplorer.CSConsole
public static void Inspect(Type type) public static void Inspect(Type type)
=> InspectorManager.Inspect(type); => InspectorManager.Inspect(type);
public static Coroutine Start(IEnumerator ienumerator) public static Coroutine Start(IEnumerator ienumerator)
=> RuntimeHelper.StartCoroutine(ienumerator); => RuntimeHelper.StartCoroutine(ienumerator);
public static void Stop(Coroutine coro) public static void Stop(Coroutine coro)
=> RuntimeHelper.StopCoroutine(coro); => RuntimeHelper.StopCoroutine(coro);
public static void Copy(object obj) public static void Copy(object obj)
=> ClipboardPanel.Copy(obj); => ClipboardPanel.Copy(obj);
public static object Paste() public static object Paste()
=> ClipboardPanel.Current; => ClipboardPanel.Current;
public static void GetUsing() public static void GetUsing()
@ -46,7 +44,7 @@ namespace UnityExplorer.CSConsole
public static void GetVars() public static void GetVars()
{ {
var vars = Evaluator.GetVars()?.Trim(); string vars = Evaluator.GetVars()?.Trim();
if (string.IsNullOrEmpty(vars)) if (string.IsNullOrEmpty(vars))
ExplorerCore.LogWarning("No variables seem to be defined!"); ExplorerCore.LogWarning("No variables seem to be defined!");
else else
@ -59,12 +57,12 @@ namespace UnityExplorer.CSConsole
.GetValue(Evaluator) is CompilationSourceFile sourceFile .GetValue(Evaluator) is CompilationSourceFile sourceFile
&& sourceFile.Containers.Any()) && sourceFile.Containers.Any())
{ {
var sb = new StringBuilder(); StringBuilder sb = new();
sb.Append($"There are {sourceFile.Containers.Count} defined classes:"); sb.Append($"There are {sourceFile.Containers.Count} defined classes:");
foreach (TypeDefinition type in sourceFile.Containers.Where(it => it is TypeDefinition)) foreach (TypeDefinition type in sourceFile.Containers.Where(it => it is TypeDefinition))
{ {
sb.Append($"\n\n{type.MemberName.Name}:"); sb.Append($"\n\n{type.MemberName.Name}:");
foreach (var member in type.Members) foreach (MemberCore member in type.Members)
sb.Append($"\n\t- {member.AttributeTargets}: \"{member.MemberName.Name}\" ({member.ModFlags})"); sb.Append($"\n\t- {member.AttributeTargets}: \"{member.MemberName.Name}\" ({member.ModFlags})");
} }
Log(sb.ToString()); Log(sb.ToString());

View File

@ -1,9 +1,5 @@
using System; using UnityExplorer.CacheObject.Views;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityExplorer.Config; using UnityExplorer.Config;
using UnityExplorer.CacheObject.Views;
namespace UnityExplorer.CacheObject namespace UnityExplorer.CacheObject
{ {

View File

@ -1,8 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text;
using UnityExplorer.Inspectors; using UnityExplorer.Inspectors;
using UniverseLib.Utility; using UniverseLib.Utility;
@ -52,7 +49,7 @@ namespace UnityExplorer.CacheObject
Arguments = CtorInfo.GetParameters(); Arguments = CtorInfo.GetParameters();
ctorReturnType = CtorInfo.DeclaringType; ctorReturnType = CtorInfo.DeclaringType;
} }
if (ctorReturnType.IsGenericTypeDefinition) if (ctorReturnType.IsGenericTypeDefinition)
GenericArguments = ctorReturnType.GetGenericArguments(); GenericArguments = ctorReturnType.GetGenericArguments();
} }

View File

@ -1,8 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text;
using UnityExplorer.Inspectors; using UnityExplorer.Inspectors;
namespace UnityExplorer.CacheObject namespace UnityExplorer.CacheObject
@ -31,7 +28,7 @@ namespace UnityExplorer.CacheObject
{ {
try try
{ {
var ret = FieldInfo.GetValue(DeclaringInstance); object ret = FieldInfo.GetValue(DeclaringInstance);
LastException = null; LastException = null;
return ret; return ret;
} }

View File

@ -1,7 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityExplorer.CacheObject.IValues; using UnityExplorer.CacheObject.IValues;
using UnityExplorer.CacheObject.Views; using UnityExplorer.CacheObject.Views;
using UniverseLib; using UniverseLib;
@ -41,7 +38,7 @@ namespace UnityExplorer.CacheObject
this.DictKey = key; this.DictKey = key;
this.DisplayedKey = key.TryCast(); this.DisplayedKey = key.TryCast();
var type = DisplayedKey.GetType(); Type type = DisplayedKey.GetType();
if (ParseUtility.CanParse(type)) if (ParseUtility.CanParse(type))
{ {
KeyInputWanted = true; KeyInputWanted = true;
@ -60,7 +57,7 @@ namespace UnityExplorer.CacheObject
{ {
base.SetDataToCell(cell); base.SetDataToCell(cell);
var kvpCell = cell as CacheKeyValuePairCell; CacheKeyValuePairCell kvpCell = cell as CacheKeyValuePairCell;
kvpCell.NameLabel.text = $"{DictIndex}:"; kvpCell.NameLabel.text = $"{DictIndex}:";
kvpCell.HiddenNameLabel.Text = ""; kvpCell.HiddenNameLabel.Text = "";

View File

@ -1,8 +1,4 @@
using System; using UnityExplorer.CacheObject.IValues;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityExplorer.CacheObject.IValues;
using UnityExplorer.CacheObject.Views; using UnityExplorer.CacheObject.Views;
namespace UnityExplorer.CacheObject namespace UnityExplorer.CacheObject
@ -25,7 +21,7 @@ namespace UnityExplorer.CacheObject
{ {
base.SetDataToCell(cell); base.SetDataToCell(cell);
var listCell = cell as CacheListEntryCell; CacheListEntryCell listCell = cell as CacheListEntryCell;
listCell.NameLabel.text = $"{ListIndex}:"; listCell.NameLabel.text = $"{ListIndex}:";
listCell.HiddenNameLabel.Text = ""; listCell.HiddenNameLabel.Text = "";

View File

@ -1,21 +1,12 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityExplorer.Runtime;
using UnityExplorer.CacheObject.Views; using UnityExplorer.CacheObject.Views;
using UnityExplorer.Inspectors; using UnityExplorer.Inspectors;
using UniverseLib.UI.Models;
using UnityExplorer.UI;
using UniverseLib;
using UniverseLib.UI;
using UnityExplorer.UI.Widgets; using UnityExplorer.UI.Widgets;
using UniverseLib.Utility; using UniverseLib;
using UniverseLib.UI.ObjectPool; using UniverseLib.UI.ObjectPool;
using System.Collections; using UniverseLib.Utility;
using HarmonyLib;
namespace UnityExplorer.CacheObject namespace UnityExplorer.CacheObject
{ {
@ -38,8 +29,8 @@ namespace UnityExplorer.CacheObject
this.Owner = inspector; this.Owner = inspector;
this.NameLabelText = this switch this.NameLabelText = this switch
{ {
CacheMethod => SignatureHighlighter.HighlightMethod(member as MethodInfo), CacheMethod => SignatureHighlighter.ParseMethod(member as MethodInfo),
CacheConstructor => SignatureHighlighter.HighlightConstructor(member as ConstructorInfo), CacheConstructor => SignatureHighlighter.ParseConstructor(member as ConstructorInfo),
_ => SignatureHighlighter.Parse(member.DeclaringType, false, member), _ => SignatureHighlighter.Parse(member.DeclaringType, false, member),
}; };
@ -105,7 +96,7 @@ namespace UnityExplorer.CacheObject
protected override bool TryAutoEvaluateIfUnitialized(CacheObjectCell objectcell) protected override bool TryAutoEvaluateIfUnitialized(CacheObjectCell objectcell)
{ {
var cell = objectcell as CacheMemberCell; CacheMemberCell cell = objectcell as CacheMemberCell;
cell.EvaluateHolder.SetActive(!ShouldAutoEvaluate); cell.EvaluateHolder.SetActive(!ShouldAutoEvaluate);
if (!ShouldAutoEvaluate) if (!ShouldAutoEvaluate)

View File

@ -1,14 +1,11 @@
using System; using HarmonyLib;
using System.Collections; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text;
using UnityExplorer.Inspectors; using UnityExplorer.Inspectors;
using UnityExplorer.Runtime; using UnityExplorer.Runtime;
using UniverseLib; using UniverseLib;
using HarmonyLib;
using HarmonyLib.Tools;
namespace UnityExplorer.CacheObject namespace UnityExplorer.CacheObject
{ {
@ -75,8 +72,8 @@ namespace UnityExplorer.CacheObject
return sorted; return sorted;
} }
static void TryCacheMember<T>(MemberInfo member, List<T> list, HashSet<string> cachedSigs, static void TryCacheMember<T>(MemberInfo member, List<T> list, HashSet<string> cachedSigs,
Type declaringType, ReflectionInspector inspector, bool ignorePropertyMethodInfos = true) Type declaringType, ReflectionInspector inspector, bool ignorePropertyMethodInfos = true)
where T : CacheMember where T : CacheMember
{ {
try try

View File

@ -1,10 +1,6 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text;
using UnityExplorer.Inspectors; using UnityExplorer.Inspectors;
using UniverseLib;
using UniverseLib.Utility; using UniverseLib.Utility;
namespace UnityExplorer.CacheObject namespace UnityExplorer.CacheObject
@ -18,7 +14,7 @@ namespace UnityExplorer.CacheObject
public override bool ShouldAutoEvaluate => false; public override bool ShouldAutoEvaluate => false;
public CacheMethod (MethodInfo mi) public CacheMethod(MethodInfo mi)
{ {
this.MethodInfo = mi; this.MethodInfo = mi;
} }
@ -36,14 +32,14 @@ namespace UnityExplorer.CacheObject
{ {
try try
{ {
var methodInfo = MethodInfo; MethodInfo methodInfo = MethodInfo;
if (methodInfo.IsGenericMethod) if (methodInfo.IsGenericMethod)
methodInfo = MethodInfo.MakeGenericMethod(Evaluator.TryParseGenericArguments()); methodInfo = MethodInfo.MakeGenericMethod(Evaluator.TryParseGenericArguments());
object ret; object ret;
if (HasArguments) if (HasArguments)
ret = methodInfo.Invoke(DeclaringInstance, Evaluator.TryParseArguments()); ret = methodInfo.Invoke(DeclaringInstance, Evaluator.TryParseArguments());
else else
ret = methodInfo.Invoke(DeclaringInstance, ArgumentUtility.EmptyArgs); ret = methodInfo.Invoke(DeclaringInstance, ArgumentUtility.EmptyArgs);
LastException = null; LastException = null;
return ret; return ret;

View File

@ -1,20 +1,12 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.Runtime;
using UnityExplorer.CacheObject.IValues; using UnityExplorer.CacheObject.IValues;
using UnityExplorer.CacheObject.Views; using UnityExplorer.CacheObject.Views;
using UniverseLib.UI.Models;
using UnityExplorer.UI;
using UniverseLib; using UniverseLib;
using UniverseLib.UI; using UniverseLib.UI;
using UniverseLib.Utility;
using UniverseLib.UI.ObjectPool; using UniverseLib.UI.ObjectPool;
using UniverseLib.Utility;
namespace UnityExplorer.CacheObject namespace UnityExplorer.CacheObject
{ {
@ -134,7 +126,7 @@ namespace UnityExplorer.CacheObject
protected virtual void ProcessOnEvaluate() protected virtual void ProcessOnEvaluate()
{ {
var prevState = State; ValueState prevState = State;
if (LastException != null) if (LastException != null)
{ {
@ -276,9 +268,9 @@ namespace UnityExplorer.CacheObject
if (cell.CopyButton != null) if (cell.CopyButton != null)
{ {
bool hasEvaluated = State != ValueState.NotEvaluated && State != ValueState.Exception; bool canCopy = State != ValueState.NotEvaluated && State != ValueState.Exception;
cell.CopyButton.Component.gameObject.SetActive(hasEvaluated); cell.CopyButton.Component.gameObject.SetActive(canCopy);
cell.PasteButton.Component.gameObject.SetActive(hasEvaluated && this.CanWrite); cell.PasteButton.Component.gameObject.SetActive(canCopy && this.CanWrite);
} }
if (!evaluated) if (!evaluated)
@ -319,7 +311,7 @@ namespace UnityExplorer.CacheObject
SetValueState(cell, new(true, inspectActive: !LastValueWasNull, subContentButtonActive: !LastValueWasNull)); SetValueState(cell, new(true, inspectActive: !LastValueWasNull, subContentButtonActive: !LastValueWasNull));
break; break;
case ValueState.Unsupported: case ValueState.Unsupported:
SetValueState(cell, new (true, inspectActive: !LastValueWasNull)); SetValueState(cell, new(true, inspectActive: !LastValueWasNull));
break; break;
} }
@ -369,7 +361,7 @@ namespace UnityExplorer.CacheObject
// set subcontent button if needed, and for null strings and exceptions // set subcontent button if needed, and for null strings and exceptions
cell.SubContentButton.Component.gameObject.SetActive( cell.SubContentButton.Component.gameObject.SetActive(
args.subContentButtonActive args.subContentButtonActive
&& (!LastValueWasNull || State == ValueState.String || State == ValueState.Exception)); && (!LastValueWasNull || State == ValueState.String || State == ValueState.Exception));
} }
@ -474,12 +466,12 @@ namespace UnityExplorer.CacheObject
public Color valueColor; public Color valueColor;
public bool valueActive, valueRichText, typeLabelActive, toggleActive, inputActive, applyActive, inspectActive, subContentButtonActive; public bool valueActive, valueRichText, typeLabelActive, toggleActive, inputActive, applyActive, inspectActive, subContentButtonActive;
public ValueStateArgs(bool valueActive = true, public ValueStateArgs(bool valueActive = true,
bool valueRichText = true, bool valueRichText = true,
Color? valueColor = null, Color? valueColor = null,
bool typeLabelActive = false, bool typeLabelActive = false,
bool toggleActive = false, bool toggleActive = false,
bool inputActive = false, bool inputActive = false,
bool applyActive = false, bool applyActive = false,
bool inspectActive = false, bool inspectActive = false,
bool subContentButtonActive = false) bool subContentButtonActive = false)

View File

@ -1,11 +1,6 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text;
using UnityEngine;
using UnityExplorer.Inspectors; using UnityExplorer.Inspectors;
using UnityExplorer.Runtime;
namespace UnityExplorer.CacheObject namespace UnityExplorer.CacheObject
{ {

View File

@ -1,9 +1,5 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityExplorer.CacheObject;
using UnityExplorer.CacheObject.Views; using UnityExplorer.CacheObject.Views;
namespace UnityExplorer.CacheObject namespace UnityExplorer.CacheObject
@ -33,7 +29,7 @@ namespace UnityExplorer.CacheObject
return; return;
} }
var entry = (CacheObjectBase)cachedEntries[index]; CacheObjectBase entry = (CacheObjectBase)cachedEntries[index];
if (entry.CellView != null && entry.CellView != cell) if (entry.CellView != null && entry.CellView != cell)
entry.UnlinkFromView(); entry.UnlinkFromView();

View File

@ -1,11 +1,6 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.CacheObject;
using UnityExplorer.UI;
using UniverseLib.UI; using UniverseLib.UI;
using UniverseLib.UI.Models; using UniverseLib.UI.Models;
using UniverseLib; using UniverseLib;
@ -32,9 +27,9 @@ namespace UnityExplorer.CacheObject.IValues
applyButton.Component.gameObject.SetActive(owner.CanWrite); applyButton.Component.gameObject.SetActive(owner.CanWrite);
foreach (var slider in sliders) foreach (Slider slider in sliders)
slider.interactable = owner.CanWrite; slider.interactable = owner.CanWrite;
foreach (var input in inputs) foreach (InputFieldRef input in inputs)
input.Component.readOnly = !owner.CanWrite; input.Component.readOnly = !owner.CanWrite;
} }
@ -54,7 +49,7 @@ namespace UnityExplorer.CacheObject.IValues
inputs[1].Text = c32.g.ToString(); inputs[1].Text = c32.g.ToString();
inputs[2].Text = c32.b.ToString(); inputs[2].Text = c32.b.ToString();
inputs[3].Text = c32.a.ToString(); inputs[3].Text = c32.a.ToString();
foreach (var slider in sliders) foreach (Slider slider in sliders)
slider.maxValue = 255; slider.maxValue = 255;
} }
else else
@ -65,7 +60,7 @@ namespace UnityExplorer.CacheObject.IValues
inputs[1].Text = EditedColor.g.ToString(); inputs[1].Text = EditedColor.g.ToString();
inputs[2].Text = EditedColor.b.ToString(); inputs[2].Text = EditedColor.b.ToString();
inputs[3].Text = EditedColor.a.ToString(); inputs[3].Text = EditedColor.a.ToString();
foreach (var slider in sliders) foreach (Slider slider in sliders)
slider.maxValue = 1; slider.maxValue = 1;
} }
@ -156,12 +151,12 @@ namespace UnityExplorer.CacheObject.IValues
// hori group // hori group
var horiGroup = UIFactory.CreateHorizontalGroup(UIRoot, "ColorEditor", false, false, true, true, 5, GameObject horiGroup = UIFactory.CreateHorizontalGroup(UIRoot, "ColorEditor", false, false, true, true, 5,
default, new Color(1, 1, 1, 0), TextAnchor.MiddleLeft); default, new Color(1, 1, 1, 0), TextAnchor.MiddleLeft);
// sliders / inputs // sliders / inputs
var grid = UIFactory.CreateGridGroup(horiGroup, "Grid", new Vector2(140, 25), new Vector2(2, 2), new Color(1, 1, 1, 0)); GameObject grid = UIFactory.CreateGridGroup(horiGroup, "Grid", new Vector2(140, 25), new Vector2(2, 2), new Color(1, 1, 1, 0));
UIFactory.SetLayoutElement(grid, minWidth: 580, minHeight: 25, flexibleWidth: 0); UIFactory.SetLayoutElement(grid, minWidth: 580, minHeight: 25, flexibleWidth: 0);
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
@ -175,7 +170,7 @@ namespace UnityExplorer.CacheObject.IValues
// image of color // image of color
var imgObj = UIFactory.CreateUIObject("ColorImageHelper", horiGroup); GameObject imgObj = UIFactory.CreateUIObject("ColorImageHelper", horiGroup);
UIFactory.SetLayoutElement(imgObj, minHeight: 25, minWidth: 50, flexibleWidth: 50); UIFactory.SetLayoutElement(imgObj, minHeight: 25, minWidth: 50, flexibleWidth: 50);
colorImage = imgObj.AddComponent<Image>(); colorImage = imgObj.AddComponent<Image>();
@ -184,18 +179,18 @@ namespace UnityExplorer.CacheObject.IValues
internal void AddEditorRow(int index, GameObject groupObj) internal void AddEditorRow(int index, GameObject groupObj)
{ {
var row = UIFactory.CreateHorizontalGroup(groupObj, "EditorRow_" + fieldNames[index], GameObject row = UIFactory.CreateHorizontalGroup(groupObj, "EditorRow_" + fieldNames[index],
false, true, true, true, 5, default, new Color(1, 1, 1, 0)); false, true, true, true, 5, default, new Color(1, 1, 1, 0));
var label = UIFactory.CreateLabel(row, "RowLabel", $"{fieldNames[index]}:", TextAnchor.MiddleRight, Color.cyan); Text label = UIFactory.CreateLabel(row, "RowLabel", $"{fieldNames[index]}:", TextAnchor.MiddleRight, Color.cyan);
UIFactory.SetLayoutElement(label.gameObject, minWidth: 17, flexibleWidth: 0, minHeight: 25); UIFactory.SetLayoutElement(label.gameObject, minWidth: 17, flexibleWidth: 0, minHeight: 25);
var input = UIFactory.CreateInputField(row, "Input", "..."); InputFieldRef input = UIFactory.CreateInputField(row, "Input", "...");
UIFactory.SetLayoutElement(input.UIRoot, minWidth: 40, minHeight: 25, flexibleHeight: 0); UIFactory.SetLayoutElement(input.UIRoot, minWidth: 40, minHeight: 25, flexibleHeight: 0);
inputs[index] = input; inputs[index] = input;
input.OnValueChanged += (string val) => { OnInputChanged(val, index); }; input.OnValueChanged += (string val) => { OnInputChanged(val, index); };
var sliderObj = UIFactory.CreateSlider(row, "Slider", out Slider slider); GameObject sliderObj = UIFactory.CreateSlider(row, "Slider", out Slider slider);
sliders[index] = slider; sliders[index] = slider;
UIFactory.SetLayoutElement(sliderObj, minHeight: 25, minWidth: 70, flexibleWidth: 999, flexibleHeight: 0); UIFactory.SetLayoutElement(sliderObj, minHeight: 25, minWidth: 70, flexibleWidth: 999, flexibleHeight: 0);
slider.minValue = 0; slider.minValue = 0;

View File

@ -1,19 +1,12 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.CacheObject;
using UnityExplorer.CacheObject.Views; using UnityExplorer.CacheObject.Views;
using UnityExplorer.Inspectors;
using UnityExplorer.UI;
using UnityExplorer.UI.Panels; using UnityExplorer.UI.Panels;
using UnityExplorer.UI.Widgets;
using UniverseLib; using UniverseLib;
using UniverseLib.UI; using UniverseLib.UI;
using UniverseLib.UI.Widgets;
using UniverseLib.UI.Widgets.ScrollView; using UniverseLib.UI.Widgets.ScrollView;
using UniverseLib.Utility; using UniverseLib.Utility;
@ -32,7 +25,7 @@ namespace UnityExplorer.CacheObject.IValues
public IDictionary RefIDictionary; public IDictionary RefIDictionary;
public int ItemCount => cachedEntries.Count; public int ItemCount => cachedEntries.Count;
private readonly List<CacheKeyValuePair> cachedEntries = new List<CacheKeyValuePair>(); private readonly List<CacheKeyValuePair> cachedEntries = new();
public ScrollPool<CacheKeyValuePairCell> DictScrollPool { get; private set; } public ScrollPool<CacheKeyValuePairCell> DictScrollPool { get; private set; }
@ -61,7 +54,7 @@ namespace UnityExplorer.CacheObject.IValues
{ {
RefIDictionary = null; RefIDictionary = null;
foreach (var entry in cachedEntries) foreach (CacheKeyValuePair entry in cachedEntries)
{ {
entry.UnlinkFromView(); entry.UnlinkFromView();
entry.ReleasePooledObjects(); entry.ReleasePooledObjects();
@ -80,7 +73,7 @@ namespace UnityExplorer.CacheObject.IValues
} }
else else
{ {
var type = value.GetActualType(); Type type = value.GetActualType();
ReflectionUtility.TryGetEntryTypes(type, out KeysType, out ValuesType); ReflectionUtility.TryGetEntryTypes(type, out KeysType, out ValuesType);
CacheEntries(value); CacheEntries(value);
@ -124,7 +117,7 @@ namespace UnityExplorer.CacheObject.IValues
{ {
for (int i = cachedEntries.Count - 1; i >= idx; i--) for (int i = cachedEntries.Count - 1; i >= idx; i--)
{ {
var cache = cachedEntries[i]; CacheKeyValuePair cache = cachedEntries[i];
if (cache.CellView != null) if (cache.CellView != null)
cache.UnlinkFromView(); cache.UnlinkFromView();
@ -153,7 +146,7 @@ namespace UnityExplorer.CacheObject.IValues
RefIDictionary[key] = value; RefIDictionary[key] = value;
var entry = cachedEntries[keyIndex]; CacheKeyValuePair entry = cachedEntries[keyIndex];
entry.SetValueFromSource(value); entry.SetValueFromSource(value);
if (entry.CellView != null) if (entry.CellView != null)
entry.SetDataToCell(entry.CellView); entry.SetDataToCell(entry.CellView);
@ -177,12 +170,12 @@ namespace UnityExplorer.CacheObject.IValues
public override void SetLayout() public override void SetLayout()
{ {
var minHeight = 5f; float minHeight = 5f;
KeyTitleLayout.minWidth = AdjustedWidth * 0.44f; KeyTitleLayout.minWidth = AdjustedWidth * 0.44f;
ValueTitleLayout.minWidth = AdjustedWidth * 0.55f; ValueTitleLayout.minWidth = AdjustedWidth * 0.55f;
foreach (var cell in DictScrollPool.CellPool) foreach (CacheKeyValuePairCell cell in DictScrollPool.CellPool)
{ {
SetCellLayout(cell); SetCellLayout(cell);
if (cell.Enabled) if (cell.Enabled)
@ -194,7 +187,7 @@ namespace UnityExplorer.CacheObject.IValues
private void SetCellLayout(CacheObjectCell objcell) private void SetCellLayout(CacheObjectCell objcell)
{ {
var cell = objcell as CacheKeyValuePairCell; CacheKeyValuePairCell cell = objcell as CacheKeyValuePairCell;
cell.KeyGroupLayout.minWidth = cell.AdjustedWidth * 0.44f; cell.KeyGroupLayout.minWidth = cell.AdjustedWidth * 0.44f;
cell.RightGroupLayout.minWidth = cell.AdjustedWidth * 0.55f; cell.RightGroupLayout.minWidth = cell.AdjustedWidth * 0.55f;
@ -221,15 +214,15 @@ namespace UnityExplorer.CacheObject.IValues
// key / value titles // key / value titles
var titleGroup = UIFactory.CreateUIObject("TitleGroup", UIRoot); GameObject titleGroup = UIFactory.CreateUIObject("TitleGroup", UIRoot);
UIFactory.SetLayoutElement(titleGroup, minHeight: 25, flexibleWidth: 9999, flexibleHeight: 0); UIFactory.SetLayoutElement(titleGroup, minHeight: 25, flexibleWidth: 9999, flexibleHeight: 0);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(titleGroup, false, true, true, true, padLeft: 65, padRight: 0, childAlignment: TextAnchor.LowerLeft); UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(titleGroup, false, true, true, true, padLeft: 65, padRight: 0, childAlignment: TextAnchor.LowerLeft);
var keyTitle = UIFactory.CreateLabel(titleGroup, "KeyTitle", "Keys", TextAnchor.MiddleLeft); Text keyTitle = UIFactory.CreateLabel(titleGroup, "KeyTitle", "Keys", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(keyTitle.gameObject, minWidth: 100, flexibleWidth: 0); UIFactory.SetLayoutElement(keyTitle.gameObject, minWidth: 100, flexibleWidth: 0);
KeyTitleLayout = keyTitle.GetComponent<LayoutElement>(); KeyTitleLayout = keyTitle.GetComponent<LayoutElement>();
var valueTitle = UIFactory.CreateLabel(titleGroup, "ValueTitle", "Values", TextAnchor.MiddleLeft); Text valueTitle = UIFactory.CreateLabel(titleGroup, "ValueTitle", "Values", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(valueTitle.gameObject, minWidth: 100, flexibleWidth: 0); UIFactory.SetLayoutElement(valueTitle.gameObject, minWidth: 100, flexibleWidth: 0);
ValueTitleLayout = valueTitle.GetComponent<LayoutElement>(); ValueTitleLayout = valueTitle.GetComponent<LayoutElement>();

View File

@ -2,13 +2,10 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Linq; using System.Linq;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.CacheObject; using UnityExplorer.UI.Panels;
using UnityExplorer.UI;
using UnityExplorer.UI.Widgets.AutoComplete; using UnityExplorer.UI.Widgets.AutoComplete;
using UniverseLib;
using UniverseLib.UI; using UniverseLib.UI;
using UniverseLib.UI.Models; using UniverseLib.UI.Models;
using UniverseLib.Utility; using UniverseLib.Utility;
@ -110,7 +107,7 @@ namespace UnityExplorer.CacheObject.IValues
{ {
try try
{ {
List<string> values = new List<string>(); List<string> values = new();
for (int i = 0; i < CurrentValues.Count; i++) for (int i = 0; i < CurrentValues.Count; i++)
{ {
if (flagToggles[i].isOn) if (flagToggles[i].isOn)
@ -138,11 +135,11 @@ namespace UnityExplorer.CacheObject.IValues
new Color(0.06f, 0.06f, 0.06f)); new Color(0.06f, 0.06f, 0.06f));
UIFactory.SetLayoutElement(UIRoot, minHeight: 25, flexibleHeight: 9999, flexibleWidth: 9999); UIFactory.SetLayoutElement(UIRoot, minHeight: 25, flexibleHeight: 9999, flexibleWidth: 9999);
var hori = UIFactory.CreateUIObject("Hori", UIRoot); GameObject hori = UIFactory.CreateUIObject("Hori", UIRoot);
UIFactory.SetLayoutElement(hori, minHeight: 25, flexibleWidth: 9999); UIFactory.SetLayoutElement(hori, minHeight: 25, flexibleWidth: 9999);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(hori, false, false, true, true, 2); UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(hori, false, false, true, true, 2);
var applyButton = UIFactory.CreateButton(hori, "ApplyButton", "Apply", new Color(0.2f, 0.27f, 0.2f)); ButtonRef applyButton = UIFactory.CreateButton(hori, "ApplyButton", "Apply", new Color(0.2f, 0.27f, 0.2f));
UIFactory.SetLayoutElement(applyButton.Component.gameObject, minHeight: 25, minWidth: 100); UIFactory.SetLayoutElement(applyButton.Component.gameObject, minHeight: 25, minWidth: 100);
applyButton.OnClick += OnApplyClicked; applyButton.OnClick += OnApplyClicked;
@ -192,11 +189,11 @@ namespace UnityExplorer.CacheObject.IValues
private void AddToggleRow() private void AddToggleRow()
{ {
var row = UIFactory.CreateUIObject("ToggleRow", toggleHolder); GameObject row = UIFactory.CreateUIObject("ToggleRow", toggleHolder);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(row, false, false, true, true, 2); UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(row, false, false, true, true, 2);
UIFactory.SetLayoutElement(row, minHeight: 25, flexibleWidth: 9999); UIFactory.SetLayoutElement(row, minHeight: 25, flexibleWidth: 9999);
var toggleObj = UIFactory.CreateToggle(row, "ToggleObj", out Toggle toggle, out Text toggleText); GameObject toggleObj = UIFactory.CreateToggle(row, "ToggleObj", out Toggle toggle, out Text toggleText);
UIFactory.SetLayoutElement(toggleObj, minHeight: 25, flexibleWidth: 9999); UIFactory.SetLayoutElement(toggleObj, minHeight: 25, flexibleWidth: 9999);
flagToggles.Add(toggle); flagToggles.Add(toggle);
@ -205,7 +202,7 @@ namespace UnityExplorer.CacheObject.IValues
#region Enum cache #region Enum cache
internal static readonly Dictionary<string, OrderedDictionary> enumCache = new Dictionary<string, OrderedDictionary>(); internal static readonly Dictionary<string, OrderedDictionary> enumCache = new();
internal static OrderedDictionary GetEnumValues(Type enumType) internal static OrderedDictionary GetEnumValues(Type enumType)
{ {
@ -213,13 +210,13 @@ namespace UnityExplorer.CacheObject.IValues
if (!enumCache.ContainsKey(enumType.AssemblyQualifiedName)) if (!enumCache.ContainsKey(enumType.AssemblyQualifiedName))
{ {
var dict = new OrderedDictionary(); OrderedDictionary dict = new();
var addedNames = new HashSet<string>(); HashSet<string> addedNames = new();
int i = 0; int i = 0;
foreach (var value in Enum.GetValues(enumType)) foreach (object value in Enum.GetValues(enumType))
{ {
var name = value.ToString(); string name = value.ToString();
if (addedNames.Contains(name)) if (addedNames.Contains(name))
continue; continue;
addedNames.Add(name); addedNames.Add(name);

View File

@ -5,15 +5,10 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.CacheObject;
using UnityExplorer.CacheObject.Views; using UnityExplorer.CacheObject.Views;
using UnityExplorer.Inspectors;
using UnityExplorer.UI;
using UnityExplorer.UI.Panels; using UnityExplorer.UI.Panels;
using UnityExplorer.UI.Widgets;
using UniverseLib; using UniverseLib;
using UniverseLib.UI; using UniverseLib.UI;
using UniverseLib.UI.Widgets;
using UniverseLib.UI.Widgets.ScrollView; using UniverseLib.UI.Widgets.ScrollView;
using UniverseLib.Utility; using UniverseLib.Utility;
@ -60,7 +55,7 @@ namespace UnityExplorer.CacheObject.IValues
{ {
RefIList = null; RefIList = null;
foreach (var entry in cachedEntries) foreach (CacheListEntry entry in cachedEntries)
{ {
entry.UnlinkFromView(); entry.UnlinkFromView();
entry.ReleasePooledObjects(); entry.ReleasePooledObjects();
@ -73,9 +68,9 @@ namespace UnityExplorer.CacheObject.IValues
public override void SetLayout() public override void SetLayout()
{ {
var minHeight = 5f; float minHeight = 5f;
foreach (var cell in ListScrollPool.CellPool) foreach (CacheListEntryCell cell in ListScrollPool.CellPool)
{ {
if (cell.Enabled) if (cell.Enabled)
minHeight += cell.Rect.rect.height; minHeight += cell.Rect.rect.height;
@ -102,7 +97,7 @@ namespace UnityExplorer.CacheObject.IValues
} }
else else
{ {
var type = value.GetActualType(); Type type = value.GetActualType();
ReflectionUtility.TryGetEntryType(type, out EntryType); ReflectionUtility.TryGetEntryType(type, out EntryType);
CacheEntries(value); CacheEntries(value);
@ -132,7 +127,7 @@ namespace UnityExplorer.CacheObject.IValues
while (enumerator.MoveNext()) while (enumerator.MoveNext())
{ {
var entry = enumerator.Current; object entry = enumerator.Current;
// If list count increased, create new cache entries // If list count increased, create new cache entries
CacheListEntry cache; CacheListEntry cache;
@ -155,7 +150,7 @@ namespace UnityExplorer.CacheObject.IValues
{ {
for (int i = cachedEntries.Count - 1; i >= idx; i--) for (int i = cachedEntries.Count - 1; i >= idx; i--)
{ {
var cache = cachedEntries[i]; CacheListEntry cache = cachedEntries[i];
if (cache.CellView != null) if (cache.CellView != null)
cache.UnlinkFromView(); cache.UnlinkFromView();
@ -174,7 +169,7 @@ namespace UnityExplorer.CacheObject.IValues
{ {
try try
{ {
var type = value.GetType(); Type type = value.GetType();
if (type.GetInterfaces().Any(it => it.IsGenericType && it.GetGenericTypeDefinition() == typeof(IList<>))) if (type.GetInterfaces().Any(it => it.IsGenericType && it.GetGenericTypeDefinition() == typeof(IList<>)))
IsWritableGenericIList = !(bool)type.GetProperty("IsReadOnly").GetValue(value, null); IsWritableGenericIList = !(bool)type.GetProperty("IsReadOnly").GetValue(value, null);
else else
@ -184,7 +179,7 @@ namespace UnityExplorer.CacheObject.IValues
{ {
// Find the "this[int index]" property. // Find the "this[int index]" property.
// It might be a private implementation. // It might be a private implementation.
foreach (var prop in type.GetProperties(ReflectionUtility.FLAGS)) foreach (PropertyInfo prop in type.GetProperties(ReflectionUtility.FLAGS))
{ {
if ((prop.Name == "Item" if ((prop.Name == "Item"
|| (prop.Name.StartsWith("System.Collections.Generic.IList<") && prop.Name.EndsWith(">.Item"))) || (prop.Name.StartsWith("System.Collections.Generic.IList<") && prop.Name.EndsWith(">.Item")))
@ -226,7 +221,7 @@ namespace UnityExplorer.CacheObject.IValues
genericIndexer.SetValue(CurrentOwner.Value, value, new object[] { index }); genericIndexer.SetValue(CurrentOwner.Value, value, new object[] { index });
} }
var entry = cachedEntries[index]; CacheListEntry entry = cachedEntries[index];
entry.SetValueFromSource(value); entry.SetValueFromSource(value);
if (entry.CellView != null) if (entry.CellView != null)

View File

@ -1,16 +1,8 @@
using System; using System.IO;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.Config; using UnityExplorer.Config;
using UnityExplorer.CacheObject;
using UnityExplorer.UI.Widgets;
using UnityExplorer.UI;
using UniverseLib.UI; using UniverseLib.UI;
using UniverseLib;
using UniverseLib.UI.Models; using UniverseLib.UI.Models;
using UniverseLib.Utility; using UniverseLib.Utility;
@ -88,7 +80,7 @@ namespace UnityExplorer.CacheObject.IValues
return; return;
} }
var path = IOUtility.EnsureValidFilePath(SaveFilePath.Text); string path = IOUtility.EnsureValidFilePath(SaveFilePath.Text);
if (File.Exists(path)) if (File.Exists(path))
File.Delete(path); File.Delete(path);
@ -110,10 +102,10 @@ namespace UnityExplorer.CacheObject.IValues
UIFactory.CreateLabel(SaveFileRow, "Info", "<color=red>String is too long! Save to file if you want to see the full string.</color>", UIFactory.CreateLabel(SaveFileRow, "Info", "<color=red>String is too long! Save to file if you want to see the full string.</color>",
TextAnchor.MiddleLeft); TextAnchor.MiddleLeft);
var horizRow = UIFactory.CreateUIObject("Horiz", SaveFileRow); GameObject horizRow = UIFactory.CreateUIObject("Horiz", SaveFileRow);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(horizRow, false, false, true, true, 4); UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(horizRow, false, false, true, true, 4);
var saveButton = UIFactory.CreateButton(horizRow, "SaveButton", "Save file"); ButtonRef saveButton = UIFactory.CreateButton(horizRow, "SaveButton", "Save file");
UIFactory.SetLayoutElement(saveButton.Component.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 0); UIFactory.SetLayoutElement(saveButton.Component.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 0);
saveButton.OnClick += OnSaveFileClicked; saveButton.OnClick += OnSaveFileClicked;

View File

@ -1,13 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.CacheObject;
using UnityExplorer.UI;
using UniverseLib.UI;
using UniverseLib.UI.Models;
using UniverseLib.UI.ObjectPool; using UniverseLib.UI.ObjectPool;
namespace UnityExplorer.CacheObject.IValues namespace UnityExplorer.CacheObject.IValues

View File

@ -2,11 +2,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.CacheObject;
using UnityExplorer.UI;
using UniverseLib; using UniverseLib;
using UniverseLib.UI; using UniverseLib.UI;
using UniverseLib.UI.Models; using UniverseLib.UI.Models;
@ -31,7 +28,7 @@ namespace UnityExplorer.CacheObject.IValues
public void SetValue(object instance, string input, int fieldIndex) public void SetValue(object instance, string input, int fieldIndex)
{ {
var field = Fields[fieldIndex]; FieldInfo field = Fields[fieldIndex];
object val; object val;
if (field.FieldType == typeof(string)) if (field.FieldType == typeof(string))
@ -51,8 +48,8 @@ namespace UnityExplorer.CacheObject.IValues
public string GetValue(object instance, int fieldIndex) public string GetValue(object instance, int fieldIndex)
{ {
var field = Fields[fieldIndex]; FieldInfo field = Fields[fieldIndex];
var value = field.GetValue(instance); object value = field.GetValue(instance);
return ParseUtility.ToStringForInput(value, field.FieldType); return ParseUtility.ToStringForInput(value, field.FieldType);
} }
} }
@ -67,12 +64,12 @@ namespace UnityExplorer.CacheObject.IValues
if (!type.IsValueType || string.IsNullOrEmpty(type.AssemblyQualifiedName) || type.FullName == SYSTEM_VOID) if (!type.IsValueType || string.IsNullOrEmpty(type.AssemblyQualifiedName) || type.FullName == SYSTEM_VOID)
return false; return false;
if (typeSupportCache.TryGetValue(type.AssemblyQualifiedName, out var info)) if (typeSupportCache.TryGetValue(type.AssemblyQualifiedName, out StructInfo info))
return info.IsSupported; return info.IsSupported;
var supported = false; bool supported = false;
var fields = type.GetFields(INSTANCE_FLAGS); FieldInfo[] fields = type.GetFields(INSTANCE_FLAGS);
if (fields.Length > 0) if (fields.Length > 0)
{ {
if (fields.Any(it => !ParseUtility.CanParse(it.FieldType))) if (fields.Any(it => !ParseUtility.CanParse(it.FieldType)))
@ -100,9 +97,9 @@ namespace UnityExplorer.CacheObject.IValues
private Type lastStructType; private Type lastStructType;
private ButtonRef applyButton; private ButtonRef applyButton;
private readonly List<GameObject> fieldRows = new List<GameObject>(); private readonly List<GameObject> fieldRows = new();
private readonly List<InputFieldRef> inputFields = new List<InputFieldRef>(); private readonly List<InputFieldRef> inputFields = new();
private readonly List<Text> labels = new List<Text>(); private readonly List<Text> labels = new();
public override void OnBorrowed(CacheObjectBase owner) public override void OnBorrowed(CacheObjectBase owner)
{ {
@ -117,7 +114,7 @@ namespace UnityExplorer.CacheObject.IValues
{ {
RefInstance = value; RefInstance = value;
var type = RefInstance.GetType(); Type type = RefInstance.GetType();
if (type != lastStructType) if (type != lastStructType)
{ {
@ -177,21 +174,21 @@ namespace UnityExplorer.CacheObject.IValues
private void AddEditorRow() private void AddEditorRow()
{ {
var row = UIFactory.CreateUIObject("HoriGroup", UIRoot); GameObject row = UIFactory.CreateUIObject("HoriGroup", UIRoot);
//row.AddComponent<ContentSizeFitter>().horizontalFit = ContentSizeFitter.FitMode.PreferredSize; //row.AddComponent<ContentSizeFitter>().horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
UIFactory.SetLayoutElement(row, minHeight: 25, flexibleWidth: 9999); UIFactory.SetLayoutElement(row, minHeight: 25, flexibleWidth: 9999);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(row, false, false, true, true, 8, childAlignment: TextAnchor.MiddleLeft); UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(row, false, false, true, true, 8, childAlignment: TextAnchor.MiddleLeft);
fieldRows.Add(row); fieldRows.Add(row);
var label = UIFactory.CreateLabel(row, "Label", "notset", TextAnchor.MiddleLeft); Text label = UIFactory.CreateLabel(row, "Label", "notset", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(label.gameObject, minHeight: 25, minWidth: 50, flexibleWidth: 0); UIFactory.SetLayoutElement(label.gameObject, minHeight: 25, minWidth: 50, flexibleWidth: 0);
label.horizontalOverflow = HorizontalWrapMode.Wrap; label.horizontalOverflow = HorizontalWrapMode.Wrap;
labels.Add(label); labels.Add(label);
var input = UIFactory.CreateInputField(row, "InputField", "..."); InputFieldRef input = UIFactory.CreateInputField(row, "InputField", "...");
UIFactory.SetLayoutElement(input.UIRoot, minHeight: 25, minWidth: 200); UIFactory.SetLayoutElement(input.UIRoot, minHeight: 25, minWidth: 200);
var fitter = input.UIRoot.AddComponent<ContentSizeFitter>(); ContentSizeFitter fitter = input.UIRoot.AddComponent<ContentSizeFitter>();
fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize; fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
fitter.horizontalFit = ContentSizeFitter.FitMode.PreferredSize; fitter.horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
input.Component.lineType = InputField.LineType.MultiLineNewline; input.Component.lineType = InputField.LineType.MultiLineNewline;

View File

@ -1,13 +1,8 @@
using System; using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.UI;
using UniverseLib;
using UniverseLib.UI; using UniverseLib.UI;
using UniverseLib.Utility; using UniverseLib.Utility;
using UniverseLib;
namespace UnityExplorer.CacheObject.Views namespace UnityExplorer.CacheObject.Views
{ {
@ -32,7 +27,7 @@ namespace UnityExplorer.CacheObject.Views
// horizontal group // horizontal group
var horiGroup = UIFactory.CreateUIObject("RightHoriGroup", UIRoot); GameObject horiGroup = UIFactory.CreateUIObject("RightHoriGroup", UIRoot);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(horiGroup, false, false, true, true, 4, childAlignment: TextAnchor.UpperLeft); UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(horiGroup, false, false, true, true, 4, childAlignment: TextAnchor.UpperLeft);
UIFactory.SetLayoutElement(horiGroup, minHeight: 25, minWidth: 200, flexibleWidth: 9999, flexibleHeight: 800); UIFactory.SetLayoutElement(horiGroup, minHeight: 25, minWidth: 200, flexibleWidth: 9999, flexibleHeight: 800);
@ -48,7 +43,7 @@ namespace UnityExplorer.CacheObject.Views
// Bool and number value interaction // Bool and number value interaction
var toggleObj = UIFactory.CreateToggle(horiGroup, "Toggle", out Toggle, out ToggleText); GameObject toggleObj = UIFactory.CreateToggle(horiGroup, "Toggle", out Toggle, out ToggleText);
UIFactory.SetLayoutElement(toggleObj, minWidth: 70, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0); UIFactory.SetLayoutElement(toggleObj, minWidth: 70, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
ToggleText.color = SignatureHighlighter.KeywordBlue; ToggleText.color = SignatureHighlighter.KeywordBlue;
Toggle.onValueChanged.AddListener(ToggleClicked); Toggle.onValueChanged.AddListener(ToggleClicked);
@ -77,7 +72,7 @@ namespace UnityExplorer.CacheObject.Views
SubContentHolder.SetActive(false); SubContentHolder.SetActive(false);
// Bottom separator // Bottom separator
var separator = UIFactory.CreateUIObject("BottomSeperator", UIRoot); GameObject separator = UIFactory.CreateUIObject("BottomSeperator", UIRoot);
UIFactory.SetLayoutElement(separator, minHeight: 1, flexibleHeight: 0, flexibleWidth: 9999); UIFactory.SetLayoutElement(separator, minHeight: 1, flexibleHeight: 0, flexibleWidth: 9999);
separator.AddComponent<Image>().color = Color.black; separator.AddComponent<Image>().color = Color.black;

View File

@ -1,13 +1,6 @@
using System; using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.CacheObject.IValues; using UnityExplorer.CacheObject.IValues;
using UnityExplorer.Inspectors;
using UnityExplorer.UI;
using UnityExplorer.UI.Widgets;
using UniverseLib.UI; using UniverseLib.UI;
using UniverseLib.UI.Models; using UniverseLib.UI.Models;
@ -24,8 +17,8 @@ namespace UnityExplorer.CacheObject.Views
public InputFieldRef KeyInputField; public InputFieldRef KeyInputField;
public Text KeyInputTypeLabel; public Text KeyInputTypeLabel;
public static Color EvenColor = new Color(0.07f, 0.07f, 0.07f); public static Color EvenColor = new(0.07f, 0.07f, 0.07f);
public static Color OddColor = new Color(0.063f, 0.063f, 0.063f); public static Color OddColor = new(0.063f, 0.063f, 0.063f);
public int AdjustedWidth => (int)Rect.rect.width - 70; public int AdjustedWidth => (int)Rect.rect.width - 70;
@ -40,7 +33,7 @@ namespace UnityExplorer.CacheObject.Views
public override GameObject CreateContent(GameObject parent) public override GameObject CreateContent(GameObject parent)
{ {
var root = base.CreateContent(parent); GameObject root = base.CreateContent(parent);
Image = root.AddComponent<Image>(); Image = root.AddComponent<Image>();
@ -53,7 +46,7 @@ namespace UnityExplorer.CacheObject.Views
this.RightGroupLayout.minWidth = AdjustedWidth * 0.55f; this.RightGroupLayout.minWidth = AdjustedWidth * 0.55f;
// Key area // Key area
var keyGroup = UIFactory.CreateUIObject("KeyHolder", root.transform.Find("HoriGroup").gameObject); GameObject keyGroup = UIFactory.CreateUIObject("KeyHolder", root.transform.Find("HoriGroup").gameObject);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(keyGroup, false, false, true, true, 2, 0, 0, 4, 4, childAlignment: TextAnchor.MiddleLeft); UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(keyGroup, false, false, true, true, 2, 0, 0, 4, 4, childAlignment: TextAnchor.MiddleLeft);
KeyGroupLayout = UIFactory.SetLayoutElement(keyGroup, minHeight: 30, minWidth: (int)(AdjustedWidth * 0.44f), flexibleWidth: 0); KeyGroupLayout = UIFactory.SetLayoutElement(keyGroup, minHeight: 30, minWidth: (int)(AdjustedWidth * 0.44f), flexibleWidth: 0);

View File

@ -1,8 +1,4 @@
using System; using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.CacheObject.IValues; using UnityExplorer.CacheObject.IValues;
@ -13,12 +9,12 @@ namespace UnityExplorer.CacheObject.Views
public Image Image { get; private set; } public Image Image { get; private set; }
public InteractiveList ListOwner => Occupant.Owner as InteractiveList; public InteractiveList ListOwner => Occupant.Owner as InteractiveList;
public static Color EvenColor = new Color(0.12f, 0.12f, 0.12f); public static Color EvenColor = new(0.12f, 0.12f, 0.12f);
public static Color OddColor = new Color(0.1f, 0.1f, 0.1f); public static Color OddColor = new(0.1f, 0.1f, 0.1f);
public override GameObject CreateContent(GameObject parent) public override GameObject CreateContent(GameObject parent)
{ {
var root = base.CreateContent(parent); GameObject root = base.CreateContent(parent);
Image = root.AddComponent<Image>(); Image = root.AddComponent<Image>();

View File

@ -1,11 +1,5 @@
using System; using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.UI;
using UnityExplorer.UI.Widgets;
using UniverseLib.UI; using UniverseLib.UI;
using UniverseLib.UI.Models; using UniverseLib.UI.Models;

View File

@ -1,8 +1,4 @@
using System; using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.UI.Panels; using UnityExplorer.UI.Panels;
using UniverseLib; using UniverseLib;
@ -116,7 +112,7 @@ namespace UnityExplorer.CacheObject.Views
UIFactory.SetLayoutElement(UIRoot, minWidth: 100, flexibleWidth: 9999, minHeight: 30, flexibleHeight: 600); UIFactory.SetLayoutElement(UIRoot, minWidth: 100, flexibleWidth: 9999, minHeight: 30, flexibleHeight: 600);
UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize; UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
var horiRow = UIFactory.CreateUIObject("HoriGroup", UIRoot); GameObject horiRow = UIFactory.CreateUIObject("HoriGroup", UIRoot);
UIFactory.SetLayoutElement(horiRow, minHeight: 29, flexibleHeight: 150, flexibleWidth: 9999); UIFactory.SetLayoutElement(horiRow, minHeight: 29, flexibleHeight: 150, flexibleWidth: 9999);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(horiRow, false, false, true, true, 5, 2, childAlignment: TextAnchor.UpperLeft); UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(horiRow, false, false, true, true, 5, 2, childAlignment: TextAnchor.UpperLeft);
horiRow.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize; horiRow.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
@ -129,7 +125,7 @@ namespace UnityExplorer.CacheObject.Views
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(NameLabel.gameObject, true, true, true, true); UIFactory.SetLayoutGroup<VerticalLayoutGroup>(NameLabel.gameObject, true, true, true, true);
HiddenNameLabel = UIFactory.CreateInputField(NameLabel.gameObject, "HiddenNameLabel", ""); HiddenNameLabel = UIFactory.CreateInputField(NameLabel.gameObject, "HiddenNameLabel", "");
var hiddenRect = HiddenNameLabel.Component.GetComponent<RectTransform>(); RectTransform hiddenRect = HiddenNameLabel.Component.GetComponent<RectTransform>();
hiddenRect.anchorMin = Vector2.zero; hiddenRect.anchorMin = Vector2.zero;
hiddenRect.anchorMax = Vector2.one; hiddenRect.anchorMax = Vector2.one;
HiddenNameLabel.Component.readOnly = true; HiddenNameLabel.Component.readOnly = true;
@ -150,7 +146,7 @@ namespace UnityExplorer.CacheObject.Views
// Right horizontal group // Right horizontal group
var rightHoriGroup = UIFactory.CreateUIObject("RightHoriGroup", RightGroupContent); GameObject rightHoriGroup = UIFactory.CreateUIObject("RightHoriGroup", RightGroupContent);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(rightHoriGroup, false, false, true, true, 4, childAlignment: TextAnchor.UpperLeft); UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(rightHoriGroup, false, false, true, true, 4, childAlignment: TextAnchor.UpperLeft);
UIFactory.SetLayoutElement(rightHoriGroup, minHeight: 25, minWidth: 200, flexibleWidth: 9999, flexibleHeight: 800); UIFactory.SetLayoutElement(rightHoriGroup, minHeight: 25, minWidth: 200, flexibleWidth: 9999, flexibleHeight: 800);
@ -166,7 +162,7 @@ namespace UnityExplorer.CacheObject.Views
// Bool and number value interaction // Bool and number value interaction
var toggleObj = UIFactory.CreateToggle(rightHoriGroup, "Toggle", out Toggle, out ToggleText); GameObject toggleObj = UIFactory.CreateToggle(rightHoriGroup, "Toggle", out Toggle, out ToggleText);
UIFactory.SetLayoutElement(toggleObj, minWidth: 70, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0); UIFactory.SetLayoutElement(toggleObj, minWidth: 70, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
ToggleText.color = SignatureHighlighter.KeywordBlue; ToggleText.color = SignatureHighlighter.KeywordBlue;
Toggle.onValueChanged.AddListener(ToggleClicked); Toggle.onValueChanged.AddListener(ToggleClicked);
@ -194,8 +190,8 @@ namespace UnityExplorer.CacheObject.Views
// Copy and Paste buttons // Copy and Paste buttons
var buttonHolder = UIFactory.CreateHorizontalGroup(rightHoriGroup, "CopyPasteButtons", false, false, true, true, 4, GameObject buttonHolder = UIFactory.CreateHorizontalGroup(rightHoriGroup, "CopyPasteButtons", false, false, true, true, 4,
bgColor: new(1,1,1,0), childAlignment: TextAnchor.MiddleLeft); bgColor: new(1, 1, 1, 0), childAlignment: TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(buttonHolder, minWidth: 60, flexibleWidth: 0); UIFactory.SetLayoutElement(buttonHolder, minWidth: 60, flexibleWidth: 0);
CopyButton = UIFactory.CreateButton(buttonHolder, "CopyButton", "Copy", new Color(0.13f, 0.13f, 0.13f, 1f)); CopyButton = UIFactory.CreateButton(buttonHolder, "CopyButton", "Copy", new Color(0.13f, 0.13f, 0.13f, 1f));
@ -219,7 +215,7 @@ namespace UnityExplorer.CacheObject.Views
SubContentHolder.SetActive(false); SubContentHolder.SetActive(false);
// Bottom separator // Bottom separator
var separator = UIFactory.CreateUIObject("BottomSeperator", UIRoot); GameObject separator = UIFactory.CreateUIObject("BottomSeperator", UIRoot);
UIFactory.SetLayoutElement(separator, minHeight: 1, flexibleHeight: 0, flexibleWidth: 9999); UIFactory.SetLayoutElement(separator, minHeight: 1, flexibleHeight: 0, flexibleWidth: 9999);
separator.AddComponent<Image>().color = Color.black; separator.AddComponent<Image>().color = Color.black;

View File

@ -1,7 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UnityExplorer.Config namespace UnityExplorer.Config
{ {

View File

@ -1,9 +1,4 @@
using System; namespace UnityExplorer.Config
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UnityExplorer.Config
{ {
public abstract class ConfigHandler public abstract class ConfigHandler
{ {

View File

@ -1,9 +1,5 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Globalization;
using System.IO; using System.IO;
using System.Linq;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityExplorer.UI; using UnityExplorer.UI;
@ -58,6 +54,10 @@ namespace UnityExplorer.Config
Handler.LoadConfig(); Handler.LoadConfig();
InternalHandler.LoadConfig(); InternalHandler.LoadConfig();
#if STANDALONE
Loader.Standalone.ExplorerEditorBehaviour.Instance.LoadConfigs();
#endif
//InitConsoleCallback(); //InitConsoleCallback();
} }
@ -81,6 +81,10 @@ namespace UnityExplorer.Config
"The key to enable or disable UnityExplorer's menu and features.", "The key to enable or disable UnityExplorer's menu and features.",
KeyCode.F7); KeyCode.F7);
Hide_On_Startup = new ConfigElement<bool>("Hide On Startup",
"Should UnityExplorer be hidden on startup?",
false);
Target_Display = new ConfigElement<int>("Target Display", Target_Display = new ConfigElement<int>("Target Display",
"The monitor index for UnityExplorer to use, if you have multiple. 0 is the default display, 1 is secondary, etc. " + "The monitor index for UnityExplorer to use, if you have multiple. 0 is the default display, 1 is secondary, etc. " +
"Restart recommended when changing this setting. Make sure your extra monitors are the same resolution as your primary monitor.", "Restart recommended when changing this setting. Make sure your extra monitors are the same resolution as your primary monitor.",
@ -90,16 +94,12 @@ namespace UnityExplorer.Config
"The vertical anchor of the main UnityExplorer Navbar, in case you want to move it.", "The vertical anchor of the main UnityExplorer Navbar, in case you want to move it.",
UIManager.VerticalAnchor.Top); UIManager.VerticalAnchor.Top);
Hide_On_Startup = new ConfigElement<bool>("Hide On Startup",
"Should UnityExplorer be hidden on startup?",
false);
World_MouseInspect_Keybind = new("World Mouse-Inspect Keybind", World_MouseInspect_Keybind = new("World Mouse-Inspect Keybind",
"Optional keybind to being a World-mode Mouse Inspect.", "Optional keybind to being a World-mode Mouse Inspect.",
KeyCode.None); KeyCode.None);
UI_MouseInspect_Keybind = new("UI Mouse-Inspect Keybind", UI_MouseInspect_Keybind = new("UI Mouse-Inspect Keybind",
"Optional keybind to begin a UI_mode Mouse Inspect.", "Optional keybind to begin a UI-mode Mouse Inspect.",
KeyCode.None); KeyCode.None);
Force_Unlock_Mouse = new ConfigElement<bool>("Force Unlock Mouse", Force_Unlock_Mouse = new ConfigElement<bool>("Force Unlock Mouse",

View File

@ -1,12 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityExplorer.UI;
using Tomlet; using Tomlet;
using Tomlet.Models; using Tomlet.Models;
using UnityExplorer.UI;
namespace UnityExplorer.Config namespace UnityExplorer.Config
{ {
@ -49,9 +46,12 @@ namespace UnityExplorer.Config
return false; return false;
TomlDocument document = TomlParser.ParseFile(CONFIG_PATH); TomlDocument document = TomlParser.ParseFile(CONFIG_PATH);
foreach (var key in document.Keys) foreach (string key in document.Keys)
{ {
var panelKey = (UIManager.Panels)Enum.Parse(typeof(UIManager.Panels), key); if (!Enum.IsDefined(typeof(UIManager.Panels), key))
continue;
UIManager.Panels panelKey = (UIManager.Panels)Enum.Parse(typeof(UIManager.Panels), key);
ConfigManager.GetPanelSaveData(panelKey).Value = document.GetString(key); ConfigManager.GetPanelSaveData(panelKey).Value = document.GetString(key);
} }
@ -69,8 +69,8 @@ namespace UnityExplorer.Config
if (UIManager.Initializing) if (UIManager.Initializing)
return; return;
var tomlDocument = TomlDocument.CreateEmpty(); TomlDocument tomlDocument = TomlDocument.CreateEmpty();
foreach (var entry in ConfigManager.InternalConfigs) foreach (KeyValuePair<string, IConfigElement> entry in ConfigManager.InternalConfigs)
tomlDocument.Put(entry.Key, entry.Value.BoxedValue as string, false); tomlDocument.Put(entry.Key, entry.Value.BoxedValue as string, false);
File.WriteAllText(CONFIG_PATH, tomlDocument.SerializedValue); File.WriteAllText(CONFIG_PATH, tomlDocument.SerializedValue);

View File

@ -1,8 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Reflection;
using System.Linq;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityExplorer.UI;
using UniverseLib;
#if CPP #if CPP
using UnhollowerRuntimeLib; using UnhollowerRuntimeLib;
#endif #endif
@ -14,7 +14,7 @@ namespace UnityExplorer
internal static ExplorerBehaviour Instance { get; private set; } internal static ExplorerBehaviour Instance { get; private set; }
#if CPP #if CPP
public ExplorerBehaviour(IntPtr ptr) : base(ptr) { } public ExplorerBehaviour(System.IntPtr ptr) : base(ptr) { }
#endif #endif
internal static void Setup() internal static void Setup()
@ -33,5 +33,39 @@ namespace UnityExplorer
{ {
ExplorerCore.Update(); ExplorerCore.Update();
} }
// For editor, to clean up objects
internal void OnDestroy()
{
OnApplicationQuit();
}
internal bool quitting;
internal void OnApplicationQuit()
{
if (quitting) return;
quitting = true;
TryDestroy(UIManager.UIRoot?.transform.root.gameObject);
TryDestroy((typeof(Universe).Assembly.GetType("UniverseLib.UniversalBehaviour")
.GetProperty("Instance", BindingFlags.Static | BindingFlags.NonPublic)
.GetValue(null, null)
as Component).gameObject);
TryDestroy(this.gameObject);
}
internal void TryDestroy(GameObject obj)
{
try
{
if (obj)
Destroy(obj);
}
catch { }
}
} }
} }

View File

@ -1,7 +1,6 @@
using System; using System;
using System.IO; using System.IO;
using UnityEngine; using UnityEngine;
using UnityExplorer.CacheObject;
using UnityExplorer.Config; using UnityExplorer.Config;
using UnityExplorer.ObjectExplorer; using UnityExplorer.ObjectExplorer;
using UnityExplorer.Runtime; using UnityExplorer.Runtime;
@ -15,7 +14,7 @@ namespace UnityExplorer
public static class ExplorerCore public static class ExplorerCore
{ {
public const string NAME = "UnityExplorer"; public const string NAME = "UnityExplorer";
public const string VERSION = "4.7.0"; public const string VERSION = "4.7.8";
public const string AUTHOR = "Sinai"; public const string AUTHOR = "Sinai";
public const string GUID = "com.sinai.unityexplorer"; public const string GUID = "com.sinai.unityexplorer";
@ -58,8 +57,6 @@ namespace UnityExplorer
// Default delay is 1 second which is usually enough. // Default delay is 1 second which is usually enough.
static void LateInit() static void LateInit()
{ {
Log($"Setting up late core features...");
SceneHandler.Init(); SceneHandler.Init();
Log($"Creating UI..."); Log($"Creating UI...");
@ -67,6 +64,8 @@ namespace UnityExplorer
UIManager.InitUI(); UIManager.InitUI();
Log($"{NAME} {VERSION} ({Universe.Context}) initialized."); Log($"{NAME} {VERSION} ({Universe.Context}) initialized.");
// InspectorManager.Inspect(typeof(Tests.TestClass));
} }
internal static void Update() internal static void Update()
@ -74,64 +73,8 @@ namespace UnityExplorer
// check master toggle // check master toggle
if (InputManager.GetKeyDown(ConfigManager.Master_Toggle.Value)) if (InputManager.GetKeyDown(ConfigManager.Master_Toggle.Value))
UIManager.ShowMenu = !UIManager.ShowMenu; UIManager.ShowMenu = !UIManager.ShowMenu;
UIManager.Update();
} }
// Can be removed eventually. For migration from <4.7.0
static void CheckLegacyExplorerFolder()
{
string legacyPath = Path.Combine(Loader.ExplorerFolderDestination, "UnityExplorer");
if (Directory.Exists(legacyPath))
{
LogWarning($"Attempting to migrate old 'UnityExplorer/' folder to 'sinai-dev-UnityExplorer/'...");
// If new folder doesn't exist yet, let's just use Move().
if (!Directory.Exists(ExplorerFolder))
{
try
{
Directory.Move(legacyPath, ExplorerFolder);
Log("Migrated successfully.");
}
catch (Exception ex)
{
LogWarning($"Exception migrating folder: {ex}");
}
}
else // We have to merge
{
try
{
CopyAll(new(legacyPath), new(ExplorerFolder));
Directory.Delete(legacyPath, true);
Log("Migrated successfully.");
}
catch (Exception ex)
{
LogWarning($"Exception migrating folder: {ex}");
}
}
}
}
public static void CopyAll(DirectoryInfo source, DirectoryInfo target)
{
// Check if the target directory exists, if not, create it.
if (!Directory.Exists(target.FullName))
Directory.CreateDirectory(target.FullName);
// Copy each file into it's new directory.
foreach (FileInfo fi in source.GetFiles())
fi.MoveTo(Path.Combine(target.ToString(), fi.Name));
// Copy each subdirectory using recursion.
foreach (DirectoryInfo diSourceSubDir in source.GetDirectories())
{
DirectoryInfo nextTargetSubDir = target.CreateSubdirectory(diSourceSubDir.Name);
CopyAll(diSourceSubDir, nextTargetSubDir);
}
}
#region LOGGING #region LOGGING
@ -177,5 +120,63 @@ namespace UnityExplorer
} }
#endregion #endregion
#region LEGACY FOLDER MIGRATION
// Can be removed eventually. For migration from <4.7.0
static void CheckLegacyExplorerFolder()
{
string legacyPath = Path.Combine(Loader.ExplorerFolderDestination, "UnityExplorer");
if (Directory.Exists(legacyPath))
{
LogWarning($"Attempting to migrate old 'UnityExplorer/' folder to 'sinai-dev-UnityExplorer/'...");
// If new folder doesn't exist yet, let's just use Move().
if (!Directory.Exists(ExplorerFolder))
{
try
{
Directory.Move(legacyPath, ExplorerFolder);
Log("Migrated successfully.");
}
catch (Exception ex)
{
LogWarning($"Exception migrating folder: {ex}");
}
}
else // We have to merge
{
try
{
CopyAll(new(legacyPath), new(ExplorerFolder));
Directory.Delete(legacyPath, true);
Log("Migrated successfully.");
}
catch (Exception ex)
{
LogWarning($"Exception migrating folder: {ex}");
}
}
}
}
public static void CopyAll(DirectoryInfo source, DirectoryInfo target)
{
Directory.CreateDirectory(target.FullName);
// Copy each file into it's new directory.
foreach (FileInfo fi in source.GetFiles())
fi.MoveTo(Path.Combine(target.ToString(), fi.Name));
// Copy each subdirectory using recursion.
foreach (DirectoryInfo diSourceSubDir in source.GetDirectories())
{
DirectoryInfo nextTargetSubDir = target.CreateSubdirectory(diSourceSubDir.Name);
CopyAll(diSourceSubDir, nextTargetSubDir);
}
}
#endregion
} }
} }

View File

@ -1,14 +1,7 @@
using System; using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.UI;
using UnityExplorer.UI.Widgets;
using UniverseLib.UI; using UniverseLib.UI;
using UniverseLib.UI.Models; using UniverseLib.UI.Models;
using UniverseLib.UI.Widgets;
using UniverseLib.UI.Widgets.ScrollView; using UniverseLib.UI.Widgets.ScrollView;
namespace UnityExplorer.Hooks namespace UnityExplorer.Hooks
@ -23,14 +16,13 @@ namespace UnityExplorer.Hooks
public float DefaultHeight => 30; public float DefaultHeight => 30;
public Text MethodNameLabel; public Text MethodNameLabel;
public Text HookedLabel;
public ButtonRef HookButton; public ButtonRef HookButton;
public int CurrentDisplayedIndex; public int CurrentDisplayedIndex;
private void OnHookClicked() private void OnHookClicked()
{ {
HookManager.Instance.AddHookClicked(CurrentDisplayedIndex); HookCreator.AddHookClicked(CurrentDisplayedIndex);
} }
public void Enable() public void Enable()
@ -51,9 +43,6 @@ namespace UnityExplorer.Hooks
UIFactory.SetLayoutElement(UIRoot, minWidth: 100, flexibleWidth: 9999, minHeight: 30, flexibleHeight: 600); UIFactory.SetLayoutElement(UIRoot, minWidth: 100, flexibleWidth: 9999, minHeight: 30, flexibleHeight: 600);
UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize; UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
HookedLabel = UIFactory.CreateLabel(UIRoot, "HookedLabel", "✓", TextAnchor.MiddleCenter, Color.green);
UIFactory.SetLayoutElement(HookedLabel.gameObject, minHeight: 25, minWidth: 100);
HookButton = UIFactory.CreateButton(UIRoot, "HookButton", "Hook", new Color(0.2f, 0.25f, 0.2f)); HookButton = UIFactory.CreateButton(UIRoot, "HookButton", "Hook", new Color(0.2f, 0.25f, 0.2f));
UIFactory.SetLayoutElement(HookButton.Component.gameObject, minHeight: 25, minWidth: 100); UIFactory.SetLayoutElement(HookButton.Component.gameObject, minHeight: 25, minWidth: 100);
HookButton.OnClick += OnHookClicked; HookButton.OnClick += OnHookClicked;

View File

@ -1,12 +1,8 @@
using System; using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.UI.Panels;
using UniverseLib.UI; using UniverseLib.UI;
using UniverseLib.UI.Models; using UniverseLib.UI.Models;
using UniverseLib.UI.Widgets;
using UniverseLib.UI.Widgets.ScrollView; using UniverseLib.UI.Widgets.ScrollView;
namespace UnityExplorer.Hooks namespace UnityExplorer.Hooks
@ -29,17 +25,18 @@ namespace UnityExplorer.Hooks
private void OnToggleActiveClicked() private void OnToggleActiveClicked()
{ {
HookManager.Instance.EnableOrDisableHookClicked(CurrentDisplayedIndex); HookList.EnableOrDisableHookClicked(CurrentDisplayedIndex);
} }
private void OnDeleteClicked() private void OnDeleteClicked()
{ {
HookManager.Instance.DeleteHookClicked(CurrentDisplayedIndex); HookList.DeleteHookClicked(CurrentDisplayedIndex);
HookCreator.AddHooksScrollPool.Refresh(true, false);
} }
private void OnEditPatchClicked() private void OnEditPatchClicked()
{ {
HookManager.Instance.EditPatchClicked(CurrentDisplayedIndex); HookList.EditPatchClicked(CurrentDisplayedIndex);
} }
public GameObject CreateContent(GameObject parent) public GameObject CreateContent(GameObject parent)
@ -53,18 +50,18 @@ namespace UnityExplorer.Hooks
MethodNameLabel = UIFactory.CreateLabel(UIRoot, "MethodName", "NOT SET", TextAnchor.MiddleLeft); MethodNameLabel = UIFactory.CreateLabel(UIRoot, "MethodName", "NOT SET", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(MethodNameLabel.gameObject, minHeight: 25, flexibleWidth: 9999); UIFactory.SetLayoutElement(MethodNameLabel.gameObject, minHeight: 25, flexibleWidth: 9999);
ToggleActiveButton = UIFactory.CreateButton(UIRoot, "ToggleActiveBtn", "Enabled", new Color(0.15f, 0.2f, 0.15f)); ToggleActiveButton = UIFactory.CreateButton(UIRoot, "ToggleActiveBtn", "On", new Color(0.15f, 0.2f, 0.15f));
UIFactory.SetLayoutElement(ToggleActiveButton.Component.gameObject, minHeight: 25, minWidth: 100); UIFactory.SetLayoutElement(ToggleActiveButton.Component.gameObject, minHeight: 25, minWidth: 35);
ToggleActiveButton.OnClick += OnToggleActiveClicked; ToggleActiveButton.OnClick += OnToggleActiveClicked;
DeleteButton = UIFactory.CreateButton(UIRoot, "DeleteButton", "Delete", new Color(0.2f, 0.15f, 0.15f)); EditPatchButton = UIFactory.CreateButton(UIRoot, "EditButton", "Edit", new Color(0.15f, 0.15f, 0.15f));
UIFactory.SetLayoutElement(DeleteButton.Component.gameObject, minHeight: 25, minWidth: 100); UIFactory.SetLayoutElement(EditPatchButton.Component.gameObject, minHeight: 25, minWidth: 35);
DeleteButton.OnClick += OnDeleteClicked;
EditPatchButton = UIFactory.CreateButton(UIRoot, "EditButton", "Edit Hook Source", new Color(0.15f, 0.15f, 0.15f));
UIFactory.SetLayoutElement(EditPatchButton.Component.gameObject, minHeight: 25, minWidth: 150);
EditPatchButton.OnClick += OnEditPatchClicked; EditPatchButton.OnClick += OnEditPatchClicked;
DeleteButton = UIFactory.CreateButton(UIRoot, "DeleteButton", "X", new Color(0.2f, 0.15f, 0.15f));
UIFactory.SetLayoutElement(DeleteButton.Component.gameObject, minHeight: 25, minWidth: 35);
DeleteButton.OnClick += OnDeleteClicked;
return UIRoot; return UIRoot;
} }

342
src/Hooks/HookCreator.cs Normal file
View File

@ -0,0 +1,342 @@
using HarmonyLib;
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.CSConsole;
using UnityExplorer.Runtime;
using UnityExplorer.UI.Panels;
using UnityExplorer.UI.Widgets;
using UnityExplorer.UI.Widgets.AutoComplete;
using UniverseLib;
using UniverseLib.UI;
using UniverseLib.UI.Models;
using UniverseLib.UI.Widgets;
using UniverseLib.UI.Widgets.ScrollView;
using UniverseLib.Utility;
namespace UnityExplorer.Hooks
{
public class HookCreator : ICellPoolDataSource<AddHookCell>
{
public int ItemCount => filteredEligibleMethods.Count;
static readonly List<MethodInfo> currentAddEligibleMethods = new();
static readonly List<MethodInfo> filteredEligibleMethods = new();
static readonly List<string> currentEligibleNamesForFiltering = new();
// hook editor
static readonly LexerBuilder Lexer = new();
internal static HookInstance CurrentEditedHook;
// Add Hooks UI
internal static GameObject AddHooksRoot;
internal static ScrollPool<AddHookCell> AddHooksScrollPool;
internal static Text AddHooksLabel;
internal static InputFieldRef AddHooksMethodFilterInput;
internal static InputFieldRef ClassSelectorInputField;
internal static Type pendingGenericDefinition;
internal static MethodInfo pendingGenericMethod;
public static bool PendingGeneric => pendingGenericDefinition != null || pendingGenericMethod != null;
// Hook Source Editor UI
public static GameObject EditorRoot { get; private set; }
public static Text EditingHookLabel { get; private set; }
public static InputFieldScroller EditorInputScroller { get; private set; }
public static InputFieldRef EditorInput => EditorInputScroller.InputField;
public static Text EditorInputText { get; private set; }
public static Text EditorHighlightText { get; private set; }
// ~~~~~~ New hook method selector ~~~~~~~
public void OnClassSelectedForHooks(string typeFullName)
{
Type type = ReflectionUtility.GetTypeByName(typeFullName);
if (type == null)
{
ExplorerCore.LogWarning($"Could not find any type by name {typeFullName}!");
return;
}
if (type.IsGenericType)
{
pendingGenericDefinition = type;
HookManagerPanel.genericArgsHandler.Show(OnGenericClassChosen, OnGenericClassCancel, type);
HookManagerPanel.Instance.SetPage(HookManagerPanel.Pages.GenericArgsSelector);
return;
}
ShowMethodsForType(type);
}
void ShowMethodsForType(Type type)
{
SetAddHooksLabelType(SignatureHighlighter.Parse(type, true));
AddHooksMethodFilterInput.Text = string.Empty;
filteredEligibleMethods.Clear();
currentAddEligibleMethods.Clear();
currentEligibleNamesForFiltering.Clear();
foreach (MethodInfo method in type.GetMethods(ReflectionUtility.FLAGS))
{
if (UERuntimeHelper.IsBlacklisted(method))
continue;
currentAddEligibleMethods.Add(method);
currentEligibleNamesForFiltering.Add(SignatureHighlighter.RemoveHighlighting(SignatureHighlighter.ParseMethod(method)));
filteredEligibleMethods.Add(method);
}
AddHooksScrollPool.Refresh(true, true);
}
void OnGenericClassChosen(Type[] genericArgs)
{
Type generic = pendingGenericDefinition.MakeGenericType(genericArgs);
ShowMethodsForType(generic);
HookManagerPanel.Instance.SetPage(HookManagerPanel.Pages.ClassMethodSelector);
}
void OnGenericClassCancel()
{
pendingGenericDefinition = null;
HookManagerPanel.Instance.SetPage(HookManagerPanel.Pages.ClassMethodSelector);
}
public void SetAddHooksLabelType(string typeText)
{
AddHooksLabel.text = $"Adding hooks to: {typeText}";
AddHooksMethodFilterInput.GameObject.SetActive(true);
AddHooksScrollPool.UIRoot.SetActive(true);
}
public static void AddHookClicked(int index)
{
if (index >= filteredEligibleMethods.Count)
return;
MethodInfo method = filteredEligibleMethods[index];
if (!method.IsGenericMethod && HookList.hookedSignatures.Contains(method.FullDescription()))
{
ExplorerCore.Log($"Non-generic methods can only be hooked once.");
return;
}
else if (method.IsGenericMethod)
{
pendingGenericMethod = method;
HookManagerPanel.genericArgsHandler.Show(OnGenericMethodChosen, OnGenericMethodCancel, method);
HookManagerPanel.Instance.SetPage(HookManagerPanel.Pages.GenericArgsSelector);
return;
}
AddHook(filteredEligibleMethods[index]);
}
static void OnGenericMethodChosen(Type[] arguments)
{
MethodInfo generic = pendingGenericMethod.MakeGenericMethod(arguments);
AddHook(generic);
}
static void OnGenericMethodCancel()
{
pendingGenericMethod = null;
HookManagerPanel.Instance.SetPage(HookManagerPanel.Pages.ClassMethodSelector);
}
public static void AddHook(MethodInfo method)
{
HookManagerPanel.Instance.SetPage(HookManagerPanel.Pages.ClassMethodSelector);
string sig = method.FullDescription();
if (HookList.hookedSignatures.Contains(sig))
{
ExplorerCore.LogWarning($"Method is already hooked!");
return;
}
HookInstance hook = new(method);
if (hook.Enabled)
{
HookList.hookedSignatures.Add(sig);
HookList.currentHooks.Add(sig, hook);
}
AddHooksScrollPool.Refresh(true, false);
HookList.HooksScrollPool.Refresh(true, false);
}
public void OnAddHookFilterInputChanged(string input)
{
filteredEligibleMethods.Clear();
if (string.IsNullOrEmpty(input))
filteredEligibleMethods.AddRange(currentAddEligibleMethods);
else
{
for (int i = 0; i < currentAddEligibleMethods.Count; i++)
{
MethodInfo eligible = currentAddEligibleMethods[i];
string sig = currentEligibleNamesForFiltering[i];
if (sig.ContainsIgnoreCase(input))
filteredEligibleMethods.Add(eligible);
}
}
AddHooksScrollPool.Refresh(true, true);
}
// Set eligible method cell
public void OnCellBorrowed(AddHookCell cell) { }
public void SetCell(AddHookCell cell, int index)
{
if (index >= filteredEligibleMethods.Count)
{
cell.Disable();
return;
}
cell.CurrentDisplayedIndex = index;
MethodInfo method = filteredEligibleMethods[index];
cell.MethodNameLabel.text = SignatureHighlighter.ParseMethod(method);
}
// ~~~~~~~~ Hook source editor ~~~~~~~~
internal static void SetEditedHook(HookInstance hook)
{
CurrentEditedHook = hook;
EditingHookLabel.text = $"Editing: {SignatureHighlighter.Parse(hook.TargetMethod.DeclaringType, false, hook.TargetMethod)}";
EditorInput.Text = hook.PatchSourceCode;
}
internal static void OnEditorInputChanged(string value)
{
EditorHighlightText.text = Lexer.BuildHighlightedString(value, 0, value.Length - 1, 0, EditorInput.Component.caretPosition, out _);
}
internal static void EditorInputCancel()
{
CurrentEditedHook = null;
HookManagerPanel.Instance.SetPage(HookManagerPanel.Pages.ClassMethodSelector);
}
internal static void EditorInputSave()
{
string input = EditorInput.Text;
bool wasEnabled = CurrentEditedHook.Enabled;
if (CurrentEditedHook.CompileAndGenerateProcessor(input))
{
if (wasEnabled)
CurrentEditedHook.Patch();
CurrentEditedHook.PatchSourceCode = input;
CurrentEditedHook = null;
HookManagerPanel.Instance.SetPage(HookManagerPanel.Pages.ClassMethodSelector);
}
}
// UI Construction
internal void ConstructAddHooksView(GameObject rightGroup)
{
AddHooksRoot = UIFactory.CreateUIObject("AddHooksPanel", rightGroup);
UIFactory.SetLayoutElement(AddHooksRoot, flexibleHeight: 9999, flexibleWidth: 9999);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(AddHooksRoot, false, false, true, true);
GameObject addRow = UIFactory.CreateHorizontalGroup(AddHooksRoot, "AddRow", false, true, true, true, 4,
new Vector4(2, 2, 2, 2), new Color(0.2f, 0.2f, 0.2f));
UIFactory.SetLayoutElement(addRow, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
ClassSelectorInputField = UIFactory.CreateInputField(addRow, "ClassInput", "Enter a class to add hooks to...");
UIFactory.SetLayoutElement(ClassSelectorInputField.Component.gameObject, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 0);
TypeCompleter completer = new(typeof(object), ClassSelectorInputField, true, false, true);
//completer.AllTypes = true;
ButtonRef addButton = UIFactory.CreateButton(addRow, "AddButton", "View Methods");
UIFactory.SetLayoutElement(addButton.Component.gameObject, minWidth: 110, minHeight: 25);
addButton.OnClick += () => { OnClassSelectedForHooks(ClassSelectorInputField.Text); };
AddHooksLabel = UIFactory.CreateLabel(AddHooksRoot, "AddLabel", "Choose a class to begin...", TextAnchor.MiddleCenter);
UIFactory.SetLayoutElement(AddHooksLabel.gameObject, minHeight: 30, minWidth: 100, flexibleWidth: 9999);
AddHooksMethodFilterInput = UIFactory.CreateInputField(AddHooksRoot, "FilterInputField", "Filter method names...");
UIFactory.SetLayoutElement(AddHooksMethodFilterInput.Component.gameObject, minHeight: 30, flexibleWidth: 9999);
AddHooksMethodFilterInput.OnValueChanged += OnAddHookFilterInputChanged;
AddHooksScrollPool = UIFactory.CreateScrollPool<AddHookCell>(AddHooksRoot, "MethodAddScrollPool",
out GameObject addScrollRoot, out GameObject addContent);
UIFactory.SetLayoutElement(addScrollRoot, flexibleHeight: 9999);
AddHooksScrollPool.Initialize(this);
AddHooksMethodFilterInput.GameObject.SetActive(false);
AddHooksScrollPool.UIRoot.SetActive(false);
}
public void ConstructEditor(GameObject parent)
{
EditorRoot = UIFactory.CreateUIObject("HookSourceEditor", parent);
UIFactory.SetLayoutElement(EditorRoot, flexibleHeight: 9999, flexibleWidth: 9999);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(EditorRoot, true, true, true, true, 2, 3, 3, 3, 3);
EditingHookLabel = UIFactory.CreateLabel(EditorRoot, "EditingHookLabel", "NOT SET", TextAnchor.MiddleCenter);
EditingHookLabel.fontStyle = FontStyle.Bold;
UIFactory.SetLayoutElement(EditingHookLabel.gameObject, flexibleWidth: 9999, minHeight: 25);
Text editorLabel = UIFactory.CreateLabel(EditorRoot,
"EditorLabel",
"* Accepted method names are <b>Prefix</b>, <b>Postfix</b>, <b>Finalizer</b> and <b>Transpiler</b> (can define multiple).\n" +
"* Your patch methods must be static.\n" +
"* Hooks are temporary! Copy the source into your IDE to avoid losing work if you wish to keep it!",
TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(editorLabel.gameObject, minHeight: 25, flexibleWidth: 9999);
GameObject editorButtonRow = UIFactory.CreateHorizontalGroup(EditorRoot, "ButtonRow", false, false, true, true, 5);
UIFactory.SetLayoutElement(editorButtonRow, minHeight: 25, flexibleWidth: 9999);
ButtonRef editorSaveButton = UIFactory.CreateButton(editorButtonRow, "DoneButton", "Save and Return", new Color(0.2f, 0.3f, 0.2f));
UIFactory.SetLayoutElement(editorSaveButton.Component.gameObject, minHeight: 25, flexibleWidth: 9999);
editorSaveButton.OnClick += EditorInputSave;
ButtonRef editorDoneButton = UIFactory.CreateButton(editorButtonRow, "DoneButton", "Cancel and Return", new Color(0.2f, 0.2f, 0.2f));
UIFactory.SetLayoutElement(editorDoneButton.Component.gameObject, minHeight: 25, flexibleWidth: 9999);
editorDoneButton.OnClick += EditorInputCancel;
int fontSize = 16;
GameObject inputObj = UIFactory.CreateScrollInputField(EditorRoot, "EditorInput", "", out InputFieldScroller inputScroller, fontSize);
EditorInputScroller = inputScroller;
EditorInput.OnValueChanged += OnEditorInputChanged;
EditorInputText = EditorInput.Component.textComponent;
EditorInputText.supportRichText = false;
EditorInputText.color = Color.clear;
EditorInput.Component.customCaretColor = true;
EditorInput.Component.caretColor = Color.white;
EditorInput.PlaceholderText.fontSize = fontSize;
// Lexer highlight text overlay
GameObject highlightTextObj = UIFactory.CreateUIObject("HighlightText", EditorInputText.gameObject);
RectTransform highlightTextRect = highlightTextObj.GetComponent<RectTransform>();
highlightTextRect.pivot = new Vector2(0, 1);
highlightTextRect.anchorMin = Vector2.zero;
highlightTextRect.anchorMax = Vector2.one;
highlightTextRect.offsetMin = Vector2.zero;
highlightTextRect.offsetMax = Vector2.zero;
EditorHighlightText = highlightTextObj.AddComponent<Text>();
EditorHighlightText.color = Color.white;
EditorHighlightText.supportRichText = true;
EditorHighlightText.fontSize = fontSize;
// Set fonts
EditorInputText.font = UniversalUI.ConsoleFont;
EditorInput.PlaceholderText.font = UniversalUI.ConsoleFont;
EditorHighlightText.font = UniversalUI.ConsoleFont;
}
}
}

View File

@ -1,11 +1,11 @@
using System; using HarmonyLib;
using System.CodeDom.Compiler; using Mono.CSharp;
using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using HarmonyLib;
using Mono.CSharp;
using UnityExplorer.CSConsole; using UnityExplorer.CSConsole;
using UniverseLib; using UniverseLib;
@ -15,12 +15,14 @@ namespace UnityExplorer.Hooks
{ {
// Static // Static
private static readonly StringBuilder evalOutput = new(); //static readonly StringBuilder evalOutput = new();
private static readonly ScriptEvaluator scriptEvaluator = new(new StringWriter(evalOutput)); static readonly StringBuilder evaluatorOutput;
static readonly ScriptEvaluator scriptEvaluator = new(new StringWriter(evaluatorOutput = new StringBuilder()));
static HookInstance() static HookInstance()
{ {
scriptEvaluator.Run("using System;"); scriptEvaluator.Run("using System;");
scriptEvaluator.Run("using System.Text;");
scriptEvaluator.Run("using System.Reflection;"); scriptEvaluator.Run("using System.Reflection;");
scriptEvaluator.Run("using System.Collections;"); scriptEvaluator.Run("using System.Collections;");
scriptEvaluator.Run("using System.Collections.Generic;"); scriptEvaluator.Run("using System.Collections.Generic;");
@ -43,7 +45,7 @@ namespace UnityExplorer.Hooks
public HookInstance(MethodInfo targetMethod) public HookInstance(MethodInfo targetMethod)
{ {
this.TargetMethod = targetMethod; this.TargetMethod = targetMethod;
this.shortSignature = $"{targetMethod.DeclaringType.Name}.{targetMethod.Name}"; this.shortSignature = TargetMethod.FullDescription();
GenerateDefaultPatchSourceCode(targetMethod); GenerateDefaultPatchSourceCode(targetMethod);
@ -60,15 +62,15 @@ namespace UnityExplorer.Hooks
{ {
Unpatch(); Unpatch();
StringBuilder codeBuilder = new();
try try
{ {
patchProcessor = ExplorerCore.Harmony.CreateProcessor(TargetMethod); patchProcessor = ExplorerCore.Harmony.CreateProcessor(TargetMethod);
// Dynamically compile the patch method // Dynamically compile the patch method
var codeBuilder = new StringBuilder(); codeBuilder.AppendLine($"static class DynamicPatch_{DateTime.Now.Ticks}");
codeBuilder.AppendLine($"public class DynamicPatch_{DateTime.Now.Ticks}");
codeBuilder.AppendLine("{"); codeBuilder.AppendLine("{");
codeBuilder.AppendLine(patchSource); codeBuilder.AppendLine(patchSource);
codeBuilder.AppendLine("}"); codeBuilder.AppendLine("}");
@ -80,11 +82,11 @@ namespace UnityExplorer.Hooks
// TODO: Publicize MCS to avoid this reflection // TODO: Publicize MCS to avoid this reflection
// Get the most recent Patch type in the source file // Get the most recent Patch type in the source file
var typeContainer = ((CompilationSourceFile)fi_sourceFile.GetValue(scriptEvaluator)) TypeContainer typeContainer = ((CompilationSourceFile)fi_sourceFile.GetValue(scriptEvaluator))
.Containers .Containers
.Last(it => it.MemberName.Name.StartsWith("DynamicPatch_")); .Last(it => it.MemberName.Name.StartsWith("DynamicPatch_"));
// Get the TypeSpec from the TypeDefinition, then get its "MetaInfo" (System.Type) // Get the TypeSpec from the TypeDefinition, then get its "MetaInfo" (System.Type)
var patchClass = ((TypeSpec)pi_Definition.GetValue((Class)typeContainer, null)).GetMetaInfo(); Type patchClass = ((TypeSpec)pi_Definition.GetValue((Class)typeContainer, null)).GetMetaInfo();
// Create the harmony patches as defined // Create the harmony patches as defined
@ -108,30 +110,59 @@ namespace UnityExplorer.Hooks
} }
catch (Exception ex) catch (Exception ex)
{ {
ExplorerCore.LogWarning($"Exception creating patch processor for target method {TargetMethod.FullDescription()}!\r\n{ex}"); if (ex is FormatException)
{
string output = scriptEvaluator._textWriter.ToString();
string[] outputSplit = output.Split('\n');
if (outputSplit.Length >= 2)
output = outputSplit[outputSplit.Length - 2];
evaluatorOutput.Clear();
if (ScriptEvaluator._reportPrinter.ErrorsCount > 0)
ExplorerCore.LogWarning($"Unable to compile the code. Evaluator's last output was:\r\n{output}");
else
ExplorerCore.LogWarning($"Exception generating patch source code: {ex}");
}
else
ExplorerCore.LogWarning($"Exception generating patch source code: {ex}");
// ExplorerCore.Log(codeBuilder.ToString());
return false; return false;
} }
} }
static string FullDescriptionClean(Type type)
{
string description = type.FullDescription().Replace("+", ".");
if (description.EndsWith("&"))
description = $"ref {description.Substring(0, description.Length - 1)}";
return description;
}
private string GenerateDefaultPatchSourceCode(MethodInfo targetMethod) private string GenerateDefaultPatchSourceCode(MethodInfo targetMethod)
{ {
var codeBuilder = new StringBuilder(); StringBuilder codeBuilder = new();
// Arguments
codeBuilder.Append("public static void Postfix(System.Reflection.MethodBase __originalMethod"); codeBuilder.Append("static void Postfix("); // System.Reflection.MethodBase __originalMethod
if (!targetMethod.IsStatic) bool isStatic = targetMethod.IsStatic;
codeBuilder.Append($", {targetMethod.DeclaringType.FullName} __instance"); if (!isStatic)
codeBuilder.Append($"{FullDescriptionClean(targetMethod.DeclaringType)} __instance");
if (targetMethod.ReturnType != typeof(void)) if (targetMethod.ReturnType != typeof(void))
codeBuilder.Append($", {targetMethod.ReturnType.FullName} __result"); {
if (!isStatic)
codeBuilder.Append(", ");
codeBuilder.Append($"{FullDescriptionClean(targetMethod.ReturnType)} __result");
}
var parameters = targetMethod.GetParameters(); ParameterInfo[] parameters = targetMethod.GetParameters();
int paramIdx = 0; int paramIdx = 0;
foreach (var param in parameters) foreach (ParameterInfo param in parameters)
{ {
codeBuilder.Append($", {param.ParameterType.FullDescription().Replace("&", "")} __{paramIdx}"); codeBuilder.Append($", {FullDescriptionClean(param.ParameterType)} __{paramIdx}");
paramIdx++; paramIdx++;
} }
@ -140,42 +171,39 @@ namespace UnityExplorer.Hooks
// Patch body // Patch body
codeBuilder.AppendLine("{"); codeBuilder.AppendLine("{");
codeBuilder.AppendLine(" try {"); codeBuilder.AppendLine(" try {");
codeBuilder.AppendLine(" StringBuilder sb = new StringBuilder();");
// Log message codeBuilder.AppendLine($" sb.AppendLine(\"---- Patched called ----\");");
codeBuilder.AppendLine($" sb.AppendLine(\"{shortSignature}\");");
var logMessage = new StringBuilder();
logMessage.Append($"Patch called: {shortSignature}\\n");
if (!targetMethod.IsStatic) if (!targetMethod.IsStatic)
logMessage.Append("__instance: {__instance.ToString()}\\n"); codeBuilder.AppendLine($" sb.Append(\"- __instance: \").AppendLine(__instance.ToString());");
paramIdx = 0; paramIdx = 0;
foreach (var param in parameters) foreach (ParameterInfo param in parameters)
{ {
logMessage.Append($"Parameter {paramIdx} {param.Name}: "); codeBuilder.Append($" sb.Append(\"- Parameter {paramIdx} '{param.Name}': \")");
Type pType = param.ParameterType; Type pType = param.ParameterType;
if (pType.IsByRef) pType = pType.GetElementType(); if (pType.IsByRef) pType = pType.GetElementType();
if (pType.IsValueType) if (pType.IsValueType)
logMessage.Append($"{{__{paramIdx}.ToString()}}"); codeBuilder.AppendLine($".AppendLine(__{paramIdx}.ToString());");
else else
logMessage.Append($"{{__{paramIdx}?.ToString() ?? \"null\"}}"); codeBuilder.AppendLine($".AppendLine(__{paramIdx}?.ToString() ?? \"null\");");
logMessage.Append("\\n");
paramIdx++; paramIdx++;
} }
if (targetMethod.ReturnType != typeof(void)) if (targetMethod.ReturnType != typeof(void))
{ {
logMessage.Append("Return value: "); codeBuilder.Append(" sb.Append(\"- Return value: \")");
if (targetMethod.ReturnType.IsValueType) if (targetMethod.ReturnType.IsValueType)
logMessage.Append("{__result.ToString()}"); codeBuilder.AppendLine(".AppendLine(__result.ToString());");
else else
logMessage.Append("{__result?.ToString() ?? \"null\"}"); codeBuilder.AppendLine(".AppendLine(__result?.ToString() ?? \"null\");");
logMessage.Append("\\n");
} }
codeBuilder.AppendLine($" UnityExplorer.ExplorerCore.Log($\"{logMessage}\");"); codeBuilder.AppendLine($" UnityExplorer.ExplorerCore.Log(sb.ToString());");
codeBuilder.AppendLine(" }"); codeBuilder.AppendLine(" }");
codeBuilder.AppendLine(" catch (System.Exception ex) {"); codeBuilder.AppendLine(" catch (System.Exception ex) {");
codeBuilder.AppendLine($" UnityExplorer.ExplorerCore.LogWarning($\"Exception in patch of {shortSignature}:\\n{{ex}}\");"); codeBuilder.AppendLine($" UnityExplorer.ExplorerCore.LogWarning($\"Exception in patch of {shortSignature}:\\n{{ex}}\");");

97
src/Hooks/HookList.cs Normal file
View File

@ -0,0 +1,97 @@
using HarmonyLib;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.UI.Panels;
using UniverseLib;
using UniverseLib.UI;
using UniverseLib.UI.Models;
using UniverseLib.UI.Widgets.ScrollView;
using UniverseLib.Utility;
namespace UnityExplorer.Hooks
{
public class HookList : ICellPoolDataSource<HookCell>
{
public int ItemCount => currentHooks.Count;
internal static readonly HashSet<string> hookedSignatures = new();
internal static readonly OrderedDictionary currentHooks = new();
internal static GameObject UIRoot;
internal static ScrollPool<HookCell> HooksScrollPool;
public static void EnableOrDisableHookClicked(int index)
{
HookInstance hook = (HookInstance)currentHooks[index];
hook.TogglePatch();
HooksScrollPool.Refresh(true, false);
}
public static void DeleteHookClicked(int index)
{
HookInstance hook = (HookInstance)currentHooks[index];
if (HookCreator.CurrentEditedHook == hook)
HookCreator.EditorInputCancel();
hook.Unpatch();
currentHooks.RemoveAt(index);
hookedSignatures.Remove(hook.TargetMethod.FullDescription());
HooksScrollPool.Refresh(true, false);
}
public static void EditPatchClicked(int index)
{
if (HookCreator.PendingGeneric)
HookManagerPanel.genericArgsHandler.Cancel();
HookManagerPanel.Instance.SetPage(HookManagerPanel.Pages.HookSourceEditor);
HookInstance hook = (HookInstance)currentHooks[index];
HookCreator.SetEditedHook(hook);
}
// Set current hook cell
public void OnCellBorrowed(HookCell cell) { }
public void SetCell(HookCell cell, int index)
{
if (index >= currentHooks.Count)
{
cell.Disable();
return;
}
cell.CurrentDisplayedIndex = index;
HookInstance hook = (HookInstance)currentHooks[index];
cell.MethodNameLabel.text = SignatureHighlighter.ParseMethod(hook.TargetMethod);
cell.ToggleActiveButton.ButtonText.text = hook.Enabled ? "On" : "Off";
RuntimeHelper.SetColorBlockAuto(cell.ToggleActiveButton.Component,
hook.Enabled ? new Color(0.15f, 0.2f, 0.15f) : new Color(0.2f, 0.2f, 0.15f));
}
// UI
internal void ConstructUI(GameObject leftGroup)
{
UIRoot = UIFactory.CreateUIObject("CurrentHooksPanel", leftGroup);
UIFactory.SetLayoutElement(UIRoot, preferredHeight: 150, flexibleHeight: 0, flexibleWidth: 9999);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(UIRoot, true, true, true, true);
Text hooksLabel = UIFactory.CreateLabel(UIRoot, "HooksLabel", "Current Hooks", TextAnchor.MiddleCenter);
UIFactory.SetLayoutElement(hooksLabel.gameObject, minHeight: 30, flexibleWidth: 9999);
HooksScrollPool = UIFactory.CreateScrollPool<HookCell>(UIRoot, "HooksScrollPool",
out GameObject hooksScroll, out GameObject hooksContent);
UIFactory.SetLayoutElement(hooksScroll, flexibleHeight: 9999);
HooksScrollPool.Initialize(this);
}
}
}

View File

@ -1,231 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Reflection;
using System.Text;
using HarmonyLib;
using UnityEngine;
using UnityExplorer.Runtime;
using UnityExplorer.CSConsole;
using UnityExplorer.UI;
using UnityExplorer.UI.Panels;
using UnityExplorer.UI.Widgets;
using UniverseLib;
using UniverseLib.UI.Widgets;
using UniverseLib.UI.Widgets.ScrollView;
using UniverseLib.Utility;
namespace UnityExplorer.Hooks
{
public class HookManager : ICellPoolDataSource<HookCell>, ICellPoolDataSource<AddHookCell>
{
private static HookManager s_instance;
public static HookManager Instance => s_instance ?? (s_instance = new HookManager());
public HookManagerPanel Panel => UIManager.GetPanel<HookManagerPanel>(UIManager.Panels.HookManager);
// This class acts as the data source for both current hooks and eligable methods when adding hooks.
// 'isAddingMethods' keeps track of which pool is currently the displayed one, so our ItemCount reflects the
// correct pool cells.
private bool isAddingMethods;
public int ItemCount => isAddingMethods ? filteredEligableMethods.Count : currentHooks.Count;
// current hooks
private readonly HashSet<string> hookedSignatures = new HashSet<string>();
private readonly OrderedDictionary currentHooks = new OrderedDictionary();
// adding hooks
private readonly List<MethodInfo> currentAddEligableMethods = new List<MethodInfo>();
private readonly List<MethodInfo> filteredEligableMethods = new List<MethodInfo>();
// hook editor
private readonly LexerBuilder Lexer = new LexerBuilder();
private HookInstance currentEditedHook;
// ~~~~~~~~~~~ Main Current Hooks window ~~~~~~~~~~~
public void EnableOrDisableHookClicked(int index)
{
var hook = (HookInstance)currentHooks[index];
hook.TogglePatch();
Panel.HooksScrollPool.Refresh(true, false);
}
public void DeleteHookClicked(int index)
{
var hook = (HookInstance)currentHooks[index];
hook.Unpatch();
currentHooks.RemoveAt(index);
hookedSignatures.Remove(hook.TargetMethod.FullDescription());
Panel.HooksScrollPool.Refresh(true, false);
}
public void EditPatchClicked(int index)
{
Panel.SetPage(HookManagerPanel.Pages.HookSourceEditor);
var hook = (HookInstance)currentHooks[index];
currentEditedHook = hook;
Panel.EditorInput.Text = hook.PatchSourceCode;
}
// Set current hook cell
public void OnCellBorrowed(HookCell cell) { }
public void SetCell(HookCell cell, int index)
{
if (index >= this.currentHooks.Count)
{
cell.Disable();
return;
}
cell.CurrentDisplayedIndex = index;
var hook = (HookInstance)this.currentHooks[index];
cell.MethodNameLabel.text = SignatureHighlighter.HighlightMethod(hook.TargetMethod);
cell.ToggleActiveButton.ButtonText.text = hook.Enabled ? "Enabled" : "Disabled";
RuntimeHelper.SetColorBlockAuto(cell.ToggleActiveButton.Component,
hook.Enabled ? new Color(0.15f, 0.2f, 0.15f) : new Color(0.2f, 0.2f, 0.15f));
}
// ~~~~~~~~~~~ Add Hooks window ~~~~~~~~~~~
public void OnClassSelectedForHooks(string typeFullName)
{
var type = ReflectionUtility.GetTypeByName(typeFullName);
if (type == null)
{
ExplorerCore.LogWarning($"Could not find any type by name {typeFullName}!");
return;
}
Panel.SetAddHooksLabelType(SignatureHighlighter.Parse(type, true));
Panel.ResetMethodFilter();
filteredEligableMethods.Clear();
currentAddEligableMethods.Clear();
foreach (var method in type.GetMethods(ReflectionUtility.FLAGS))
{
if (method.IsGenericMethod || UERuntimeHelper.IsBlacklisted(method))
continue;
currentAddEligableMethods.Add(method);
filteredEligableMethods.Add(method);
}
isAddingMethods = true;
Panel.SetPage(HookManagerPanel.Pages.ClassMethodSelector);
Panel.AddHooksScrollPool.Refresh(true, true);
}
public void DoneAddingHooks()
{
isAddingMethods = false;
Panel.SetPage(HookManagerPanel.Pages.CurrentHooks);
Panel.HooksScrollPool.Refresh(true, false);
}
public void AddHookClicked(int index)
{
if (index >= this.filteredEligableMethods.Count)
return;
AddHook(filteredEligableMethods[index]);
Panel.AddHooksScrollPool.Refresh(true, false);
}
public void AddHook(MethodInfo method)
{
var sig = method.FullDescription();
if (hookedSignatures.Contains(sig))
return;
var hook = new HookInstance(method);
if (hook.Enabled)
{
hookedSignatures.Add(sig);
currentHooks.Add(sig, hook);
}
}
public void OnAddHookFilterInputChanged(string input)
{
filteredEligableMethods.Clear();
if (string.IsNullOrEmpty(input))
filteredEligableMethods.AddRange(currentAddEligableMethods);
else
{
foreach (var method in currentAddEligableMethods)
{
if (method.Name.ContainsIgnoreCase(input))
filteredEligableMethods.Add(method);
}
}
Panel.AddHooksScrollPool.Refresh(true, true);
}
// Set eligable method cell
public void OnCellBorrowed(AddHookCell cell) { }
public void SetCell(AddHookCell cell, int index)
{
if (index >= this.filteredEligableMethods.Count)
{
cell.Disable();
return;
}
cell.CurrentDisplayedIndex = index;
var method = this.filteredEligableMethods[index];
cell.MethodNameLabel.text = SignatureHighlighter.HighlightMethod(method);
var sig = method.FullDescription();
if (hookedSignatures.Contains(sig))
{
cell.HookButton.Component.gameObject.SetActive(false);
cell.HookedLabel.gameObject.SetActive(true);
}
else
{
cell.HookButton.Component.gameObject.SetActive(true);
cell.HookedLabel.gameObject.SetActive(false);
}
}
// ~~~~~~~~~~~ Hook source editor window ~~~~~~~~~~~
public void OnEditorInputChanged(string value)
{
Panel.EditorHighlightText.text = Lexer.BuildHighlightedString(value, 0, value.Length - 1, 0,
Panel.EditorInput.Component.caretPosition, out _);
}
public void EditorInputCancel()
{
currentEditedHook = null;
Panel.SetPage(HookManagerPanel.Pages.CurrentHooks);
}
public void EditorInputSave()
{
var input = Panel.EditorInput.Text;
bool wasEnabled = currentEditedHook.Enabled;
if (currentEditedHook.CompileAndGenerateProcessor(input))
{
if (wasEnabled)
currentEditedHook.Patch();
currentEditedHook.PatchSourceCode = input;
currentEditedHook = null;
Panel.SetPage(HookManagerPanel.Pages.CurrentHooks);
}
}
}
}

View File

@ -2,18 +2,15 @@
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UniverseLib.Input;
using UnityExplorer.UI;
using UniverseLib.UI.Models;
using UnityExplorer.UI.Panels; using UnityExplorer.UI.Panels;
using UnityExplorer.UI.Widgets; using UnityExplorer.UI.Widgets;
using UnityExplorer.UI.Widgets.AutoComplete; using UnityExplorer.UI.Widgets.AutoComplete;
using UniverseLib.UI.Widgets;
using UniverseLib.UI;
using UniverseLib; using UniverseLib;
using UniverseLib.UI;
using UniverseLib.UI.Models;
using UniverseLib.UI.Widgets;
using UniverseLib.UI.Widgets.ScrollView; using UniverseLib.UI.Widgets.ScrollView;
using UniverseLib.Utility; using UniverseLib.Utility;
@ -29,7 +26,7 @@ namespace UnityExplorer.Inspectors
public TransformTree TransformTree; public TransformTree TransformTree;
private ScrollPool<TransformCell> transformScroll; private ScrollPool<TransformCell> transformScroll;
private readonly List<GameObject> cachedChildren = new List<GameObject>(); private readonly List<GameObject> cachedChildren = new();
public ComponentList ComponentList; public ComponentList ComponentList;
private ScrollPool<ComponentCell> componentScroll; private ScrollPool<ComponentCell> componentScroll;
@ -77,7 +74,7 @@ namespace UnityExplorer.Inspectors
InspectorManager.ReleaseInspector(this); InspectorManager.ReleaseInspector(this);
} }
public void ChangeTarget(GameObject newTarget) public void OnTransformCellClicked(GameObject newTarget)
{ {
this.Target = newTarget; this.Target = newTarget;
GOControls.UpdateGameObjectInfo(true, true); GOControls.UpdateGameObjectInfo(true, true);
@ -127,10 +124,10 @@ namespace UnityExplorer.Inspectors
return cachedChildren; return cachedChildren;
} }
private readonly List<Component> componentEntries = new List<Component>(); private readonly List<Component> componentEntries = new();
private readonly HashSet<int> compInstanceIDs = new HashSet<int>(); private readonly HashSet<int> compInstanceIDs = new();
private readonly List<Behaviour> behaviourEntries = new List<Behaviour>(); private readonly List<Behaviour> behaviourEntries = new();
private readonly List<bool> behaviourEnabledStates = new List<bool>(); private readonly List<bool> behaviourEnabledStates = new();
// ComponentList.GetRootEntriesMethod // ComponentList.GetRootEntriesMethod
private List<Component> GetComponentEntries() => GOTarget ? componentEntries : Enumerable.Empty<Component>().ToList(); private List<Component> GetComponentEntries() => GOTarget ? componentEntries : Enumerable.Empty<Component>().ToList();
@ -149,13 +146,13 @@ namespace UnityExplorer.Inspectors
} }
// Check if we actually need to refresh the component cells or not. // Check if we actually need to refresh the component cells or not.
var comps = GOTarget.GetComponents<Component>(); IEnumerable<Component> comps = GOTarget.GetComponents<Component>();
var behaviours = GOTarget.GetComponents<Behaviour>(); IEnumerable<Behaviour> behaviours = GOTarget.GetComponents<Behaviour>();
bool needRefresh = false; bool needRefresh = false;
int count = 0; int count = 0;
foreach (var comp in comps) foreach (Component comp in comps)
{ {
if (!comp) if (!comp)
continue; continue;
@ -173,7 +170,7 @@ namespace UnityExplorer.Inspectors
else else
{ {
count = 0; count = 0;
foreach (var behaviour in behaviours) foreach (Behaviour behaviour in behaviours)
{ {
if (!behaviour) if (!behaviour)
continue; continue;
@ -194,19 +191,35 @@ namespace UnityExplorer.Inspectors
componentEntries.Clear(); componentEntries.Clear();
compInstanceIDs.Clear(); compInstanceIDs.Clear();
foreach (var comp in comps) foreach (Component comp in comps)
{ {
if (!comp) continue; if (!comp)
continue;
componentEntries.Add(comp); componentEntries.Add(comp);
compInstanceIDs.Add(comp.GetInstanceID()); compInstanceIDs.Add(comp.GetInstanceID());
} }
behaviourEntries.Clear(); behaviourEntries.Clear();
behaviourEnabledStates.Clear(); behaviourEnabledStates.Clear();
foreach (var behaviour in behaviours) foreach (Behaviour behaviour in behaviours)
{ {
if (!behaviour) continue; if (!behaviour)
behaviourEntries.Add(behaviour); continue;
// Don't ask me how, but in some games this can be true for certain components.
// They get picked up from GetComponents<Behaviour>, but they are not actually Behaviour...?
if (!typeof(Behaviour).IsAssignableFrom(behaviour.GetType()))
continue;
try
{
behaviourEntries.Add(behaviour);
}
catch (Exception ex)
{
ExplorerCore.LogWarning(ex);
}
behaviourEnabledStates.Add(behaviour.enabled); behaviourEnabledStates.Add(behaviour.enabled);
} }
@ -217,7 +230,7 @@ namespace UnityExplorer.Inspectors
private void OnAddChildClicked(string input) private void OnAddChildClicked(string input)
{ {
var newObject = new GameObject(input); GameObject newObject = new(input);
newObject.transform.parent = GOTarget.transform; newObject.transform.parent = GOTarget.transform;
TransformTree.RefreshData(true, false, true, false); TransformTree.RefreshData(true, false, true, false);
@ -250,7 +263,7 @@ namespace UnityExplorer.Inspectors
UIRoot = UIFactory.CreateVerticalGroup(parent, "GameObjectInspector", true, false, true, true, 5, UIRoot = UIFactory.CreateVerticalGroup(parent, "GameObjectInspector", true, false, true, true, 5,
new Vector4(4, 4, 4, 4), new Color(0.065f, 0.065f, 0.065f)); new Vector4(4, 4, 4, 4), new Color(0.065f, 0.065f, 0.065f));
var scrollObj = UIFactory.CreateScrollView(UIRoot, "GameObjectInspector", out Content, out var scrollbar, GameObject scrollObj = UIFactory.CreateScrollView(UIRoot, "GameObjectInspector", out Content, out AutoSliderScrollbar scrollbar,
new Color(0.065f, 0.065f, 0.065f)); new Color(0.065f, 0.065f, 0.065f));
UIFactory.SetLayoutElement(scrollObj, minHeight: 250, preferredHeight: 300, flexibleHeight: 0, flexibleWidth: 9999); UIFactory.SetLayoutElement(scrollObj, minHeight: 250, preferredHeight: 300, flexibleHeight: 0, flexibleWidth: 9999);
@ -268,27 +281,27 @@ namespace UnityExplorer.Inspectors
private void ConstructLists() private void ConstructLists()
{ {
var listHolder = UIFactory.CreateUIObject("ListHolders", UIRoot); GameObject listHolder = UIFactory.CreateUIObject("ListHolders", UIRoot);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(listHolder, false, true, true, true, 8, 2, 2, 2, 2); UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(listHolder, false, true, true, true, 8, 2, 2, 2, 2);
UIFactory.SetLayoutElement(listHolder, minHeight: 150, flexibleWidth: 9999, flexibleHeight: 9999); UIFactory.SetLayoutElement(listHolder, minHeight: 150, flexibleWidth: 9999, flexibleHeight: 9999);
// Left group (Children) // Left group (Children)
var leftGroup = UIFactory.CreateUIObject("ChildrenGroup", listHolder); GameObject leftGroup = UIFactory.CreateUIObject("ChildrenGroup", listHolder);
UIFactory.SetLayoutElement(leftGroup, flexibleWidth: 9999, flexibleHeight: 9999); UIFactory.SetLayoutElement(leftGroup, flexibleWidth: 9999, flexibleHeight: 9999);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(leftGroup, false, false, true, true, 2); UIFactory.SetLayoutGroup<VerticalLayoutGroup>(leftGroup, false, false, true, true, 2);
var childrenLabel = UIFactory.CreateLabel(leftGroup, "ChildListTitle", "Children", TextAnchor.MiddleCenter, default, false, 16); Text childrenLabel = UIFactory.CreateLabel(leftGroup, "ChildListTitle", "Children", TextAnchor.MiddleCenter, default, false, 16);
UIFactory.SetLayoutElement(childrenLabel.gameObject, flexibleWidth: 9999); UIFactory.SetLayoutElement(childrenLabel.gameObject, flexibleWidth: 9999);
// Add Child // Add Child
var addChildRow = UIFactory.CreateUIObject("AddChildRow", leftGroup); GameObject addChildRow = UIFactory.CreateUIObject("AddChildRow", leftGroup);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(addChildRow, false, false, true, true, 2); UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(addChildRow, false, false, true, true, 2);
addChildInput = UIFactory.CreateInputField(addChildRow, "AddChildInput", "Enter a name..."); addChildInput = UIFactory.CreateInputField(addChildRow, "AddChildInput", "Enter a name...");
UIFactory.SetLayoutElement(addChildInput.Component.gameObject, minHeight: 25, preferredWidth: 9999); UIFactory.SetLayoutElement(addChildInput.Component.gameObject, minHeight: 25, preferredWidth: 9999);
var addChildButton = UIFactory.CreateButton(addChildRow, "AddChildButton", "Add Child"); ButtonRef addChildButton = UIFactory.CreateButton(addChildRow, "AddChildButton", "Add Child");
UIFactory.SetLayoutElement(addChildButton.Component.gameObject, minHeight: 25, minWidth: 80); UIFactory.SetLayoutElement(addChildButton.Component.gameObject, minHeight: 25, minWidth: 80);
addChildButton.OnClick += () => { OnAddChildClicked(addChildInput.Text); }; addChildButton.OnClick += () => { OnAddChildClicked(addChildInput.Text); };
@ -296,35 +309,31 @@ namespace UnityExplorer.Inspectors
transformScroll = UIFactory.CreateScrollPool<TransformCell>(leftGroup, "TransformTree", out GameObject transformObj, transformScroll = UIFactory.CreateScrollPool<TransformCell>(leftGroup, "TransformTree", out GameObject transformObj,
out GameObject transformContent, new Color(0.11f, 0.11f, 0.11f)); out GameObject transformContent, new Color(0.11f, 0.11f, 0.11f));
UIFactory.SetLayoutElement(transformObj, flexibleHeight: 9999);
UIFactory.SetLayoutElement(transformContent, flexibleHeight: 9999);
TransformTree = new TransformTree(transformScroll, GetTransformEntries); TransformTree = new TransformTree(transformScroll, GetTransformEntries, OnTransformCellClicked);
TransformTree.Init();
TransformTree.OnClickOverrideHandler = ChangeTarget;
// Right group (Components) // Right group (Components)
var rightGroup = UIFactory.CreateUIObject("ComponentGroup", listHolder); GameObject rightGroup = UIFactory.CreateUIObject("ComponentGroup", listHolder);
UIFactory.SetLayoutElement(rightGroup, flexibleWidth: 9999, flexibleHeight: 9999); UIFactory.SetLayoutElement(rightGroup, flexibleWidth: 9999, flexibleHeight: 9999);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(rightGroup, false, false, true, true, 2); UIFactory.SetLayoutGroup<VerticalLayoutGroup>(rightGroup, false, false, true, true, 2);
var compLabel = UIFactory.CreateLabel(rightGroup, "CompListTitle", "Components", TextAnchor.MiddleCenter, default, false, 16); Text compLabel = UIFactory.CreateLabel(rightGroup, "CompListTitle", "Components", TextAnchor.MiddleCenter, default, false, 16);
UIFactory.SetLayoutElement(compLabel.gameObject, flexibleWidth: 9999); UIFactory.SetLayoutElement(compLabel.gameObject, flexibleWidth: 9999);
// Add Comp // Add Comp
var addCompRow = UIFactory.CreateUIObject("AddCompRow", rightGroup); GameObject addCompRow = UIFactory.CreateUIObject("AddCompRow", rightGroup);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(addCompRow, false, false, true, true, 2); UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(addCompRow, false, false, true, true, 2);
addCompInput = UIFactory.CreateInputField(addCompRow, "AddCompInput", "Enter a Component type..."); addCompInput = UIFactory.CreateInputField(addCompRow, "AddCompInput", "Enter a Component type...");
UIFactory.SetLayoutElement(addCompInput.Component.gameObject, minHeight: 25, preferredWidth: 9999); UIFactory.SetLayoutElement(addCompInput.Component.gameObject, minHeight: 25, preferredWidth: 9999);
var addCompButton = UIFactory.CreateButton(addCompRow, "AddCompButton", "Add Comp"); ButtonRef addCompButton = UIFactory.CreateButton(addCompRow, "AddCompButton", "Add Comp");
UIFactory.SetLayoutElement(addCompButton.Component.gameObject, minHeight: 25, minWidth: 80); UIFactory.SetLayoutElement(addCompButton.Component.gameObject, minHeight: 25, minWidth: 80);
addCompButton.OnClick += () => { OnAddComponentClicked(addCompInput.Text); }; addCompButton.OnClick += () => { OnAddComponentClicked(addCompInput.Text); };
// comp autocompleter // comp autocompleter
new TypeCompleter(typeof(Component), addCompInput); new TypeCompleter(typeof(Component), addCompInput, false, false, false);
// Component List // Component List
@ -333,8 +342,10 @@ namespace UnityExplorer.Inspectors
UIFactory.SetLayoutElement(compObj, flexibleHeight: 9999); UIFactory.SetLayoutElement(compObj, flexibleHeight: 9999);
UIFactory.SetLayoutElement(compContent, flexibleHeight: 9999); UIFactory.SetLayoutElement(compContent, flexibleHeight: 9999);
ComponentList = new ComponentList(componentScroll, GetComponentEntries); ComponentList = new ComponentList(componentScroll, GetComponentEntries)
ComponentList.Parent = this; {
Parent = this
};
componentScroll.Initialize(ComponentList); componentScroll.Initialize(ComponentList);
} }

View File

@ -1,13 +1,10 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UniverseLib;
using UniverseLib.UI; using UniverseLib.UI;
using UniverseLib.UI.Models; using UniverseLib.UI.Models;
using UniverseLib.UI.Widgets.ButtonList; using UniverseLib.UI.Widgets.ButtonList;
using UniverseLib;
namespace UnityExplorer.Inspectors namespace UnityExplorer.Inspectors
{ {
@ -31,7 +28,7 @@ namespace UnityExplorer.Inspectors
public override GameObject CreateContent(GameObject parent) public override GameObject CreateContent(GameObject parent)
{ {
var root = base.CreateContent(parent); GameObject root = base.CreateContent(parent);
// Add mask to button so text doesnt overlap on Close button // Add mask to button so text doesnt overlap on Close button
//this.Button.Component.gameObject.AddComponent<Mask>().showMaskGraphic = true; //this.Button.Component.gameObject.AddComponent<Mask>().showMaskGraphic = true;
@ -39,7 +36,7 @@ namespace UnityExplorer.Inspectors
// Behaviour toggle // Behaviour toggle
var toggleObj = UIFactory.CreateToggle(UIRoot, "BehaviourToggle", out BehaviourToggle, out var behavText); GameObject toggleObj = UIFactory.CreateToggle(UIRoot, "BehaviourToggle", out BehaviourToggle, out Text behavText);
UIFactory.SetLayoutElement(toggleObj, minHeight: 25, minWidth: 25); UIFactory.SetLayoutElement(toggleObj, minHeight: 25, minWidth: 25);
BehaviourToggle.onValueChanged.AddListener(BehaviourToggled); BehaviourToggle.onValueChanged.AddListener(BehaviourToggled);
// put at first object // put at first object

View File

@ -1,7 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine; using UnityEngine;
using UniverseLib; using UniverseLib;
using UniverseLib.UI.Widgets.ButtonList; using UniverseLib.UI.Widgets.ButtonList;
@ -45,12 +43,12 @@ namespace UnityExplorer.Inspectors
private void OnComponentClicked(int index) private void OnComponentClicked(int index)
{ {
var entries = GetEntries(); List<Component> entries = GetEntries();
if (index < 0 || index >= entries.Count) if (index < 0 || index >= entries.Count)
return; return;
var comp = entries[index]; Component comp = entries[index];
if (comp) if (comp)
InspectorManager.Inspect(comp); InspectorManager.Inspect(comp);
} }
@ -59,8 +57,8 @@ namespace UnityExplorer.Inspectors
{ {
try try
{ {
var entries = GetEntries(); List<Component> entries = GetEntries();
var comp = entries[index]; Component comp = entries[index];
if (comp.TryCast<Behaviour>() is Behaviour behaviour) if (comp.TryCast<Behaviour>() is Behaviour behaviour)
behaviour.enabled = value; behaviour.enabled = value;
@ -75,8 +73,8 @@ namespace UnityExplorer.Inspectors
{ {
try try
{ {
var entries = GetEntries(); List<Component> entries = GetEntries();
var comp = entries[index]; Component comp = entries[index];
GameObject.DestroyImmediate(comp); GameObject.DestroyImmediate(comp);
@ -88,16 +86,16 @@ namespace UnityExplorer.Inspectors
} }
} }
private static readonly Dictionary<string, string> compToStringCache = new Dictionary<string, string>(); private static readonly Dictionary<string, string> compToStringCache = new();
// Called from ButtonListHandler.SetCell, will be valid // Called from ButtonListHandler.SetCell, will be valid
private void SetComponentCell(ComponentCell cell, int index) private void SetComponentCell(ComponentCell cell, int index)
{ {
var entries = GetEntries(); List<Component> entries = GetEntries();
cell.Enable(); cell.Enable();
var comp = entries[index]; Component comp = entries[index];
var type = comp.GetActualType(); Type type = comp.GetActualType();
if (!compToStringCache.ContainsKey(type.AssemblyQualifiedName)) if (!compToStringCache.ContainsKey(type.AssemblyQualifiedName))
compToStringCache.Add(type.AssemblyQualifiedName, SignatureHighlighter.Parse(type, true)); compToStringCache.Add(type.AssemblyQualifiedName, SignatureHighlighter.Parse(type, true));

View File

@ -1,14 +1,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UniverseLib.Input;
using UnityExplorer.UI; using UnityExplorer.UI;
using UniverseLib.UI;
using UniverseLib;
using UnityExplorer.UI.Panels; using UnityExplorer.UI.Panels;
using UniverseLib;
using UniverseLib.Input;
using UniverseLib.UI;
using UniverseLib.UI.Models; using UniverseLib.UI.Models;
using UniverseLib.Utility; using UniverseLib.Utility;
@ -149,7 +148,7 @@ namespace UnityExplorer.Inspectors
{ {
if (this.GOTarget && this.GOTarget.transform.parent) if (this.GOTarget && this.GOTarget.transform.parent)
{ {
Parent.ChangeTarget(this.GOTarget.transform.parent.gameObject); Parent.OnTransformCellClicked(this.GOTarget.transform.parent.gameObject);
} }
} }
@ -176,14 +175,14 @@ namespace UnityExplorer.Inspectors
else else
{ {
// look for inactive objects // look for inactive objects
var name = input.Split('/').Last(); string name = input.Split('/').Last();
var allObjects = RuntimeHelper.FindObjectsOfTypeAll(typeof(GameObject)); UnityEngine.Object[] allObjects = RuntimeHelper.FindObjectsOfTypeAll(typeof(GameObject));
var shortList = new List<GameObject>(); List<GameObject> shortList = new();
foreach (var obj in allObjects) foreach (UnityEngine.Object obj in allObjects)
if (obj.name == name) shortList.Add(obj.TryCast<GameObject>()); if (obj.name == name) shortList.Add(obj.TryCast<GameObject>());
foreach (var go in shortList) foreach (GameObject go in shortList)
{ {
var path = go.transform.GetTransformPath(true); string path = go.transform.GetTransformPath(true);
if (path.EndsWith("/")) if (path.EndsWith("/"))
path = path.Remove(path.Length - 1); path = path.Remove(path.Length - 1);
if (path == input) if (path == input)
@ -245,7 +244,7 @@ namespace UnityExplorer.Inspectors
private void OnExploreButtonClicked() private void OnExploreButtonClicked()
{ {
var panel = UIManager.GetPanel<UI.Panels.ObjectExplorerPanel>(UIManager.Panels.ObjectExplorer); ObjectExplorerPanel panel = UIManager.GetPanel<UI.Panels.ObjectExplorerPanel>(UIManager.Panels.ObjectExplorer);
panel.SceneExplorer.JumpToTransform(this.Parent.GOTarget.transform); panel.SceneExplorer.JumpToTransform(this.Parent.GOTarget.transform);
} }
@ -259,7 +258,7 @@ namespace UnityExplorer.Inspectors
{ {
try try
{ {
var enumVal = hideFlagsValues[FlagsDropdown.options[value].text]; HideFlags enumVal = hideFlagsValues[FlagsDropdown.options[value].text];
GOTarget.hideFlags = enumVal; GOTarget.hideFlags = enumVal;
UpdateGameObjectInfo(false, true); UpdateGameObjectInfo(false, true);
@ -278,7 +277,7 @@ namespace UnityExplorer.Inspectors
private void OnInstantiateClicked() private void OnInstantiateClicked()
{ {
var clone = GameObject.Instantiate(this.GOTarget); GameObject clone = GameObject.Instantiate(this.GOTarget);
InspectorManager.Inspect(clone); InspectorManager.Inspect(clone);
} }
@ -322,7 +321,7 @@ namespace UnityExplorer.Inspectors
public void UpdateTransformControlValues(bool force) public void UpdateTransformControlValues(bool force)
{ {
var transform = GOTarget.transform; Transform transform = GOTarget.transform;
if (force || (!PositionControl.Input.Component.isFocused && lastPosValue != transform.position)) if (force || (!PositionControl.Input.Component.isFocused && lastPosValue != transform.position))
{ {
PositionControl.Input.Text = ParseUtility.ToStringForInput(transform.position, typeof(Vector3)); PositionControl.Input.Text = ParseUtility.ToStringForInput(transform.position, typeof(Vector3));
@ -404,7 +403,7 @@ namespace UnityExplorer.Inspectors
return; return;
} }
var transform = GOTarget.transform; Transform transform = GOTarget.transform;
Vector3 vector = Vector2.zero; Vector3 vector = Vector2.zero;
switch (currentSlidingVectorControl.parentControl.Type) switch (currentSlidingVectorControl.parentControl.Type)
@ -453,14 +452,14 @@ namespace UnityExplorer.Inspectors
private void ConstructTopInfo() private void ConstructTopInfo()
{ {
var topInfoHolder = UIFactory.CreateVerticalGroup(Parent.Content, "TopInfoHolder", false, false, true, true, 3, GameObject topInfoHolder = UIFactory.CreateVerticalGroup(Parent.Content, "TopInfoHolder", false, false, true, true, 3,
new Vector4(3, 3, 3, 3), new Color(0.1f, 0.1f, 0.1f), TextAnchor.MiddleLeft); new Vector4(3, 3, 3, 3), new Color(0.1f, 0.1f, 0.1f), TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(topInfoHolder, minHeight: 100, flexibleWidth: 9999); UIFactory.SetLayoutElement(topInfoHolder, minHeight: 100, flexibleWidth: 9999);
topInfoHolder.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize; topInfoHolder.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
// first row (parent, path) // first row (parent, path)
var firstRow = UIFactory.CreateUIObject("ParentRow", topInfoHolder); GameObject firstRow = UIFactory.CreateUIObject("ParentRow", topInfoHolder);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(firstRow, false, false, true, true, 5, 0, 0, 0, 0, default); UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(firstRow, false, false, true, true, 5, 0, 0, 0, 0, default);
UIFactory.SetLayoutElement(firstRow, minHeight: 25, flexibleWidth: 9999); UIFactory.SetLayoutElement(firstRow, minHeight: 25, flexibleWidth: 9999);
@ -475,7 +474,7 @@ namespace UnityExplorer.Inspectors
UIFactory.SetLayoutElement(PathInput.UIRoot, minHeight: 25, minWidth: 100, flexibleWidth: 9999); UIFactory.SetLayoutElement(PathInput.UIRoot, minHeight: 25, minWidth: 100, flexibleWidth: 9999);
PathInput.Component.lineType = InputField.LineType.MultiLineSubmit; PathInput.Component.lineType = InputField.LineType.MultiLineSubmit;
var copyButton = UIFactory.CreateButton(firstRow, "CopyButton", "Copy to Clipboard", new Color(0.2f, 0.2f, 0.2f, 1)); ButtonRef copyButton = UIFactory.CreateButton(firstRow, "CopyButton", "Copy to Clipboard", new Color(0.2f, 0.2f, 0.2f, 1));
copyButton.ButtonText.color = Color.yellow; copyButton.ButtonText.color = Color.yellow;
UIFactory.SetLayoutElement(copyButton.Component.gameObject, minHeight: 25, minWidth: 120); UIFactory.SetLayoutElement(copyButton.Component.gameObject, minHeight: 25, minWidth: 120);
copyButton.OnClick += OnCopyClicked; copyButton.OnClick += OnCopyClicked;
@ -488,10 +487,10 @@ namespace UnityExplorer.Inspectors
// Title and update row // Title and update row
var titleRow = UIFactory.CreateUIObject("TitleRow", topInfoHolder); GameObject titleRow = UIFactory.CreateUIObject("TitleRow", topInfoHolder);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(titleRow, false, false, true, true, 5); UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(titleRow, false, false, true, true, 5);
var titleLabel = UIFactory.CreateLabel(titleRow, "Title", SignatureHighlighter.Parse(typeof(GameObject), false), Text titleLabel = UIFactory.CreateLabel(titleRow, "Title", SignatureHighlighter.Parse(typeof(GameObject), false),
TextAnchor.MiddleLeft, fontSize: 17); TextAnchor.MiddleLeft, fontSize: 17);
UIFactory.SetLayoutElement(titleLabel.gameObject, minHeight: 30, minWidth: 100); UIFactory.SetLayoutElement(titleLabel.gameObject, minHeight: 30, minWidth: 100);
@ -504,25 +503,25 @@ namespace UnityExplorer.Inspectors
// second row (toggles, instanceID, tag, buttons) // second row (toggles, instanceID, tag, buttons)
var secondRow = UIFactory.CreateUIObject("ParentRow", topInfoHolder); GameObject secondRow = UIFactory.CreateUIObject("ParentRow", topInfoHolder);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(secondRow, false, false, true, true, 5, 0, 0, 0, 0, default); UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(secondRow, false, false, true, true, 5, 0, 0, 0, 0, default);
UIFactory.SetLayoutElement(secondRow, minHeight: 25, flexibleWidth: 9999); UIFactory.SetLayoutElement(secondRow, minHeight: 25, flexibleWidth: 9999);
// activeSelf // activeSelf
var activeToggleObj = UIFactory.CreateToggle(secondRow, "ActiveSelf", out ActiveSelfToggle, out ActiveSelfText); GameObject activeToggleObj = UIFactory.CreateToggle(secondRow, "ActiveSelf", out ActiveSelfToggle, out ActiveSelfText);
UIFactory.SetLayoutElement(activeToggleObj, minHeight: 25, minWidth: 100); UIFactory.SetLayoutElement(activeToggleObj, minHeight: 25, minWidth: 100);
ActiveSelfText.text = "ActiveSelf"; ActiveSelfText.text = "ActiveSelf";
ActiveSelfToggle.onValueChanged.AddListener(OnActiveSelfToggled); ActiveSelfToggle.onValueChanged.AddListener(OnActiveSelfToggled);
// isStatic // isStatic
var isStaticObj = UIFactory.CreateToggle(secondRow, "IsStatic", out IsStaticToggle, out Text staticText); GameObject isStaticObj = UIFactory.CreateToggle(secondRow, "IsStatic", out IsStaticToggle, out Text staticText);
UIFactory.SetLayoutElement(isStaticObj, minHeight: 25, minWidth: 80); UIFactory.SetLayoutElement(isStaticObj, minHeight: 25, minWidth: 80);
staticText.text = "IsStatic"; staticText.text = "IsStatic";
staticText.color = Color.grey; staticText.color = Color.grey;
IsStaticToggle.interactable = false; IsStaticToggle.interactable = false;
// InstanceID // InstanceID
var instanceIdLabel = UIFactory.CreateLabel(secondRow, "InstanceIDLabel", "Instance ID:", TextAnchor.MiddleRight, Color.grey); Text instanceIdLabel = UIFactory.CreateLabel(secondRow, "InstanceIDLabel", "Instance ID:", TextAnchor.MiddleRight, Color.grey);
UIFactory.SetLayoutElement(instanceIdLabel.gameObject, minHeight: 25, minWidth: 90); UIFactory.SetLayoutElement(instanceIdLabel.gameObject, minHeight: 25, minWidth: 90);
InstanceIDInput = UIFactory.CreateInputField(secondRow, "InstanceIDInput", "error"); InstanceIDInput = UIFactory.CreateInputField(secondRow, "InstanceIDInput", "error");
@ -531,7 +530,7 @@ namespace UnityExplorer.Inspectors
InstanceIDInput.Component.readOnly = true; InstanceIDInput.Component.readOnly = true;
//Tag //Tag
var tagLabel = UIFactory.CreateLabel(secondRow, "TagLabel", "Tag:", TextAnchor.MiddleRight, Color.grey); Text tagLabel = UIFactory.CreateLabel(secondRow, "TagLabel", "Tag:", TextAnchor.MiddleRight, Color.grey);
UIFactory.SetLayoutElement(tagLabel.gameObject, minHeight: 25, minWidth: 40); UIFactory.SetLayoutElement(tagLabel.gameObject, minHeight: 25, minWidth: 40);
TagInput = UIFactory.CreateInputField(secondRow, "TagInput", "none"); TagInput = UIFactory.CreateInputField(secondRow, "TagInput", "none");
@ -540,29 +539,29 @@ namespace UnityExplorer.Inspectors
TagInput.Component.GetOnEndEdit().AddListener((string val) => { OnTagEndEdit(val); }); TagInput.Component.GetOnEndEdit().AddListener((string val) => { OnTagEndEdit(val); });
// Instantiate // Instantiate
var instantiateBtn = UIFactory.CreateButton(secondRow, "InstantiateBtn", "Instantiate", new Color(0.2f, 0.2f, 0.2f)); ButtonRef instantiateBtn = UIFactory.CreateButton(secondRow, "InstantiateBtn", "Instantiate", new Color(0.2f, 0.2f, 0.2f));
UIFactory.SetLayoutElement(instantiateBtn.Component.gameObject, minHeight: 25, minWidth: 120); UIFactory.SetLayoutElement(instantiateBtn.Component.gameObject, minHeight: 25, minWidth: 120);
instantiateBtn.OnClick += OnInstantiateClicked; instantiateBtn.OnClick += OnInstantiateClicked;
// Destroy // Destroy
var destroyBtn = UIFactory.CreateButton(secondRow, "DestroyBtn", "Destroy", new Color(0.3f, 0.2f, 0.2f)); ButtonRef destroyBtn = UIFactory.CreateButton(secondRow, "DestroyBtn", "Destroy", new Color(0.3f, 0.2f, 0.2f));
UIFactory.SetLayoutElement(destroyBtn.Component.gameObject, minHeight: 25, minWidth: 80); UIFactory.SetLayoutElement(destroyBtn.Component.gameObject, minHeight: 25, minWidth: 80);
destroyBtn.OnClick += OnDestroyClicked; destroyBtn.OnClick += OnDestroyClicked;
// third row (scene, layer, flags) // third row (scene, layer, flags)
var thirdrow = UIFactory.CreateUIObject("ParentRow", topInfoHolder); GameObject thirdrow = UIFactory.CreateUIObject("ParentRow", topInfoHolder);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(thirdrow, false, false, true, true, 5, 0, 0, 0, 0, default); UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(thirdrow, false, false, true, true, 5, 0, 0, 0, 0, default);
UIFactory.SetLayoutElement(thirdrow, minHeight: 25, flexibleWidth: 9999); UIFactory.SetLayoutElement(thirdrow, minHeight: 25, flexibleWidth: 9999);
// Inspect in Explorer button // Inspect in Explorer button
var explorerBtn = UIFactory.CreateButton(thirdrow, "ExploreBtn", "Show in Explorer", new Color(0.15f, 0.15f, 0.15f)); ButtonRef explorerBtn = UIFactory.CreateButton(thirdrow, "ExploreBtn", "Show in Explorer", new Color(0.15f, 0.15f, 0.15f));
UIFactory.SetLayoutElement(explorerBtn.Component.gameObject, minHeight: 25, minWidth: 100); UIFactory.SetLayoutElement(explorerBtn.Component.gameObject, minHeight: 25, minWidth: 100);
explorerBtn.ButtonText.fontSize = 12; explorerBtn.ButtonText.fontSize = 12;
explorerBtn.OnClick += OnExploreButtonClicked; explorerBtn.OnClick += OnExploreButtonClicked;
// Scene // Scene
var sceneLabel = UIFactory.CreateLabel(thirdrow, "SceneLabel", "Scene:", TextAnchor.MiddleLeft, Color.grey); Text sceneLabel = UIFactory.CreateLabel(thirdrow, "SceneLabel", "Scene:", TextAnchor.MiddleLeft, Color.grey);
UIFactory.SetLayoutElement(sceneLabel.gameObject, minHeight: 25, minWidth: 50); UIFactory.SetLayoutElement(sceneLabel.gameObject, minHeight: 25, minWidth: 50);
SceneInput = UIFactory.CreateInputField(thirdrow, "SceneInput", "untitled"); SceneInput = UIFactory.CreateInputField(thirdrow, "SceneInput", "untitled");
@ -571,29 +570,29 @@ namespace UnityExplorer.Inspectors
SceneInput.Component.textComponent.color = new Color(0.7f, 0.7f, 0.7f); SceneInput.Component.textComponent.color = new Color(0.7f, 0.7f, 0.7f);
// Layer // Layer
var layerLabel = UIFactory.CreateLabel(thirdrow, "LayerLabel", "Layer:", TextAnchor.MiddleLeft, Color.grey); Text layerLabel = UIFactory.CreateLabel(thirdrow, "LayerLabel", "Layer:", TextAnchor.MiddleLeft, Color.grey);
UIFactory.SetLayoutElement(layerLabel.gameObject, minHeight: 25, minWidth: 50); UIFactory.SetLayoutElement(layerLabel.gameObject, minHeight: 25, minWidth: 50);
var layerDrop = UIFactory.CreateDropdown(thirdrow, "LayerDropdown", out LayerDropdown, "0", 14, OnLayerDropdownChanged); GameObject layerDrop = UIFactory.CreateDropdown(thirdrow, "LayerDropdown", out LayerDropdown, "0", 14, OnLayerDropdownChanged);
UIFactory.SetLayoutElement(layerDrop, minHeight: 25, minWidth: 110, flexibleWidth: 999); UIFactory.SetLayoutElement(layerDrop, minHeight: 25, minWidth: 110, flexibleWidth: 999);
LayerDropdown.captionText.color = SignatureHighlighter.EnumGreen; LayerDropdown.captionText.color = SignatureHighlighter.EnumGreen;
if (layerToNames == null) if (layerToNames == null)
GetLayerNames(); GetLayerNames();
foreach (var name in layerToNames) foreach (string name in layerToNames)
LayerDropdown.options.Add(new Dropdown.OptionData(name)); LayerDropdown.options.Add(new Dropdown.OptionData(name));
LayerDropdown.value = 0; LayerDropdown.value = 0;
LayerDropdown.RefreshShownValue(); LayerDropdown.RefreshShownValue();
// Flags // Flags
var flagsLabel = UIFactory.CreateLabel(thirdrow, "FlagsLabel", "Flags:", TextAnchor.MiddleRight, Color.grey); Text flagsLabel = UIFactory.CreateLabel(thirdrow, "FlagsLabel", "Flags:", TextAnchor.MiddleRight, Color.grey);
UIFactory.SetLayoutElement(flagsLabel.gameObject, minHeight: 25, minWidth: 50); UIFactory.SetLayoutElement(flagsLabel.gameObject, minHeight: 25, minWidth: 50);
var flagsDrop = UIFactory.CreateDropdown(thirdrow, "FlagsDropdown", out FlagsDropdown, "None", 14, OnFlagsDropdownChanged); GameObject flagsDrop = UIFactory.CreateDropdown(thirdrow, "FlagsDropdown", out FlagsDropdown, "None", 14, OnFlagsDropdownChanged);
FlagsDropdown.captionText.color = SignatureHighlighter.EnumGreen; FlagsDropdown.captionText.color = SignatureHighlighter.EnumGreen;
UIFactory.SetLayoutElement(flagsDrop, minHeight: 25, minWidth: 135, flexibleWidth: 999); UIFactory.SetLayoutElement(flagsDrop, minHeight: 25, minWidth: 135, flexibleWidth: 999);
if (hideFlagsValues == null) if (hideFlagsValues == null)
GetHideFlagNames(); GetHideFlagNames();
foreach (var name in hideFlagsValues.Keys) foreach (string name in hideFlagsValues.Keys)
FlagsDropdown.options.Add(new Dropdown.OptionData(name)); FlagsDropdown.options.Add(new Dropdown.OptionData(name));
FlagsDropdown.value = 0; FlagsDropdown.value = 0;
FlagsDropdown.RefreshShownValue(); FlagsDropdown.RefreshShownValue();
@ -606,7 +605,7 @@ namespace UnityExplorer.Inspectors
layerToNames = new List<string>(); layerToNames = new List<string>();
for (int i = 0; i < 32; i++) for (int i = 0; i < 32; i++)
{ {
var name = RuntimeHelper.LayerToName(i); string name = RuntimeHelper.LayerToName(i);
if (string.IsNullOrEmpty(name)) if (string.IsNullOrEmpty(name))
name = i.ToString(); name = i.ToString();
layerToNames.Add(name); layerToNames.Add(name);
@ -619,7 +618,7 @@ namespace UnityExplorer.Inspectors
{ {
hideFlagsValues = new Dictionary<string, HideFlags>(); hideFlagsValues = new Dictionary<string, HideFlags>();
var names = Enum.GetValues(typeof(HideFlags)); Array names = Enum.GetValues(typeof(HideFlags));
foreach (HideFlags value in names) foreach (HideFlags value in names)
{ {
hideFlagsValues.Add(value.ToString(), value); hideFlagsValues.Add(value.ToString(), value);
@ -633,7 +632,7 @@ namespace UnityExplorer.Inspectors
private void ConstructTransformControls() private void ConstructTransformControls()
{ {
var transformGroup = UIFactory.CreateVerticalGroup(Parent.Content, "TransformControls", false, false, true, true, 2, GameObject transformGroup = UIFactory.CreateVerticalGroup(Parent.Content, "TransformControls", false, false, true, true, 2,
new Vector4(2, 2, 0, 0), new Color(0.1f, 0.1f, 0.1f)); new Vector4(2, 2, 0, 0), new Color(0.1f, 0.1f, 0.1f));
UIFactory.SetLayoutElement(transformGroup, minHeight: 100, flexibleWidth: 9999); UIFactory.SetLayoutElement(transformGroup, minHeight: 100, flexibleWidth: 9999);
//transformGroup.SetActive(false); //transformGroup.SetActive(false);
@ -650,19 +649,19 @@ namespace UnityExplorer.Inspectors
private TransformControl AddTransformRow(GameObject transformGroup, string title, TransformType type) private TransformControl AddTransformRow(GameObject transformGroup, string title, TransformType type)
{ {
var rowObj = UIFactory.CreateUIObject("Row_" + title, transformGroup); GameObject rowObj = UIFactory.CreateUIObject("Row_" + title, transformGroup);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(rowObj, false, false, true, true, 5, 0, 0, 0, 0, default); UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(rowObj, false, false, true, true, 5, 0, 0, 0, 0, default);
UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleWidth: 9999); UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleWidth: 9999);
var titleLabel = UIFactory.CreateLabel(rowObj, "PositionLabel", title, TextAnchor.MiddleRight, Color.grey); Text titleLabel = UIFactory.CreateLabel(rowObj, "PositionLabel", title, TextAnchor.MiddleRight, Color.grey);
UIFactory.SetLayoutElement(titleLabel.gameObject, minHeight: 25, minWidth: 110); UIFactory.SetLayoutElement(titleLabel.gameObject, minHeight: 25, minWidth: 110);
var inputField = UIFactory.CreateInputField(rowObj, "InputField", "..."); InputFieldRef inputField = UIFactory.CreateInputField(rowObj, "InputField", "...");
UIFactory.SetLayoutElement(inputField.Component.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 999); UIFactory.SetLayoutElement(inputField.Component.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 999);
inputField.Component.GetOnEndEdit().AddListener((string value) => { OnTransformInputEndEdit(type, value); }); inputField.Component.GetOnEndEdit().AddListener((string value) => { OnTransformInputEndEdit(type, value); });
var control = new TransformControl(type, inputField); TransformControl control = new(type, inputField);
AddVectorAxisSlider(rowObj, "X", 0, control); AddVectorAxisSlider(rowObj, "X", 0, control);
AddVectorAxisSlider(rowObj, "Y", 1, control); AddVectorAxisSlider(rowObj, "Y", 1, control);
@ -673,16 +672,16 @@ namespace UnityExplorer.Inspectors
private VectorSlider AddVectorAxisSlider(GameObject parent, string title, int axis, TransformControl control) private VectorSlider AddVectorAxisSlider(GameObject parent, string title, int axis, TransformControl control)
{ {
var label = UIFactory.CreateLabel(parent, "Label_" + title, title + ":", TextAnchor.MiddleRight, Color.grey); Text label = UIFactory.CreateLabel(parent, "Label_" + title, title + ":", TextAnchor.MiddleRight, Color.grey);
UIFactory.SetLayoutElement(label.gameObject, minHeight: 25, minWidth: 30); UIFactory.SetLayoutElement(label.gameObject, minHeight: 25, minWidth: 30);
var sliderObj = UIFactory.CreateSlider(parent, "Slider_" + title, out var slider); GameObject sliderObj = UIFactory.CreateSlider(parent, "Slider_" + title, out Slider slider);
UIFactory.SetLayoutElement(sliderObj, minHeight: 25, minWidth: 120, flexibleWidth: 0); UIFactory.SetLayoutElement(sliderObj, minHeight: 25, minWidth: 120, flexibleWidth: 0);
slider.m_FillImage.color = Color.clear; slider.m_FillImage.color = Color.clear;
slider.minValue = -1; slider.minValue = -1;
slider.maxValue = 1; slider.maxValue = 1;
var sliderControl = new VectorSlider(axis, slider, control); VectorSlider sliderControl = new(axis, slider, control);
slider.onValueChanged.AddListener((float val) => slider.onValueChanged.AddListener((float val) =>
{ {

View File

@ -1,13 +1,8 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.UI;
using UniverseLib.UI.Models;
using UnityExplorer.UI.Panels; using UnityExplorer.UI.Panels;
using UniverseLib.UI; using UniverseLib;
using UniverseLib.UI.ObjectPool; using UniverseLib.UI.ObjectPool;
namespace UnityExplorer.Inspectors namespace UnityExplorer.Inspectors
@ -16,6 +11,7 @@ namespace UnityExplorer.Inspectors
{ {
public bool IsActive { get; internal set; } public bool IsActive { get; internal set; }
public object Target { get; set; } public object Target { get; set; }
public Type TargetType { get; protected set; }
public InspectorTab Tab { get; internal set; } public InspectorTab Tab { get; internal set; }
@ -31,6 +27,8 @@ namespace UnityExplorer.Inspectors
public virtual void OnBorrowedFromPool(object target) public virtual void OnBorrowedFromPool(object target)
{ {
this.Target = target; this.Target = target;
this.TargetType = target is Type type ? type : target.GetActualType();
Tab = Pool<InspectorTab>.Borrow(); Tab = Pool<InspectorTab>.Borrow();
Tab.UIRoot.transform.SetParent(InspectorPanel.Instance.NavbarHolder.transform, false); Tab.UIRoot.transform.SetParent(InspectorPanel.Instance.NavbarHolder.transform, false);

View File

@ -1,16 +1,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.UI;
using UnityExplorer.CacheObject; using UnityExplorer.CacheObject;
using UnityExplorer.Inspectors; using UnityExplorer.Inspectors;
using UniverseLib.UI.Models; using UnityExplorer.UI;
using UnityExplorer.UI.Panels; using UnityExplorer.UI.Panels;
using UniverseLib; using UniverseLib;
using UniverseLib.UI;
using UniverseLib.UI.ObjectPool; using UniverseLib.UI.ObjectPool;
using UniverseLib.Utility; using UniverseLib.Utility;
@ -27,7 +23,7 @@ namespace UnityExplorer
public static event Action OnInspectedTabsChanged; public static event Action OnInspectedTabsChanged;
public static void Inspect(object obj, CacheObjectBase sourceCache = null) public static void Inspect(object obj, CacheObjectBase parent = null)
{ {
if (obj.IsNullOrDestroyed()) if (obj.IsNullOrDestroyed())
return; return;
@ -40,19 +36,34 @@ namespace UnityExplorer
if (obj is GameObject) if (obj is GameObject)
CreateInspector<GameObjectInspector>(obj); CreateInspector<GameObjectInspector>(obj);
else else
CreateInspector<ReflectionInspector>(obj, false, sourceCache); CreateInspector<ReflectionInspector>(obj, false, parent);
} }
public static void Inspect(Type type) public static void Inspect(Type type)
{ {
if (TryFocusActiveInspector(type))
return;
CreateInspector<ReflectionInspector>(type, true); CreateInspector<ReflectionInspector>(type, true);
} }
private static bool TryFocusActiveInspector(object target) static bool TryFocusActiveInspector(object target)
{ {
foreach (var inspector in Inspectors) foreach (InspectorBase inspector in Inspectors)
{ {
if (inspector.Target.ReferenceEqual(target)) bool shouldFocus = false;
if (target is Type targetAsType)
{
if (inspector.TargetType.FullName == targetAsType.FullName)
shouldFocus = true;
}
else if(inspector.Target.ReferenceEqual(target))
{
shouldFocus = true;
}
if (shouldFocus)
{ {
UIManager.SetPanelActive(UIManager.Panels.Inspector, true); UIManager.SetPanelActive(UIManager.Panels.Inspector, true);
SetInspectorActive(inspector); SetInspectorActive(inspector);
@ -80,7 +91,7 @@ namespace UnityExplorer
} }
} }
internal static void CloseAllTabs() public static void CloseAllTabs()
{ {
if (Inspectors.Any()) if (Inspectors.Any())
{ {
@ -93,18 +104,17 @@ namespace UnityExplorer
UIManager.SetPanelActive(UIManager.Panels.Inspector, false); UIManager.SetPanelActive(UIManager.Panels.Inspector, false);
} }
private static void CreateInspector<T>(object target, bool staticReflection = false, static void CreateInspector<T>(object target, bool staticReflection = false, CacheObjectBase parent = null) where T : InspectorBase
CacheObjectBase parentObject = null) where T : InspectorBase
{ {
var inspector = Pool<T>.Borrow(); T inspector = Pool<T>.Borrow();
Inspectors.Add(inspector); Inspectors.Add(inspector);
inspector.Target = target; inspector.Target = target;
if (parentObject != null && parentObject.CanWrite) if (parent != null && parent.CanWrite)
{ {
// only set parent cache object if we are inspecting a struct, otherwise there is no point. // only set parent cache object if we are inspecting a struct, otherwise there is no point.
if (target.GetType().IsValueType && inspector is ReflectionInspector ri) if (target.GetType().IsValueType && inspector is ReflectionInspector ri)
ri.ParentCacheObject = parentObject; ri.ParentCacheObject = parent;
} }
UIManager.SetPanelActive(UIManager.Panels.Inspector, true); UIManager.SetPanelActive(UIManager.Panels.Inspector, true);
@ -119,7 +129,7 @@ namespace UnityExplorer
OnInspectedTabsChanged?.Invoke(); OnInspectedTabsChanged?.Invoke();
} }
internal static void ReleaseInspector<T>(T inspector) where T : InspectorBase public static void ReleaseInspector<T>(T inspector) where T : InspectorBase
{ {
if (lastActiveInspector == inspector) if (lastActiveInspector == inspector)
lastActiveInspector = null; lastActiveInspector = null;
@ -164,7 +174,7 @@ namespace UnityExplorer
{ {
PanelWidth = width; PanelWidth = width;
foreach (var obj in Inspectors) foreach (InspectorBase obj in Inspectors)
{ {
if (obj is ReflectionInspector inspector) if (obj is ReflectionInspector inspector)
{ {

View File

@ -1,15 +1,8 @@
using System; using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.UI;
using UniverseLib.UI.Models;
using UnityExplorer.UI.Widgets;
using UniverseLib.UI;
using UniverseLib; using UniverseLib;
using UnityExplorer.UI.Panels; using UniverseLib.UI;
using UniverseLib.UI.Models;
using UniverseLib.UI.ObjectPool; using UniverseLib.UI.ObjectPool;
namespace UnityExplorer.Inspectors namespace UnityExplorer.Inspectors

View File

@ -1,19 +1,13 @@
using System; using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI; using UnityEngine.UI;
using UniverseLib.Input; using UnityExplorer.Config;
using UnityExplorer.Runtime;
using UnityExplorer.Inspectors.MouseInspectors; using UnityExplorer.Inspectors.MouseInspectors;
using UnityExplorer.UI; using UnityExplorer.UI;
using UnityExplorer.UI.Panels; using UnityExplorer.UI.Panels;
using UniverseLib; using UniverseLib.Input;
using UniverseLib.UI; using UniverseLib.UI;
using UniverseLib.UI.Panels;
using UniverseLib.Utility; using UniverseLib.Utility;
using UnityExplorer.Config;
namespace UnityExplorer.Inspectors namespace UnityExplorer.Inspectors
{ {
@ -23,7 +17,7 @@ namespace UnityExplorer.Inspectors
UI UI
} }
public class MouseInspector : UIPanel public class MouseInspector : PanelBase
{ {
public static MouseInspector Instance { get; private set; } public static MouseInspector Instance { get; private set; }
@ -44,22 +38,21 @@ namespace UnityExplorer.Inspectors
// UIPanel // UIPanel
internal static readonly string UIBaseGUID = $"{ExplorerCore.GUID}.MouseInspector"; internal static readonly string UIBaseGUID = $"{ExplorerCore.GUID}.MouseInspector";
private UIBase inspectorUIBase; internal static UIBase inspectorUIBase;
public override string Name => "Inspect Under Mouse"; public override string Name => "Inspect Under Mouse";
public override UIManager.Panels PanelType => UIManager.Panels.MouseInspector;
public override int MinWidth => -1; public override int MinWidth => -1;
public override int MinHeight => -1; public override int MinHeight => -1;
public override Vector2 DefaultAnchorMin => Vector2.zero;
public override Vector2 DefaultAnchorMax => Vector2.zero;
public override bool CanDragAndResize => false; public override bool CanDragAndResize => false;
public override bool NavButtonWanted => false;
public override bool ShouldSaveActiveState => false;
public override bool ShowByDefault => false;
internal Text objNameLabel; internal Text objNameLabel;
internal Text objPathLabel; internal Text objPathLabel;
internal Text mousePosLabel; internal Text mousePosLabel;
public MouseInspector() public MouseInspector(UIBase owner) : base(owner)
{ {
Instance = this; Instance = this;
worldInspector = new WorldInspector(); worldInspector = new WorldInspector();
@ -84,11 +77,12 @@ namespace UnityExplorer.Inspectors
CurrentInspector.OnBeginMouseInspect(); CurrentInspector.OnBeginMouseInspect();
PanelDragger.ForceEnd(); PanelManager.ForceEndResize();
UIManager.NavBarRect.gameObject.SetActive(false); UIManager.NavBarRect.gameObject.SetActive(false);
UIManager.PanelHolder.SetActive(false); UIManager.UiBase.Panels.PanelHolder.SetActive(false);
UIManager.UiBase.SetOnTop();
UIRoot.SetActive(true); SetActive(true);
} }
internal void ClearHitData() internal void ClearHitData()
@ -106,9 +100,9 @@ namespace UnityExplorer.Inspectors
Inspecting = false; Inspecting = false;
UIManager.NavBarRect.gameObject.SetActive(true); UIManager.NavBarRect.gameObject.SetActive(true);
UIManager.PanelHolder.SetActive(true); UIManager.UiBase.Panels.PanelHolder.SetActive(true);
var drop = InspectorPanel.Instance.MouseInspectDropdown; Dropdown drop = InspectorPanel.Instance.MouseInspectDropdown;
if (drop.transform.Find("Dropdown List") is Transform list) if (drop.transform.Find("Dropdown List") is Transform list)
drop.DestroyDropdownList(list.gameObject); drop.DestroyDropdownList(list.gameObject);
@ -130,7 +124,7 @@ namespace UnityExplorer.Inspectors
if (InputManager.GetKeyDown(ConfigManager.World_MouseInspect_Keybind.Value)) if (InputManager.GetKeyDown(ConfigManager.World_MouseInspect_Keybind.Value))
Instance.StartInspect(MouseInspectMode.World); Instance.StartInspect(MouseInspectMode.World);
} }
if (Inspecting) if (Inspecting)
UpdateInspect(); UpdateInspect();
@ -152,7 +146,7 @@ namespace UnityExplorer.Inspectors
return; return;
} }
var mousePos = InputManager.MousePosition; Vector3 mousePos = InputManager.MousePosition;
if (mousePos != lastMousePos) if (mousePos != lastMousePos)
UpdatePosition(mousePos); UpdatePosition(mousePos);
@ -181,34 +175,36 @@ namespace UnityExplorer.Inspectors
mousePos.y -= 10; mousePos.y -= 10;
// calculate and set our UI position // calculate and set our UI position
var inversePos = inspectorUIBase.RootObject.transform.InverseTransformPoint(mousePos); Vector3 inversePos = inspectorUIBase.RootObject.transform.InverseTransformPoint(mousePos);
UIRoot.transform.localPosition = new Vector3(inversePos.x, inversePos.y, 0); UIRoot.transform.localPosition = new Vector3(inversePos.x, inversePos.y, 0);
} }
// UI Construction // UI Construction
protected internal override void DoSetDefaultPosAndAnchors() public override void SetDefaultSizeAndPosition()
{ {
base.SetDefaultSizeAndPosition();
Rect.anchorMin = Vector2.zero; Rect.anchorMin = Vector2.zero;
Rect.anchorMax = Vector2.zero; Rect.anchorMax = Vector2.zero;
Rect.pivot = new Vector2(0.5f, 1); Rect.pivot = new Vector2(0.5f, 1);
Rect.sizeDelta = new Vector2(700, 150); Rect.sizeDelta = new Vector2(700, 150);
} }
public override void ConstructPanelContent() protected override void ConstructPanelContent()
{ {
// hide title bar // hide title bar
this.TitleBar.SetActive(false); this.TitleBar.SetActive(false);
this.UIRoot.transform.SetParent(UIManager.UIRoot.transform, false); this.UIRoot.transform.SetParent(UIManager.UIRoot.transform, false);
var inspectContent = UIFactory.CreateVerticalGroup(this.uiContent, "InspectContent", true, true, true, true, 3, new Vector4(2, 2, 2, 2)); GameObject inspectContent = UIFactory.CreateVerticalGroup(this.ContentRoot, "InspectContent", true, true, true, true, 3, new Vector4(2, 2, 2, 2));
UIFactory.SetLayoutElement(inspectContent, flexibleWidth: 9999, flexibleHeight: 9999); UIFactory.SetLayoutElement(inspectContent, flexibleWidth: 9999, flexibleHeight: 9999);
// Title text // Title text
var title = UIFactory.CreateLabel(inspectContent, Text title = UIFactory.CreateLabel(inspectContent,
"InspectLabel", "InspectLabel",
"<b>Mouse Inspector</b> (press <b>ESC</b> to cancel)", "<b>Mouse Inspector</b> (press <b>ESC</b> to cancel)",
TextAnchor.MiddleCenter); TextAnchor.MiddleCenter);
UIFactory.SetLayoutElement(title.gameObject, flexibleWidth: 9999); UIFactory.SetLayoutElement(title.gameObject, flexibleWidth: 9999);
@ -225,11 +221,10 @@ namespace UnityExplorer.Inspectors
UIRoot.SetActive(false); UIRoot.SetActive(false);
// Create a new canvas for this panel to live on. //// Create a new canvas for this panel to live on.
// It needs to always be shown on the main display, other panels can move displays. //// It needs to always be shown on the main display, other panels can move displays.
//
inspectorUIBase = UniversalUI.RegisterUI(UIBaseGUID, null); //UIRoot.transform.SetParent(inspectorUIBase.RootObject.transform);
UIRoot.transform.SetParent(inspectorUIBase.RootObject.transform);
} }
} }
} }

View File

@ -1,8 +1,4 @@
using System; using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
namespace UnityExplorer.Inspectors.MouseInspectors namespace UnityExplorer.Inspectors.MouseInspectors
{ {

View File

@ -1,29 +1,26 @@
using System; using System.Collections;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.EventSystems; using UnityEngine.EventSystems;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.UI; using UnityExplorer.UI;
using UnityExplorer.UI.Panels; using UnityExplorer.UI.Panels;
using UniverseLib; using UniverseLib;
using UniverseLib.Input;
namespace UnityExplorer.Inspectors.MouseInspectors namespace UnityExplorer.Inspectors.MouseInspectors
{ {
public class UiInspector : MouseInspectorBase public class UiInspector : MouseInspectorBase
{ {
public static readonly List<GameObject> LastHitObjects = new List<GameObject>(); public static readonly List<GameObject> LastHitObjects = new();
private static GraphicRaycaster[] graphicRaycasters; private static GraphicRaycaster[] graphicRaycasters;
private static readonly List<GameObject> currentHitObjects = new List<GameObject>(); private static readonly List<GameObject> currentHitObjects = new();
private static readonly List<Graphic> wasDisabledGraphics = new List<Graphic>(); private static readonly List<Graphic> wasDisabledGraphics = new();
private static readonly List<CanvasGroup> wasDisabledCanvasGroups = new List<CanvasGroup>(); private static readonly List<CanvasGroup> wasDisabledCanvasGroups = new();
private static readonly List<GameObject> objectsAddedCastersTo = new List<GameObject>(); private static readonly List<GameObject> objectsAddedCastersTo = new();
public override void OnBeginMouseInspect() public override void OnBeginMouseInspect()
{ {
@ -46,7 +43,7 @@ namespace UnityExplorer.Inspectors.MouseInspectors
IEnumerator SetPanelActiveCoro() IEnumerator SetPanelActiveCoro()
{ {
yield return null; yield return null;
var panel = UIManager.GetPanel<MouseInspectorResultsPanel>(UIManager.Panels.UIInspectorResults); MouseInspectorResultsPanel panel = UIManager.GetPanel<MouseInspectorResultsPanel>(UIManager.Panels.UIInspectorResults);
panel.SetActive(true); panel.SetActive(true);
panel.ShowResults(); panel.ShowResults();
} }
@ -55,28 +52,28 @@ namespace UnityExplorer.Inspectors.MouseInspectors
{ {
currentHitObjects.Clear(); currentHitObjects.Clear();
var ped = new PointerEventData(null) PointerEventData ped = new(null)
{ {
position = mousePos position = mousePos
}; };
foreach (var gr in graphicRaycasters) foreach (GraphicRaycaster gr in graphicRaycasters)
{ {
if (!gr || !gr.canvas) if (!gr || !gr.canvas)
continue; continue;
var list = new List<RaycastResult>(); List<RaycastResult> list = new();
RuntimeHelper.GraphicRaycast(gr, ped, list); RuntimeHelper.GraphicRaycast(gr, ped, list);
if (list.Count > 0) if (list.Count > 0)
{ {
foreach (var hit in list) foreach (RaycastResult hit in list)
{ {
if (hit.gameObject) if (hit.gameObject)
currentHitObjects.Add(hit.gameObject); currentHitObjects.Add(hit.gameObject);
} }
} }
} }
if (currentHitObjects.Any()) if (currentHitObjects.Any())
MouseInspector.Instance.objNameLabel.text = $"Click to view UI Objects under mouse: {currentHitObjects.Count}"; MouseInspector.Instance.objNameLabel.text = $"Click to view UI Objects under mouse: {currentHitObjects.Count}";
else else
@ -85,9 +82,9 @@ namespace UnityExplorer.Inspectors.MouseInspectors
private static void SetupUIRaycast() private static void SetupUIRaycast()
{ {
foreach (var obj in RuntimeHelper.FindObjectsOfTypeAll(typeof(Canvas))) foreach (UnityEngine.Object obj in RuntimeHelper.FindObjectsOfTypeAll(typeof(Canvas)))
{ {
var canvas = obj.TryCast<Canvas>(); Canvas canvas = obj.TryCast<Canvas>();
if (!canvas || !canvas.enabled || !canvas.gameObject.activeInHierarchy) if (!canvas || !canvas.enabled || !canvas.gameObject.activeInHierarchy)
continue; continue;
if (!canvas.GetComponent<GraphicRaycaster>()) if (!canvas.GetComponent<GraphicRaycaster>())
@ -99,7 +96,7 @@ namespace UnityExplorer.Inspectors.MouseInspectors
} }
// recache Graphic Raycasters each time we start // recache Graphic Raycasters each time we start
var casters = RuntimeHelper.FindObjectsOfTypeAll(typeof(GraphicRaycaster)); UnityEngine.Object[] casters = RuntimeHelper.FindObjectsOfTypeAll(typeof(GraphicRaycaster));
graphicRaycasters = new GraphicRaycaster[casters.Length]; graphicRaycasters = new GraphicRaycaster[casters.Length];
for (int i = 0; i < casters.Length; i++) for (int i = 0; i < casters.Length; i++)
{ {
@ -107,9 +104,9 @@ namespace UnityExplorer.Inspectors.MouseInspectors
} }
// enable raycastTarget on Graphics // enable raycastTarget on Graphics
foreach (var obj in RuntimeHelper.FindObjectsOfTypeAll(typeof(Graphic))) foreach (UnityEngine.Object obj in RuntimeHelper.FindObjectsOfTypeAll(typeof(Graphic)))
{ {
var graphic = obj.TryCast<Graphic>(); Graphic graphic = obj.TryCast<Graphic>();
if (!graphic || !graphic.enabled || graphic.raycastTarget || !graphic.gameObject.activeInHierarchy) if (!graphic || !graphic.enabled || graphic.raycastTarget || !graphic.gameObject.activeInHierarchy)
continue; continue;
graphic.raycastTarget = true; graphic.raycastTarget = true;
@ -118,9 +115,9 @@ namespace UnityExplorer.Inspectors.MouseInspectors
} }
// enable blocksRaycasts on CanvasGroups // enable blocksRaycasts on CanvasGroups
foreach (var obj in RuntimeHelper.FindObjectsOfTypeAll(typeof(CanvasGroup))) foreach (UnityEngine.Object obj in RuntimeHelper.FindObjectsOfTypeAll(typeof(CanvasGroup)))
{ {
var canvas = obj.TryCast<CanvasGroup>(); CanvasGroup canvas = obj.TryCast<CanvasGroup>();
if (!canvas || !canvas.gameObject.activeInHierarchy || canvas.blocksRaycasts) if (!canvas || !canvas.gameObject.activeInHierarchy || canvas.blocksRaycasts)
continue; continue;
canvas.blocksRaycasts = true; canvas.blocksRaycasts = true;
@ -131,16 +128,16 @@ namespace UnityExplorer.Inspectors.MouseInspectors
public override void OnEndInspect() public override void OnEndInspect()
{ {
foreach (var obj in objectsAddedCastersTo) foreach (GameObject obj in objectsAddedCastersTo)
{ {
if (obj.GetComponent<GraphicRaycaster>() is GraphicRaycaster raycaster) if (obj.GetComponent<GraphicRaycaster>() is GraphicRaycaster raycaster)
GameObject.Destroy(raycaster); GameObject.Destroy(raycaster);
} }
foreach (var graphic in wasDisabledGraphics) foreach (Graphic graphic in wasDisabledGraphics)
graphic.raycastTarget = false; graphic.raycastTarget = false;
foreach (var canvas in wasDisabledCanvasGroups) foreach (CanvasGroup canvas in wasDisabledCanvasGroups)
canvas.blocksRaycasts = false; canvas.blocksRaycasts = false;
objectsAddedCastersTo.Clear(); objectsAddedCastersTo.Clear();

View File

@ -1,9 +1,4 @@
using System; using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UniverseLib;
using UniverseLib.Utility; using UniverseLib.Utility;
namespace UnityExplorer.Inspectors.MouseInspectors namespace UnityExplorer.Inspectors.MouseInspectors
@ -45,7 +40,7 @@ namespace UnityExplorer.Inspectors.MouseInspectors
return; return;
} }
var ray = MainCamera.ScreenPointToRay(mousePos); Ray ray = MainCamera.ScreenPointToRay(mousePos);
Physics.Raycast(ray, out RaycastHit hit, 1000f); Physics.Raycast(ray, out RaycastHit hit, 1000f);
if (hit.transform) if (hit.transform)

View File

@ -33,54 +33,52 @@ namespace UnityExplorer.Inspectors
public class ReflectionInspector : InspectorBase, ICellPoolDataSource<CacheMemberCell>, ICacheObjectController public class ReflectionInspector : InspectorBase, ICellPoolDataSource<CacheMemberCell>, ICacheObjectController
{ {
public CacheObjectBase ParentCacheObject { get; set; } public CacheObjectBase ParentCacheObject { get; set; }
public Type TargetType { get; private set; } //public Type TargetType { get; private set; }
public bool StaticOnly { get; internal set; } public bool StaticOnly { get; internal set; }
public bool CanWrite => true; public bool CanWrite => true;
public bool AutoUpdateWanted => autoUpdateToggle.isOn; public bool AutoUpdateWanted => autoUpdateToggle.isOn;
private List<CacheMember> members = new(); List<CacheMember> members = new();
private readonly List<CacheMember> filteredMembers = new(); readonly List<CacheMember> filteredMembers = new();
private BindingFlags scopeFlagsFilter; string nameFilter;
private string nameFilter; BindingFlags scopeFlagsFilter;
MemberFilter memberFilter = MemberFilter.All;
private MemberFilter MemberFilter = MemberFilter.All;
// Updating // Updating
private bool refreshWanted; bool refreshWanted;
private string lastNameFilter; string lastNameFilter;
private BindingFlags lastFlagsFilter; BindingFlags lastFlagsFilter;
private MemberFilter lastMemberFilter = MemberFilter.All; MemberFilter lastMemberFilter = MemberFilter.All;
private float timeOfLastAutoUpdate; float timeOfLastAutoUpdate;
// UI // UI
internal GameObject mainContentHolder; static int LeftGroupWidth { get; set; }
private static int LeftGroupWidth { get; set; } static int RightGroupWidth { get; set; }
private static int RightGroupWidth { get; set; }
static readonly Color disabledButtonColor = new(0.24f, 0.24f, 0.24f);
static readonly Color enabledButtonColor = new(0.2f, 0.27f, 0.2f);
public GameObject ContentRoot { get; private set; }
public ScrollPool<CacheMemberCell> MemberScrollPool { get; private set; } public ScrollPool<CacheMemberCell> MemberScrollPool { get; private set; }
public int ItemCount => filteredMembers.Count; public int ItemCount => filteredMembers.Count;
public UnityObjectWidget UnityWidget { get; private set; }
public string TabButtonText { get; set; }
public UnityObjectWidget UnityWidget; InputFieldRef hiddenNameText;
Text nameText;
Text assemblyText;
Toggle autoUpdateToggle;
public InputFieldRef HiddenNameText; ButtonRef makeGenericButton;
public Text NameText; GenericConstructorWidget genericConstructor;
public Text AssemblyText;
private Toggle autoUpdateToggle;
internal string currentBaseTabText; InputFieldRef filterInputField;
readonly List<Toggle> memberTypeToggles = new();
private readonly Dictionary<BindingFlags, ButtonRef> scopeFilterButtons = new(); readonly Dictionary<BindingFlags, ButtonRef> scopeFilterButtons = new();
private readonly List<Toggle> memberTypeToggles = new();
private InputFieldRef filterInputField;
// const
private readonly Color disabledButtonColor = new(0.24f, 0.24f, 0.24f);
private readonly Color enabledButtonColor = new(0.2f, 0.27f, 0.2f);
// Setup // Setup
@ -107,7 +105,7 @@ namespace UnityExplorer.Inspectors
public override void OnReturnToPool() public override void OnReturnToPool()
{ {
foreach (var member in members) foreach (CacheMember member in members)
{ {
member.UnlinkFromView(); member.UnlinkFromView();
member.ReleasePooledObjects(); member.ReleasePooledObjects();
@ -125,6 +123,8 @@ namespace UnityExplorer.Inspectors
this.UnityWidget = null; this.UnityWidget = null;
} }
genericConstructor?.Cancel();
base.OnReturnToPool(); base.OnReturnToPool();
} }
@ -138,6 +138,8 @@ namespace UnityExplorer.Inspectors
Target = null; Target = null;
TargetType = target as Type; TargetType = target as Type;
prefix = "[S]"; prefix = "[S]";
makeGenericButton.GameObject.SetActive(TargetType.IsGenericTypeDefinition);
} }
else else
{ {
@ -146,17 +148,17 @@ namespace UnityExplorer.Inspectors
} }
// Setup main labels and tab text // Setup main labels and tab text
currentBaseTabText = $"{prefix} {SignatureHighlighter.Parse(TargetType, false)}"; TabButtonText = $"{prefix} {SignatureHighlighter.Parse(TargetType, false)}";
Tab.TabText.text = currentBaseTabText; Tab.TabText.text = TabButtonText;
NameText.text = SignatureHighlighter.Parse(TargetType, true); nameText.text = SignatureHighlighter.Parse(TargetType, true);
HiddenNameText.Text = SignatureHighlighter.RemoveHighlighting(NameText.text); hiddenNameText.Text = SignatureHighlighter.RemoveHighlighting(nameText.text);
string asmText; string asmText;
if (TargetType.Assembly is AssemblyBuilder || string.IsNullOrEmpty(TargetType.Assembly.Location)) if (TargetType.Assembly is AssemblyBuilder || string.IsNullOrEmpty(TargetType.Assembly.Location))
asmText = $"{TargetType.Assembly.GetName().Name} <color=grey><i>(in memory)</i></color>"; asmText = $"{TargetType.Assembly.GetName().Name} <color=grey><i>(in memory)</i></color>";
else else
asmText = Path.GetFileName(TargetType.Assembly.Location); asmText = Path.GetFileName(TargetType.Assembly.Location);
AssemblyText.text = $"<color=grey>Assembly:</color> {asmText}"; assemblyText.text = $"<color=grey>Assembly:</color> {asmText}";
// Unity object helper widget // Unity object helper widget
@ -175,7 +177,7 @@ namespace UnityExplorer.Inspectors
scopeFilterButtons[BindingFlags.Default].Component.gameObject.SetActive(!StaticOnly); scopeFilterButtons[BindingFlags.Default].Component.gameObject.SetActive(!StaticOnly);
scopeFilterButtons[BindingFlags.Instance].Component.gameObject.SetActive(!StaticOnly); scopeFilterButtons[BindingFlags.Instance].Component.gameObject.SetActive(!StaticOnly);
foreach (var toggle in memberTypeToggles) foreach (Toggle toggle in memberTypeToggles)
toggle.isOn = true; toggle.isOn = true;
refreshWanted = true; refreshWanted = true;
@ -195,11 +197,11 @@ namespace UnityExplorer.Inspectors
} }
// check filter changes or force-refresh // check filter changes or force-refresh
if (refreshWanted || nameFilter != lastNameFilter || scopeFlagsFilter != lastFlagsFilter || lastMemberFilter != MemberFilter) if (refreshWanted || nameFilter != lastNameFilter || scopeFlagsFilter != lastFlagsFilter || lastMemberFilter != memberFilter)
{ {
lastNameFilter = nameFilter; lastNameFilter = nameFilter;
lastFlagsFilter = scopeFlagsFilter; lastFlagsFilter = scopeFlagsFilter;
lastMemberFilter = MemberFilter; lastMemberFilter = memberFilter;
FilterMembers(); FilterMembers();
MemberScrollPool.Refresh(true, true); MemberScrollPool.Refresh(true, true);
@ -219,24 +221,15 @@ namespace UnityExplorer.Inspectors
} }
} }
public void UpdateClicked()
{
UpdateDisplayedMembers();
}
// Filtering // Filtering
public void SetFilter(string name) => SetFilter(name, scopeFlagsFilter);
public void SetFilter(BindingFlags flags) => SetFilter(nameFilter, flags);
public void SetFilter(string name, BindingFlags flags) public void SetFilter(string name, BindingFlags flags)
{ {
this.nameFilter = name; this.nameFilter = name;
if (flags != scopeFlagsFilter) if (flags != scopeFlagsFilter)
{ {
var btn = scopeFilterButtons[scopeFlagsFilter].Component; Button btn = scopeFilterButtons[scopeFlagsFilter].Component;
RuntimeHelper.SetColorBlock(btn, disabledButtonColor, disabledButtonColor * 1.3f); RuntimeHelper.SetColorBlock(btn, disabledButtonColor, disabledButtonColor * 1.3f);
this.scopeFlagsFilter = flags; this.scopeFlagsFilter = flags;
@ -245,21 +238,13 @@ namespace UnityExplorer.Inspectors
} }
} }
private void OnMemberTypeToggled(MemberFilter flag, bool val) void FilterMembers()
{
if (!val)
MemberFilter &= ~flag;
else
MemberFilter |= flag;
}
private void FilterMembers()
{ {
filteredMembers.Clear(); filteredMembers.Clear();
for (int i = 0; i < members.Count; i++) for (int i = 0; i < members.Count; i++)
{ {
var member = members[i]; CacheMember member = members[i];
if (scopeFlagsFilter != BindingFlags.Default) if (scopeFlagsFilter != BindingFlags.Default)
{ {
@ -268,10 +253,10 @@ namespace UnityExplorer.Inspectors
continue; continue;
} }
if ((member is CacheMethod && !MemberFilter.HasFlag(MemberFilter.Method)) if ((member is CacheMethod && !memberFilter.HasFlag(MemberFilter.Method))
|| (member is CacheField && !MemberFilter.HasFlag(MemberFilter.Field)) || (member is CacheField && !memberFilter.HasFlag(MemberFilter.Field))
|| (member is CacheProperty && !MemberFilter.HasFlag(MemberFilter.Property)) || (member is CacheProperty && !memberFilter.HasFlag(MemberFilter.Property))
|| (member is CacheConstructor && !MemberFilter.HasFlag(MemberFilter.Constructor))) || (member is CacheConstructor && !memberFilter.HasFlag(MemberFilter.Constructor)))
continue; continue;
if (!string.IsNullOrEmpty(nameFilter) && !member.NameForFiltering.ContainsIgnoreCase(nameFilter)) if (!string.IsNullOrEmpty(nameFilter) && !member.NameForFiltering.ContainsIgnoreCase(nameFilter))
@ -281,14 +266,14 @@ namespace UnityExplorer.Inspectors
} }
} }
private void UpdateDisplayedMembers() void UpdateDisplayedMembers()
{ {
bool shouldRefresh = false; bool shouldRefresh = false;
foreach (var cell in MemberScrollPool.CellPool) foreach (CacheMemberCell cell in MemberScrollPool.CellPool)
{ {
if (!cell.Enabled || cell.Occupant == null) if (!cell.Enabled || cell.Occupant == null)
continue; continue;
var member = cell.MemberOccupant; CacheMember member = cell.MemberOccupant;
if (member.ShouldAutoEvaluate) if (member.ShouldAutoEvaluate)
{ {
shouldRefresh = true; shouldRefresh = true;
@ -316,17 +301,17 @@ namespace UnityExplorer.Inspectors
{ {
CalculateLayouts(); CalculateLayouts();
foreach (var cell in MemberScrollPool.CellPool) foreach (CacheMemberCell cell in MemberScrollPool.CellPool)
SetCellLayout(cell); SetCellLayout(cell);
} }
private void CalculateLayouts() void CalculateLayouts()
{ {
LeftGroupWidth = (int)Math.Max(200, (0.4f * InspectorManager.PanelWidth) - 5); LeftGroupWidth = (int)Math.Max(200, (0.4f * InspectorManager.PanelWidth) - 5);
RightGroupWidth = (int)Math.Max(200, InspectorManager.PanelWidth - LeftGroupWidth - 65); RightGroupWidth = (int)Math.Max(200, InspectorManager.PanelWidth - LeftGroupWidth - 65);
} }
private void SetCellLayout(CacheObjectCell cell) void SetCellLayout(CacheObjectCell cell)
{ {
cell.NameLayout.minWidth = LeftGroupWidth; cell.NameLayout.minWidth = LeftGroupWidth;
cell.RightGroupLayout.minWidth = RightGroupWidth; cell.RightGroupLayout.minWidth = RightGroupWidth;
@ -335,11 +320,66 @@ namespace UnityExplorer.Inspectors
cell.Occupant.IValue.SetLayout(); cell.Occupant.IValue.SetLayout();
} }
private void OnCopyClicked() // UI listeners
void OnUpdateClicked()
{
UpdateDisplayedMembers();
}
public void OnSetNameFilter(string name)
{
SetFilter(name, scopeFlagsFilter);
}
public void OnSetFlags(BindingFlags flags)
{
SetFilter(nameFilter, flags);
}
void OnMemberTypeToggled(MemberFilter flag, bool val)
{
if (!val)
memberFilter &= ~flag;
else
memberFilter |= flag;
}
void OnCopyClicked()
{ {
ClipboardPanel.Copy(this.Target ?? this.TargetType); ClipboardPanel.Copy(this.Target ?? this.TargetType);
} }
void OnMakeGenericClicked()
{
ContentRoot.SetActive(false);
if (genericConstructor == null)
{
genericConstructor = new();
genericConstructor.ConstructUI(UIRoot);
}
genericConstructor.UIRoot.SetActive(true);
genericConstructor.Show(OnGenericSubmit, OnGenericCancel, TargetType);
}
void OnGenericSubmit(Type[] args)
{
ContentRoot.SetActive(true);
genericConstructor.UIRoot.SetActive(false);
Type newType = TargetType.MakeGenericType(args);
InspectorManager.Inspect(newType);
//InspectorManager.ReleaseInspector(this);
}
void OnGenericCancel()
{
ContentRoot.SetActive(true);
genericConstructor.UIRoot.SetActive(false);
}
// UI Construction // UI Construction
public override GameObject CreateContent(GameObject parent) public override GameObject CreateContent(GameObject parent)
@ -349,51 +389,57 @@ namespace UnityExplorer.Inspectors
// Class name, assembly // Class name, assembly
var topRow = UIFactory.CreateHorizontalGroup(UIRoot, "TopRow", false, false, true, true, 4, default, new(1, 1, 1, 0), TextAnchor.MiddleLeft); GameObject topRow = UIFactory.CreateHorizontalGroup(UIRoot, "TopRow", false, false, true, true, 4, default,
new(0.1f, 0.1f, 0.1f), TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(topRow, minHeight: 25, flexibleWidth: 9999); UIFactory.SetLayoutElement(topRow, minHeight: 25, flexibleWidth: 9999);
var titleHolder = UIFactory.CreateUIObject("TitleHolder", topRow); GameObject titleHolder = UIFactory.CreateUIObject("TitleHolder", topRow);
UIFactory.SetLayoutElement(titleHolder, minHeight: 35, flexibleHeight: 0, flexibleWidth: 9999); UIFactory.SetLayoutElement(titleHolder, minHeight: 35, flexibleHeight: 0, flexibleWidth: 9999);
NameText = UIFactory.CreateLabel(titleHolder, "VisibleTitle", "NotSet", TextAnchor.MiddleLeft); nameText = UIFactory.CreateLabel(titleHolder, "VisibleTitle", "NotSet", TextAnchor.MiddleLeft);
var namerect = NameText.GetComponent<RectTransform>(); RectTransform namerect = nameText.GetComponent<RectTransform>();
namerect.anchorMin = new Vector2(0, 0); namerect.anchorMin = new Vector2(0, 0);
namerect.anchorMax = new Vector2(1, 1); namerect.anchorMax = new Vector2(1, 1);
NameText.fontSize = 17; nameText.fontSize = 17;
UIFactory.SetLayoutElement(NameText.gameObject, minHeight: 35, flexibleHeight: 0, minWidth: 300, flexibleWidth: 9999); UIFactory.SetLayoutElement(nameText.gameObject, minHeight: 35, flexibleHeight: 0, minWidth: 300, flexibleWidth: 9999);
HiddenNameText = UIFactory.CreateInputField(titleHolder, "Title", "not set"); hiddenNameText = UIFactory.CreateInputField(titleHolder, "Title", "not set");
var hiddenrect = HiddenNameText.Component.gameObject.GetComponent<RectTransform>(); RectTransform hiddenrect = hiddenNameText.Component.gameObject.GetComponent<RectTransform>();
hiddenrect.anchorMin = new Vector2(0, 0); hiddenrect.anchorMin = new Vector2(0, 0);
hiddenrect.anchorMax = new Vector2(1, 1); hiddenrect.anchorMax = new Vector2(1, 1);
HiddenNameText.Component.readOnly = true; hiddenNameText.Component.readOnly = true;
HiddenNameText.Component.lineType = InputField.LineType.MultiLineNewline; hiddenNameText.Component.lineType = InputField.LineType.MultiLineNewline;
HiddenNameText.Component.gameObject.GetComponent<Image>().color = Color.clear; hiddenNameText.Component.gameObject.GetComponent<Image>().color = Color.clear;
HiddenNameText.Component.textComponent.horizontalOverflow = HorizontalWrapMode.Wrap; hiddenNameText.Component.textComponent.horizontalOverflow = HorizontalWrapMode.Wrap;
HiddenNameText.Component.textComponent.fontSize = 17; hiddenNameText.Component.textComponent.fontSize = 17;
HiddenNameText.Component.textComponent.color = Color.clear; hiddenNameText.Component.textComponent.color = Color.clear;
UIFactory.SetLayoutElement(HiddenNameText.Component.gameObject, minHeight: 35, flexibleHeight: 0, flexibleWidth: 9999); UIFactory.SetLayoutElement(hiddenNameText.Component.gameObject, minHeight: 35, flexibleHeight: 0, flexibleWidth: 9999);
var copyButton = UIFactory.CreateButton(topRow, "CopyButton", "Copy to Clipboard", new Color(0.2f, 0.2f, 0.2f, 1)); makeGenericButton = UIFactory.CreateButton(topRow, "MakeGenericButton", "Construct Generic", new Color(0.2f, 0.3f, 0.2f));
UIFactory.SetLayoutElement(makeGenericButton.GameObject, minWidth: 140, minHeight: 25);
makeGenericButton.OnClick += OnMakeGenericClicked;
makeGenericButton.GameObject.SetActive(false);
ButtonRef copyButton = UIFactory.CreateButton(topRow, "CopyButton", "Copy to Clipboard", new Color(0.2f, 0.2f, 0.2f, 1));
copyButton.ButtonText.color = Color.yellow; copyButton.ButtonText.color = Color.yellow;
UIFactory.SetLayoutElement(copyButton.Component.gameObject, minHeight: 25, minWidth: 120, flexibleWidth: 0); UIFactory.SetLayoutElement(copyButton.Component.gameObject, minHeight: 25, minWidth: 120, flexibleWidth: 0);
copyButton.OnClick += OnCopyClicked; copyButton.OnClick += OnCopyClicked;
AssemblyText = UIFactory.CreateLabel(UIRoot, "AssemblyLabel", "not set", TextAnchor.MiddleLeft); assemblyText = UIFactory.CreateLabel(UIRoot, "AssemblyLabel", "not set", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(AssemblyText.gameObject, minHeight: 25, flexibleWidth: 9999); UIFactory.SetLayoutElement(assemblyText.gameObject, minHeight: 25, flexibleWidth: 9999);
mainContentHolder = UIFactory.CreateVerticalGroup(UIRoot, "MemberHolder", false, false, true, true, 5, new Vector4(2, 2, 2, 2), ContentRoot = UIFactory.CreateVerticalGroup(UIRoot, "MemberHolder", false, false, true, true, 5, new Vector4(2, 2, 2, 2),
new Color(0.12f, 0.12f, 0.12f)); new Color(0.12f, 0.12f, 0.12f));
UIFactory.SetLayoutElement(mainContentHolder, flexibleWidth: 9999, flexibleHeight: 9999); UIFactory.SetLayoutElement(ContentRoot, flexibleWidth: 9999, flexibleHeight: 9999);
ConstructFirstRow(mainContentHolder); ConstructFirstRow(ContentRoot);
ConstructSecondRow(mainContentHolder); ConstructSecondRow(ContentRoot);
// Member scroll pool // Member scroll pool
var memberBorder = UIFactory.CreateVerticalGroup(mainContentHolder, "ScrollPoolHolder", false, false, true, true, padding: new Vector4(2, 2, 2, 2), GameObject memberBorder = UIFactory.CreateVerticalGroup(ContentRoot, "ScrollPoolHolder", false, false, true, true,
bgColor: new Color(0.05f, 0.05f, 0.05f)); padding: new Vector4(2, 2, 2, 2), bgColor: new Color(0.05f, 0.05f, 0.05f));
UIFactory.SetLayoutElement(memberBorder, flexibleWidth: 9999, flexibleHeight: 9999); UIFactory.SetLayoutElement(memberBorder, flexibleWidth: 9999, flexibleHeight: 9999);
MemberScrollPool = UIFactory.CreateScrollPool<CacheMemberCell>(memberBorder, "MemberList", out GameObject scrollObj, MemberScrollPool = UIFactory.CreateScrollPool<CacheMemberCell>(memberBorder, "MemberList", out GameObject scrollObj,
@ -411,29 +457,29 @@ namespace UnityExplorer.Inspectors
// First row // First row
private void ConstructFirstRow(GameObject parent) void ConstructFirstRow(GameObject parent)
{ {
var rowObj = UIFactory.CreateUIObject("FirstRow", parent); GameObject rowObj = UIFactory.CreateUIObject("FirstRow", parent);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(rowObj, true, true, true, true, 5, 2, 2, 2, 2); UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(rowObj, true, true, true, true, 5, 2, 2, 2, 2);
UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999); UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
var nameLabel = UIFactory.CreateLabel(rowObj, "NameFilterLabel", "Filter names:", TextAnchor.MiddleLeft, Color.grey); Text nameLabel = UIFactory.CreateLabel(rowObj, "NameFilterLabel", "Filter names:", TextAnchor.MiddleLeft, Color.grey);
UIFactory.SetLayoutElement(nameLabel.gameObject, minHeight: 25, minWidth: 90, flexibleWidth: 0); UIFactory.SetLayoutElement(nameLabel.gameObject, minHeight: 25, minWidth: 90, flexibleWidth: 0);
filterInputField = UIFactory.CreateInputField(rowObj, "NameFilterInput", "..."); filterInputField = UIFactory.CreateInputField(rowObj, "NameFilterInput", "...");
UIFactory.SetLayoutElement(filterInputField.UIRoot, minHeight: 25, flexibleWidth: 300); UIFactory.SetLayoutElement(filterInputField.UIRoot, minHeight: 25, flexibleWidth: 300);
filterInputField.OnValueChanged += (string val) => { SetFilter(val); }; filterInputField.OnValueChanged += (string val) => { OnSetNameFilter(val); };
var spacer = UIFactory.CreateUIObject("Spacer", rowObj); GameObject spacer = UIFactory.CreateUIObject("Spacer", rowObj);
UIFactory.SetLayoutElement(spacer, minWidth: 25); UIFactory.SetLayoutElement(spacer, minWidth: 25);
// Update button and toggle // Update button and toggle
var updateButton = UIFactory.CreateButton(rowObj, "UpdateButton", "Update displayed values", new Color(0.22f, 0.28f, 0.22f)); ButtonRef updateButton = UIFactory.CreateButton(rowObj, "UpdateButton", "Update displayed values", new Color(0.22f, 0.28f, 0.22f));
UIFactory.SetLayoutElement(updateButton.Component.gameObject, minHeight: 25, minWidth: 175, flexibleWidth: 0); UIFactory.SetLayoutElement(updateButton.Component.gameObject, minHeight: 25, minWidth: 175, flexibleWidth: 0);
updateButton.OnClick += UpdateClicked; updateButton.OnClick += OnUpdateClicked;
var toggleObj = UIFactory.CreateToggle(rowObj, "AutoUpdateToggle", out autoUpdateToggle, out Text toggleText); GameObject toggleObj = UIFactory.CreateToggle(rowObj, "AutoUpdateToggle", out autoUpdateToggle, out Text toggleText);
UIFactory.SetLayoutElement(toggleObj, minWidth: 125, minHeight: 25); UIFactory.SetLayoutElement(toggleObj, minWidth: 125, minHeight: 25);
autoUpdateToggle.isOn = false; autoUpdateToggle.isOn = false;
toggleText.text = "Auto-update"; toggleText.text = "Auto-update";
@ -441,21 +487,21 @@ namespace UnityExplorer.Inspectors
// Second row // Second row
private void ConstructSecondRow(GameObject parent) void ConstructSecondRow(GameObject parent)
{ {
var rowObj = UIFactory.CreateUIObject("SecondRow", parent); GameObject rowObj = UIFactory.CreateUIObject("SecondRow", parent);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(rowObj, false, false, true, true, 5, 2, 2, 2, 2); UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(rowObj, false, false, true, true, 5, 2, 2, 2, 2);
UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999); UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
// Scope buttons // Scope buttons
var scopeLabel = UIFactory.CreateLabel(rowObj, "ScopeLabel", "Scope:", TextAnchor.MiddleLeft, Color.grey); Text scopeLabel = UIFactory.CreateLabel(rowObj, "ScopeLabel", "Scope:", TextAnchor.MiddleLeft, Color.grey);
UIFactory.SetLayoutElement(scopeLabel.gameObject, minHeight: 25, minWidth: 60, flexibleWidth: 0); UIFactory.SetLayoutElement(scopeLabel.gameObject, minHeight: 25, minWidth: 60, flexibleWidth: 0);
AddScopeFilterButton(rowObj, BindingFlags.Default, true); AddScopeFilterButton(rowObj, BindingFlags.Default, true);
AddScopeFilterButton(rowObj, BindingFlags.Instance); AddScopeFilterButton(rowObj, BindingFlags.Instance);
AddScopeFilterButton(rowObj, BindingFlags.Static); AddScopeFilterButton(rowObj, BindingFlags.Static);
var spacer = UIFactory.CreateUIObject("Spacer", rowObj); GameObject spacer = UIFactory.CreateUIObject("Spacer", rowObj);
UIFactory.SetLayoutElement(spacer, minWidth: 15); UIFactory.SetLayoutElement(spacer, minWidth: 15);
// Member type toggles // Member type toggles
@ -466,21 +512,21 @@ namespace UnityExplorer.Inspectors
AddMemberTypeToggle(rowObj, MemberTypes.Constructor, 110); AddMemberTypeToggle(rowObj, MemberTypes.Constructor, 110);
} }
private void AddScopeFilterButton(GameObject parent, BindingFlags flags, bool setAsActive = false) void AddScopeFilterButton(GameObject parent, BindingFlags flags, bool setAsActive = false)
{ {
string lbl = flags == BindingFlags.Default ? "All" : flags.ToString(); string lbl = flags == BindingFlags.Default ? "All" : flags.ToString();
var color = setAsActive ? enabledButtonColor : disabledButtonColor; Color color = setAsActive ? enabledButtonColor : disabledButtonColor;
var button = UIFactory.CreateButton(parent, "Filter_" + flags, lbl, color); ButtonRef button = UIFactory.CreateButton(parent, "Filter_" + flags, lbl, color);
UIFactory.SetLayoutElement(button.Component.gameObject, minHeight: 25, flexibleHeight: 0, minWidth: 70, flexibleWidth: 0); UIFactory.SetLayoutElement(button.Component.gameObject, minHeight: 25, flexibleHeight: 0, minWidth: 70, flexibleWidth: 0);
scopeFilterButtons.Add(flags, button); scopeFilterButtons.Add(flags, button);
button.OnClick += () => { SetFilter(flags); }; button.OnClick += () => { OnSetFlags(flags); };
} }
private void AddMemberTypeToggle(GameObject parent, MemberTypes type, int width) void AddMemberTypeToggle(GameObject parent, MemberTypes type, int width)
{ {
var toggleObj = UIFactory.CreateToggle(parent, "Toggle_" + type, out Toggle toggle, out Text toggleText); GameObject toggleObj = UIFactory.CreateToggle(parent, "Toggle_" + type, out Toggle toggle, out Text toggleText);
UIFactory.SetLayoutElement(toggleObj, minHeight: 25, minWidth: width); UIFactory.SetLayoutElement(toggleObj, minHeight: 25, minWidth: width);
string color = type switch string color = type switch
{ {

View File

@ -2,8 +2,6 @@
using BepInEx.Configuration; using BepInEx.Configuration;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityExplorer.Config; using UnityExplorer.Config;
namespace UnityExplorer.Loader.BIE namespace UnityExplorer.Loader.BIE
@ -21,7 +19,7 @@ namespace UnityExplorer.Loader.BIE
public override void RegisterConfigElement<T>(ConfigElement<T> config) public override void RegisterConfigElement<T>(ConfigElement<T> config)
{ {
var entry = Config.Bind(CTG_NAME, config.Name, config.Value, config.Description); ConfigEntry<T> entry = Config.Bind(CTG_NAME, config.Name, config.Value, config.Description);
entry.SettingChanged += (object o, EventArgs e) => entry.SettingChanged += (object o, EventArgs e) =>
{ {
@ -47,13 +45,13 @@ namespace UnityExplorer.Loader.BIE
public override void LoadConfig() public override void LoadConfig()
{ {
foreach (var entry in ConfigManager.ConfigElements) foreach (KeyValuePair<string, IConfigElement> entry in ConfigManager.ConfigElements)
{ {
var key = entry.Key; string key = entry.Key;
var def = new ConfigDefinition(CTG_NAME, key); ConfigDefinition def = new(CTG_NAME, key);
if (Config.ContainsKey(def) && Config[def] is ConfigEntryBase configEntry) if (Config.ContainsKey(def) && Config[def] is ConfigEntryBase configEntry)
{ {
var config = entry.Value; IConfigElement config = entry.Value;
config.BoxedValue = configEntry.BoxedValue; config.BoxedValue = configEntry.BoxedValue;
} }
} }
@ -61,7 +59,7 @@ namespace UnityExplorer.Loader.BIE
public override void SaveConfig() public override void SaveConfig()
{ {
// not required Config.Save();
} }
} }
} }

View File

@ -3,14 +3,8 @@ using BepInEx;
using BepInEx.Logging; using BepInEx.Logging;
using HarmonyLib; using HarmonyLib;
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityExplorer.Config; using UnityExplorer.Config;
using UniverseLib.Input;
using UnityExplorer.Loader.BIE; using UnityExplorer.Loader.BIE;
#if CPP #if CPP
using BepInEx.IL2CPP; using BepInEx.IL2CPP;
@ -45,7 +39,7 @@ namespace UnityExplorer
public Harmony HarmonyInstance => s_harmony; public Harmony HarmonyInstance => s_harmony;
private static readonly Harmony s_harmony = new(ExplorerCore.GUID); private static readonly Harmony s_harmony = new(ExplorerCore.GUID);
public string ExplorerFolderName => ExplorerCore.DEFAULT_EXPLORER_FOLDER_NAME; public string ExplorerFolderName => ExplorerCore.DEFAULT_EXPLORER_FOLDER_NAME;
public string ExplorerFolderDestination => Paths.PluginPath; public string ExplorerFolderDestination => Paths.PluginPath;

View File

@ -1,7 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityExplorer.Config; using UnityExplorer.Config;
namespace UnityExplorer namespace UnityExplorer

View File

@ -6,27 +6,53 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using UnityEngine; using UnityEngine;
using UnityExplorer.Config;
using UnityExplorer.UI;
using UniverseLib;
namespace UnityExplorer.Loader.Standalone namespace UnityExplorer.Loader.Standalone
{ {
public class ExplorerEditorBehaviour : MonoBehaviour public class ExplorerEditorBehaviour : MonoBehaviour
{ {
internal static ExplorerEditorBehaviour Instance { get; private set; }
public bool Hide_On_Startup = true;
public KeyCode Master_Toggle_Key = KeyCode.F7;
public UIManager.VerticalAnchor Main_Navbar_Anchor = UIManager.VerticalAnchor.Top;
public bool Log_Unity_Debug = false;
public float Startup_Delay_Time = 1f;
public KeyCode World_MouseInspect_Keybind;
public KeyCode UI_MouseInspect_Keybind;
public bool Force_Unlock_Mouse = true;
public KeyCode Force_Unlock_Toggle;
public bool Disable_EventSystem_Override;
internal void Awake() internal void Awake()
{ {
Instance = this;
ExplorerEditorLoader.Initialize(); ExplorerEditorLoader.Initialize();
DontDestroyOnLoad(this); DontDestroyOnLoad(this);
this.gameObject.hideFlags = HideFlags.HideAndDontSave; this.gameObject.hideFlags = HideFlags.HideAndDontSave;
} }
internal void OnDestroy()
{
OnApplicationQuit();
}
internal void OnApplicationQuit() internal void OnApplicationQuit()
{ {
if (UI.UIManager.UIRoot) Destroy(this.gameObject);
Destroy(UI.UIManager.UIRoot.transform.root.gameObject); }
internal void LoadConfigs()
{
ConfigManager.Hide_On_Startup.Value = this.Hide_On_Startup;
ConfigManager.Master_Toggle.Value = this.Master_Toggle_Key;
ConfigManager.Main_Navbar_Anchor.Value = this.Main_Navbar_Anchor;
ConfigManager.Log_Unity_Debug.Value = this.Log_Unity_Debug;
ConfigManager.Startup_Delay_Time.Value = this.Startup_Delay_Time;
ConfigManager.World_MouseInspect_Keybind.Value = this.World_MouseInspect_Keybind;
ConfigManager.UI_MouseInspect_Keybind.Value = this.UI_MouseInspect_Keybind;
ConfigManager.Force_Unlock_Mouse.Value = this.Force_Unlock_Mouse;
ConfigManager.Force_Unlock_Toggle.Value = this.Force_Unlock_Toggle;
ConfigManager.Disable_EventSystem_Override.Value = this.Disable_EventSystem_Override;
} }
} }
} }

View File

@ -36,7 +36,7 @@ namespace UnityExplorer.Loader.Standalone
protected override void CheckExplorerFolder() protected override void CheckExplorerFolder()
{ {
if (explorerFolderDest == null) if (explorerFolderDest == null)
explorerFolderDest = Application.dataPath; explorerFolderDest = Path.GetDirectoryName(Application.dataPath);
} }
} }
} }

View File

@ -1,14 +1,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UniverseLib.UI.Models;
using UnityExplorer.UI.Panels; using UnityExplorer.UI.Panels;
using UnityExplorer.UI.Widgets.AutoComplete; using UnityExplorer.UI.Widgets.AutoComplete;
using UniverseLib.UI;
using UniverseLib; using UniverseLib;
using UniverseLib.UI;
using UniverseLib.UI.Models;
using UniverseLib.UI.Widgets.ButtonList; using UniverseLib.UI.Widgets.ButtonList;
using UniverseLib.UI.Widgets.ScrollView; using UniverseLib.UI.Widgets.ScrollView;
using UniverseLib.Utility; using UniverseLib.Utility;
@ -35,12 +34,15 @@ namespace UnityExplorer.ObjectExplorer
private ScrollPool<ButtonCell> resultsScrollPool; private ScrollPool<ButtonCell> resultsScrollPool;
private List<object> currentResults = new(); private List<object> currentResults = new();
//public TypeCompleter typeAutocompleter;
public TypeCompleter unityObjectTypeCompleter;
public TypeCompleter allTypesCompleter;
public override GameObject UIRoot => uiRoot; public override GameObject UIRoot => uiRoot;
private GameObject uiRoot; private GameObject uiRoot;
private GameObject sceneFilterRow; private GameObject sceneFilterRow;
private GameObject childFilterRow; private GameObject childFilterRow;
private GameObject classInputRow; private GameObject classInputRow;
public TypeCompleter typeAutocompleter;
private GameObject nameInputRow; private GameObject nameInputRow;
private InputFieldRef nameInputField; private InputFieldRef nameInputField;
private Text resultsLabel; private Text resultsLabel;
@ -73,7 +75,7 @@ namespace UnityExplorer.ObjectExplorer
//var type = ReflectionUtility.GetTypeByName(desiredTypeInput); //var type = ReflectionUtility.GetTypeByName(desiredTypeInput);
if (ReflectionUtility.GetTypeByName(desiredTypeInput) is Type cachedType) if (ReflectionUtility.GetTypeByName(desiredTypeInput) is Type cachedType)
{ {
var type = cachedType; Type type = cachedType;
lastTypeCanHaveGameObject = typeof(Component).IsAssignableFrom(type) || type == typeof(GameObject); lastTypeCanHaveGameObject = typeof(Component).IsAssignableFrom(type) || type == typeof(GameObject);
sceneFilterRow.SetActive(lastTypeCanHaveGameObject); sceneFilterRow.SetActive(lastTypeCanHaveGameObject);
childFilterRow.SetActive(lastTypeCanHaveGameObject); childFilterRow.SetActive(lastTypeCanHaveGameObject);
@ -99,14 +101,18 @@ namespace UnityExplorer.ObjectExplorer
nameInputRow.SetActive(context == SearchContext.UnityObject); nameInputRow.SetActive(context == SearchContext.UnityObject);
if (context == SearchContext.Class) switch (context)
typeAutocompleter.AllTypes = true;
else
{ {
typeAutocompleter.BaseType = context == SearchContext.UnityObject ? typeof(UnityEngine.Object) : typeof(object); case SearchContext.UnityObject:
typeAutocompleter.AllTypes = false; unityObjectTypeCompleter.Enabled = true;
allTypesCompleter.Enabled = false;
break;
case SearchContext.Singleton:
case SearchContext.Class:
allTypesCompleter.Enabled = true;
unityObjectTypeCompleter.Enabled = false;
break;
} }
typeAutocompleter.CacheTypes();
} }
private void OnSceneFilterDropChanged(int value) => sceneFilter = (SceneFilter)value; private void OnSceneFilterDropChanged(int value) => sceneFilter = (SceneFilter)value;
@ -135,7 +141,7 @@ namespace UnityExplorer.ObjectExplorer
string text; string text;
if (context == SearchContext.Class) if (context == SearchContext.Class)
{ {
var type = currentResults[index] as Type; Type type = currentResults[index] as Type;
text = $"{SignatureHighlighter.Parse(type, true)} <color=grey><i>({type.Assembly.GetName().Name})</i></color>"; text = $"{SignatureHighlighter.Parse(type, true)} <color=grey><i>({type.Assembly.GetName().Name})</i></color>";
} }
else else
@ -164,14 +170,14 @@ namespace UnityExplorer.ObjectExplorer
// Search context row // Search context row
var contextGroup = UIFactory.CreateHorizontalGroup(uiRoot, "SearchContextRow", false, true, true, true, 2, new Vector4(2, 2, 2, 2)); GameObject contextGroup = UIFactory.CreateHorizontalGroup(uiRoot, "SearchContextRow", false, true, true, true, 2, new Vector4(2, 2, 2, 2));
UIFactory.SetLayoutElement(contextGroup, minHeight: 25, flexibleHeight: 0); UIFactory.SetLayoutElement(contextGroup, minHeight: 25, flexibleHeight: 0);
var contextLbl = UIFactory.CreateLabel(contextGroup, "SearchContextLabel", "Searching for:", TextAnchor.MiddleLeft); Text contextLbl = UIFactory.CreateLabel(contextGroup, "SearchContextLabel", "Searching for:", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(contextLbl.gameObject, minWidth: 110, flexibleWidth: 0); UIFactory.SetLayoutElement(contextLbl.gameObject, minWidth: 110, flexibleWidth: 0);
var contextDropObj = UIFactory.CreateDropdown(contextGroup, "ContextDropdown", out Dropdown contextDrop, null, 14, OnContextDropdownChanged); GameObject contextDropObj = UIFactory.CreateDropdown(contextGroup, "ContextDropdown", out Dropdown contextDrop, null, 14, OnContextDropdownChanged);
foreach (var name in Enum.GetNames(typeof(SearchContext))) foreach (string name in Enum.GetNames(typeof(SearchContext)))
contextDrop.options.Add(new Dropdown.OptionData(name)); contextDrop.options.Add(new Dropdown.OptionData(name));
UIFactory.SetLayoutElement(contextDropObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999); UIFactory.SetLayoutElement(contextDropObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
@ -180,13 +186,15 @@ namespace UnityExplorer.ObjectExplorer
classInputRow = UIFactory.CreateHorizontalGroup(uiRoot, "ClassRow", false, true, true, true, 2, new Vector4(2, 2, 2, 2)); classInputRow = UIFactory.CreateHorizontalGroup(uiRoot, "ClassRow", false, true, true, true, 2, new Vector4(2, 2, 2, 2));
UIFactory.SetLayoutElement(classInputRow, minHeight: 25, flexibleHeight: 0); UIFactory.SetLayoutElement(classInputRow, minHeight: 25, flexibleHeight: 0);
var unityClassLbl = UIFactory.CreateLabel(classInputRow, "ClassLabel", "Class filter:", TextAnchor.MiddleLeft); Text unityClassLbl = UIFactory.CreateLabel(classInputRow, "ClassLabel", "Class filter:", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(unityClassLbl.gameObject, minWidth: 110, flexibleWidth: 0); UIFactory.SetLayoutElement(unityClassLbl.gameObject, minWidth: 110, flexibleWidth: 0);
var classInputField = UIFactory.CreateInputField(classInputRow, "ClassInput", "..."); InputFieldRef classInputField = UIFactory.CreateInputField(classInputRow, "ClassInput", "...");
UIFactory.SetLayoutElement(classInputField.UIRoot, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999); UIFactory.SetLayoutElement(classInputField.UIRoot, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
typeAutocompleter = new TypeCompleter(typeof(UnityEngine.Object), classInputField); unityObjectTypeCompleter = new(typeof(UnityEngine.Object), classInputField, true, false, true);
allTypesCompleter = new(null, classInputField, true, false, true);
allTypesCompleter.Enabled = false;
classInputField.OnValueChanged += OnTypeInputChanged; classInputField.OnValueChanged += OnTypeInputChanged;
//unityObjectClassRow.SetActive(false); //unityObjectClassRow.SetActive(false);
@ -196,11 +204,11 @@ namespace UnityExplorer.ObjectExplorer
childFilterRow = UIFactory.CreateHorizontalGroup(uiRoot, "ChildFilterRow", false, true, true, true, 2, new Vector4(2, 2, 2, 2)); childFilterRow = UIFactory.CreateHorizontalGroup(uiRoot, "ChildFilterRow", false, true, true, true, 2, new Vector4(2, 2, 2, 2));
UIFactory.SetLayoutElement(childFilterRow, minHeight: 25, flexibleHeight: 0); UIFactory.SetLayoutElement(childFilterRow, minHeight: 25, flexibleHeight: 0);
var childLbl = UIFactory.CreateLabel(childFilterRow, "ChildLabel", "Child filter:", TextAnchor.MiddleLeft); Text childLbl = UIFactory.CreateLabel(childFilterRow, "ChildLabel", "Child filter:", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(childLbl.gameObject, minWidth: 110, flexibleWidth: 0); UIFactory.SetLayoutElement(childLbl.gameObject, minWidth: 110, flexibleWidth: 0);
var childDropObj = UIFactory.CreateDropdown(childFilterRow, "ChildFilterDropdown", out Dropdown childDrop, null, 14, OnChildFilterDropChanged); GameObject childDropObj = UIFactory.CreateDropdown(childFilterRow, "ChildFilterDropdown", out Dropdown childDrop, null, 14, OnChildFilterDropChanged);
foreach (var name in Enum.GetNames(typeof(ChildFilter))) foreach (string name in Enum.GetNames(typeof(ChildFilter)))
childDrop.options.Add(new Dropdown.OptionData(name)); childDrop.options.Add(new Dropdown.OptionData(name));
UIFactory.SetLayoutElement(childDropObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999); UIFactory.SetLayoutElement(childDropObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
@ -211,11 +219,11 @@ namespace UnityExplorer.ObjectExplorer
sceneFilterRow = UIFactory.CreateHorizontalGroup(uiRoot, "SceneFilterRow", false, true, true, true, 2, new Vector4(2, 2, 2, 2)); sceneFilterRow = UIFactory.CreateHorizontalGroup(uiRoot, "SceneFilterRow", false, true, true, true, 2, new Vector4(2, 2, 2, 2));
UIFactory.SetLayoutElement(sceneFilterRow, minHeight: 25, flexibleHeight: 0); UIFactory.SetLayoutElement(sceneFilterRow, minHeight: 25, flexibleHeight: 0);
var sceneLbl = UIFactory.CreateLabel(sceneFilterRow, "SceneLabel", "Scene filter:", TextAnchor.MiddleLeft); Text sceneLbl = UIFactory.CreateLabel(sceneFilterRow, "SceneLabel", "Scene filter:", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(sceneLbl.gameObject, minWidth: 110, flexibleWidth: 0); UIFactory.SetLayoutElement(sceneLbl.gameObject, minWidth: 110, flexibleWidth: 0);
var sceneDropObj = UIFactory.CreateDropdown(sceneFilterRow, "SceneFilterDropdown", out Dropdown sceneDrop, null, 14, OnSceneFilterDropChanged); GameObject sceneDropObj = UIFactory.CreateDropdown(sceneFilterRow, "SceneFilterDropdown", out Dropdown sceneDrop, null, 14, OnSceneFilterDropChanged);
foreach (var name in Enum.GetNames(typeof(SceneFilter))) foreach (string name in Enum.GetNames(typeof(SceneFilter)))
{ {
if (!SceneHandler.DontDestroyExists && name == "DontDestroyOnLoad") if (!SceneHandler.DontDestroyExists && name == "DontDestroyOnLoad")
continue; continue;
@ -230,7 +238,7 @@ namespace UnityExplorer.ObjectExplorer
nameInputRow = UIFactory.CreateHorizontalGroup(uiRoot, "NameRow", true, true, true, true, 2, new Vector4(2, 2, 2, 2)); nameInputRow = UIFactory.CreateHorizontalGroup(uiRoot, "NameRow", true, true, true, true, 2, new Vector4(2, 2, 2, 2));
UIFactory.SetLayoutElement(nameInputRow, minHeight: 25, flexibleHeight: 0); UIFactory.SetLayoutElement(nameInputRow, minHeight: 25, flexibleHeight: 0);
var nameLbl = UIFactory.CreateLabel(nameInputRow, "NameFilterLabel", "Name contains:", TextAnchor.MiddleLeft); Text nameLbl = UIFactory.CreateLabel(nameInputRow, "NameFilterLabel", "Name contains:", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(nameLbl.gameObject, minWidth: 110, flexibleWidth: 0); UIFactory.SetLayoutElement(nameLbl.gameObject, minWidth: 110, flexibleWidth: 0);
nameInputField = UIFactory.CreateInputField(nameInputRow, "NameFilterInput", "..."); nameInputField = UIFactory.CreateInputField(nameInputRow, "NameFilterInput", "...");
@ -238,13 +246,13 @@ namespace UnityExplorer.ObjectExplorer
// Search button // Search button
var searchButton = UIFactory.CreateButton(uiRoot, "SearchButton", "Search"); ButtonRef searchButton = UIFactory.CreateButton(uiRoot, "SearchButton", "Search");
UIFactory.SetLayoutElement(searchButton.Component.gameObject, minHeight: 25, flexibleHeight: 0); UIFactory.SetLayoutElement(searchButton.Component.gameObject, minHeight: 25, flexibleHeight: 0);
searchButton.OnClick += DoSearch; searchButton.OnClick += DoSearch;
// Results count label // Results count label
var resultsCountRow = UIFactory.CreateHorizontalGroup(uiRoot, "ResultsCountRow", true, true, true, true); GameObject resultsCountRow = UIFactory.CreateHorizontalGroup(uiRoot, "ResultsCountRow", true, true, true, true);
UIFactory.SetLayoutElement(resultsCountRow, minHeight: 25, flexibleHeight: 0); UIFactory.SetLayoutElement(resultsCountRow, minHeight: 25, flexibleHeight: 0);
resultsLabel = UIFactory.CreateLabel(resultsCountRow, "ResultsLabel", "0 results", TextAnchor.MiddleCenter); resultsLabel = UIFactory.CreateLabel(resultsCountRow, "ResultsLabel", "0 results", TextAnchor.MiddleCenter);

View File

@ -1,20 +1,19 @@
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.SceneManagement; using UnityEngine.SceneManagement;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.UI; using UnityExplorer.UI;
using UniverseLib.UI.Models;
using UnityExplorer.UI.Panels; using UnityExplorer.UI.Panels;
using UnityExplorer.UI.Widgets; using UnityExplorer.UI.Widgets;
using UniverseLib.UI;
using UniverseLib; using UniverseLib;
using System.Collections; using UniverseLib.UI;
using UniverseLib.UI.Models;
using UniverseLib.Utility; using UniverseLib.Utility;
using UniverseLib.UI.Widgets;
namespace UnityExplorer.ObjectExplorer namespace UnityExplorer.ObjectExplorer
{ {
@ -76,7 +75,7 @@ namespace UnityExplorer.ObjectExplorer
this.Parent.SetTab(0); this.Parent.SetTab(0);
// select the transform's scene // select the transform's scene
var go = transform.gameObject; GameObject go = transform.gameObject;
if (SceneHandler.SelectedScene != go.scene) if (SceneHandler.SelectedScene != go.scene)
{ {
int idx; int idx;
@ -109,7 +108,7 @@ namespace UnityExplorer.ObjectExplorer
if (sceneToDropdownOption.ContainsKey(scene)) if (sceneToDropdownOption.ContainsKey(scene))
{ {
var opt = sceneToDropdownOption[scene]; Dropdown.OptionData opt = sceneToDropdownOption[scene];
int idx = sceneDropdown.options.IndexOf(opt); int idx = sceneDropdown.options.IndexOf(opt);
if (sceneDropdown.value != idx) if (sceneDropdown.value != idx)
sceneDropdown.value = idx; sceneDropdown.value = idx;
@ -136,7 +135,7 @@ namespace UnityExplorer.ObjectExplorer
sceneToDropdownOption.Clear(); sceneToDropdownOption.Clear();
sceneDropdown.options.Clear(); sceneDropdown.options.Clear();
foreach (var scene in loadedScenes) foreach (Scene scene in loadedScenes)
{ {
if (sceneToDropdownOption.ContainsKey(scene)) if (sceneToDropdownOption.ContainsKey(scene))
continue; continue;
@ -148,7 +147,7 @@ namespace UnityExplorer.ObjectExplorer
else if (string.IsNullOrEmpty(name)) else if (string.IsNullOrEmpty(name))
name = "<untitled>"; name = "<untitled>";
var option = new Dropdown.OptionData(name); Dropdown.OptionData option = new(name);
sceneDropdown.options.Add(option); sceneDropdown.options.Add(option);
sceneToDropdownOption.Add(scene, option); sceneToDropdownOption.Add(scene, option);
} }
@ -158,7 +157,7 @@ namespace UnityExplorer.ObjectExplorer
{ {
if ((!string.IsNullOrEmpty(input) && !Tree.Filtering) || (string.IsNullOrEmpty(input) && Tree.Filtering)) if ((!string.IsNullOrEmpty(input) && !Tree.Filtering) || (string.IsNullOrEmpty(input) && Tree.Filtering))
{ {
Tree.cachedTransforms.Clear(); Tree.Clear();
} }
Tree.CurrentFilter = input; Tree.CurrentFilter = input;
@ -167,7 +166,7 @@ namespace UnityExplorer.ObjectExplorer
private void TryLoadScene(LoadSceneMode mode, Dropdown allSceneDrop) private void TryLoadScene(LoadSceneMode mode, Dropdown allSceneDrop)
{ {
var text = allSceneDrop.captionText.text; string text = allSceneDrop.captionText.text;
if (text == DEFAULT_LOAD_TEXT) if (text == DEFAULT_LOAD_TEXT)
return; return;
@ -191,18 +190,18 @@ namespace UnityExplorer.ObjectExplorer
// Tool bar (top area) // Tool bar (top area)
var toolbar = UIFactory.CreateVerticalGroup(uiRoot, "Toolbar", true, true, true, true, 2, new Vector4(2, 2, 2, 2), GameObject toolbar = UIFactory.CreateVerticalGroup(uiRoot, "Toolbar", true, true, true, true, 2, new Vector4(2, 2, 2, 2),
new Color(0.15f, 0.15f, 0.15f)); new Color(0.15f, 0.15f, 0.15f));
// Scene selector dropdown // Scene selector dropdown
var dropRow = UIFactory.CreateHorizontalGroup(toolbar, "DropdownRow", true, true, true, true, 5, default, new Color(1, 1, 1, 0)); GameObject dropRow = UIFactory.CreateHorizontalGroup(toolbar, "DropdownRow", true, true, true, true, 5, default, new Color(1, 1, 1, 0));
UIFactory.SetLayoutElement(dropRow, minHeight: 25, flexibleWidth: 9999); UIFactory.SetLayoutElement(dropRow, minHeight: 25, flexibleWidth: 9999);
var dropLabel = UIFactory.CreateLabel(dropRow, "SelectorLabel", "Scene:", TextAnchor.MiddleLeft, Color.cyan, false, 15); Text dropLabel = UIFactory.CreateLabel(dropRow, "SelectorLabel", "Scene:", TextAnchor.MiddleLeft, Color.cyan, false, 15);
UIFactory.SetLayoutElement(dropLabel.gameObject, minHeight: 25, minWidth: 60, flexibleWidth: 0); UIFactory.SetLayoutElement(dropLabel.gameObject, minHeight: 25, minWidth: 60, flexibleWidth: 0);
var dropdownObj = UIFactory.CreateDropdown(dropRow, "SceneDropdown", out sceneDropdown, "<notset>", 13, OnSceneSelectionDropdownChanged); GameObject dropdownObj = UIFactory.CreateDropdown(dropRow, "SceneDropdown", out sceneDropdown, "<notset>", 13, OnSceneSelectionDropdownChanged);
UIFactory.SetLayoutElement(dropdownObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999); UIFactory.SetLayoutElement(dropdownObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
SceneHandler.Update(); SceneHandler.Update();
@ -211,11 +210,11 @@ namespace UnityExplorer.ObjectExplorer
// Filter row // Filter row
var filterRow = UIFactory.CreateHorizontalGroup(toolbar, "FilterGroup", true, true, true, true, 2, new Vector4(2, 2, 2, 2)); GameObject filterRow = UIFactory.CreateHorizontalGroup(toolbar, "FilterGroup", true, true, true, true, 2, new Vector4(2, 2, 2, 2));
UIFactory.SetLayoutElement(filterRow, minHeight: 25, flexibleHeight: 0); UIFactory.SetLayoutElement(filterRow, minHeight: 25, flexibleHeight: 0);
//Filter input field //Filter input field
var inputField = UIFactory.CreateInputField(filterRow, "FilterInput", "Search and press enter..."); InputFieldRef inputField = UIFactory.CreateInputField(filterRow, "FilterInput", "Search and press enter...");
inputField.Component.targetGraphic.color = new Color(0.2f, 0.2f, 0.2f); inputField.Component.targetGraphic.color = new Color(0.2f, 0.2f, 0.2f);
RuntimeHelper.SetColorBlock(inputField.Component, new Color(0.4f, 0.4f, 0.4f), new Color(0.2f, 0.2f, 0.2f), RuntimeHelper.SetColorBlock(inputField.Component, new Color(0.4f, 0.4f, 0.4f), new Color(0.2f, 0.2f, 0.2f),
new Color(0.08f, 0.08f, 0.08f)); new Color(0.08f, 0.08f, 0.08f));
@ -228,11 +227,11 @@ namespace UnityExplorer.ObjectExplorer
refreshRow = UIFactory.CreateHorizontalGroup(toolbar, "RefreshGroup", true, true, true, true, 2, new Vector4(2, 2, 2, 2)); refreshRow = UIFactory.CreateHorizontalGroup(toolbar, "RefreshGroup", true, true, true, true, 2, new Vector4(2, 2, 2, 2));
UIFactory.SetLayoutElement(refreshRow, minHeight: 30, flexibleHeight: 0); UIFactory.SetLayoutElement(refreshRow, minHeight: 30, flexibleHeight: 0);
var refreshButton = UIFactory.CreateButton(refreshRow, "RefreshButton", "Update"); ButtonRef refreshButton = UIFactory.CreateButton(refreshRow, "RefreshButton", "Update");
UIFactory.SetLayoutElement(refreshButton.Component.gameObject, minWidth: 65, flexibleWidth: 0); UIFactory.SetLayoutElement(refreshButton.Component.gameObject, minWidth: 65, flexibleWidth: 0);
refreshButton.OnClick += UpdateTree; refreshButton.OnClick += UpdateTree;
var refreshToggle = UIFactory.CreateToggle(refreshRow, "RefreshToggle", out Toggle toggle, out Text text); GameObject refreshToggle = UIFactory.CreateToggle(refreshRow, "RefreshToggle", out Toggle toggle, out Text text);
UIFactory.SetLayoutElement(refreshToggle, flexibleWidth: 9999); UIFactory.SetLayoutElement(refreshToggle, flexibleWidth: 9999);
text.text = "Auto-update (1 second)"; text.text = "Auto-update (1 second)";
text.alignment = TextAnchor.MiddleLeft; text.alignment = TextAnchor.MiddleLeft;
@ -245,24 +244,23 @@ namespace UnityExplorer.ObjectExplorer
// tree labels row // tree labels row
var labelsRow = UIFactory.CreateHorizontalGroup(toolbar, "LabelsRow", true, true, true, true, 2, new Vector4(2, 2, 2, 2)); GameObject labelsRow = UIFactory.CreateHorizontalGroup(toolbar, "LabelsRow", true, true, true, true, 2, new Vector4(2, 2, 2, 2));
UIFactory.SetLayoutElement(labelsRow, minHeight: 30, flexibleHeight: 0); UIFactory.SetLayoutElement(labelsRow, minHeight: 30, flexibleHeight: 0);
var nameLabel = UIFactory.CreateLabel(labelsRow, "NameLabel", "Name", TextAnchor.MiddleLeft, color: Color.grey); Text nameLabel = UIFactory.CreateLabel(labelsRow, "NameLabel", "Name", TextAnchor.MiddleLeft, color: Color.grey);
UIFactory.SetLayoutElement(nameLabel.gameObject, flexibleWidth: 9999, minHeight: 25); UIFactory.SetLayoutElement(nameLabel.gameObject, flexibleWidth: 9999, minHeight: 25);
var indexLabel = UIFactory.CreateLabel(labelsRow, "IndexLabel", "Sibling Index", TextAnchor.MiddleLeft, fontSize: 12, color: Color.grey); Text indexLabel = UIFactory.CreateLabel(labelsRow, "IndexLabel", "Sibling Index", TextAnchor.MiddleLeft, fontSize: 12, color: Color.grey);
UIFactory.SetLayoutElement(indexLabel.gameObject, minWidth: 100, flexibleWidth: 0, minHeight: 25); UIFactory.SetLayoutElement(indexLabel.gameObject, minWidth: 100, flexibleWidth: 0, minHeight: 25);
// Transform Tree // Transform Tree
var scrollPool = UIFactory.CreateScrollPool<TransformCell>(uiRoot, "TransformTree", out GameObject scrollObj, UniverseLib.UI.Widgets.ScrollView.ScrollPool<TransformCell> scrollPool = UIFactory.CreateScrollPool<TransformCell>(uiRoot, "TransformTree", out GameObject scrollObj,
out GameObject scrollContent, new Color(0.11f, 0.11f, 0.11f)); out GameObject scrollContent, new Color(0.11f, 0.11f, 0.11f));
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999); UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
UIFactory.SetLayoutElement(scrollContent, flexibleHeight: 9999); UIFactory.SetLayoutElement(scrollContent, flexibleHeight: 9999);
Tree = new TransformTree(scrollPool, GetRootEntries); Tree = new TransformTree(scrollPool, GetRootEntries, OnCellClicked);
Tree.Init();
Tree.RefreshData(true, true, true, false); Tree.RefreshData(true, true, true, false);
//scrollPool.Viewport.GetComponent<Mask>().enabled = false; //scrollPool.Viewport.GetComponent<Mask>().enabled = false;
//UIRoot.GetComponent<Mask>().enabled = false; //UIRoot.GetComponent<Mask>().enabled = false;
@ -274,6 +272,8 @@ namespace UnityExplorer.ObjectExplorer
RuntimeHelper.StartCoroutine(TempFixCoro()); RuntimeHelper.StartCoroutine(TempFixCoro());
} }
void OnCellClicked(GameObject obj) => InspectorManager.Inspect(obj);
// To "fix" a strange FPS drop issue with MelonLoader. // To "fix" a strange FPS drop issue with MelonLoader.
private IEnumerator TempFixCoro() private IEnumerator TempFixCoro()
{ {
@ -294,7 +294,7 @@ namespace UnityExplorer.ObjectExplorer
allSceneDropdown.options.Clear(); allSceneDropdown.options.Clear();
allSceneDropdown.options.Add(new Dropdown.OptionData(DEFAULT_LOAD_TEXT)); allSceneDropdown.options.Add(new Dropdown.OptionData(DEFAULT_LOAD_TEXT));
foreach (var scene in SceneHandler.AllSceneNames) foreach (string scene in SceneHandler.AllSceneNames)
{ {
if (string.IsNullOrEmpty(filter) || scene.ContainsIgnoreCase(filter)) if (string.IsNullOrEmpty(filter) || scene.ContainsIgnoreCase(filter))
allSceneDropdown.options.Add(new Dropdown.OptionData(Path.GetFileNameWithoutExtension(scene))); allSceneDropdown.options.Add(new Dropdown.OptionData(Path.GetFileNameWithoutExtension(scene)));
@ -308,7 +308,7 @@ namespace UnityExplorer.ObjectExplorer
private void RefreshSceneLoaderButtons() private void RefreshSceneLoaderButtons()
{ {
var text = allSceneDropdown.captionText.text; string text = allSceneDropdown.captionText.text;
if (text == DEFAULT_LOAD_TEXT) if (text == DEFAULT_LOAD_TEXT)
{ {
loadButton.Component.interactable = false; loadButton.Component.interactable = false;
@ -328,30 +328,30 @@ namespace UnityExplorer.ObjectExplorer
{ {
if (SceneHandler.WasAbleToGetScenesInBuild) if (SceneHandler.WasAbleToGetScenesInBuild)
{ {
var sceneLoaderObj = UIFactory.CreateVerticalGroup(uiRoot, "SceneLoader", true, true, true, true); GameObject sceneLoaderObj = UIFactory.CreateVerticalGroup(uiRoot, "SceneLoader", true, true, true, true);
UIFactory.SetLayoutElement(sceneLoaderObj, minHeight: 25); UIFactory.SetLayoutElement(sceneLoaderObj, minHeight: 25);
// Title // Title
var loaderTitle = UIFactory.CreateLabel(sceneLoaderObj, "SceneLoaderLabel", "Scene Loader", TextAnchor.MiddleLeft, Color.white, true, 14); Text loaderTitle = UIFactory.CreateLabel(sceneLoaderObj, "SceneLoaderLabel", "Scene Loader", TextAnchor.MiddleLeft, Color.white, true, 14);
UIFactory.SetLayoutElement(loaderTitle.gameObject, minHeight: 25, flexibleHeight: 0); UIFactory.SetLayoutElement(loaderTitle.gameObject, minHeight: 25, flexibleHeight: 0);
// Search filter // Search filter
var searchFilterObj = UIFactory.CreateInputField(sceneLoaderObj, "SearchFilterInput", "Filter scene names..."); InputFieldRef searchFilterObj = UIFactory.CreateInputField(sceneLoaderObj, "SearchFilterInput", "Filter scene names...");
UIFactory.SetLayoutElement(searchFilterObj.UIRoot, minHeight: 25, flexibleHeight: 0); UIFactory.SetLayoutElement(searchFilterObj.UIRoot, minHeight: 25, flexibleHeight: 0);
searchFilterObj.OnValueChanged += RefreshSceneLoaderOptions; searchFilterObj.OnValueChanged += RefreshSceneLoaderOptions;
// Dropdown // Dropdown
var allSceneDropObj = UIFactory.CreateDropdown(sceneLoaderObj, "SceneLoaderDropdown", out allSceneDropdown, "", 14, null); GameObject allSceneDropObj = UIFactory.CreateDropdown(sceneLoaderObj, "SceneLoaderDropdown", out allSceneDropdown, "", 14, null);
UIFactory.SetLayoutElement(allSceneDropObj, minHeight: 25, minWidth: 150, flexibleWidth: 0, flexibleHeight: 0); UIFactory.SetLayoutElement(allSceneDropObj, minHeight: 25, minWidth: 150, flexibleWidth: 0, flexibleHeight: 0);
RefreshSceneLoaderOptions(string.Empty); RefreshSceneLoaderOptions(string.Empty);
// Button row // Button row
var buttonRow = UIFactory.CreateHorizontalGroup(sceneLoaderObj, "LoadButtons", true, true, true, true, 4); GameObject buttonRow = UIFactory.CreateHorizontalGroup(sceneLoaderObj, "LoadButtons", true, true, true, true, 4);
loadButton = UIFactory.CreateButton(buttonRow, "LoadSceneButton", "Load (Single)", new Color(0.1f, 0.3f, 0.3f)); loadButton = UIFactory.CreateButton(buttonRow, "LoadSceneButton", "Load (Single)", new Color(0.1f, 0.3f, 0.3f));
UIFactory.SetLayoutElement(loadButton.Component.gameObject, minHeight: 25, minWidth: 150); UIFactory.SetLayoutElement(loadButton.Component.gameObject, minHeight: 25, minWidth: 150);
@ -367,7 +367,7 @@ namespace UnityExplorer.ObjectExplorer
TryLoadScene(LoadSceneMode.Additive, allSceneDropdown); TryLoadScene(LoadSceneMode.Additive, allSceneDropdown);
}; };
var disabledColor = new Color(0.24f, 0.24f, 0.24f); Color disabledColor = new(0.24f, 0.24f, 0.24f);
RuntimeHelper.SetColorBlock(loadButton.Component, disabled: disabledColor); RuntimeHelper.SetColorBlock(loadButton.Component, disabled: disabledColor);
RuntimeHelper.SetColorBlock(loadAdditiveButton.Component, disabled: disabledColor); RuntimeHelper.SetColorBlock(loadAdditiveButton.Component, disabled: disabledColor);

View File

@ -1,8 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.SceneManagement; using UnityEngine.SceneManagement;
using UniverseLib; using UniverseLib;
@ -65,11 +63,11 @@ namespace UnityExplorer.ObjectExplorer
if (sceneUtil == null) if (sceneUtil == null)
throw new Exception("This version of Unity does not ship with the 'SceneUtility' class, or it was not unstripped."); throw new Exception("This version of Unity does not ship with the 'SceneUtility' class, or it was not unstripped.");
var method = sceneUtil.GetMethod("GetScenePathByBuildIndex", ReflectionUtility.FLAGS); System.Reflection.MethodInfo method = sceneUtil.GetMethod("GetScenePathByBuildIndex", ReflectionUtility.FLAGS);
int sceneCount = SceneManager.sceneCountInBuildSettings; int sceneCount = SceneManager.sceneCountInBuildSettings;
for (int i = 0; i < sceneCount; i++) for (int i = 0; i < sceneCount; i++)
{ {
var scenePath = (string)method.Invoke(null, new object[] { i }); string scenePath = (string)method.Invoke(null, new object[] { i });
AllSceneNames.Add(scenePath); AllSceneNames.Add(scenePath);
} }
@ -85,9 +83,9 @@ namespace UnityExplorer.ObjectExplorer
internal static void Update() internal static void Update()
{ {
// Inspected scene will exist if it's DontDestroyOnLoad or HideAndDontSave // Inspected scene will exist if it's DontDestroyOnLoad or HideAndDontSave
bool inspectedExists = bool inspectedExists =
SelectedScene.HasValue SelectedScene.HasValue
&& ((DontDestroyExists && SelectedScene.Value.handle == -12) && ((DontDestroyExists && SelectedScene.Value.handle == -12)
|| SelectedScene.Value.handle == -1); || SelectedScene.Value.handle == -1);
LoadedScenes.Clear(); LoadedScenes.Clear();
@ -121,11 +119,11 @@ namespace UnityExplorer.ObjectExplorer
CurrentRootObjects = RuntimeHelper.GetRootGameObjects((Scene)SelectedScene); CurrentRootObjects = RuntimeHelper.GetRootGameObjects((Scene)SelectedScene);
else else
{ {
var allObjects = RuntimeHelper.FindObjectsOfTypeAll(typeof(GameObject)); UnityEngine.Object[] allObjects = RuntimeHelper.FindObjectsOfTypeAll(typeof(GameObject));
var objects = new List<GameObject>(); List<GameObject> objects = new();
foreach (var obj in allObjects) foreach (UnityEngine.Object obj in allObjects)
{ {
var go = obj.TryCast<GameObject>(); GameObject go = obj.TryCast<GameObject>();
if (go.transform.parent == null && !go.scene.IsValid()) if (go.transform.parent == null && !go.scene.IsValid())
objects.Add(go); objects.Add(go);
} }

View File

@ -2,12 +2,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.SceneManagement; using UnityEngine.SceneManagement;
using UnityExplorer.Runtime;
using UniverseLib; using UniverseLib;
using UniverseLib.Input;
using UniverseLib.Utility; using UniverseLib.Utility;
namespace UnityExplorer.ObjectExplorer namespace UnityExplorer.ObjectExplorer
@ -50,7 +47,7 @@ namespace UnityExplorer.ObjectExplorer
internal static List<object> UnityObjectSearch(string input, string customTypeInput, ChildFilter childFilter, SceneFilter sceneFilter) internal static List<object> UnityObjectSearch(string input, string customTypeInput, ChildFilter childFilter, SceneFilter sceneFilter)
{ {
var results = new List<object>(); List<object> results = new();
Type searchType = null; Type searchType = null;
if (!string.IsNullOrEmpty(customTypeInput)) if (!string.IsNullOrEmpty(customTypeInput))
@ -69,7 +66,7 @@ namespace UnityExplorer.ObjectExplorer
if (searchType == null) if (searchType == null)
searchType = typeof(UnityEngine.Object); searchType = typeof(UnityEngine.Object);
var allObjects = RuntimeHelper.FindObjectsOfTypeAll(searchType); UnityEngine.Object[] allObjects = RuntimeHelper.FindObjectsOfTypeAll(searchType);
// perform filter comparers // perform filter comparers
@ -79,14 +76,14 @@ namespace UnityExplorer.ObjectExplorer
bool shouldFilterGOs = searchType == typeof(GameObject) || typeof(Component).IsAssignableFrom(searchType); bool shouldFilterGOs = searchType == typeof(GameObject) || typeof(Component).IsAssignableFrom(searchType);
foreach (var obj in allObjects) foreach (UnityEngine.Object obj in allObjects)
{ {
// name check // name check
if (!string.IsNullOrEmpty(nameFilter) && !obj.name.ContainsIgnoreCase(nameFilter)) if (!string.IsNullOrEmpty(nameFilter) && !obj.name.ContainsIgnoreCase(nameFilter))
continue; continue;
GameObject go = null; GameObject go = null;
var type = obj.GetActualType(); Type type = obj.GetActualType();
if (type == typeof(GameObject)) if (type == typeof(GameObject))
go = obj.TryCast<GameObject>(); go = obj.TryCast<GameObject>();
@ -130,15 +127,15 @@ namespace UnityExplorer.ObjectExplorer
internal static List<object> ClassSearch(string input) internal static List<object> ClassSearch(string input)
{ {
var list = new List<object>(); List<object> list = new();
var nameFilter = ""; string nameFilter = "";
if (!string.IsNullOrEmpty(input)) if (!string.IsNullOrEmpty(input))
nameFilter = input; nameFilter = input;
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
{ {
foreach (var type in asm.TryGetTypes()) foreach (Type type in asm.GetTypes())
{ {
if (!string.IsNullOrEmpty(nameFilter) && !type.FullName.ContainsIgnoreCase(nameFilter)) if (!string.IsNullOrEmpty(nameFilter) && !type.FullName.ContainsIgnoreCase(nameFilter))
continue; continue;
@ -165,30 +162,30 @@ namespace UnityExplorer.ObjectExplorer
internal static List<object> InstanceSearch(string input) internal static List<object> InstanceSearch(string input)
{ {
var instances = new List<object>(); List<object> instances = new();
var nameFilter = ""; string nameFilter = "";
if (!string.IsNullOrEmpty(input)) if (!string.IsNullOrEmpty(input))
nameFilter = input; nameFilter = input;
var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static; BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
{ {
// Search all non-static, non-enum classes. // Search all non-static, non-enum classes.
foreach (var type in asm.TryGetTypes().Where(it => !(it.IsSealed && it.IsAbstract) && !it.IsEnum)) foreach (Type type in asm.GetTypes().Where(it => !(it.IsSealed && it.IsAbstract) && !it.IsEnum))
{ {
try try
{ {
if (!string.IsNullOrEmpty(nameFilter) && !type.FullName.ContainsIgnoreCase(nameFilter)) if (!string.IsNullOrEmpty(nameFilter) && !type.FullName.ContainsIgnoreCase(nameFilter))
continue; continue;
ReflectionUtility.FindSingleton(instanceNames, type, flags, instances); ReflectionUtility.FindSingleton(instanceNames, type, flags, instances);
} }
catch { } catch { }
} }
} }
return instances; return instances;
} }

View File

@ -1,13 +1,7 @@
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using UnityExplorer.Config; using UnityExplorer.Config;
using UniverseLib; using UniverseLib;
@ -20,7 +14,7 @@ namespace UnityExplorer.Runtime
public static UERuntimeHelper Instance; public static UERuntimeHelper Instance;
public static void Init() public static void Init()
{ {
#if CPP #if CPP
Instance = new Il2CppHelper(); Instance = new Il2CppHelper();
#else #else
@ -50,10 +44,10 @@ namespace UnityExplorer.Runtime
try try
{ {
var sigs = blacklist.Split(';'); string[] sigs = blacklist.Split(';');
foreach (var sig in sigs) foreach (string sig in sigs)
{ {
var s = sig.Trim(); string s = sig.Trim();
if (string.IsNullOrEmpty(s)) if (string.IsNullOrEmpty(s))
continue; continue;
if (!currentBlacklist.Contains(s)) if (!currentBlacklist.Contains(s))
@ -65,7 +59,7 @@ namespace UnityExplorer.Runtime
ExplorerCore.LogWarning($"Exception parsing blacklist string: {ex.ReflectionExToString()}"); ExplorerCore.LogWarning($"Exception parsing blacklist string: {ex.ReflectionExToString()}");
} }
foreach (var sig in Instance.DefaultReflectionBlacklist) foreach (string sig in Instance.DefaultReflectionBlacklist)
{ {
if (!currentBlacklist.Contains(sig)) if (!currentBlacklist.Contains(sig))
currentBlacklist.Add(sig); currentBlacklist.Add(sig);
@ -84,7 +78,7 @@ namespace UnityExplorer.Runtime
if (string.IsNullOrEmpty(member.DeclaringType?.Namespace)) if (string.IsNullOrEmpty(member.DeclaringType?.Namespace))
return false; return false;
var sig = $"{member.DeclaringType.FullName}.{member.Name}"; string sig = $"{member.DeclaringType.FullName}.{member.Name}";
return currentBlacklist.Contains(sig); return currentBlacklist.Contains(sig);
} }

View File

@ -2,15 +2,13 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityExplorer.CacheObject;
namespace UnityExplorer.Runtime namespace UnityExplorer.Runtime
{ {
internal static class UnityCrashPrevention internal static class UnityCrashPrevention
{ {
static readonly HarmonyLib.Harmony harmony = new ($"{ExplorerCore.GUID}.crashprevention"); static readonly HarmonyLib.Harmony harmony = new($"{ExplorerCore.GUID}.crashprevention");
internal static void Init() internal static void Init()
{ {
@ -27,7 +25,7 @@ namespace UnityExplorer.Runtime
try try
{ {
harmony.Patch( harmony.Patch(
HarmonyLib.AccessTools.Method(typeof(T), orig, argTypes), HarmonyLib.AccessTools.Method(typeof(T), orig, argTypes),
new HarmonyLib.HarmonyMethod(HarmonyLib.AccessTools.Method(typeof(UnityCrashPrevention), prefix))); new HarmonyLib.HarmonyMethod(HarmonyLib.AccessTools.Method(typeof(UnityCrashPrevention), prefix)));
} }
catch //(Exception ex) catch //(Exception ex)

View File

@ -1,12 +1,8 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityExplorer.UI;
using UnityExplorer.CacheObject.IValues;
#if CPP #if CPP
using UnhollowerRuntimeLib; using UnhollowerRuntimeLib;
using UnhollowerBaseLib; using UnhollowerBaseLib;
@ -74,7 +70,7 @@ namespace UnityExplorer.Tests
{ {
get get
{ {
var list = new List<object>(); List<object> list = new();
int count = UnityEngine.Random.Range(0, 100); int count = UnityEngine.Random.Range(0, 100);
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
list.Add(GetRandomObject()); list.Add(GetRandomObject());
@ -178,6 +174,7 @@ namespace UnityExplorer.Tests
public static Il2CppSystem.Collections.IDictionary IL2CPP_IDict; public static Il2CppSystem.Collections.IDictionary IL2CPP_IDict;
public static Il2CppSystem.Collections.IList IL2CPP_IList; public static Il2CppSystem.Collections.IList IL2CPP_IList;
public static Dictionary<Il2CppSystem.Object, Il2CppSystem.Object> IL2CPP_BoxedDict; public static Dictionary<Il2CppSystem.Object, Il2CppSystem.Object> IL2CPP_BoxedDict;
public static Il2CppSystem.Array IL2CPP_NonGenericArray;
public static Il2CppSystem.Object IL2CPP_BoxedInt; public static Il2CppSystem.Object IL2CPP_BoxedInt;
public static Il2CppSystem.Int32 IL2CPP_Int; public static Il2CppSystem.Int32 IL2CPP_Int;
@ -191,6 +188,9 @@ namespace UnityExplorer.Tests
private static void Init_IL2CPP() private static void Init_IL2CPP()
{ {
ExplorerCore.Log("IL2CPP 0: Non-generic array");
IL2CPP_NonGenericArray = new Il2CppStructArray<int>(5).TryCast<Il2CppSystem.Array>();
ExplorerCore.Log($"IL2CPP 1: Il2Cpp Dictionary<string, string>"); ExplorerCore.Log($"IL2CPP 1: Il2Cpp Dictionary<string, string>");
IL2CPP_Dict = new Il2CppSystem.Collections.Generic.Dictionary<string, string>(); IL2CPP_Dict = new Il2CppSystem.Collections.Generic.Dictionary<string, string>();
IL2CPP_Dict.Add("key1", "value1"); IL2CPP_Dict.Add("key1", "value1");
@ -209,12 +209,12 @@ namespace UnityExplorer.Tests
IL2CPP_HashTable.Add("key3", "value3"); IL2CPP_HashTable.Add("key3", "value3");
ExplorerCore.Log($"IL2CPP 3: Il2Cpp IDictionary"); ExplorerCore.Log($"IL2CPP 3: Il2Cpp IDictionary");
var dict2 = new Il2CppSystem.Collections.Generic.Dictionary<string, string>(); Il2CppSystem.Collections.Generic.Dictionary<string, string> dict2 = new Il2CppSystem.Collections.Generic.Dictionary<string, string>();
dict2.Add("key1", "value1"); dict2.Add("key1", "value1");
IL2CPP_IDict = dict2.TryCast<Il2CppSystem.Collections.IDictionary>(); IL2CPP_IDict = dict2.TryCast<Il2CppSystem.Collections.IDictionary>();
ExplorerCore.Log($"IL2CPP 4: Il2Cpp List of Il2Cpp Object"); ExplorerCore.Log($"IL2CPP 4: Il2Cpp List of Il2Cpp Object");
var list = new Il2CppSystem.Collections.Generic.List<Il2CppSystem.Object>(5); Il2CppSystem.Collections.Generic.List<Il2CppSystem.Object> list = new Il2CppSystem.Collections.Generic.List<Il2CppSystem.Object>(5);
list.Add("one"); list.Add("one");
list.Add("two"); list.Add("two");
IL2CPP_IList = list.TryCast<Il2CppSystem.Collections.IList>(); IL2CPP_IList = list.TryCast<Il2CppSystem.Collections.IList>();
@ -240,14 +240,14 @@ namespace UnityExplorer.Tests
// boxed enum test // boxed enum test
try try
{ {
var cppType = Il2CppType.Of<CameraClearFlags>(); Il2CppSystem.Type cppType = Il2CppType.Of<CameraClearFlags>();
if (cppType != null) if (cppType is not null)
{ {
var boxedEnum = Il2CppSystem.Enum.Parse(cppType, "Color"); Il2CppSystem.Object boxedEnum = Il2CppSystem.Enum.Parse(cppType, "Color");
IL2CPP_listOfBoxedObjects.Add(boxedEnum); IL2CPP_listOfBoxedObjects.Add(boxedEnum);
} }
var structBox = Vector3.one.BoxIl2CppObject(); Il2CppSystem.Object structBox = Vector3.one.BoxIl2CppObject();
IL2CPP_listOfBoxedObjects.Add(structBox); IL2CPP_listOfBoxedObjects.Add(structBox);
} }

View File

@ -1,8 +1,4 @@
using System; using System.Collections;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityExplorer.Config; using UnityExplorer.Config;
using UniverseLib; using UniverseLib;
@ -45,7 +41,7 @@ namespace UnityExplorer.UI
ConfigManager.Target_Display.Value = 0; ConfigManager.Target_Display.Value = 0;
return; return;
} }
ActiveDisplayIndex = display; ActiveDisplayIndex = display;
ActiveDisplay.Activate(); ActiveDisplay.Activate();
@ -72,7 +68,7 @@ namespace UnityExplorer.UI
yield return null; yield return null;
yield return null; yield return null;
foreach (var panel in UIManager.UIPanels.Values) foreach (Panels.UEPanel panel in UIManager.UIPanels.Values)
{ {
panel.EnsureValidSize(); panel.EnsureValidSize();
panel.EnsureValidPosition(); panel.EnsureValidPosition();

19
src/UI/ExplorerUIBase.cs Normal file
View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UniverseLib.UI;
using UniverseLib.UI.Panels;
namespace UnityExplorer.UI
{
internal class ExplorerUIBase : UIBase
{
public ExplorerUIBase(string id, Action updateMethod) : base(id, updateMethod) { }
protected override PanelManager CreatePanelManager()
{
return new UEPanelManager(this);
}
}
}

View File

@ -1,10 +1,5 @@
using System; using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UniverseLib.Input;
using UniverseLib.UI; using UniverseLib.UI;
namespace UnityExplorer.UI namespace UnityExplorer.UI
@ -48,7 +43,7 @@ namespace UnityExplorer.UI
popupLabel = UIFactory.CreateLabel(UIManager.UIRoot, "ClipboardNotification", "", TextAnchor.MiddleCenter); popupLabel = UIFactory.CreateLabel(UIManager.UIRoot, "ClipboardNotification", "", TextAnchor.MiddleCenter);
popupLabel.rectTransform.sizeDelta = new(500, 100); popupLabel.rectTransform.sizeDelta = new(500, 100);
popupLabel.gameObject.AddComponent<Outline>(); popupLabel.gameObject.AddComponent<Outline>();
var popupGroup = popupLabel.gameObject.AddComponent<CanvasGroup>(); CanvasGroup popupGroup = popupLabel.gameObject.AddComponent<CanvasGroup>();
popupGroup.blocksRaycasts = false; popupGroup.blocksRaycasts = false;
} }
} }

View File

@ -2,34 +2,36 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using UnityEngine; using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI; using UnityEngine.UI;
using UniverseLib.Input;
using UnityExplorer.Runtime;
using UnityExplorer.UI;
using UnityExplorer.UI.Panels; using UnityExplorer.UI.Panels;
using UniverseLib.UI.Widgets; using UnityExplorer.UI.Widgets.AutoComplete;
using UniverseLib; using UniverseLib;
using UniverseLib.Input;
using UniverseLib.UI; using UniverseLib.UI;
using UniverseLib.UI.Models;
using UniverseLib.UI.Widgets.ButtonList; using UniverseLib.UI.Widgets.ButtonList;
using UniverseLib.UI.Widgets.ScrollView; using UniverseLib.UI.Widgets.ScrollView;
using UniverseLib.Utility; using UniverseLib.Utility;
using UniverseLib.UI.Models;
namespace UnityExplorer.UI.Widgets.AutoComplete namespace UnityExplorer.UI.Panels
{ {
// Shared modal panel for "AutoComplete" suggestions. // Shared modal panel for "AutoComplete" suggestions.
// A data source implements ISuggestionProvider and uses TakeOwnership and ReleaseOwnership // A data source implements ISuggestionProvider and uses TakeOwnership and ReleaseOwnership
// for control, and SetSuggestions to set the actual suggestion data. // for control, and SetSuggestions to set the actual suggestion data.
public class AutoCompleteModal : UIPanel public class AutoCompleteModal : UEPanel
{ {
public static AutoCompleteModal Instance => UIManager.GetPanel<AutoCompleteModal>(UIManager.Panels.AutoCompleter); public static AutoCompleteModal Instance => UIManager.GetPanel<AutoCompleteModal>(UIManager.Panels.AutoCompleter);
public override string Name => "AutoCompleter"; public override string Name => "AutoCompleter";
public override UIManager.Panels PanelType => UIManager.Panels.AutoCompleter; public override UIManager.Panels PanelType => UIManager.Panels.AutoCompleter;
public override int MinWidth => -1;
public override int MinHeight => -1; public override int MinWidth => 100;
public override int MinHeight => 25;
public override Vector2 DefaultAnchorMin => new(MIN_X, 0.4f);
public override Vector2 DefaultAnchorMax => new(0.68f, MAX_Y);
const float MIN_X = 0.42f;
const float MAX_Y = 0.6f;
public override bool CanDragAndResize => true; public override bool CanDragAndResize => true;
public override bool ShouldSaveActiveState => false; public override bool ShouldSaveActiveState => false;
@ -48,10 +50,10 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
public static bool Suggesting(ISuggestionProvider handler) => CurrentHandler == handler && Instance.UIRoot.activeSelf; public static bool Suggesting(ISuggestionProvider handler) => CurrentHandler == handler && Instance.UIRoot.activeSelf;
public AutoCompleteModal() public AutoCompleteModal(UIBase owner) : base(owner)
{ {
OnPanelsReordered += UIPanel_OnPanelsReordered; UIManager.UiBase.Panels.OnPanelsReordered += UIPanel_OnPanelsReordered;
OnClickedOutsidePanels += AutoCompleter_OnClickedOutsidePanels; UIManager.UiBase.Panels.OnClickedOutsidePanels += AutoCompleter_OnClickedOutsidePanels;
} }
public static void TakeOwnership(ISuggestionProvider provider) public static void TakeOwnership(ISuggestionProvider provider)
@ -67,15 +69,22 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
if (CurrentHandler == provider) if (CurrentHandler == provider)
{ {
Suggestions.Clear();
CurrentHandler = null; CurrentHandler = null;
UIRoot.SetActive(false); UIRoot.SetActive(false);
} }
} }
public void SetSuggestions(IEnumerable<Suggestion> suggestions) public void SetSuggestions(List<Suggestion> suggestions, bool jumpToTop = false)
{ {
Suggestions = suggestions as List<Suggestion> ?? suggestions.ToList(); Suggestions = suggestions;
SelectedIndex = 0;
if (jumpToTop)
{
SelectedIndex = 0;
if (scrollPool.DataSource.ItemCount > 0)
scrollPool.JumpToIndex(0, null);
}
if (!Suggestions.Any()) if (!Suggestions.Any())
base.UIRoot.SetActive(false); base.UIRoot.SetActive(false);
@ -84,7 +93,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
base.UIRoot.SetActive(true); base.UIRoot.SetActive(true);
base.UIRoot.transform.SetAsLastSibling(); base.UIRoot.transform.SetAsLastSibling();
buttonListDataHandler.RefreshData(); buttonListDataHandler.RefreshData();
scrollPool.Refresh(true, true); scrollPool.Refresh(true, false);
} }
} }
@ -184,7 +193,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
private void OnCellClicked(int dataIndex) private void OnCellClicked(int dataIndex)
{ {
var suggestion = Suggestions[dataIndex]; Suggestion suggestion = Suggestions[dataIndex];
CurrentHandler.OnSuggestionClicked(suggestion); CurrentHandler.OnSuggestionClicked(suggestion);
} }
@ -192,13 +201,19 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
private void SetCell(ButtonCell cell, int index) private void SetCell(ButtonCell cell, int index)
{ {
if (CurrentHandler == null)
{
UIRoot.SetActive(false);
return;
}
if (index < 0 || index >= Suggestions.Count) if (index < 0 || index >= Suggestions.Count)
{ {
cell.Disable(); cell.Disable();
return; return;
} }
var suggestion = Suggestions[index]; Suggestion suggestion = Suggestions[index];
cell.Button.ButtonText.text = suggestion.DisplayText; cell.Button.ButtonText.text = suggestion.DisplayText;
if (CurrentHandler.AllowNavigation && index == SelectedIndex && setFirstCell) if (CurrentHandler.AllowNavigation && index == SelectedIndex && setFirstCell)
@ -230,7 +245,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
if (CurrentHandler.AnchorToCaretPosition) if (CurrentHandler.AnchorToCaretPosition)
{ {
var textGen = input.Component.cachedInputTextGenerator; TextGenerator textGen = input.Component.cachedInputTextGenerator;
int caretIdx = Math.Max(0, Math.Min(textGen.characterCount - 1, input.Component.caretPosition)); int caretIdx = Math.Max(0, Math.Min(textGen.characterCount - 1, input.Component.caretPosition));
// normalize the caret horizontal position // normalize the caret horizontal position
@ -267,7 +282,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
if (!this.UIRoot || !this.UIRoot.activeInHierarchy) if (!this.UIRoot || !this.UIRoot.activeInHierarchy)
return; return;
if (this.UIRoot.transform.GetSiblingIndex() != UIManager.PanelHolder.transform.childCount - 1) if (this.UIRoot.transform.GetSiblingIndex() != UIManager.UiBase.Panels.PanelHolder.transform.childCount - 1)
{ {
if (CurrentHandler != null) if (CurrentHandler != null)
ReleaseOwnership(CurrentHandler); ReleaseOwnership(CurrentHandler);
@ -276,46 +291,36 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
} }
} }
// UI Construction public override void OnFinishResize()
const float MIN_X = 0.42f;
const float MAX_Y = 0.6f;
protected internal override void DoSetDefaultPosAndAnchors()
{ {
Rect.pivot = new Vector2(0f, 1f); float xDiff = Rect.anchorMin.x - MIN_X;
Rect.anchorMin = new Vector2(MIN_X, 0.4f); float yDiff = Rect.anchorMax.y - MAX_Y;
Rect.anchorMax = new Vector2(0.68f, MAX_Y);
}
public override void OnFinishResize(RectTransform panel)
{
float xDiff = panel.anchorMin.x - MIN_X;
float yDiff = panel.anchorMax.y - MAX_Y;
if (xDiff != 0 || yDiff != 0) if (xDiff != 0 || yDiff != 0)
{ {
panel.anchorMin = new(MIN_X, panel.anchorMin.y - yDiff); Rect.anchorMin = new(MIN_X, Rect.anchorMin.y - yDiff);
panel.anchorMax = new(panel.anchorMax.x - xDiff, MAX_Y); Rect.anchorMax = new(Rect.anchorMax.x - xDiff, MAX_Y);
} }
base.OnFinishResize(panel); base.OnFinishResize();
} }
public override void ConstructPanelContent() // UI Construction
protected override void ConstructPanelContent()
{ {
// hide the titlebar // hide the titlebar
this.TitleBar.gameObject.SetActive(false); this.TitleBar.gameObject.SetActive(false);
buttonListDataHandler = new ButtonListHandler<Suggestion, ButtonCell>(scrollPool, GetEntries, SetCell, ShouldDisplay, OnCellClicked); buttonListDataHandler = new ButtonListHandler<Suggestion, ButtonCell>(scrollPool, GetEntries, SetCell, ShouldDisplay, OnCellClicked);
scrollPool = UIFactory.CreateScrollPool<ButtonCell>(this.uiContent, "AutoCompleter", out GameObject scrollObj, scrollPool = UIFactory.CreateScrollPool<ButtonCell>(this.ContentRoot, "AutoCompleter", out GameObject scrollObj,
out GameObject scrollContent); out GameObject scrollContent);
scrollPool.Initialize(buttonListDataHandler); scrollPool.Initialize(buttonListDataHandler);
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999); UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(scrollContent, true, false, true, false); UIFactory.SetLayoutGroup<VerticalLayoutGroup>(scrollContent, true, false, true, false);
navigationTipRow = UIFactory.CreateHorizontalGroup(this.uiContent, "BottomRow", true, true, true, true, 0, new Vector4(2, 2, 2, 2)); navigationTipRow = UIFactory.CreateHorizontalGroup(this.ContentRoot, "BottomRow", true, true, true, true, 0, new Vector4(2, 2, 2, 2));
UIFactory.SetLayoutElement(navigationTipRow, minHeight: 20, flexibleWidth: 9999); UIFactory.SetLayoutElement(navigationTipRow, minHeight: 20, flexibleWidth: 9999);
UIFactory.CreateLabel(navigationTipRow, "HelpText", "Up/Down to select, Enter to use, Esc to close", UIFactory.CreateLabel(navigationTipRow, "HelpText", "Up/Down to select, Enter to use, Esc to close",
TextAnchor.MiddleLeft, Color.grey, false, 13); TextAnchor.MiddleLeft, Color.grey, false, 13);

View File

@ -1,14 +1,8 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.Config;
using UnityExplorer.CSConsole; using UnityExplorer.CSConsole;
using UnityExplorer.UI.Widgets;
using UniverseLib; using UniverseLib;
using UniverseLib.UI; using UniverseLib.UI;
using UniverseLib.UI.Models; using UniverseLib.UI.Models;
@ -16,12 +10,15 @@ using UniverseLib.UI.Widgets;
namespace UnityExplorer.UI.Panels namespace UnityExplorer.UI.Panels
{ {
public class CSConsolePanel : UIPanel public class CSConsolePanel : UEPanel
{ {
public override string Name => "C# Console"; public override string Name => "C# Console";
public override UIManager.Panels PanelType => UIManager.Panels.CSConsole; public override UIManager.Panels PanelType => UIManager.Panels.CSConsole;
public override int MinWidth => 750; public override int MinWidth => 750;
public override int MinHeight => 300; public override int MinHeight => 300;
public override Vector2 DefaultAnchorMin => new(0.4f, 0.175f);
public override Vector2 DefaultAnchorMax => new(0.85f, 0.925f);
public InputFieldScroller InputScroller { get; private set; } public InputFieldScroller InputScroller { get; private set; }
public InputFieldRef Input => InputScroller.InputField; public InputFieldRef Input => InputScroller.InputField;
@ -41,6 +38,10 @@ namespace UnityExplorer.UI.Panels
public Action<bool> OnAutoIndentToggled; public Action<bool> OnAutoIndentToggled;
public Action OnPanelResized; public Action OnPanelResized;
public CSConsolePanel(UIBase owner) : base(owner)
{
}
private void InvokeOnValueChanged(string value) private void InvokeOnValueChanged(string value)
{ {
if (value.Length == UniversalUI.MAX_INPUTFIELD_CHARS) if (value.Length == UniversalUI.MAX_INPUTFIELD_CHARS)
@ -58,49 +59,41 @@ namespace UnityExplorer.UI.Panels
// UI Construction // UI Construction
public override void OnFinishResize(RectTransform panel) public override void OnFinishResize()
{ {
OnPanelResized?.Invoke(); OnPanelResized?.Invoke();
} }
protected internal override void DoSetDefaultPosAndAnchors() protected override void ConstructPanelContent()
{
Rect.localPosition = Vector2.zero;
Rect.pivot = new Vector2(0f, 1f);
Rect.anchorMin = new Vector2(0.4f, 0.175f);
Rect.anchorMax = new Vector2(0.85f, 0.925f);
}
public override void ConstructPanelContent()
{ {
// Tools Row // Tools Row
var toolsRow = UIFactory.CreateHorizontalGroup(this.uiContent, "ToggleRow", false, false, true, true, 5, new Vector4(8, 8, 10, 5), GameObject toolsRow = UIFactory.CreateHorizontalGroup(this.ContentRoot, "ToggleRow", false, false, true, true, 5, new Vector4(8, 8, 10, 5),
default, TextAnchor.MiddleLeft); default, TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(toolsRow, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999); UIFactory.SetLayoutElement(toolsRow, minHeight: 25, flexibleHeight: 0, flexibleWidth: 9999);
// Buttons // Buttons
var compileButton = UIFactory.CreateButton(toolsRow, "CompileButton", "Compile", new Color(0.33f, 0.5f, 0.33f)); ButtonRef compileButton = UIFactory.CreateButton(toolsRow, "CompileButton", "Compile", new Color(0.33f, 0.5f, 0.33f));
UIFactory.SetLayoutElement(compileButton.Component.gameObject, minHeight: 28, minWidth: 130, flexibleHeight: 0); UIFactory.SetLayoutElement(compileButton.Component.gameObject, minHeight: 28, minWidth: 130, flexibleHeight: 0);
compileButton.ButtonText.fontSize = 15; compileButton.ButtonText.fontSize = 15;
compileButton.OnClick += () => { OnCompileClicked?.Invoke(); }; compileButton.OnClick += () => { OnCompileClicked?.Invoke(); };
var resetButton = UIFactory.CreateButton(toolsRow, "ResetButton", "Reset", new Color(0.33f, 0.33f, 0.33f)); ButtonRef resetButton = UIFactory.CreateButton(toolsRow, "ResetButton", "Reset", new Color(0.33f, 0.33f, 0.33f));
UIFactory.SetLayoutElement(resetButton.Component.gameObject, minHeight: 28, minWidth: 80, flexibleHeight: 0); UIFactory.SetLayoutElement(resetButton.Component.gameObject, minHeight: 28, minWidth: 80, flexibleHeight: 0);
resetButton.ButtonText.fontSize = 15; resetButton.ButtonText.fontSize = 15;
resetButton.OnClick += () => { OnResetClicked?.Invoke(); }; resetButton.OnClick += () => { OnResetClicked?.Invoke(); };
// Help dropdown // Help dropdown
var helpDrop = UIFactory.CreateDropdown(toolsRow, "HelpDropdown", out var dropdown, "Help", 14, null); GameObject helpDrop = UIFactory.CreateDropdown(toolsRow, "HelpDropdown", out Dropdown dropdown, "Help", 14, null);
UIFactory.SetLayoutElement(helpDrop, minHeight: 25, minWidth: 100); UIFactory.SetLayoutElement(helpDrop, minHeight: 25, minWidth: 100);
HelpDropdown = dropdown; HelpDropdown = dropdown;
HelpDropdown.onValueChanged.AddListener((int val) => { this.OnHelpDropdownChanged?.Invoke(val); }); HelpDropdown.onValueChanged.AddListener((int val) => { this.OnHelpDropdownChanged?.Invoke(val); });
// Enable Ctrl+R toggle // Enable Ctrl+R toggle
var ctrlRToggleObj = UIFactory.CreateToggle(toolsRow, "CtrlRToggle", out var CtrlRToggle, out Text ctrlRToggleText); GameObject ctrlRToggleObj = UIFactory.CreateToggle(toolsRow, "CtrlRToggle", out Toggle CtrlRToggle, out Text ctrlRToggleText);
UIFactory.SetLayoutElement(ctrlRToggleObj, minWidth: 150, flexibleWidth: 0, minHeight: 25); UIFactory.SetLayoutElement(ctrlRToggleObj, minWidth: 150, flexibleWidth: 0, minHeight: 25);
ctrlRToggleText.alignment = TextAnchor.UpperLeft; ctrlRToggleText.alignment = TextAnchor.UpperLeft;
ctrlRToggleText.text = "Compile on Ctrl+R"; ctrlRToggleText.text = "Compile on Ctrl+R";
@ -108,7 +101,7 @@ namespace UnityExplorer.UI.Panels
// Enable Suggestions toggle // Enable Suggestions toggle
var suggestToggleObj = UIFactory.CreateToggle(toolsRow, "SuggestionToggle", out var SuggestionsToggle, out Text suggestToggleText); GameObject suggestToggleObj = UIFactory.CreateToggle(toolsRow, "SuggestionToggle", out Toggle SuggestionsToggle, out Text suggestToggleText);
UIFactory.SetLayoutElement(suggestToggleObj, minWidth: 120, flexibleWidth: 0, minHeight: 25); UIFactory.SetLayoutElement(suggestToggleObj, minWidth: 120, flexibleWidth: 0, minHeight: 25);
suggestToggleText.alignment = TextAnchor.UpperLeft; suggestToggleText.alignment = TextAnchor.UpperLeft;
suggestToggleText.text = "Suggestions"; suggestToggleText.text = "Suggestions";
@ -116,7 +109,7 @@ namespace UnityExplorer.UI.Panels
// Enable Auto-indent toggle // Enable Auto-indent toggle
var autoIndentToggleObj = UIFactory.CreateToggle(toolsRow, "IndentToggle", out var AutoIndentToggle, out Text autoIndentToggleText); GameObject autoIndentToggleObj = UIFactory.CreateToggle(toolsRow, "IndentToggle", out Toggle AutoIndentToggle, out Text autoIndentToggleText);
UIFactory.SetLayoutElement(autoIndentToggleObj, minWidth: 120, flexibleWidth: 0, minHeight: 25); UIFactory.SetLayoutElement(autoIndentToggleObj, minWidth: 120, flexibleWidth: 0, minHeight: 25);
autoIndentToggleText.alignment = TextAnchor.UpperLeft; autoIndentToggleText.alignment = TextAnchor.UpperLeft;
autoIndentToggleText.text = "Auto-indent"; autoIndentToggleText.text = "Auto-indent";
@ -124,7 +117,7 @@ namespace UnityExplorer.UI.Panels
// Console Input // Console Input
var inputArea = UIFactory.CreateUIObject("InputGroup", uiContent); GameObject inputArea = UIFactory.CreateUIObject("InputGroup", ContentRoot);
UIFactory.SetLayoutElement(inputArea, flexibleWidth: 9999, flexibleHeight: 9999); UIFactory.SetLayoutElement(inputArea, flexibleWidth: 9999, flexibleHeight: 9999);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(inputArea, false, true, true, true); UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(inputArea, false, true, true, true);
inputArea.AddComponent<Image>().color = Color.white; inputArea.AddComponent<Image>().color = Color.white;
@ -132,8 +125,8 @@ namespace UnityExplorer.UI.Panels
// line numbers // line numbers
var linesHolder = UIFactory.CreateUIObject("LinesHolder", inputArea); GameObject linesHolder = UIFactory.CreateUIObject("LinesHolder", inputArea);
var linesRect = linesHolder.GetComponent<RectTransform>(); RectTransform linesRect = linesHolder.GetComponent<RectTransform>();
linesRect.pivot = new Vector2(0, 1); linesRect.pivot = new Vector2(0, 1);
linesRect.anchorMin = new Vector2(0, 0); linesRect.anchorMin = new Vector2(0, 0);
linesRect.anchorMax = new Vector2(0, 1); linesRect.anchorMax = new Vector2(0, 1);
@ -149,8 +142,8 @@ namespace UnityExplorer.UI.Panels
int fontSize = 16; int fontSize = 16;
var inputObj = UIFactory.CreateScrollInputField(inputArea, "ConsoleInput", ConsoleController.STARTUP_TEXT, GameObject inputObj = UIFactory.CreateScrollInputField(inputArea, "ConsoleInput", ConsoleController.STARTUP_TEXT,
out var inputScroller, fontSize); out InputFieldScroller inputScroller, fontSize);
InputScroller = inputScroller; InputScroller = inputScroller;
ConsoleController.defaultInputFieldAlpha = Input.Component.selectionColor.a; ConsoleController.defaultInputFieldAlpha = Input.Component.selectionColor.a;
Input.OnValueChanged += InvokeOnValueChanged; Input.OnValueChanged += InvokeOnValueChanged;
@ -173,8 +166,8 @@ namespace UnityExplorer.UI.Panels
Input.PlaceholderText.fontSize = fontSize; Input.PlaceholderText.fontSize = fontSize;
// Lexer highlight text overlay // Lexer highlight text overlay
var highlightTextObj = UIFactory.CreateUIObject("HighlightText", InputText.gameObject); GameObject highlightTextObj = UIFactory.CreateUIObject("HighlightText", InputText.gameObject);
var highlightTextRect = highlightTextObj.GetComponent<RectTransform>(); RectTransform highlightTextRect = highlightTextObj.GetComponent<RectTransform>();
highlightTextRect.pivot = new Vector2(0, 1); highlightTextRect.pivot = new Vector2(0, 1);
highlightTextRect.anchorMin = Vector2.zero; highlightTextRect.anchorMin = Vector2.zero;
highlightTextRect.anchorMax = Vector2.one; highlightTextRect.anchorMax = Vector2.one;

View File

@ -1,29 +1,24 @@
using System; using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.CacheObject;
using UnityExplorer.CacheObject.Views;
using UnityExplorer.Config;
using UniverseLib; using UniverseLib;
using UniverseLib.Input;
using UniverseLib.UI; using UniverseLib.UI;
using UniverseLib.UI.Widgets;
using UniverseLib.Utility; using UniverseLib.Utility;
namespace UnityExplorer.UI.Panels namespace UnityExplorer.UI.Panels
{ {
public class ClipboardPanel : UIPanel public class ClipboardPanel : UEPanel
{ {
public static object Current { get; private set; } public static object Current { get; private set; }
public override UIManager.Panels PanelType => UIManager.Panels.Clipboard;
public override string Name => "Clipboard"; public override string Name => "Clipboard";
public override UIManager.Panels PanelType => UIManager.Panels.Clipboard;
public override int MinWidth => 500; public override int MinWidth => 500;
public override int MinHeight => 95; public override int MinHeight => 95;
public override Vector2 DefaultAnchorMin => new(0.1f, 0.05f);
public override Vector2 DefaultAnchorMax => new(0.4f, 0.15f);
public override bool CanDragAndResize => true; public override bool CanDragAndResize => true;
public override bool NavButtonWanted => true; public override bool NavButtonWanted => true;
public override bool ShouldSaveActiveState => true; public override bool ShouldSaveActiveState => true;
@ -31,6 +26,10 @@ namespace UnityExplorer.UI.Panels
private static Text CurrentPasteLabel; private static Text CurrentPasteLabel;
public ClipboardPanel(UIBase owner) : base(owner)
{
}
public static void Copy(object obj) public static void Copy(object obj)
{ {
Current = obj; Current = obj;
@ -41,14 +40,14 @@ namespace UnityExplorer.UI.Panels
public static bool TryPaste(Type targetType, out object paste) public static bool TryPaste(Type targetType, out object paste)
{ {
paste = Current; paste = Current;
var pasteType = Current?.GetActualType(); Type pasteType = Current?.GetActualType();
if (Current != null && !targetType.IsAssignableFrom(pasteType)) if (Current != null && !targetType.IsAssignableFrom(pasteType))
{ {
Notification.ShowMessage($"Cannot assign '{pasteType.Name}' to '{targetType.Name}'!"); Notification.ShowMessage($"Cannot assign '{pasteType.Name}' to '{targetType.Name}'!");
return false; return false;
} }
Notification.ShowMessage("Pasted!"); Notification.ShowMessage("Pasted!");
return true; return true;
} }
@ -74,35 +73,35 @@ namespace UnityExplorer.UI.Panels
InspectorManager.Inspect(Current); InspectorManager.Inspect(Current);
} }
protected internal override void DoSetDefaultPosAndAnchors() public override void SetDefaultSizeAndPosition()
{ {
base.SetDefaultSizeAndPosition();
this.Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, MinWidth); this.Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, MinWidth);
this.Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, MinHeight); this.Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, MinHeight);
this.Rect.anchorMin = new Vector2(0.1f, 0.05f);
this.Rect.anchorMax = new Vector2(0.4f, 0.15f);
} }
public override void ConstructPanelContent() protected override void ConstructPanelContent()
{ {
this.UIRoot.GetComponent<Image>().color = new(0.1f, 0.1f, 0.1f); this.UIRoot.GetComponent<Image>().color = new(0.1f, 0.1f, 0.1f);
// Actual panel content // Actual panel content
var firstRow = UIFactory.CreateHorizontalGroup(uiContent, "FirstRow", false, false, true, true, 5, new(2,2,2,2), new(1,1,1,0)); GameObject firstRow = UIFactory.CreateHorizontalGroup(ContentRoot, "FirstRow", false, false, true, true, 5, new(2, 2, 2, 2), new(1, 1, 1, 0));
UIFactory.SetLayoutElement(firstRow, minHeight: 25, flexibleWidth: 999); UIFactory.SetLayoutElement(firstRow, minHeight: 25, flexibleWidth: 999);
// Title for "Current Paste:" // Title for "Current Paste:"
var currentPasteTitle = UIFactory.CreateLabel(firstRow, "CurrentPasteTitle", "Current paste:", TextAnchor.MiddleLeft, color: Color.grey); Text currentPasteTitle = UIFactory.CreateLabel(firstRow, "CurrentPasteTitle", "Current paste:", TextAnchor.MiddleLeft, color: Color.grey);
UIFactory.SetLayoutElement(currentPasteTitle.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 999); UIFactory.SetLayoutElement(currentPasteTitle.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 999);
// Clear clipboard button // Clear clipboard button
var clearButton = UIFactory.CreateButton(firstRow, "ClearPasteButton", "Clear Clipboard"); UniverseLib.UI.Models.ButtonRef clearButton = UIFactory.CreateButton(firstRow, "ClearPasteButton", "Clear Clipboard");
UIFactory.SetLayoutElement(clearButton.Component.gameObject, minWidth: 120, minHeight: 25, flexibleWidth: 0); UIFactory.SetLayoutElement(clearButton.Component.gameObject, minWidth: 120, minHeight: 25, flexibleWidth: 0);
clearButton.OnClick += () => Copy(null); clearButton.OnClick += () => Copy(null);
// Current Paste info row // Current Paste info row
var currentPasteHolder = UIFactory.CreateHorizontalGroup(uiContent, "SecondRow", false, false, true, true, 0, GameObject currentPasteHolder = UIFactory.CreateHorizontalGroup(ContentRoot, "SecondRow", false, false, true, true, 0,
new(2, 2, 2, 2), childAlignment: TextAnchor.UpperCenter); new(2, 2, 2, 2), childAlignment: TextAnchor.UpperCenter);
// Actual current paste info label // Actual current paste info label
@ -111,7 +110,7 @@ namespace UnityExplorer.UI.Panels
UpdateCurrentPasteInfo(); UpdateCurrentPasteInfo();
// Inspect button // Inspect button
var inspectButton = UIFactory.CreateButton(currentPasteHolder, "InspectButton", "Inspect"); UniverseLib.UI.Models.ButtonRef inspectButton = UIFactory.CreateButton(currentPasteHolder, "InspectButton", "Inspect");
UIFactory.SetLayoutElement(inspectButton.Component.gameObject, minHeight: 25, flexibleHeight: 0, minWidth: 80, flexibleWidth: 0); UIFactory.SetLayoutElement(inspectButton.Component.gameObject, minHeight: 25, flexibleHeight: 0, minWidth: 80, flexibleWidth: 0);
inspectButton.OnClick += InspectClipboard; inspectButton.OnClick += InspectClipboard;
} }

View File

@ -0,0 +1,394 @@
using HarmonyLib;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using UniverseLib;
using UniverseLib.Input;
using UniverseLib.UI;
using UniverseLib.UI.Models;
using UniverseLib.Utility;
namespace UnityExplorer.UI.Panels
{
internal class FreeCamPanel : UEPanel
{
public FreeCamPanel(UIBase owner) : base(owner)
{
}
public override string Name => "Freecam";
public override UIManager.Panels PanelType => UIManager.Panels.Freecam;
public override int MinWidth => 400;
public override int MinHeight => 320;
public override Vector2 DefaultAnchorMin => new(0.4f, 0.4f);
public override Vector2 DefaultAnchorMax => new(0.6f, 0.6f);
public override bool NavButtonWanted => true;
public override bool ShouldSaveActiveState => true;
internal static bool inFreeCamMode;
internal static bool usingGameCamera;
internal static Camera ourCamera;
internal static Camera lastMainCamera;
internal static FreeCamBehaviour freeCamScript;
internal static float desiredMoveSpeed = 10f;
internal static Vector3 originalCameraPosition;
internal static Quaternion originalCameraRotation;
internal static Vector3? currentUserCameraPosition;
internal static Quaternion? currentUserCameraRotation;
internal static Vector3 previousMousePosition;
internal static Vector3 lastSetCameraPosition;
static ButtonRef startStopButton;
static Toggle useGameCameraToggle;
static InputFieldRef positionInput;
static InputFieldRef moveSpeedInput;
static ButtonRef inspectButton;
internal static void BeginFreecam()
{
inFreeCamMode = true;
previousMousePosition = InputManager.MousePosition;
CacheMainCamera();
SetupFreeCamera();
inspectButton.GameObject.SetActive(true);
}
static void CacheMainCamera()
{
Camera currentMain = Camera.main;
if (currentMain)
{
lastMainCamera = currentMain;
originalCameraPosition = currentMain.transform.position;
originalCameraRotation = currentMain.transform.rotation;
if (currentUserCameraPosition == null)
{
currentUserCameraPosition = currentMain.transform.position;
currentUserCameraRotation = currentMain.transform.rotation;
}
}
else
originalCameraRotation = Quaternion.identity;
}
static void SetupFreeCamera()
{
if (useGameCameraToggle.isOn)
{
if (!lastMainCamera)
{
ExplorerCore.LogWarning($"There is no previous Camera found, reverting to default Free Cam.");
useGameCameraToggle.isOn = false;
}
else
{
usingGameCamera = true;
ourCamera = lastMainCamera;
}
}
if (!useGameCameraToggle.isOn)
{
usingGameCamera = false;
if (lastMainCamera)
lastMainCamera.enabled = false;
}
if (!ourCamera)
{
ourCamera = new GameObject("UE_Freecam").AddComponent<Camera>();
ourCamera.gameObject.tag = "MainCamera";
GameObject.DontDestroyOnLoad(ourCamera.gameObject);
ourCamera.gameObject.hideFlags = HideFlags.HideAndDontSave;
}
if (!freeCamScript)
freeCamScript = ourCamera.gameObject.AddComponent<FreeCamBehaviour>();
ourCamera.transform.position = (Vector3)currentUserCameraPosition;
ourCamera.transform.rotation = (Quaternion)currentUserCameraRotation;
ourCamera.gameObject.SetActive(true);
ourCamera.enabled = true;
}
internal static void EndFreecam()
{
inFreeCamMode = false;
if (usingGameCamera)
{
ourCamera = null;
if (lastMainCamera)
{
lastMainCamera.transform.position = originalCameraPosition;
lastMainCamera.transform.rotation = originalCameraRotation;
}
}
if (ourCamera)
ourCamera.gameObject.SetActive(false);
else
inspectButton.GameObject.SetActive(false);
if (freeCamScript)
{
GameObject.Destroy(freeCamScript);
freeCamScript = null;
}
if (lastMainCamera)
lastMainCamera.enabled = true;
}
static void SetCameraPosition(Vector3 pos)
{
if (!ourCamera || lastSetCameraPosition == pos)
return;
ourCamera.transform.position = pos;
lastSetCameraPosition = pos;
}
internal static void UpdatePositionInput()
{
if (!ourCamera)
return;
lastSetCameraPosition = ourCamera.transform.position;
positionInput.Text = ParseUtility.ToStringForInput<Vector3>(lastSetCameraPosition);
}
// ~~~~~~~~ UI construction / callbacks ~~~~~~~~
protected override void ConstructPanelContent()
{
startStopButton = UIFactory.CreateButton(ContentRoot, "ToggleButton", "Freecam");
UIFactory.SetLayoutElement(startStopButton.GameObject, minWidth: 150, minHeight: 25, flexibleWidth: 9999);
startStopButton.OnClick += StartStopButton_OnClick;
SetToggleButtonState();
AddSpacer(5);
GameObject toggleObj = UIFactory.CreateToggle(ContentRoot, "UseGameCameraToggle", out useGameCameraToggle, out Text toggleText);
UIFactory.SetLayoutElement(toggleObj, minHeight: 25, flexibleWidth: 9999);
useGameCameraToggle.onValueChanged.AddListener(OnUseGameCameraToggled);
useGameCameraToggle.isOn = false;
toggleText.text = "Use Game Camera?";
AddSpacer(5);
GameObject posRow = AddInputField("Position", "Freecam Pos:", "eg. 0 0 0", out positionInput, PositionInput_OnEndEdit);
ButtonRef resetPosButton = UIFactory.CreateButton(posRow, "ResetButton", "Reset");
UIFactory.SetLayoutElement(resetPosButton.GameObject, minWidth: 70, minHeight: 25);
resetPosButton.OnClick += OnResetPosButtonClicked;
AddSpacer(5);
AddInputField("MoveSpeed", "Move Speed:", "Default: 1", out moveSpeedInput, MoveSpeedInput_OnEndEdit);
moveSpeedInput.Text = desiredMoveSpeed.ToString();
AddSpacer(5);
string instructions = @"Controls:
- WASD / Arrows: Movement
- Space / PgUp: Move up
- LeftCtrl / PgDown: Move down
- Right Mouse Button: Free look
- Shift: Super speed";
Text instructionsText = UIFactory.CreateLabel(ContentRoot, "Instructions", instructions, TextAnchor.UpperLeft);
UIFactory.SetLayoutElement(instructionsText.gameObject, flexibleWidth: 9999, flexibleHeight: 9999);
AddSpacer(5);
inspectButton = UIFactory.CreateButton(ContentRoot, "InspectButton", "Inspect Free Camera");
UIFactory.SetLayoutElement(inspectButton.GameObject, flexibleWidth: 9999, minHeight: 25);
inspectButton.OnClick += () => { InspectorManager.Inspect(ourCamera); };
inspectButton.GameObject.SetActive(false);
AddSpacer(5);
}
void AddSpacer(int height)
{
GameObject obj = UIFactory.CreateUIObject("Spacer", ContentRoot);
UIFactory.SetLayoutElement(obj, minHeight: height, flexibleHeight: 0);
}
GameObject AddInputField(string name, string labelText, string placeHolder, out InputFieldRef inputField, Action<string> onInputEndEdit)
{
GameObject row = UIFactory.CreateHorizontalGroup(ContentRoot, $"{name}_Group", false, false, true, true, 3, default, new(1, 1, 1, 0));
Text posLabel = UIFactory.CreateLabel(row, $"{name}_Label", labelText);
UIFactory.SetLayoutElement(posLabel.gameObject, minWidth: 100, minHeight: 25);
inputField = UIFactory.CreateInputField(row, $"{name}_Input", placeHolder);
UIFactory.SetLayoutElement(inputField.GameObject, minWidth: 125, minHeight: 25, flexibleWidth: 9999);
inputField.Component.GetOnEndEdit().AddListener(onInputEndEdit);
return row;
}
void StartStopButton_OnClick()
{
EventSystemHelper.SetSelectedGameObject(null);
if (inFreeCamMode)
EndFreecam();
else
BeginFreecam();
SetToggleButtonState();
}
void SetToggleButtonState()
{
if (inFreeCamMode)
{
RuntimeHelper.SetColorBlockAuto(startStopButton.Component, new(0.4f, 0.2f, 0.2f));
startStopButton.ButtonText.text = "End Freecam";
}
else
{
RuntimeHelper.SetColorBlockAuto(startStopButton.Component, new(0.2f, 0.4f, 0.2f));
startStopButton.ButtonText.text = "Begin Freecam";
}
}
void OnUseGameCameraToggled(bool value)
{
EventSystemHelper.SetSelectedGameObject(null);
if (!inFreeCamMode)
return;
EndFreecam();
BeginFreecam();
}
void OnResetPosButtonClicked()
{
currentUserCameraPosition = originalCameraPosition;
currentUserCameraRotation = originalCameraRotation;
if (inFreeCamMode && ourCamera)
{
ourCamera.transform.position = (Vector3)currentUserCameraPosition;
ourCamera.transform.rotation = (Quaternion)currentUserCameraRotation;
}
positionInput.Text = ParseUtility.ToStringForInput<Vector3>(originalCameraPosition);
}
void PositionInput_OnEndEdit(string input)
{
EventSystemHelper.SetSelectedGameObject(null);
if (!ParseUtility.TryParse(input, out Vector3 parsed, out Exception parseEx))
{
ExplorerCore.LogWarning($"Could not parse position to Vector3: {parseEx.ReflectionExToString()}");
UpdatePositionInput();
return;
}
SetCameraPosition(parsed);
}
void MoveSpeedInput_OnEndEdit(string input)
{
EventSystemHelper.SetSelectedGameObject(null);
if (!ParseUtility.TryParse(input, out float parsed, out Exception parseEx))
{
ExplorerCore.LogWarning($"Could not parse value: {parseEx.ReflectionExToString()}");
moveSpeedInput.Text = desiredMoveSpeed.ToString();
return;
}
desiredMoveSpeed = parsed;
}
}
internal class FreeCamBehaviour : MonoBehaviour
{
#if CPP
static FreeCamBehaviour()
{
UnhollowerRuntimeLib.ClassInjector.RegisterTypeInIl2Cpp<FreeCamBehaviour>();
}
public FreeCamBehaviour(IntPtr ptr) : base(ptr) { }
#endif
internal void Update()
{
if (FreeCamPanel.inFreeCamMode)
{
if (!FreeCamPanel.ourCamera)
{
FreeCamPanel.EndFreecam();
return;
}
Transform transform = FreeCamPanel.ourCamera.transform;
FreeCamPanel.currentUserCameraPosition = transform.position;
FreeCamPanel.currentUserCameraRotation = transform.rotation;
float moveSpeed = FreeCamPanel.desiredMoveSpeed * Time.deltaTime;
if (InputManager.GetKey(KeyCode.LeftShift) || InputManager.GetKey(KeyCode.RightShift))
moveSpeed *= 10f;
if (InputManager.GetKey(KeyCode.LeftArrow) || InputManager.GetKey(KeyCode.A))
transform.position += transform.right * -1 * moveSpeed;
if (InputManager.GetKey(KeyCode.RightArrow) || InputManager.GetKey(KeyCode.D))
transform.position += transform.right * moveSpeed;
if (InputManager.GetKey(KeyCode.UpArrow) || InputManager.GetKey(KeyCode.W))
transform.position += transform.forward * moveSpeed;
if (InputManager.GetKey(KeyCode.DownArrow) || InputManager.GetKey(KeyCode.S))
transform.position += transform.forward * -1 * moveSpeed;
if (InputManager.GetKey(KeyCode.Space) || InputManager.GetKey(KeyCode.PageUp))
transform.position += transform.up * moveSpeed;
if (InputManager.GetKey(KeyCode.LeftControl) || InputManager.GetKey(KeyCode.PageDown))
transform.position += transform.up * -1 * moveSpeed;
if (InputManager.GetMouseButton(1))
{
Vector3 mouseDelta = InputManager.MousePosition - FreeCamPanel.previousMousePosition;
float newRotationX = transform.localEulerAngles.y + mouseDelta.x * 0.3f;
float newRotationY = transform.localEulerAngles.x - mouseDelta.y * 0.3f;
transform.localEulerAngles = new Vector3(newRotationY, newRotationX, 0f);
}
FreeCamPanel.UpdatePositionInput();
FreeCamPanel.previousMousePosition = InputManager.MousePosition;
}
}
}
}

View File

@ -1,13 +1,10 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.Config;
using UnityExplorer.Hooks; using UnityExplorer.Hooks;
using UnityExplorer.UI.Widgets; using UnityExplorer.UI.Widgets;
using UnityExplorer.UI.Widgets.AutoComplete; using UnityExplorer.UI.Widgets.AutoComplete;
using UniverseLib;
using UniverseLib.UI; using UniverseLib.UI;
using UniverseLib.UI.Models; using UniverseLib.UI.Models;
using UniverseLib.UI.Widgets; using UniverseLib.UI.Widgets;
@ -15,189 +12,99 @@ using UniverseLib.UI.Widgets.ScrollView;
namespace UnityExplorer.UI.Panels namespace UnityExplorer.UI.Panels
{ {
public class HookManagerPanel : UIPanel public class HookManagerPanel : UEPanel
{ {
public static HookManagerPanel Instance { get; private set; }
public enum Pages public enum Pages
{ {
CurrentHooks,
ClassMethodSelector, ClassMethodSelector,
HookSourceEditor HookSourceEditor,
GenericArgsSelector,
} }
public static HookCreator hookCreator;
public static HookList hookList;
public static GenericConstructorWidget genericArgsHandler;
// Panel
public override UIManager.Panels PanelType => UIManager.Panels.HookManager; public override UIManager.Panels PanelType => UIManager.Panels.HookManager;
public override string Name => "Hooks"; public override string Name => "Hooks";
public override int MinWidth => 500;
public override int MinHeight => 600;
public override bool ShowByDefault => false; public override bool ShowByDefault => false;
public override int MinWidth => 400;
public override int MinHeight => 400;
public override Vector2 DefaultAnchorMin => new(0.5f, 0.5f);
public override Vector2 DefaultAnchorMax => new(0.5f, 0.5f);
public Pages CurrentPage { get; private set; } = Pages.CurrentHooks; public Pages CurrentPage { get; private set; } = Pages.ClassMethodSelector;
private GameObject currentHooksPanel; public HookManagerPanel(UIBase owner) : base(owner)
public ScrollPool<HookCell> HooksScrollPool;
private InputFieldRef classSelectorInputField;
private GameObject addHooksPanel;
public ScrollPool<AddHookCell> AddHooksScrollPool;
private Text addHooksLabel;
private InputFieldRef AddHooksMethodFilterInput;
private GameObject editorPanel;
public InputFieldScroller EditorInputScroller { get; private set; }
public InputFieldRef EditorInput => EditorInputScroller.InputField;
public Text EditorInputText { get; private set; }
public Text EditorHighlightText { get; private set; }
private void OnClassInputAddClicked()
{ {
HookManager.Instance.OnClassSelectedForHooks(this.classSelectorInputField.Text);
} }
public void SetAddHooksLabelType(string typeText) => addHooksLabel.text = $"Adding hooks to: {typeText}";
public void SetPage(Pages page) public void SetPage(Pages page)
{ {
switch (page) switch (page)
{ {
case Pages.CurrentHooks:
currentHooksPanel.SetActive(true);
addHooksPanel.SetActive(false);
editorPanel.SetActive(false);
break;
case Pages.ClassMethodSelector: case Pages.ClassMethodSelector:
currentHooksPanel.SetActive(false); HookCreator.AddHooksRoot.SetActive(true);
addHooksPanel.SetActive(true); HookCreator.EditorRoot.SetActive(false);
editorPanel.SetActive(false); genericArgsHandler.UIRoot.SetActive(false);
break; break;
case Pages.HookSourceEditor: case Pages.HookSourceEditor:
currentHooksPanel.SetActive(false); HookCreator.AddHooksRoot.SetActive(false);
addHooksPanel.SetActive(false); HookCreator.EditorRoot.SetActive(true);
editorPanel.SetActive(true); genericArgsHandler.UIRoot.SetActive(false);
break;
case Pages.GenericArgsSelector:
HookCreator.AddHooksRoot.SetActive(false);
HookCreator.EditorRoot.SetActive(false);
genericArgsHandler.UIRoot.SetActive(true);
break; break;
} }
} }
public void ResetMethodFilter() => AddHooksMethodFilterInput.Text = string.Empty; public override void SetDefaultSizeAndPosition()
public override void ConstructPanelContent()
{ {
// ~~~~~~~~~ Active hooks scroll pool base.SetDefaultSizeAndPosition();
currentHooksPanel = UIFactory.CreateUIObject("CurrentHooksPanel", this.uiContent);
UIFactory.SetLayoutElement(currentHooksPanel, flexibleHeight: 9999, flexibleWidth: 9999);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(currentHooksPanel, true, true, true, true);
var addRow = UIFactory.CreateHorizontalGroup(currentHooksPanel, "AddRow", false, true, true, true, 4,
new Vector4(2, 2, 2, 2), new Color(0.2f, 0.2f, 0.2f));
UIFactory.SetLayoutElement(addRow, minHeight: 30, flexibleWidth: 9999);
classSelectorInputField = UIFactory.CreateInputField(addRow, "ClassInput", "Enter a class to add hooks to...");
UIFactory.SetLayoutElement(classSelectorInputField.Component.gameObject, flexibleWidth: 9999);
new TypeCompleter(typeof(object), classSelectorInputField, true, false);
var addButton = UIFactory.CreateButton(addRow, "AddButton", "Add Hooks");
UIFactory.SetLayoutElement(addButton.Component.gameObject, minWidth: 100, minHeight: 25);
addButton.OnClick += OnClassInputAddClicked;
var hooksLabel = UIFactory.CreateLabel(currentHooksPanel, "HooksLabel", "Current Hooks", TextAnchor.MiddleCenter);
UIFactory.SetLayoutElement(hooksLabel.gameObject, minHeight: 30, flexibleWidth: 9999);
HooksScrollPool = UIFactory.CreateScrollPool<HookCell>(currentHooksPanel, "HooksScrollPool",
out GameObject hooksScroll, out GameObject hooksContent);
UIFactory.SetLayoutElement(hooksScroll, flexibleHeight: 9999);
HooksScrollPool.Initialize(HookManager.Instance);
// ~~~~~~~~~ Add hooks panel
addHooksPanel = UIFactory.CreateUIObject("AddHooksPanel", this.uiContent);
UIFactory.SetLayoutElement(addHooksPanel, flexibleHeight: 9999, flexibleWidth: 9999);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(addHooksPanel, true, true, true, true);
addHooksLabel = UIFactory.CreateLabel(addHooksPanel, "AddLabel", "NOT SET", TextAnchor.MiddleCenter);
UIFactory.SetLayoutElement(addHooksLabel.gameObject, minHeight: 30, minWidth: 100, flexibleWidth: 9999);
var buttonRow = UIFactory.CreateHorizontalGroup(addHooksPanel, "ButtonRow", false, false, true, true, 5);
UIFactory.SetLayoutElement(buttonRow, minHeight: 25, flexibleWidth: 9999);
var doneButton = UIFactory.CreateButton(buttonRow, "DoneButton", "Done", new Color(0.2f, 0.3f, 0.2f));
UIFactory.SetLayoutElement(doneButton.Component.gameObject, minHeight: 25, flexibleWidth: 9999);
doneButton.OnClick += HookManager.Instance.DoneAddingHooks;
AddHooksMethodFilterInput = UIFactory.CreateInputField(addHooksPanel, "FilterInputField", "Filter method names...");
UIFactory.SetLayoutElement(AddHooksMethodFilterInput.Component.gameObject, minHeight: 30, flexibleWidth: 9999);
AddHooksMethodFilterInput.OnValueChanged += HookManager.Instance.OnAddHookFilterInputChanged;
AddHooksScrollPool = UIFactory.CreateScrollPool<AddHookCell>(addHooksPanel, "MethodAddScrollPool",
out GameObject addScrollRoot, out GameObject addContent);
UIFactory.SetLayoutElement(addScrollRoot, flexibleHeight: 9999);
AddHooksScrollPool.Initialize(HookManager.Instance);
addHooksPanel.gameObject.SetActive(false);
// ~~~~~~~~~ Hook source editor panel
editorPanel = UIFactory.CreateUIObject("HookSourceEditor", this.uiContent);
UIFactory.SetLayoutElement(editorPanel, flexibleHeight: 9999, flexibleWidth: 9999);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(editorPanel, true, true, true, true);
var editorLabel = UIFactory.CreateLabel(editorPanel,
"EditorLabel",
"Edit Harmony patch source as desired. Accepted method names are Prefix, Postfix, Finalizer and Transpiler (can define multiple).\n\n" +
"Hooks are temporary! Please copy the source into your IDE to avoid losing work if you wish to keep it!",
TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(editorLabel.gameObject, minHeight: 25, flexibleWidth: 9999);
var editorButtonRow = UIFactory.CreateHorizontalGroup(editorPanel, "ButtonRow", false, false, true, true, 5);
UIFactory.SetLayoutElement(editorButtonRow, minHeight: 25, flexibleWidth: 9999);
var editorSaveButton = UIFactory.CreateButton(editorButtonRow, "DoneButton", "Save and Return", new Color(0.2f, 0.3f, 0.2f));
UIFactory.SetLayoutElement(editorSaveButton.Component.gameObject, minHeight: 25, flexibleWidth: 9999);
editorSaveButton.OnClick += HookManager.Instance.EditorInputSave;
var editorDoneButton = UIFactory.CreateButton(editorButtonRow, "DoneButton", "Cancel and Return", new Color(0.2f, 0.2f, 0.2f));
UIFactory.SetLayoutElement(editorDoneButton.Component.gameObject, minHeight: 25, flexibleWidth: 9999);
editorDoneButton.OnClick += HookManager.Instance.EditorInputCancel;
int fontSize = 16;
var inputObj = UIFactory.CreateScrollInputField(editorPanel, "EditorInput", "", out var inputScroller, fontSize);
EditorInputScroller = inputScroller;
EditorInput.OnValueChanged += HookManager.Instance.OnEditorInputChanged;
EditorInputText = EditorInput.Component.textComponent;
EditorInputText.supportRichText = false;
EditorInputText.color = Color.clear;
EditorInput.Component.customCaretColor = true;
EditorInput.Component.caretColor = Color.white;
EditorInput.PlaceholderText.fontSize = fontSize;
// Lexer highlight text overlay
var highlightTextObj = UIFactory.CreateUIObject("HighlightText", EditorInputText.gameObject);
var highlightTextRect = highlightTextObj.GetComponent<RectTransform>();
highlightTextRect.pivot = new Vector2(0, 1);
highlightTextRect.anchorMin = Vector2.zero;
highlightTextRect.anchorMax = Vector2.one;
highlightTextRect.offsetMin = Vector2.zero;
highlightTextRect.offsetMax = Vector2.zero;
EditorHighlightText = highlightTextObj.AddComponent<Text>();
EditorHighlightText.color = Color.white;
EditorHighlightText.supportRichText = true;
EditorHighlightText.fontSize = fontSize;
// Set fonts
EditorInputText.font = UniversalUI.ConsoleFont;
EditorInput.PlaceholderText.font = UniversalUI.ConsoleFont;
EditorHighlightText.font = UniversalUI.ConsoleFont;
editorPanel.SetActive(false);
}
protected internal override void DoSetDefaultPosAndAnchors()
{
this.Rect.anchorMin = new Vector2(0.5f, 0.5f);
this.Rect.anchorMax = new Vector2(0.5f, 0.5f);
this.Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, MinWidth); this.Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, MinWidth);
this.Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, MinHeight); this.Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, MinHeight);
} }
protected override void ConstructPanelContent()
{
Instance = this;
hookList = new();
hookCreator = new();
genericArgsHandler = new();
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(ContentRoot, true, false);
// GameObject baseHoriGroup = UIFactory.CreateHorizontalGroup(ContentRoot, "HoriGroup", true, true, true, true);
// UIFactory.SetLayoutElement(baseHoriGroup, flexibleWidth: 9999, flexibleHeight: 9999);
// // Left Group
//GameObject leftGroup = UIFactory.CreateVerticalGroup(ContentRoot, "LeftGroup", true, true, true, true);
UIFactory.SetLayoutElement(ContentRoot.gameObject, minWidth: 300, flexibleWidth: 9999, flexibleHeight: 9999);
hookList.ConstructUI(ContentRoot);
// // Right Group
//GameObject rightGroup = UIFactory.CreateVerticalGroup(ContentRoot, "RightGroup", true, true, true, true);
UIFactory.SetLayoutElement(ContentRoot, minWidth: 300, flexibleWidth: 9999, flexibleHeight: 9999);
hookCreator.ConstructAddHooksView(ContentRoot);
hookCreator.ConstructEditor(ContentRoot);
HookCreator.EditorRoot.SetActive(false);
genericArgsHandler.ConstructUI(ContentRoot);
genericArgsHandler.UIRoot.SetActive(false);
}
} }
} }

View File

@ -1,27 +1,22 @@
using System; using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.Config;
using UnityExplorer.Inspectors; using UnityExplorer.Inspectors;
using UniverseLib.UI; using UniverseLib.UI;
namespace UnityExplorer.UI.Panels namespace UnityExplorer.UI.Panels
{ {
public class InspectorPanel : UIPanel public class InspectorPanel : UEPanel
{ {
public static InspectorPanel Instance { get; private set; } public static InspectorPanel Instance { get; private set; }
public InspectorPanel() { Instance = this; }
public override string Name => "Inspector"; public override string Name => "Inspector";
public override UIManager.Panels PanelType => UIManager.Panels.Inspector; public override UIManager.Panels PanelType => UIManager.Panels.Inspector;
public override bool ShouldSaveActiveState => false; public override bool ShouldSaveActiveState => false;
public override int MinWidth => 810; public override int MinWidth => 810;
public override int MinHeight => 350; public override int MinHeight => 350;
public override Vector2 DefaultAnchorMin => new(0.35f, 0.175f);
public override Vector2 DefaultAnchorMax => new(0.8f, 0.925f);
public GameObject NavbarHolder; public GameObject NavbarHolder;
public Dropdown MouseInspectDropdown; public Dropdown MouseInspectDropdown;
@ -31,34 +26,31 @@ namespace UnityExplorer.UI.Panels
public static float CurrentPanelWidth => Instance.Rect.rect.width; public static float CurrentPanelWidth => Instance.Rect.rect.width;
public static float CurrentPanelHeight => Instance.Rect.rect.height; public static float CurrentPanelHeight => Instance.Rect.rect.height;
public InspectorPanel(UIBase owner) : base(owner)
{
Instance = this;
}
public override void Update() public override void Update()
{ {
InspectorManager.Update(); InspectorManager.Update();
} }
public override void OnFinishResize(RectTransform panel) public override void OnFinishResize()
{ {
base.OnFinishResize(panel); base.OnFinishResize();
InspectorManager.PanelWidth = this.Rect.rect.width; InspectorManager.PanelWidth = this.Rect.rect.width;
InspectorManager.OnPanelResized(panel.rect.width); InspectorManager.OnPanelResized(Rect.rect.width);
} }
protected internal override void DoSetDefaultPosAndAnchors() protected override void ConstructPanelContent()
{ {
Rect.localPosition = Vector2.zero; GameObject closeHolder = this.TitleBar.transform.Find("CloseHolder").gameObject;
Rect.pivot = new Vector2(0f, 1f);
Rect.anchorMin = new Vector2(0.35f, 0.175f);
Rect.anchorMax = new Vector2(0.8f, 0.925f);
}
public override void ConstructPanelContent()
{
var closeHolder = this.TitleBar.transform.Find("CloseHolder").gameObject;
// Inspect under mouse dropdown on title bar // Inspect under mouse dropdown on title bar
var mouseDropdown = UIFactory.CreateDropdown(closeHolder, "MouseInspectDropdown", out MouseInspectDropdown, "Mouse Inspect", 14, GameObject mouseDropdown = UIFactory.CreateDropdown(closeHolder, "MouseInspectDropdown", out MouseInspectDropdown, "Mouse Inspect", 14,
MouseInspector.OnDropdownSelect); MouseInspector.OnDropdownSelect);
UIFactory.SetLayoutElement(mouseDropdown, minHeight: 25, minWidth: 140); UIFactory.SetLayoutElement(mouseDropdown, minHeight: 25, minWidth: 140);
MouseInspectDropdown.options.Add(new Dropdown.OptionData("Mouse Inspect")); MouseInspectDropdown.options.Add(new Dropdown.OptionData("Mouse Inspect"));
@ -68,7 +60,7 @@ namespace UnityExplorer.UI.Panels
// add close all button to titlebar // add close all button to titlebar
var closeAllBtn = UIFactory.CreateButton(closeHolder.gameObject, "CloseAllBtn", "Close All", UniverseLib.UI.Models.ButtonRef closeAllBtn = UIFactory.CreateButton(closeHolder.gameObject, "CloseAllBtn", "Close All",
new Color(0.3f, 0.2f, 0.2f)); new Color(0.3f, 0.2f, 0.2f));
UIFactory.SetLayoutElement(closeAllBtn.Component.gameObject, minHeight: 25, minWidth: 80); UIFactory.SetLayoutElement(closeAllBtn.Component.gameObject, minHeight: 25, minWidth: 80);
closeAllBtn.Component.transform.SetSiblingIndex(closeAllBtn.Component.transform.GetSiblingIndex() - 1); closeAllBtn.Component.transform.SetSiblingIndex(closeAllBtn.Component.transform.GetSiblingIndex() - 1);
@ -76,19 +68,19 @@ namespace UnityExplorer.UI.Panels
// this.UIRoot.GetComponent<Mask>().enabled = false; // this.UIRoot.GetComponent<Mask>().enabled = false;
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(this.uiContent, true, true, true, true, 4, padLeft: 5, padRight: 5); UIFactory.SetLayoutGroup<VerticalLayoutGroup>(this.ContentRoot, true, true, true, true, 4, padLeft: 5, padRight: 5);
this.NavbarHolder = UIFactory.CreateGridGroup(this.uiContent, "Navbar", new Vector2(200, 22), new Vector2(4, 4), this.NavbarHolder = UIFactory.CreateGridGroup(this.ContentRoot, "Navbar", new Vector2(200, 22), new Vector2(4, 4),
new Color(0.05f, 0.05f, 0.05f)); new Color(0.05f, 0.05f, 0.05f));
//UIFactory.SetLayoutElement(NavbarHolder, flexibleWidth: 9999, minHeight: 0, preferredHeight: 0, flexibleHeight: 9999); //UIFactory.SetLayoutElement(NavbarHolder, flexibleWidth: 9999, minHeight: 0, preferredHeight: 0, flexibleHeight: 9999);
NavbarHolder.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize; NavbarHolder.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
this.ContentHolder = UIFactory.CreateVerticalGroup(this.uiContent, "ContentHolder", true, true, true, true, 0, default, this.ContentHolder = UIFactory.CreateVerticalGroup(this.ContentRoot, "ContentHolder", true, true, true, true, 0, default,
new Color(0.1f, 0.1f, 0.1f)); new Color(0.1f, 0.1f, 0.1f));
UIFactory.SetLayoutElement(ContentHolder, flexibleHeight: 9999); UIFactory.SetLayoutElement(ContentHolder, flexibleHeight: 9999);
ContentRect = ContentHolder.GetComponent<RectTransform>(); ContentRect = ContentHolder.GetComponent<RectTransform>();
UIManager.SetPanelActive(PanelType, false); this.SetActive(false);
} }
} }
} }

View File

@ -3,23 +3,18 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.Config; using UnityExplorer.Config;
using UnityExplorer.UI.Widgets;
using UniverseLib; using UniverseLib;
using UniverseLib.UI; using UniverseLib.UI;
using UniverseLib.UI.Models; using UniverseLib.UI.Models;
using UniverseLib.UI.Widgets;
using UniverseLib.UI.Widgets.ScrollView; using UniverseLib.UI.Widgets.ScrollView;
using UniverseLib.Utility; using UniverseLib.Utility;
namespace UnityExplorer.UI.Panels namespace UnityExplorer.UI.Panels
{ {
// TODO move the logic out of this class into a LogUtil class (also move ExplorerCore.Log into that) public class LogPanel : UEPanel, ICellPoolDataSource<ConsoleLogCell>
public class LogPanel : UIPanel, ICellPoolDataSource<ConsoleLogCell>
{ {
public struct LogInfo public struct LogInfo
{ {
@ -29,7 +24,7 @@ namespace UnityExplorer.UI.Panels
public LogInfo(string message, LogType type) { this.message = message; this.type = type; } public LogInfo(string message, LogType type) { this.message = message; this.type = type; }
} }
private static readonly List<LogInfo> Logs = new List<LogInfo>(); private static readonly List<LogInfo> Logs = new();
private static string CurrentStreamPath; private static string CurrentStreamPath;
public override string Name => "Log"; public override string Name => "Log";
@ -37,6 +32,9 @@ namespace UnityExplorer.UI.Panels
public override int MinWidth => 350; public override int MinWidth => 350;
public override int MinHeight => 75; public override int MinHeight => 75;
public override Vector2 DefaultAnchorMin => new(0.5f, 0.03f);
public override Vector2 DefaultAnchorMax => new(0.9f, 0.2f);
public override bool ShouldSaveActiveState => true; public override bool ShouldSaveActiveState => true;
public override bool ShowByDefault => true; public override bool ShowByDefault => true;
@ -44,7 +42,7 @@ namespace UnityExplorer.UI.Panels
private static ScrollPool<ConsoleLogCell> logScrollPool; private static ScrollPool<ConsoleLogCell> logScrollPool;
public LogPanel() public LogPanel(UIBase owner) : base(owner)
{ {
SetupIO(); SetupIO();
} }
@ -67,16 +65,16 @@ namespace UnityExplorer.UI.Panels
private void SetupIO() private void SetupIO()
{ {
var fileName = $"UnityExplorer {DateTime.Now:u}.txt"; string fileName = $"UnityExplorer {DateTime.Now:u}.txt";
fileName = IOUtility.EnsureValidFilename(fileName); fileName = IOUtility.EnsureValidFilename(fileName);
var path = Path.Combine(ExplorerCore.ExplorerFolder, "Logs"); string path = Path.Combine(ExplorerCore.ExplorerFolder, "Logs");
CurrentStreamPath = IOUtility.EnsureValidFilePath(Path.Combine(path, fileName)); CurrentStreamPath = IOUtility.EnsureValidFilePath(Path.Combine(path, fileName));
// clean old log(s) // clean old log(s)
var files = Directory.GetFiles(path); string[] files = Directory.GetFiles(path);
if (files.Length >= 10) if (files.Length >= 10)
{ {
var sorted = files.ToList(); List<string> sorted = files.ToList();
// sort by 'datetime.ToString("u")' will put the oldest ones first // sort by 'datetime.ToString("u")' will put the oldest ones first
sorted.Sort(); sorted.Sort();
for (int i = 0; i < files.Length - 9; i++) for (int i = 0; i < files.Length - 9; i++)
@ -113,7 +111,7 @@ namespace UnityExplorer.UI.Panels
// Cell pool // Cell pool
private static readonly Dictionary<LogType, Color> logColors = new Dictionary<LogType, Color> private static readonly Dictionary<LogType, Color> logColors = new()
{ {
{ LogType.Log, Color.white }, { LogType.Log, Color.white },
{ LogType.Warning, Color.yellow }, { LogType.Warning, Color.yellow },
@ -122,8 +120,8 @@ namespace UnityExplorer.UI.Panels
{ LogType.Exception, Color.red }, { LogType.Exception, Color.red },
}; };
private readonly Color logEvenColor = new Color(0.34f, 0.34f, 0.34f); private readonly Color logEvenColor = new(0.34f, 0.34f, 0.34f);
private readonly Color logOddColor = new Color(0.28f, 0.28f, 0.28f); private readonly Color logOddColor = new(0.28f, 0.28f, 0.28f);
public void OnCellBorrowed(ConsoleLogCell cell) { } public void OnCellBorrowed(ConsoleLogCell cell) { }
@ -138,50 +136,42 @@ namespace UnityExplorer.UI.Panels
// Logs are displayed in reverse order (newest at top) // Logs are displayed in reverse order (newest at top)
index = Logs.Count - index - 1; index = Logs.Count - index - 1;
var log = Logs[index]; LogInfo log = Logs[index];
cell.IndexLabel.text = $"{index}:"; cell.IndexLabel.text = $"{index}:";
cell.Input.Text = log.message; cell.Input.Text = log.message;
cell.Input.Component.textComponent.color = logColors[log.type]; cell.Input.Component.textComponent.color = logColors[log.type];
var color = index % 2 == 0 ? logEvenColor : logOddColor; Color color = index % 2 == 0 ? logEvenColor : logOddColor;
RuntimeHelper.SetColorBlock(cell.Input.Component, color); RuntimeHelper.SetColorBlock(cell.Input.Component, color);
} }
protected internal override void DoSetDefaultPosAndAnchors()
{
Rect.localPosition = Vector2.zero;
Rect.pivot = new Vector2(0f, 1f);
Rect.anchorMin = new Vector2(0.5f, 0.03f);
Rect.anchorMax = new Vector2(0.9f, 0.2f);
}
// UI Construction // UI Construction
public override void ConstructPanelContent() protected override void ConstructPanelContent()
{ {
// Log scroll pool // Log scroll pool
logScrollPool = UIFactory.CreateScrollPool<ConsoleLogCell>(this.uiContent, "Logs", out GameObject scrollObj, logScrollPool = UIFactory.CreateScrollPool<ConsoleLogCell>(this.ContentRoot, "Logs", out GameObject scrollObj,
out GameObject scrollContent, new Color(0.03f, 0.03f, 0.03f)); out GameObject scrollContent, new Color(0.03f, 0.03f, 0.03f));
UIFactory.SetLayoutElement(scrollObj, flexibleWidth: 9999, flexibleHeight: 9999); UIFactory.SetLayoutElement(scrollObj, flexibleWidth: 9999, flexibleHeight: 9999);
// Buttons and toggles // Buttons and toggles
var optionsRow = UIFactory.CreateUIObject("OptionsRow", this.uiContent); GameObject optionsRow = UIFactory.CreateUIObject("OptionsRow", this.ContentRoot);
UIFactory.SetLayoutElement(optionsRow, minHeight: 25, flexibleWidth: 9999); UIFactory.SetLayoutElement(optionsRow, minHeight: 25, flexibleWidth: 9999);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(optionsRow, false, false, true, true, 5, 2, 2, 2, 2); UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(optionsRow, false, false, true, true, 5, 2, 2, 2, 2);
var clearButton = UIFactory.CreateButton(optionsRow, "ClearButton", "Clear", new Color(0.2f, 0.2f, 0.2f)); ButtonRef clearButton = UIFactory.CreateButton(optionsRow, "ClearButton", "Clear", new Color(0.2f, 0.2f, 0.2f));
UIFactory.SetLayoutElement(clearButton.Component.gameObject, minHeight: 23, flexibleHeight: 0, minWidth: 60); UIFactory.SetLayoutElement(clearButton.Component.gameObject, minHeight: 23, flexibleHeight: 0, minWidth: 60);
clearButton.OnClick += ClearLogs; clearButton.OnClick += ClearLogs;
clearButton.Component.transform.SetSiblingIndex(1); clearButton.Component.transform.SetSiblingIndex(1);
var fileButton = UIFactory.CreateButton(optionsRow, "FileButton", "Open Log File", new Color(0.2f, 0.2f, 0.2f)); ButtonRef fileButton = UIFactory.CreateButton(optionsRow, "FileButton", "Open Log File", new Color(0.2f, 0.2f, 0.2f));
UIFactory.SetLayoutElement(fileButton.Component.gameObject, minHeight: 23, flexibleHeight: 0, minWidth: 100); UIFactory.SetLayoutElement(fileButton.Component.gameObject, minHeight: 23, flexibleHeight: 0, minWidth: 100);
fileButton.OnClick += OpenLogFile; fileButton.OnClick += OpenLogFile;
fileButton.Component.transform.SetSiblingIndex(2); fileButton.Component.transform.SetSiblingIndex(2);
var unityToggle = UIFactory.CreateToggle(optionsRow, "UnityLogToggle", out var toggle, out var toggleText); GameObject unityToggle = UIFactory.CreateToggle(optionsRow, "UnityLogToggle", out Toggle toggle, out Text toggleText);
UIFactory.SetLayoutElement(unityToggle, minHeight: 25, minWidth: 150); UIFactory.SetLayoutElement(unityToggle, minHeight: 25, minWidth: 150);
toggleText.text = "Log Unity Debug?"; toggleText.text = "Log Unity Debug?";
toggle.isOn = ConfigManager.Log_Unity_Debug.Value; toggle.isOn = ConfigManager.Log_Unity_Debug.Value;

View File

@ -1,20 +1,14 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityExplorer.Inspectors.MouseInspectors; using UnityExplorer.Inspectors.MouseInspectors;
using UnityExplorer.UI.Widgets;
using UniverseLib;
using UniverseLib.UI; using UniverseLib.UI;
using UniverseLib.UI.Widgets;
using UniverseLib.UI.Widgets.ButtonList; using UniverseLib.UI.Widgets.ButtonList;
using UniverseLib.UI.Widgets.ScrollView; using UniverseLib.UI.Widgets.ScrollView;
using UniverseLib.Utility; using UniverseLib.Utility;
namespace UnityExplorer.UI.Panels namespace UnityExplorer.UI.Panels
{ {
public class MouseInspectorResultsPanel : UIPanel public class MouseInspectorResultsPanel : UEPanel
{ {
public override UIManager.Panels PanelType => UIManager.Panels.UIInspectorResults; public override UIManager.Panels PanelType => UIManager.Panels.UIInspectorResults;
@ -22,6 +16,9 @@ namespace UnityExplorer.UI.Panels
public override int MinWidth => 500; public override int MinWidth => 500;
public override int MinHeight => 500; public override int MinHeight => 500;
public override Vector2 DefaultAnchorMin => new(0.5f, 0.5f);
public override Vector2 DefaultAnchorMax => new(0.5f, 0.5f);
public override bool CanDragAndResize => true; public override bool CanDragAndResize => true;
public override bool NavButtonWanted => false; public override bool NavButtonWanted => false;
public override bool ShouldSaveActiveState => false; public override bool ShouldSaveActiveState => false;
@ -30,6 +27,10 @@ namespace UnityExplorer.UI.Panels
private ButtonListHandler<GameObject, ButtonCell> dataHandler; private ButtonListHandler<GameObject, ButtonCell> dataHandler;
private ScrollPool<ButtonCell> buttonScrollPool; private ScrollPool<ButtonCell> buttonScrollPool;
public MouseInspectorResultsPanel(UIBase owner) : base(owner)
{
}
public void ShowResults() public void ShowResults()
{ {
dataHandler.RefreshData(); dataHandler.RefreshData();
@ -53,27 +54,27 @@ namespace UnityExplorer.UI.Panels
if (index >= UiInspector.LastHitObjects.Count) if (index >= UiInspector.LastHitObjects.Count)
return; return;
var obj = UiInspector.LastHitObjects[index]; GameObject obj = UiInspector.LastHitObjects[index];
cell.Button.ButtonText.text = $"<color=cyan>{obj.name}</color> ({obj.transform.GetTransformPath(true)})"; cell.Button.ButtonText.text = $"<color=cyan>{obj.name}</color> ({obj.transform.GetTransformPath(true)})";
} }
public override void ConstructPanelContent() public override void SetDefaultSizeAndPosition()
{
base.SetDefaultSizeAndPosition();
this.Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 500f);
this.Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 500f);
}
protected override void ConstructPanelContent()
{ {
dataHandler = new ButtonListHandler<GameObject, ButtonCell>(buttonScrollPool, GetEntries, SetCell, ShouldDisplayCell, OnCellClicked); dataHandler = new ButtonListHandler<GameObject, ButtonCell>(buttonScrollPool, GetEntries, SetCell, ShouldDisplayCell, OnCellClicked);
buttonScrollPool = UIFactory.CreateScrollPool<ButtonCell>(this.uiContent, "ResultsList", out GameObject scrollObj, buttonScrollPool = UIFactory.CreateScrollPool<ButtonCell>(this.ContentRoot, "ResultsList", out GameObject scrollObj,
out GameObject scrollContent); out GameObject scrollContent);
buttonScrollPool.Initialize(dataHandler); buttonScrollPool.Initialize(dataHandler);
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999); UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
} }
protected internal override void DoSetDefaultPosAndAnchors()
{
this.Rect.anchorMin = new Vector2(0.5f, 0.5f);
this.Rect.anchorMax = new Vector2(0.5f, 0.5f);
this.Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 500f);
this.Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 500f);
}
} }
} }

View File

@ -1,28 +1,23 @@
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using UnityExplorer.Config;
using UniverseLib.UI.Models;
using UnityExplorer.ObjectExplorer; using UnityExplorer.ObjectExplorer;
using UnityExplorer.UI.Widgets;
using UniverseLib.UI;
using UniverseLib; using UniverseLib;
using UniverseLib.UI;
using UniverseLib.UI.Models;
namespace UnityExplorer.UI.Panels namespace UnityExplorer.UI.Panels
{ {
public class ObjectExplorerPanel : UIPanel public class ObjectExplorerPanel : UEPanel
{ {
public override string Name => "Object Explorer"; public override string Name => "Object Explorer";
public override UIManager.Panels PanelType => UIManager.Panels.ObjectExplorer; public override UIManager.Panels PanelType => UIManager.Panels.ObjectExplorer;
public override int MinWidth => 350; public override int MinWidth => 350;
public override int MinHeight => 200; public override int MinHeight => 200;
public override Vector2 DefaultAnchorMin => new(0.125f, 0.175f);
public override Vector2 DefaultAnchorMax => new(0.325f, 0.925f);
public SceneExplorer SceneExplorer; public SceneExplorer SceneExplorer;
public ObjectSearch ObjectSearch; public ObjectSearch ObjectSearch;
@ -31,18 +26,22 @@ namespace UnityExplorer.UI.Panels
public override bool ShouldSaveActiveState => true; public override bool ShouldSaveActiveState => true;
public int SelectedTab = 0; public int SelectedTab = 0;
private readonly List<UIModel> tabPages = new List<UIModel>(); private readonly List<UIModel> tabPages = new();
private readonly List<ButtonRef> tabButtons = new List<ButtonRef>(); private readonly List<ButtonRef> tabButtons = new();
public ObjectExplorerPanel(UIBase owner) : base(owner)
{
}
public void SetTab(int tabIndex) public void SetTab(int tabIndex)
{ {
if (SelectedTab != -1) if (SelectedTab != -1)
DisableTab(SelectedTab); DisableTab(SelectedTab);
var content = tabPages[tabIndex]; UIModel content = tabPages[tabIndex];
content.SetActive(true); content.SetActive(true);
var button = tabButtons[tabIndex]; ButtonRef button = tabButtons[tabIndex];
RuntimeHelper.SetColorBlock(button.Component, UniversalUI.EnabledButtonColor, UniversalUI.EnabledButtonColor * 1.2f); RuntimeHelper.SetColorBlock(button.Component, UniversalUI.EnabledButtonColor, UniversalUI.EnabledButtonColor * 1.2f);
SelectedTab = tabIndex; SelectedTab = tabIndex;
@ -88,28 +87,20 @@ namespace UnityExplorer.UI.Panels
SetTab(SelectedTab); SetTab(SelectedTab);
} }
protected internal override void DoSetDefaultPosAndAnchors() protected override void ConstructPanelContent()
{
Rect.localPosition = Vector2.zero;
Rect.pivot = new Vector2(0f, 1f);
Rect.anchorMin = new Vector2(0.125f, 0.175f);
Rect.anchorMax = new Vector2(0.325f, 0.925f);
}
public override void ConstructPanelContent()
{ {
// Tab bar // Tab bar
var tabGroup = UIFactory.CreateHorizontalGroup(uiContent, "TabBar", true, true, true, true, 2, new Vector4(2, 2, 2, 2)); GameObject tabGroup = UIFactory.CreateHorizontalGroup(ContentRoot, "TabBar", true, true, true, true, 2, new Vector4(2, 2, 2, 2));
UIFactory.SetLayoutElement(tabGroup, minHeight: 25, flexibleHeight: 0); UIFactory.SetLayoutElement(tabGroup, minHeight: 25, flexibleHeight: 0);
// Scene Explorer // Scene Explorer
SceneExplorer = new SceneExplorer(this); SceneExplorer = new SceneExplorer(this);
SceneExplorer.ConstructUI(uiContent); SceneExplorer.ConstructUI(ContentRoot);
tabPages.Add(SceneExplorer); tabPages.Add(SceneExplorer);
// Object search // Object search
ObjectSearch = new ObjectSearch(this); ObjectSearch = new ObjectSearch(this);
ObjectSearch.ConstructUI(uiContent); ObjectSearch.ConstructUI(ContentRoot);
tabPages.Add(ObjectSearch); tabPages.Add(ObjectSearch);
// set up tabs // set up tabs
@ -117,12 +108,12 @@ namespace UnityExplorer.UI.Panels
AddTabButton(tabGroup, "Object Search"); AddTabButton(tabGroup, "Object Search");
// default active state: Active // default active state: Active
UIManager.SetPanelActive(PanelType, true); this.SetActive(true);
} }
private void AddTabButton(GameObject tabGroup, string label) private void AddTabButton(GameObject tabGroup, string label)
{ {
var button = UIFactory.CreateButton(tabGroup, $"Button_{label}", label); ButtonRef button = UIFactory.CreateButton(tabGroup, $"Button_{label}", label);
int idx = tabButtons.Count; int idx = tabButtons.Count;
//button.onClick.AddListener(() => { SetTab(idx); }); //button.onClick.AddListener(() => { SetTab(idx); });

View File

@ -1,32 +1,29 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.Config;
using UnityExplorer.CacheObject; using UnityExplorer.CacheObject;
using UnityExplorer.CacheObject.Views; using UnityExplorer.CacheObject.Views;
using UnityExplorer.UI.Widgets; using UnityExplorer.Config;
using UniverseLib.UI.Widgets;
using UniverseLib.UI; using UniverseLib.UI;
using UniverseLib.UI.Widgets.ScrollView; using UniverseLib.UI.Widgets.ScrollView;
namespace UnityExplorer.UI.Panels namespace UnityExplorer.UI.Panels
{ {
public class OptionsPanel : UIPanel, ICacheObjectController, ICellPoolDataSource<ConfigEntryCell> public class OptionsPanel : UEPanel, ICacheObjectController, ICellPoolDataSource<ConfigEntryCell>
{ {
public override string Name => "Options"; public override string Name => "Options";
public override UIManager.Panels PanelType => UIManager.Panels.Options; public override UIManager.Panels PanelType => UIManager.Panels.Options;
public override int MinWidth => 600; public override int MinWidth => 600;
public override int MinHeight => 200; public override int MinHeight => 200;
public override Vector2 DefaultAnchorMin => new(0.5f, 0.1f);
public override Vector2 DefaultAnchorMax => new(0.5f, 0.85f);
public override bool ShouldSaveActiveState => false; public override bool ShouldSaveActiveState => false;
public override bool ShowByDefault => false; public override bool ShowByDefault => false;
// Entry holders // Entry holders
private readonly List<CacheConfigEntry> configEntries = new List<CacheConfigEntry>(); private readonly List<CacheConfigEntry> configEntries = new();
// ICacheObjectController // ICacheObjectController
public CacheObjectBase ParentCacheObject => null; public CacheObjectBase ParentCacheObject => null;
@ -37,14 +34,19 @@ namespace UnityExplorer.UI.Panels
// ICellPoolDataSource // ICellPoolDataSource
public int ItemCount => configEntries.Count; public int ItemCount => configEntries.Count;
public OptionsPanel() public OptionsPanel(UIBase owner) : base(owner)
{ {
foreach (var entry in ConfigManager.ConfigElements) foreach (KeyValuePair<string, IConfigElement> entry in ConfigManager.ConfigElements)
{ {
var cache = new CacheConfigEntry(entry.Value); CacheConfigEntry cache = new(entry.Value)
cache.Owner = this; {
Owner = this
};
configEntries.Add(cache); configEntries.Add(cache);
} }
foreach (CacheConfigEntry config in configEntries)
config.UpdateValueFromSource();
} }
public void OnCellBorrowed(ConfigEntryCell cell) public void OnCellBorrowed(ConfigEntryCell cell)
@ -58,32 +60,30 @@ namespace UnityExplorer.UI.Panels
// UI Construction // UI Construction
protected internal override void DoSetDefaultPosAndAnchors() public override void SetDefaultSizeAndPosition()
{ {
Rect.localPosition = Vector2.zero; base.SetDefaultSizeAndPosition();
Rect.pivot = new Vector2(0f, 1f);
Rect.anchorMin = new Vector2(0.5f, 0.1f);
Rect.anchorMax = new Vector2(0.5f, 0.85f);
Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 600f); Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 600f);
} }
public override void ConstructPanelContent() protected override void ConstructPanelContent()
{ {
// Save button // Save button
var saveBtn = UIFactory.CreateButton(this.uiContent, "Save", "Save Options", new Color(0.2f, 0.3f, 0.2f)); UniverseLib.UI.Models.ButtonRef saveBtn = UIFactory.CreateButton(this.ContentRoot, "Save", "Save Options", new Color(0.2f, 0.3f, 0.2f));
UIFactory.SetLayoutElement(saveBtn.Component.gameObject, flexibleWidth: 9999, minHeight: 30, flexibleHeight: 0); UIFactory.SetLayoutElement(saveBtn.Component.gameObject, flexibleWidth: 9999, minHeight: 30, flexibleHeight: 0);
saveBtn.OnClick += ConfigManager.Handler.SaveConfig; saveBtn.OnClick += ConfigManager.Handler.SaveConfig;
// Config entries // Config entries
var scrollPool = UIFactory.CreateScrollPool<ConfigEntryCell>(this.uiContent, "ConfigEntries", out GameObject scrollObj, ScrollPool<ConfigEntryCell> scrollPool = UIFactory.CreateScrollPool<ConfigEntryCell>(
this.ContentRoot,
"ConfigEntries",
out GameObject scrollObj,
out GameObject scrollContent); out GameObject scrollContent);
scrollPool.Initialize(this); scrollPool.Initialize(this);
foreach (var config in configEntries)
config.UpdateValueFromSource();
} }
} }
} }

View File

@ -1,492 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
using UniverseLib.Input;
using UniverseLib.UI.Models;
using UnityExplorer.UI.Widgets.AutoComplete;
using UniverseLib.UI;
using UniverseLib;
using UniverseLib.Utility;
namespace UnityExplorer.UI.Panels
{
public class PanelDragger
{
private enum MouseState
{
Down,
Held,
NotPressed
}
#region Static
public static bool Resizing { get; private set; }
public static bool ResizePrompting => resizeCursorObj && resizeCursorObj.activeSelf;
public static GameObject resizeCursorObj;
internal static bool wasAnyDragging;
internal static List<PanelDragger> Instances = new();
private static bool handledInstanceThisFrame;
static PanelDragger()
{
UIPanel.OnPanelsReordered += OnPanelsReordered;
}
internal static void ForceEnd()
{
resizeCursorObj.SetActive(false);
wasAnyDragging = false;
Resizing = false;
foreach (var instance in Instances)
{
instance.WasDragging = false;
instance.WasResizing = false;
}
}
public static void OnPanelsReordered()
{
Instances.Sort((a, b) => b.Panel.GetSiblingIndex().CompareTo(a.Panel.GetSiblingIndex()));
// move AutoCompleter to bottom
if (AutoCompleteModal.Instance != null)
{
var idx = Instances.IndexOf(AutoCompleteModal.Instance.Dragger);
Instances.RemoveAt(idx);
Instances.Insert(0, AutoCompleteModal.Instance.Dragger);
}
}
public static void UpdateInstances()
{
if (!DisplayManager.MouseInTargetDisplay)
return;
if (!resizeCursorObj)
CreateCursorUI();
MouseState state;
if (InputManager.GetMouseButtonDown(0))
state = MouseState.Down;
else if (InputManager.GetMouseButton(0))
state = MouseState.Held;
else
state = MouseState.NotPressed;
var mousePos = DisplayManager.MousePosition;
handledInstanceThisFrame = false;
foreach (var instance in Instances)
{
if (!instance.Panel.gameObject.activeSelf)
continue;
instance.Update(state, mousePos);
if (handledInstanceThisFrame)
break;
}
if (wasAnyDragging && state == MouseState.NotPressed)
{
foreach (var instance in Instances)
instance.WasDragging = false;
wasAnyDragging = false;
}
}
#endregion
// Instance
public UIPanel UIPanel { get; private set; }
public bool AllowDragAndResize => UIPanel.CanDragAndResize;
public RectTransform Panel { get; set; }
public event Action<RectTransform> OnFinishResize;
public event Action<RectTransform> OnFinishDrag;
// Dragging
public RectTransform DragableArea { get; set; }
public bool WasDragging { get; set; }
private Vector2 lastDragPosition;
// Resizing
private const int RESIZE_THICKNESS = 10;
private bool WasResizing { get; set; }
private ResizeTypes currentResizeType = ResizeTypes.NONE;
private Vector2 lastResizePos;
private bool WasHoveringResize => resizeCursorObj.activeInHierarchy;
private ResizeTypes lastResizeHoverType;
private Rect totalResizeRect;
public PanelDragger(RectTransform dragArea, RectTransform panelToDrag, UIPanel panel)
{
this.UIPanel = panel;
Instances.Add(this);
DragableArea = dragArea;
Panel = panelToDrag;
UpdateResizeCache();
}
public void Destroy()
{
if (resizeCursorObj)
GameObject.Destroy(resizeCursorObj);
if (Instances.Contains(this))
Instances.Remove(this);
}
private void Update(MouseState state, Vector3 rawMousePos)
{
ResizeTypes type;
Vector3 resizePos = Panel.InverseTransformPoint(rawMousePos);
bool inResizePos = !UIManager.NavBarRect.rect.Contains(UIManager.NavBarRect.InverseTransformPoint(rawMousePos))
&& MouseInResizeArea(resizePos);
Vector3 dragPos = DragableArea.InverseTransformPoint(rawMousePos);
bool inDragPos = DragableArea.rect.Contains(dragPos);
if (WasHoveringResize && resizeCursorObj)
UpdateHoverImagePos();
switch (state)
{
case MouseState.Down:
if (inDragPos || inResizePos)
UIManager.SetPanelActive(Panel, true);
if (inDragPos)
{
if (AllowDragAndResize)
OnBeginDrag();
handledInstanceThisFrame = true;
return;
}
else if (inResizePos)
{
type = GetResizeType(resizePos);
if (type != ResizeTypes.NONE)
OnBeginResize(type);
handledInstanceThisFrame = true;
}
break;
case MouseState.Held:
if (WasDragging)
{
OnDrag();
handledInstanceThisFrame = true;
}
else if (WasResizing)
{
OnResize();
handledInstanceThisFrame = true;
}
break;
case MouseState.NotPressed:
if (AllowDragAndResize && inDragPos)
{
if (WasDragging)
OnEndDrag();
if (WasHoveringResize)
OnHoverResizeEnd();
handledInstanceThisFrame = true;
}
else if (inResizePos || WasResizing)
{
if (WasResizing)
OnEndResize();
type = GetResizeType(resizePos);
if (type != ResizeTypes.NONE)
OnHoverResize(type);
else if (WasHoveringResize)
OnHoverResizeEnd();
handledInstanceThisFrame = true;
}
else if (WasHoveringResize)
OnHoverResizeEnd();
break;
}
return;
}
#region DRAGGING
public void OnBeginDrag()
{
wasAnyDragging = true;
WasDragging = true;
lastDragPosition = DisplayManager.MousePosition;
}
public void OnDrag()
{
var mousePos = DisplayManager.MousePosition;
Vector2 diff = (Vector2)mousePos - lastDragPosition;
lastDragPosition = mousePos;
Panel.localPosition = Panel.localPosition + (Vector3)diff;
UIPanel.EnsureValidPosition(Panel);
}
public void OnEndDrag()
{
WasDragging = false;
OnFinishDrag?.Invoke(Panel);
}
#endregion
#region RESIZE
private readonly Dictionary<ResizeTypes, Rect> m_resizeMask = new()
{
{ ResizeTypes.Top, default },
{ ResizeTypes.Left, default },
{ ResizeTypes.Right, default },
{ ResizeTypes.Bottom, default },
};
[Flags]
public enum ResizeTypes : ulong
{
NONE = 0,
Top = 1,
Left = 2,
Right = 4,
Bottom = 8,
TopLeft = Top | Left,
TopRight = Top | Right,
BottomLeft = Bottom | Left,
BottomRight = Bottom | Right,
}
// private const int HALF_THICKESS = RESIZE_THICKNESS / 2;
private const int DBL_THICKESS = RESIZE_THICKNESS * 2;
private void UpdateResizeCache()
{
totalResizeRect = new Rect(Panel.rect.x - RESIZE_THICKNESS + 1,
Panel.rect.y - RESIZE_THICKNESS + 1,
Panel.rect.width + DBL_THICKESS - 2,
Panel.rect.height + DBL_THICKESS - 2);
// calculate the four cross sections to use as flags
if (AllowDragAndResize)
{
m_resizeMask[ResizeTypes.Bottom] = new Rect(
totalResizeRect.x,
totalResizeRect.y,
totalResizeRect.width,
RESIZE_THICKNESS);
m_resizeMask[ResizeTypes.Left] = new Rect(
totalResizeRect.x,
totalResizeRect.y,
RESIZE_THICKNESS,
totalResizeRect.height);
m_resizeMask[ResizeTypes.Top] = new Rect(
totalResizeRect.x,
Panel.rect.y + Panel.rect.height - 2,
totalResizeRect.width,
RESIZE_THICKNESS);
m_resizeMask[ResizeTypes.Right] = new Rect(
totalResizeRect.x + Panel.rect.width + RESIZE_THICKNESS - 2,
totalResizeRect.y,
RESIZE_THICKNESS,
totalResizeRect.height);
}
}
private bool MouseInResizeArea(Vector2 mousePos)
{
return totalResizeRect.Contains(mousePos);
}
private ResizeTypes GetResizeType(Vector2 mousePos)
{
// Calculate which part of the resize area we're in, if any.
// More readable method commented out below.
int mask = 0;
mask |= (int)ResizeTypes.Top * (m_resizeMask[ResizeTypes.Top].Contains(mousePos) ? 1 : 0);
mask |= (int)ResizeTypes.Bottom * (m_resizeMask[ResizeTypes.Bottom].Contains(mousePos) ? 1 : 0);
mask |= (int)ResizeTypes.Left * (m_resizeMask[ResizeTypes.Left].Contains(mousePos) ? 1 : 0);
mask |= (int)ResizeTypes.Right * (m_resizeMask[ResizeTypes.Right].Contains(mousePos) ? 1 : 0);
//if (m_resizeMask[ResizeTypes.Top].Contains(mousePos))
// mask |= ResizeTypes.Top;
//else if (m_resizeMask[ResizeTypes.Bottom].Contains(mousePos))
// mask |= ResizeTypes.Bottom;
//if (m_resizeMask[ResizeTypes.Left].Contains(mousePos))
// mask |= ResizeTypes.Left;
//else if (m_resizeMask[ResizeTypes.Right].Contains(mousePos))
// mask |= ResizeTypes.Right;
return (ResizeTypes)mask;
}
public void OnHoverResize(ResizeTypes resizeType)
{
if (WasHoveringResize && lastResizeHoverType == resizeType)
return;
// we are entering resize, or the resize type has changed.
//WasHoveringResize = true;
lastResizeHoverType = resizeType;
resizeCursorObj.SetActive(true);
resizeCursorObj.transform.SetAsLastSibling();
// set the rotation for the resize icon
float iconRotation = 0f;
switch (resizeType)
{
case ResizeTypes.TopRight:
case ResizeTypes.BottomLeft:
iconRotation = 45f; break;
case ResizeTypes.Top:
case ResizeTypes.Bottom:
iconRotation = 90f; break;
case ResizeTypes.TopLeft:
case ResizeTypes.BottomRight:
iconRotation = 135f; break;
}
Quaternion rot = resizeCursorObj.transform.rotation;
rot.eulerAngles = new Vector3(0, 0, iconRotation);
resizeCursorObj.transform.rotation = rot;
UpdateHoverImagePos();
}
// update the resize icon position to be above the mouse
private void UpdateHoverImagePos()
{
resizeCursorObj.transform.localPosition = UIManager.UIRootRect.InverseTransformPoint(DisplayManager.MousePosition);
}
public void OnHoverResizeEnd()
{
//WasHoveringResize = false;
resizeCursorObj.SetActive(false);
}
public void OnBeginResize(ResizeTypes resizeType)
{
currentResizeType = resizeType;
lastResizePos = DisplayManager.MousePosition;
WasResizing = true;
Resizing = true;
}
public void OnResize()
{
Vector3 mousePos = DisplayManager.MousePosition;
Vector2 diff = lastResizePos - (Vector2)mousePos;
if ((Vector2)mousePos == lastResizePos)
return;
if (mousePos.x < 0 || mousePos.y < 0 || mousePos.x > DisplayManager.Width || mousePos.y > DisplayManager.Height)
return;
lastResizePos = mousePos;
float diffX = (float)((decimal)diff.x / DisplayManager.Width);
float diffY = (float)((decimal)diff.y / DisplayManager.Height);
Vector2 anchorMin = Panel.anchorMin;
Vector2 anchorMax = Panel.anchorMax;
if (currentResizeType.HasFlag(ResizeTypes.Left))
anchorMin.x -= diffX;
else if (currentResizeType.HasFlag(ResizeTypes.Right))
anchorMax.x -= diffX;
if (currentResizeType.HasFlag(ResizeTypes.Top))
anchorMax.y -= diffY;
else if (currentResizeType.HasFlag(ResizeTypes.Bottom))
anchorMin.y -= diffY;
var prevMin = Panel.anchorMin;
var prevMax = Panel.anchorMax;
Panel.anchorMin = new Vector2(anchorMin.x, anchorMin.y);
Panel.anchorMax = new Vector2(anchorMax.x, anchorMax.y);
if (Panel.rect.width < UIPanel.MinWidth)
{
Panel.anchorMin = new Vector2(prevMin.x, Panel.anchorMin.y);
Panel.anchorMax = new Vector2(prevMax.x, Panel.anchorMax.y);
}
if (Panel.rect.height < UIPanel.MinHeight)
{
Panel.anchorMin = new Vector2(Panel.anchorMin.x, prevMin.y);
Panel.anchorMax = new Vector2(Panel.anchorMax.x, prevMax.y);
}
}
public void OnEndResize()
{
WasResizing = false;
Resizing = false;
try { OnHoverResizeEnd(); } catch { }
UpdateResizeCache();
OnFinishResize?.Invoke(Panel);
}
internal static void CreateCursorUI()
{
try
{
var text = UIFactory.CreateLabel(UIManager.UIRoot, "ResizeCursor", "↔", TextAnchor.MiddleCenter, Color.white, true, 35);
resizeCursorObj = text.gameObject;
var outline = text.gameObject.AddComponent<Outline>();
outline.effectColor = Color.black;
outline.effectDistance = new(1, 1);
RectTransform rect = resizeCursorObj.GetComponent<RectTransform>();
rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 64);
rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 64);
resizeCursorObj.SetActive(false);
}
catch (Exception e)
{
ExplorerCore.LogWarning("Exception creating Resize Cursor UI!\r\n" + e.ToString());
}
}
#endregion
}
}

266
src/UI/Panels/UEPanel.cs Normal file
View File

@ -0,0 +1,266 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.Config;
using UniverseLib;
using UniverseLib.Input;
using UniverseLib.UI;
using UniverseLib.UI.Models;
using UniverseLib.UI.Panels;
namespace UnityExplorer.UI.Panels
{
public abstract class UEPanel : PanelBase
{
protected UEPanel(UIBase owner) : base(owner) { }
public abstract UIManager.Panels PanelType { get; }
public virtual bool ShowByDefault => false;
public virtual bool ShouldSaveActiveState => true;
public virtual bool NavButtonWanted => true;
public ButtonRef NavButton { get; internal set; }
protected override PanelDragger CreatePanelDragger()
{
return new UEPanelDragger(this);
}
public override void OnFinishDrag()
{
base.OnFinishDrag();
SaveInternalData();
}
public override void OnFinishResize()
{
base.OnFinishResize();
SaveInternalData();
}
public override void SetActive(bool active)
{
if (this.Enabled != active)
{
base.SetActive(active);
if (!ApplyingSaveData)
SaveInternalData();
if (NavButtonWanted && NavButton != null)
{
Color color = active ? UniversalUI.EnabledButtonColor : UniversalUI.DisabledButtonColor;
RuntimeHelper.SetColorBlock(NavButton.Component, color, color * 1.2f);
}
}
if (!active)
{
if (Dragger != null)
this.Dragger.WasDragging = false;
}
else
{
this.UIRoot.transform.SetAsLastSibling();
(this.Owner.Panels as UEPanelManager).DoInvokeOnPanelsReordered();
}
}
// Save Data
public bool ApplyingSaveData { get; set; }
public void SaveInternalData()
{
if (UIManager.Initializing || ApplyingSaveData)
return;
SetSaveDataToConfigValue();
}
private void SetSaveDataToConfigValue()
=> ConfigManager.GetPanelSaveData(this.PanelType).Value = this.ToSaveData();
public virtual string ToSaveData()
{
try
{
return string.Join("|", new string[]
{
$"{ShouldSaveActiveState && Enabled}",
Rect.RectAnchorsToString(),
Rect.RectPositionToString()
});
}
catch (Exception ex)
{
ExplorerCore.LogWarning($"Exception generating Panel save data: {ex}");
return "";
}
}
public virtual void ApplySaveData()
{
string data = ConfigManager.GetPanelSaveData(this.PanelType).Value;
ApplySaveData(data);
}
protected virtual void ApplySaveData(string data)
{
if (string.IsNullOrEmpty(data))
return;
string[] split = data.Split('|');
try
{
Rect.SetAnchorsFromString(split[1]);
Rect.SetPositionFromString(split[2]);
this.EnsureValidSize();
this.EnsureValidPosition();
this.SetActive(bool.Parse(split[0]));
}
catch
{
ExplorerCore.LogWarning("Invalid or corrupt panel save data! Restoring to default.");
SetDefaultSizeAndPosition();
SetSaveDataToConfigValue();
}
}
public override void ConstructUI()
{
base.ConstructUI();
if (NavButtonWanted)
{
// create navbar button
NavButton = UIFactory.CreateButton(UIManager.NavbarTabButtonHolder, $"Button_{PanelType}", Name);
GameObject navBtn = NavButton.Component.gameObject;
navBtn.AddComponent<ContentSizeFitter>().horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(navBtn, false, true, true, true, 0, 0, 0, 5, 5, TextAnchor.MiddleCenter);
UIFactory.SetLayoutElement(navBtn, minWidth: 80);
RuntimeHelper.SetColorBlock(NavButton.Component, UniversalUI.DisabledButtonColor, UniversalUI.DisabledButtonColor * 1.2f);
NavButton.OnClick += () => { UIManager.TogglePanel(PanelType); };
GameObject txtObj = navBtn.transform.Find("Text").gameObject;
txtObj.AddComponent<ContentSizeFitter>().horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
}
this.SetActive(true);
this.SetActive(false);
this.SetActive(ShowByDefault);
}
protected override void LateConstructUI()
{
ApplyingSaveData = true;
base.LateConstructUI();
// apply panel save data or revert to default
try
{
ApplySaveData();
}
catch (Exception ex)
{
ExplorerCore.Log($"Exception loading panel save data: {ex}");
SetDefaultSizeAndPosition();
}
// simple listener for saving enabled state
this.OnToggleEnabled += (bool val) =>
{
SaveInternalData();
};
ApplyingSaveData = false;
Dragger.OnEndResize();
}
}
#region WINDOW ANCHORS / POSITION SAVE DATA HELPERS
public static class RectSaveExtensions
{
// Window Anchors helpers
internal static string RectAnchorsToString(this RectTransform rect)
{
if (!rect)
throw new ArgumentNullException("rect");
return string.Format(CultureInfo.InvariantCulture, "{0},{1},{2},{3}", new object[]
{
rect.anchorMin.x,
rect.anchorMin.y,
rect.anchorMax.x,
rect.anchorMax.y
});
}
internal static void SetAnchorsFromString(this RectTransform panel, string stringAnchors)
{
if (string.IsNullOrEmpty(stringAnchors))
throw new ArgumentNullException("stringAnchors");
if (stringAnchors.Contains(" "))
// outdated save data, not worth recovering just reset it.
throw new Exception("invalid save data, resetting.");
string[] split = stringAnchors.Split(',');
if (split.Length != 4)
throw new Exception($"stringAnchors split is unexpected length: {split.Length}");
Vector4 anchors;
anchors.x = float.Parse(split[0], CultureInfo.InvariantCulture);
anchors.y = float.Parse(split[1], CultureInfo.InvariantCulture);
anchors.z = float.Parse(split[2], CultureInfo.InvariantCulture);
anchors.w = float.Parse(split[3], CultureInfo.InvariantCulture);
panel.anchorMin = new Vector2(anchors.x, anchors.y);
panel.anchorMax = new Vector2(anchors.z, anchors.w);
}
internal static string RectPositionToString(this RectTransform rect)
{
if (!rect)
throw new ArgumentNullException("rect");
return string.Format(CultureInfo.InvariantCulture, "{0},{1}", new object[]
{
rect.anchoredPosition.x, rect.anchoredPosition.y
});
}
internal static void SetPositionFromString(this RectTransform rect, string stringPosition)
{
if (string.IsNullOrEmpty(stringPosition))
throw new ArgumentNullException(stringPosition);
if (stringPosition.Contains(" "))
// outdated save data, not worth recovering just reset it.
throw new Exception("invalid save data, resetting.");
string[] split = stringPosition.Split(',');
if (split.Length != 2)
throw new Exception($"stringPosition split is unexpected length: {split.Length}");
Vector3 vector = rect.anchoredPosition;
vector.x = float.Parse(split[0], CultureInfo.InvariantCulture);
vector.y = float.Parse(split[1], CultureInfo.InvariantCulture);
rect.anchoredPosition = vector;
}
}
#endregion
}

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.UI.Widgets.AutoComplete;
using UniverseLib.Input;
using UniverseLib.UI;
using UniverseLib.UI.Panels;
using UniverseLib.Utility;
namespace UnityExplorer.UI.Panels
{
public class UEPanelDragger : PanelDragger
{
public UEPanelDragger(PanelBase uiPanel) : base(uiPanel) { }
protected override bool MouseInResizeArea(Vector2 mousePos)
{
return !UIManager.NavBarRect.rect.Contains(UIManager.NavBarRect.InverseTransformPoint(mousePos))
&& base.MouseInResizeArea(mousePos);
}
}
}

View File

@ -1,423 +0,0 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.Config;
using UniverseLib.Input;
using UnityExplorer.UI.Widgets;
using UniverseLib.UI.Models;
using UniverseLib.UI;
using UniverseLib;
using System.Collections;
namespace UnityExplorer.UI.Panels
{
public abstract class UIPanel : UIBehaviourModel
{
#region STATIC
internal static void InvokeOnPanelsReordered() => OnPanelsReordered?.Invoke();
public static event Action OnPanelsReordered;
public static event Action OnClickedOutsidePanels;
internal static readonly List<UIPanel> instances = new();
internal static readonly Dictionary<int, UIPanel> transformToPanelDict = new();
public static void UpdateFocus()
{
if (PanelDragger.ResizePrompting)
return;
// if the user is clicking
if (DisplayManager.MouseInTargetDisplay
&& (InputManager.GetMouseButtonDown(0) || InputManager.GetMouseButtonDown(1)))
{
int count = UIManager.PanelHolder.transform.childCount;
Vector3 mousePos = DisplayManager.MousePosition;
bool clickedInAny = false;
for (int i = count - 1; i >= 0; i--)
{
// make sure this is a real recognized panel
Transform transform = UIManager.PanelHolder.transform.GetChild(i);
if (!transformToPanelDict.TryGetValue(transform.GetInstanceID(), out UIPanel panel))
continue;
// check if our mouse is clicking inside the panel
Vector3 pos = panel.Rect.InverseTransformPoint(mousePos);
if (!panel.Enabled || !panel.Rect.rect.Contains(pos))
continue;
// if this is not the top panel, reorder and invoke the onchanged event
if (transform.GetSiblingIndex() != count - 1)
{
transform.SetAsLastSibling();
OnPanelsReordered?.Invoke();
}
// panel was found, break
clickedInAny = true;
break;
}
if (!clickedInAny)
OnClickedOutsidePanels?.Invoke();
}
}
#endregion
// INSTANCE
public UIPanel()
{
instances.Add(this);
}
public abstract UIManager.Panels PanelType { get; }
public abstract string Name { get; }
public abstract int MinWidth { get; }
public abstract int MinHeight { get; }
public virtual bool ShowByDefault => false;
public virtual bool ShouldSaveActiveState => true;
public virtual bool CanDragAndResize => true;
public virtual bool NavButtonWanted => true;
public ButtonRef NavButton { get; internal set; }
public PanelDragger Dragger { get; internal set; }
public override GameObject UIRoot => uiRoot;
protected GameObject uiRoot;
protected GameObject uiContent;
public RectTransform Rect { get; private set; }
public GameObject TitleBar { get; private set; }
public virtual void OnFinishResize(RectTransform panel)
{
SaveInternalData();
}
public virtual void OnFinishDrag(RectTransform panel)
{
SaveInternalData();
}
public override void SetActive(bool active)
{
if (this.Enabled != active)
{
base.SetActive(active);
if (!ApplyingSaveData)
SaveInternalData();
if (NavButtonWanted)
{
var color = active ? UniversalUI.EnabledButtonColor : UniversalUI.DisabledButtonColor;
RuntimeHelper.SetColorBlock(NavButton.Component, color, color * 1.2f);
}
}
if (!active)
this.Dragger.WasDragging = false;
else
{
this.UIRoot.transform.SetAsLastSibling();
InvokeOnPanelsReordered();
}
}
public override void Destroy()
{
instances.Remove(this);
base.Destroy();
}
protected internal abstract void DoSetDefaultPosAndAnchors();
public void SetTransformDefaults()
{
DoSetDefaultPosAndAnchors();
}
public void EnsureValidSize()
{
if (Rect.rect.width < MinWidth)
Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, MinWidth);
if (Rect.rect.height < MinHeight)
Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, MinHeight);
}
public void EnsureValidPosition() => EnsureValidPosition(this.Rect);
public static void EnsureValidPosition(RectTransform panel)
{
var pos = panel.localPosition;
// Prevent panel going oustide screen bounds
var halfW = DisplayManager.Width * 0.5f;
var halfH = DisplayManager.Height * 0.5f;
pos.x = Math.Max(-halfW - panel.rect.width + 50, Math.Min(pos.x, halfW - 50));
pos.y = Math.Max(-halfH + 50, Math.Min(pos.y, halfH));
panel.localPosition = pos;
}
// Save Data
public bool ApplyingSaveData { get; set; }
public void SaveInternalData()
{
if (UIManager.Initializing)
return;
SetSaveDataToConfigValue();
}
private void SetSaveDataToConfigValue() => ConfigManager.GetPanelSaveData(this.PanelType).Value = this.ToSaveData();
public virtual string ToSaveData()
{
try
{
return string.Join("|", new string[]
{
$"{ShouldSaveActiveState && Enabled}",
Rect.RectAnchorsToString(),
Rect.RectPositionToString()
});
}
catch (Exception ex)
{
ExplorerCore.LogWarning($"Exception generating Panel save data: {ex}");
return "";
}
}
public virtual void ApplySaveData()
{
string data = ConfigManager.GetPanelSaveData(this.PanelType).Value;
ApplySaveData(data);
}
protected virtual void ApplySaveData(string data)
{
if (string.IsNullOrEmpty(data))
return;
var split = data.Split('|');
try
{
Rect.SetAnchorsFromString(split[1]);
Rect.SetPositionFromString(split[2]);
UIManager.SetPanelActive(this.PanelType, bool.Parse(split[0]));
}
catch
{
ExplorerCore.LogWarning("Invalid or corrupt panel save data! Restoring to default.");
SetTransformDefaults();
SetSaveDataToConfigValue();
}
}
// UI Construction
public abstract void ConstructPanelContent();
public void ConstructUI()
{
//this.Enabled = true;
if (NavButtonWanted)
{
// create navbar button
NavButton = UIFactory.CreateButton(UIManager.NavbarTabButtonHolder, $"Button_{PanelType}", Name);
var navBtn = NavButton.Component.gameObject;
navBtn.AddComponent<ContentSizeFitter>().horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(navBtn, false, true, true, true, 0, 0, 0, 5, 5, TextAnchor.MiddleCenter);
UIFactory.SetLayoutElement(navBtn, minWidth: 80);
RuntimeHelper.SetColorBlock(NavButton.Component, UniversalUI.DisabledButtonColor, UniversalUI.DisabledButtonColor * 1.2f);
NavButton.OnClick += () => { UIManager.TogglePanel(PanelType); };
var txtObj = navBtn.transform.Find("Text").gameObject;
txtObj.AddComponent<ContentSizeFitter>().horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
}
// create core canvas
uiRoot = UIFactory.CreatePanel(Name, UIManager.PanelHolder, out uiContent);
Rect = this.uiRoot.GetComponent<RectTransform>();
//UIFactory.SetLayoutGroup<VerticalLayoutGroup>(this.uiRoot, false, false, true, true, 0, 2, 2, 2, 2, TextAnchor.UpperLeft);
int id = this.uiRoot.transform.GetInstanceID();
transformToPanelDict.Add(id, this);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(this.uiContent, false, false, true, true, 2, 2, 2, 2, 2, TextAnchor.UpperLeft);
// Title bar
TitleBar = UIFactory.CreateHorizontalGroup(uiContent, "TitleBar", false, true, true, true, 2,
new Vector4(2, 2, 2, 2), new Color(0.06f, 0.06f, 0.06f));
UIFactory.SetLayoutElement(TitleBar, minHeight: 25, flexibleHeight: 0);
// Title text
var titleTxt = UIFactory.CreateLabel(TitleBar, "TitleBar", Name, TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(titleTxt.gameObject, minWidth: 250, minHeight: 25, flexibleHeight: 0);
// close button
var closeHolder = UIFactory.CreateUIObject("CloseHolder", TitleBar);
UIFactory.SetLayoutElement(closeHolder, minHeight: 25, flexibleHeight: 0, minWidth: 30, flexibleWidth: 9999);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(closeHolder, false, false, true, true, 3, childAlignment: TextAnchor.MiddleRight);
var closeBtn = UIFactory.CreateButton(closeHolder, "CloseButton", "—");
UIFactory.SetLayoutElement(closeBtn.Component.gameObject, minHeight: 25, minWidth: 25, flexibleWidth: 0);
RuntimeHelper.SetColorBlock(closeBtn.Component, new Color(0.33f, 0.32f, 0.31f));
closeBtn.OnClick += () =>
{
UIManager.SetPanelActive(this.PanelType, false);
SaveInternalData();
};
if (!CanDragAndResize)
TitleBar.SetActive(false);
// Panel dragger
Dragger = new PanelDragger(TitleBar.GetComponent<RectTransform>(), Rect, this);
Dragger.OnFinishResize += OnFinishResize;
Dragger.OnFinishDrag += OnFinishDrag;
// content (abstract)
ConstructPanelContent();
UIManager.SetPanelActive(this.PanelType, true);
UIManager.SetPanelActive(this.PanelType, false);
UIManager.SetPanelActive(this.PanelType, ShowByDefault);
ApplyingSaveData = true;
SetTransformDefaults();
// apply panel save data or revert to default
try
{
ApplySaveData();
}
catch (Exception ex)
{
ExplorerCore.Log($"Exception loading panel save data: {ex}");
SetTransformDefaults();
}
RuntimeHelper.StartCoroutine(LateSetupCoroutine());
// simple listener for saving enabled state
this.OnToggleEnabled += (bool val) =>
{
SaveInternalData();
};
ApplyingSaveData = false;
}
private IEnumerator LateSetupCoroutine()
{
yield return null;
// ensure initialized position is valid
EnsureValidSize();
EnsureValidPosition(this.Rect);
// update dragger and save data
Dragger.OnEndResize();
}
public override void ConstructUI(GameObject parent) => ConstructUI();
}
#region WINDOW ANCHORS / POSITION HELPERS
public static class RectSaveExtensions
{
// Window Anchors helpers
internal static string RectAnchorsToString(this RectTransform rect)
{
if (!rect)
throw new ArgumentNullException("rect");
return string.Format(CultureInfo.InvariantCulture, "{0},{1},{2},{3}", new object[]
{
rect.anchorMin.x,
rect.anchorMin.y,
rect.anchorMax.x,
rect.anchorMax.y
});
}
internal static void SetAnchorsFromString(this RectTransform panel, string stringAnchors)
{
if (string.IsNullOrEmpty(stringAnchors))
throw new ArgumentNullException("stringAnchors");
if (stringAnchors.Contains(" "))
// outdated save data, not worth recovering just reset it.
throw new Exception("invalid save data, resetting.");
var split = stringAnchors.Split(',');
if (split.Length != 4)
throw new Exception($"stringAnchors split is unexpected length: {split.Length}");
Vector4 anchors;
anchors.x = float.Parse(split[0], CultureInfo.InvariantCulture);
anchors.y = float.Parse(split[1], CultureInfo.InvariantCulture);
anchors.z = float.Parse(split[2], CultureInfo.InvariantCulture);
anchors.w = float.Parse(split[3], CultureInfo.InvariantCulture);
panel.anchorMin = new Vector2(anchors.x, anchors.y);
panel.anchorMax = new Vector2(anchors.z, anchors.w);
}
internal static string RectPositionToString(this RectTransform rect)
{
if (!rect)
throw new ArgumentNullException("rect");
return string.Format(CultureInfo.InvariantCulture, "{0},{1}", new object[]
{
rect.anchoredPosition.x, rect.anchoredPosition.y
});
}
internal static void SetPositionFromString(this RectTransform rect, string stringPosition)
{
if (string.IsNullOrEmpty(stringPosition))
throw new ArgumentNullException(stringPosition);
if (stringPosition.Contains(" "))
// outdated save data, not worth recovering just reset it.
throw new Exception("invalid save data, resetting.");
var split = stringPosition.Split(',');
if (split.Length != 2)
throw new Exception($"stringPosition split is unexpected length: {split.Length}");
Vector3 vector = rect.anchoredPosition;
vector.x = float.Parse(split[0], CultureInfo.InvariantCulture);
vector.y = float.Parse(split[1], CultureInfo.InvariantCulture);
rect.anchoredPosition = vector;
}
}
#endregion
}

39
src/UI/UEPanelManager.cs Normal file
View File

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityExplorer.UI.Panels;
using UniverseLib.UI;
using UniverseLib.UI.Panels;
namespace UnityExplorer.UI
{
public class UEPanelManager : PanelManager
{
public UEPanelManager(UIBase owner) : base(owner) { }
protected override Vector3 MousePosition => DisplayManager.MousePosition;
protected override Vector2 ScreenDimensions => new(DisplayManager.Width, DisplayManager.Height);
protected override bool MouseInTargetDisplay => DisplayManager.MouseInTargetDisplay;
internal void DoInvokeOnPanelsReordered()
{
InvokeOnPanelsReordered();
}
protected override void SortDraggerHeirarchy()
{
base.SortDraggerHeirarchy();
// move AutoCompleter to first update
if (!UIManager.Initializing && AutoCompleteModal.Instance != null)
{
this.draggerInstances.Remove(AutoCompleteModal.Instance.Dragger);
this.draggerInstances.Insert(0, AutoCompleteModal.Instance.Dragger);
}
}
}
}

View File

@ -10,8 +10,7 @@ using UniverseLib;
using UniverseLib.Input; using UniverseLib.Input;
using UniverseLib.UI; using UniverseLib.UI;
using UniverseLib.UI.Models; using UniverseLib.UI.Models;
using UniverseLib.UI.ObjectPool; using UniverseLib.UI.Panels;
using UniverseLib.UI.Widgets;
using UniverseLib.UI.Widgets.ScrollView; using UniverseLib.UI.Widgets.ScrollView;
using UniverseLib.Utility; using UniverseLib.Utility;
@ -27,10 +26,10 @@ namespace UnityExplorer.UI
Options, Options,
ConsoleLog, ConsoleLog,
AutoCompleter, AutoCompleter,
MouseInspector,
UIInspectorResults, UIInspectorResults,
HookManager, HookManager,
Clipboard Clipboard,
Freecam
} }
public enum VerticalAnchor public enum VerticalAnchor
@ -48,8 +47,7 @@ namespace UnityExplorer.UI
public static RectTransform UIRootRect { get; private set; } public static RectTransform UIRootRect { get; private set; }
public static Canvas UICanvas { get; private set; } public static Canvas UICanvas { get; private set; }
internal static GameObject PanelHolder { get; private set; } internal static readonly Dictionary<Panels, UEPanel> UIPanels = new();
internal static readonly Dictionary<Panels, UIPanel> UIPanels = new();
public static RectTransform NavBarRect; public static RectTransform NavBarRect;
public static GameObject NavbarTabButtonHolder; public static GameObject NavbarTabButtonHolder;
@ -81,7 +79,7 @@ namespace UnityExplorer.UI
internal static void InitUI() internal static void InitUI()
{ {
UiBase = UniversalUI.RegisterUI(ExplorerCore.GUID, Update); UiBase = UniversalUI.RegisterUI<ExplorerUIBase>(ExplorerCore.GUID, Update);
UIRootRect = UIRoot.GetComponent<RectTransform>(); UIRootRect = UIRoot.GetComponent<RectTransform>();
UICanvas = UIRoot.GetComponent<Canvas>(); UICanvas = UIRoot.GetComponent<Canvas>();
@ -93,36 +91,32 @@ namespace UnityExplorer.UI
lastScreenHeight = display.renderingHeight; lastScreenHeight = display.renderingHeight;
// Create UI. // Create UI.
CreatePanelHolder();
CreateTopNavBar(); CreateTopNavBar();
// This could be automated with Assembly.GetTypes(), // This could be automated with Assembly.GetTypes(),
// but the order is important and I'd have to write something to handle the order. // but the order is important and I'd have to write something to handle the order.
UIPanels.Add(Panels.AutoCompleter, new AutoCompleteModal()); UIPanels.Add(Panels.AutoCompleter, new AutoCompleteModal(UiBase));
UIPanels.Add(Panels.ObjectExplorer, new ObjectExplorerPanel()); UIPanels.Add(Panels.ObjectExplorer, new ObjectExplorerPanel(UiBase));
UIPanels.Add(Panels.Inspector, new InspectorPanel()); UIPanels.Add(Panels.Inspector, new InspectorPanel(UiBase));
UIPanels.Add(Panels.CSConsole, new CSConsolePanel()); UIPanels.Add(Panels.CSConsole, new CSConsolePanel(UiBase));
UIPanels.Add(Panels.HookManager, new HookManagerPanel()); UIPanels.Add(Panels.HookManager, new HookManagerPanel(UiBase));
UIPanels.Add(Panels.Clipboard, new ClipboardPanel()); UIPanels.Add(Panels.Freecam, new FreeCamPanel(UiBase));
UIPanels.Add(Panels.ConsoleLog, new LogPanel()); UIPanels.Add(Panels.Clipboard, new ClipboardPanel(UiBase));
UIPanels.Add(Panels.Options, new OptionsPanel()); UIPanels.Add(Panels.ConsoleLog, new LogPanel(UiBase));
UIPanels.Add(Panels.UIInspectorResults, new MouseInspectorResultsPanel()); UIPanels.Add(Panels.Options, new OptionsPanel(UiBase));
UIPanels.Add(Panels.MouseInspector, new MouseInspector()); UIPanels.Add(Panels.UIInspectorResults, new MouseInspectorResultsPanel(UiBase));
foreach (var panel in UIPanels.Values) MouseInspector.inspectorUIBase = UniversalUI.RegisterUI(MouseInspector.UIBaseGUID, null);
panel.ConstructUI(); new MouseInspector(MouseInspector.inspectorUIBase);
// Call some initialize methods // Call some initialize methods
Notification.Init(); Notification.Init();
ConsoleController.Init(); ConsoleController.Init();
// Add this listener to prevent ScrollPool doing anything while we are resizing panels
ScrollPool<ICell>.writingLockedListeners.Add(() => !PanelDragger.Resizing);
// Set default menu visibility // Set default menu visibility
ShowMenu = !ConfigManager.Hide_On_Startup.Value; ShowMenu = !ConfigManager.Hide_On_Startup.Value;
// Failsafe fix, in some games all dropdowns displayed values are blank on startup for some reason. // Failsafe fix, in some games all dropdowns displayed values are blank on startup for some reason.
foreach (var dropdown in UIRoot.GetComponentsInChildren<Dropdown>(true)) foreach (Dropdown dropdown in UIRoot.GetComponentsInChildren<Dropdown>(true))
dropdown.RefreshShownValue(); dropdown.RefreshShownValue();
Initializing = false; Initializing = false;
@ -146,10 +140,6 @@ namespace UnityExplorer.UI
if (InputManager.GetKeyDown(ConfigManager.Force_Unlock_Toggle.Value)) if (InputManager.GetKeyDown(ConfigManager.Force_Unlock_Toggle.Value))
UniverseLib.Config.ConfigManager.Force_Unlock_Mouse = !UniverseLib.Config.ConfigManager.Force_Unlock_Mouse; UniverseLib.Config.ConfigManager.Force_Unlock_Mouse = !UniverseLib.Config.ConfigManager.Force_Unlock_Mouse;
// update focused panel
UIPanel.UpdateFocus();
PanelDragger.UpdateInstances();
// update the timescale value // update the timescale value
if (!timeInput.Component.isFocused && lastTimeScale != Time.timeScale) if (!timeInput.Component.isFocused && lastTimeScale != Time.timeScale)
{ {
@ -167,40 +157,33 @@ namespace UnityExplorer.UI
} }
// check screen dimension change // check screen dimension change
var display = DisplayManager.ActiveDisplay; Display display = DisplayManager.ActiveDisplay;
if (display.renderingWidth != lastScreenWidth || display.renderingHeight != lastScreenHeight) if (display.renderingWidth != lastScreenWidth || display.renderingHeight != lastScreenHeight)
OnScreenDimensionsChanged(); OnScreenDimensionsChanged();
} }
// Panels // Panels
public static UIPanel GetPanel(Panels panel) => UIPanels[panel]; public static UEPanel GetPanel(Panels panel) => UIPanels[panel];
public static T GetPanel<T>(Panels panel) where T : UIPanel => (T)UIPanels[panel]; public static T GetPanel<T>(Panels panel) where T : UEPanel => (T)UIPanels[panel];
public static void TogglePanel(Panels panel) public static void TogglePanel(Panels panel)
{ {
var uiPanel = GetPanel(panel); UEPanel uiPanel = GetPanel(panel);
SetPanelActive(panel, !uiPanel.Enabled); SetPanelActive(panel, !uiPanel.Enabled);
} }
public static void SetPanelActive(Panels panelType, bool active) public static void SetPanelActive(Panels panelType, bool active)
{ {
GetPanel(panelType) GetPanel(panelType).SetActive(active);
.SetActive(active);
} }
public static void SetPanelActive(UIPanel panel, bool active) public static void SetPanelActive(UEPanel panel, bool active)
{ {
panel.SetActive(active); panel.SetActive(active);
} }
internal static void SetPanelActive(Transform transform, bool value)
{
if (UIPanel.transformToPanelDict.TryGetValue(transform.GetInstanceID(), out UIPanel panel))
panel.SetActive(value);
}
// navbar // navbar
public static void SetNavBarAnchor() public static void SetNavBarAnchor()
@ -227,14 +210,14 @@ namespace UnityExplorer.UI
private static void OnScreenDimensionsChanged() private static void OnScreenDimensionsChanged()
{ {
var display = DisplayManager.ActiveDisplay; Display display = DisplayManager.ActiveDisplay;
lastScreenWidth = display.renderingWidth; lastScreenWidth = display.renderingWidth;
lastScreenHeight = display.renderingHeight; lastScreenHeight = display.renderingHeight;
foreach (var panel in UIPanels) foreach (KeyValuePair<Panels, UEPanel> panel in UIPanels)
{ {
panel.Value.EnsureValidSize(); panel.Value.EnsureValidSize();
UIPanel.EnsureValidPosition(panel.Value.Rect); panel.Value.EnsureValidPosition();
panel.Value.Dragger.OnEndResize(); panel.Value.Dragger.OnEndResize();
} }
} }
@ -287,23 +270,9 @@ namespace UnityExplorer.UI
// UI Construction // UI Construction
private static void CreatePanelHolder()
{
PanelHolder = new GameObject("PanelHolder");
PanelHolder.transform.SetParent(UIRoot.transform, false);
PanelHolder.layer = 5;
var rect = PanelHolder.AddComponent<RectTransform>();
rect.sizeDelta = Vector2.zero;
rect.anchoredPosition = Vector2.zero;
rect.pivot = new Vector2(0.5f, 0.5f);
rect.anchorMin = Vector2.zero;
rect.anchorMax = Vector2.one;
PanelHolder.transform.SetAsFirstSibling();
}
private static void CreateTopNavBar() private static void CreateTopNavBar()
{ {
var navbarPanel = UIFactory.CreateUIObject("MainNavbar", UIRoot); GameObject navbarPanel = UIFactory.CreateUIObject("MainNavbar", UIRoot);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(navbarPanel, false, false, true, true, 5, 4, 4, 4, 4, TextAnchor.MiddleCenter); UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(navbarPanel, false, false, true, true, 5, 4, 4, 4, 4, TextAnchor.MiddleCenter);
navbarPanel.AddComponent<Image>().color = new Color(0.1f, 0.1f, 0.1f); navbarPanel.AddComponent<Image>().color = new Color(0.1f, 0.1f, 0.1f);
NavBarRect = navbarPanel.GetComponent<RectTransform>(); NavBarRect = navbarPanel.GetComponent<RectTransform>();
@ -319,9 +288,9 @@ namespace UnityExplorer.UI
// UnityExplorer title // UnityExplorer title
string titleTxt = $"{ExplorerCore.NAME} <i><color=grey>{ExplorerCore.VERSION}</color></i>"; string titleTxt = $"UE <i><color=grey>{ExplorerCore.VERSION}</color></i>";
var title = UIFactory.CreateLabel(navbarPanel, "Title", titleTxt, TextAnchor.MiddleLeft, default, true, 17); Text title = UIFactory.CreateLabel(navbarPanel, "Title", titleTxt, TextAnchor.MiddleCenter, default, true, 14);
UIFactory.SetLayoutElement(title.gameObject, minWidth: 170, flexibleWidth: 0); UIFactory.SetLayoutElement(title.gameObject, minWidth: 75, flexibleWidth: 0);
// panel tabs // panel tabs
@ -331,7 +300,7 @@ namespace UnityExplorer.UI
// Time controls // Time controls
var timeLabel = UIFactory.CreateLabel(navbarPanel, "TimeLabel", "Time:", TextAnchor.MiddleRight, Color.grey); Text timeLabel = UIFactory.CreateLabel(navbarPanel, "TimeLabel", "Time:", TextAnchor.MiddleRight, Color.grey);
UIFactory.SetLayoutElement(timeLabel.gameObject, minHeight: 25, minWidth: 50); UIFactory.SetLayoutElement(timeLabel.gameObject, minHeight: 25, minWidth: 50);
timeInput = UIFactory.CreateInputField(navbarPanel, "TimeInput", "timeScale"); timeInput = UIFactory.CreateInputField(navbarPanel, "TimeInput", "timeScale");

View File

@ -2,8 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
using UnityExplorer.CacheObject.IValues; using UnityExplorer.CacheObject.IValues;
using UniverseLib; using UnityExplorer.UI.Panels;
using UniverseLib.UI;
using UniverseLib.UI.Models; using UniverseLib.UI.Models;
using UniverseLib.Utility; using UniverseLib.Utility;
@ -30,8 +29,8 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
public InputFieldRef InputField { get; } public InputFieldRef InputField { get; }
public bool AnchorToCaretPosition => false; public bool AnchorToCaretPosition => false;
private readonly List<Suggestion> suggestions = new List<Suggestion>(); private readonly List<Suggestion> suggestions = new();
private readonly HashSet<string> suggestedValues = new HashSet<string>(); private readonly HashSet<string> suggestedValues = new();
private OrderedDictionary enumValues; private OrderedDictionary enumValues;
@ -58,7 +57,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
private string GetLastSplitInput(string fullInput) private string GetLastSplitInput(string fullInput)
{ {
string ret = fullInput; string ret = fullInput;
int lastSplit = fullInput.LastIndexOf(','); int lastSplit = fullInput.LastIndexOf(',');
if (lastSplit >= 0) if (lastSplit >= 0)
{ {
@ -139,13 +138,13 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
for (int i = 0; i < this.enumValues.Count; i++) for (int i = 0; i < this.enumValues.Count; i++)
{ {
var enumValue = (CachedEnumValue)enumValues[i]; CachedEnumValue enumValue = (CachedEnumValue)enumValues[i];
if (enumValue.Name.ContainsIgnoreCase(value)) if (enumValue.Name.ContainsIgnoreCase(value))
AddSuggestion(enumValue.Name); AddSuggestion(enumValue.Name);
} }
} }
internal static readonly Dictionary<string, string> sharedValueToLabel = new Dictionary<string, string>(4096); internal static readonly Dictionary<string, string> sharedValueToLabel = new(4096);
void AddSuggestion(string value) void AddSuggestion(string value)
{ {

View File

@ -1,11 +1,4 @@
using System; using UniverseLib.UI.Models;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UniverseLib.UI;
using UniverseLib.UI.Models;
namespace UnityExplorer.UI.Widgets.AutoComplete namespace UnityExplorer.UI.Widgets.AutoComplete
{ {

View File

@ -1,10 +1,4 @@
using System; namespace UnityExplorer.UI.Widgets.AutoComplete
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
namespace UnityExplorer.UI.Widgets.AutoComplete
{ {
public struct Suggestion public struct Suggestion
{ {

View File

@ -1,9 +1,11 @@
using HarmonyLib; using System;
using System; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using UnityEngine;
using UnityExplorer.UI.Panels;
using UniverseLib; using UniverseLib;
using UniverseLib.UI;
using UniverseLib.UI.Models; using UniverseLib.UI.Models;
using UniverseLib.Utility; using UniverseLib.Utility;
@ -13,133 +15,217 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
{ {
public bool Enabled public bool Enabled
{ {
get => _enabled; get => enabled;
set set
{ {
_enabled = value; enabled = value;
if (!_enabled) if (!enabled)
{
AutoCompleteModal.Instance.ReleaseOwnership(this); AutoCompleteModal.Instance.ReleaseOwnership(this);
if (getSuggestionsCoroutine != null)
RuntimeHelper.StopCoroutine(getSuggestionsCoroutine);
}
} }
} }
private bool _enabled = true; bool enabled = true;
public event Action<Suggestion> SuggestionClicked; public event Action<Suggestion> SuggestionClicked;
public Type BaseType { get; set; }
public Type[] GenericConstraints { get; set; }
public bool AllTypes { get; set; }
private readonly bool allowAbstract;
private readonly bool allowEnum;
public InputFieldRef InputField { get; } public InputFieldRef InputField { get; }
public bool AnchorToCaretPosition => false; public bool AnchorToCaretPosition => false;
private readonly List<Suggestion> suggestions = new(); readonly bool allowAbstract;
private readonly HashSet<string> suggestedNames = new(); readonly bool allowEnum;
readonly bool allowGeneric;
private HashSet<Type> allowedTypes; public Type BaseType { get; set; }
HashSet<Type> allowedTypes;
string pendingInput;
Coroutine getSuggestionsCoroutine;
readonly Stopwatch cacheTypesStopwatch = new();
private string chosenSuggestion; readonly List<Suggestion> suggestions = new();
readonly HashSet<string> suggestedTypes = new();
string chosenSuggestion;
readonly List<Suggestion> loadingSuggestions = new()
{
new("<color=grey>Loading...</color>", "")
};
bool ISuggestionProvider.AllowNavigation => false; bool ISuggestionProvider.AllowNavigation => false;
public TypeCompleter(Type baseType, InputFieldRef inputField) : this(baseType, inputField, true, true) { } static readonly Dictionary<string, Type> shorthandToType = new()
{
{ "object", typeof(object) },
{ "string", typeof(string) },
{ "bool", typeof(bool) },
{ "byte", typeof(byte) },
{ "sbyte", typeof(sbyte) },
{ "char", typeof(char) },
{ "decimal", typeof(decimal) },
{ "double", typeof(double) },
{ "float", typeof(float) },
{ "int", typeof(int) },
{ "uint", typeof(uint) },
{ "long", typeof(long) },
{ "ulong", typeof(ulong) },
{ "short", typeof(short) },
{ "ushort", typeof(ushort) },
{ "void", typeof(void) },
};
public TypeCompleter(Type baseType, InputFieldRef inputField, bool allowAbstract, bool allowEnum) public TypeCompleter(Type baseType, InputFieldRef inputField) : this(baseType, inputField, true, true, true) { }
public TypeCompleter(Type baseType, InputFieldRef inputField, bool allowAbstract, bool allowEnum, bool allowGeneric)
{ {
BaseType = baseType; BaseType = baseType;
InputField = inputField; InputField = inputField;
this.allowAbstract = allowAbstract; this.allowAbstract = allowAbstract;
this.allowEnum = allowEnum; this.allowEnum = allowEnum;
this.allowGeneric = allowGeneric;
inputField.OnValueChanged += OnInputFieldChanged; inputField.OnValueChanged += OnInputFieldChanged;
if (BaseType != null) CacheTypes();
CacheTypes();
}
public void CacheTypes()
{
if (!AllTypes)
allowedTypes = ReflectionUtility.GetImplementationsOf(BaseType, allowAbstract, allowEnum, false);
else
{
allowedTypes = new();
foreach (var entry in ReflectionUtility.AllTypes)
{
// skip <PrivateImplementationDetails> and <AnonymousClass> classes
var type = entry.Value;
if (type.FullName.Contains("PrivateImplementationDetails")
|| type.FullName.Contains("DisplayClass")
|| type.FullName.Contains('<'))
{
continue;
}
allowedTypes.Add(type);
}
}
} }
public void OnSuggestionClicked(Suggestion suggestion) public void OnSuggestionClicked(Suggestion suggestion)
{ {
chosenSuggestion = suggestion.UnderlyingValue;
InputField.Text = suggestion.UnderlyingValue; InputField.Text = suggestion.UnderlyingValue;
SuggestionClicked?.Invoke(suggestion); SuggestionClicked?.Invoke(suggestion);
suggestions.Clear(); suggestions.Clear();
AutoCompleteModal.Instance.SetSuggestions(suggestions); //AutoCompleteModal.Instance.SetSuggestions(suggestions, true);
chosenSuggestion = suggestion.UnderlyingValue; AutoCompleteModal.Instance.ReleaseOwnership(this);
} }
private void OnInputFieldChanged(string value) public void CacheTypes()
{
allowedTypes = null;
cacheTypesStopwatch.Reset();
cacheTypesStopwatch.Start();
ReflectionUtility.GetImplementationsOf(BaseType, OnTypesCached, allowAbstract, allowGeneric, allowEnum);
}
void OnTypesCached(HashSet<Type> set)
{
allowedTypes = set;
// ExplorerCore.Log($"Cached {allowedTypes.Count} TypeCompleter types in {cacheTypesStopwatch.ElapsedMilliseconds * 0.001f} seconds.");
if (pendingInput != null)
{
GetSuggestions(pendingInput);
pendingInput = null;
}
}
void OnInputFieldChanged(string input)
{ {
if (!Enabled) if (!Enabled)
return; return;
if (string.IsNullOrEmpty(value) || value == chosenSuggestion) if (input != chosenSuggestion)
{
chosenSuggestion = null; chosenSuggestion = null;
if (string.IsNullOrEmpty(input) || input == chosenSuggestion)
{
if (getSuggestionsCoroutine != null)
RuntimeHelper.StopCoroutine(getSuggestionsCoroutine);
AutoCompleteModal.Instance.ReleaseOwnership(this); AutoCompleteModal.Instance.ReleaseOwnership(this);
} }
else else
{ {
GetSuggestions(value); GetSuggestions(input);
AutoCompleteModal.TakeOwnership(this);
AutoCompleteModal.Instance.SetSuggestions(suggestions);
} }
} }
private void GetSuggestions(string value) void GetSuggestions(string input)
{ {
suggestions.Clear(); if (allowedTypes == null)
suggestedNames.Clear();
if (BaseType == null)
{ {
ExplorerCore.LogWarning("Autocompleter Base type is null!"); if (pendingInput != null)
{
AutoCompleteModal.TakeOwnership(this);
AutoCompleteModal.Instance.SetSuggestions(loadingSuggestions, true);
}
pendingInput = input;
return; return;
} }
if (getSuggestionsCoroutine != null)
RuntimeHelper.StopCoroutine(getSuggestionsCoroutine);
getSuggestionsCoroutine = RuntimeHelper.StartCoroutine(GetSuggestionsAsync(input));
}
IEnumerator GetSuggestionsAsync(string input)
{
suggestions.Clear();
suggestedTypes.Clear();
AutoCompleteModal.TakeOwnership(this);
AutoCompleteModal.Instance.SetSuggestions(suggestions, true);
// shorthand types all inherit from System.Object
if (shorthandToType.TryGetValue(input, out Type shorthand) && allowedTypes.Contains(shorthand))
AddSuggestion(shorthand);
foreach (KeyValuePair<string, Type> entry in shorthandToType)
{
if (allowedTypes.Contains(entry.Value) && entry.Key.StartsWith(input, StringComparison.InvariantCultureIgnoreCase))
AddSuggestion(entry.Value);
}
// Check for exact match first // Check for exact match first
if (ReflectionUtility.GetTypeByName(value) is Type t && allowedTypes.Contains(t)) if (ReflectionUtility.GetTypeByName(input) is Type t && allowedTypes.Contains(t))
AddSuggestion(t); AddSuggestion(t);
foreach (var entry in allowedTypes) if (!suggestions.Any())
AutoCompleteModal.Instance.SetSuggestions(loadingSuggestions, false);
else
AutoCompleteModal.Instance.SetSuggestions(suggestions, false);
Stopwatch sw = new();
sw.Start();
// ExplorerCore.Log($"Checking {allowedTypes.Count} types...");
foreach (Type entry in allowedTypes)
{ {
if (entry.FullName.ContainsIgnoreCase(value)) if (AutoCompleteModal.CurrentHandler == null)
yield break;
if (sw.ElapsedMilliseconds > 10)
{
yield return null;
if (suggestions.Any())
AutoCompleteModal.Instance.SetSuggestions(suggestions, false);
sw.Reset();
sw.Start();
}
if (entry.FullName.ContainsIgnoreCase(input))
AddSuggestion(entry); AddSuggestion(entry);
} }
AutoCompleteModal.Instance.SetSuggestions(suggestions, false);
// ExplorerCore.Log($"Fetched {suggestions.Count} TypeCompleter suggestions in {sw.ElapsedMilliseconds * 0.001f} seconds.");
} }
internal static readonly Dictionary<string, string> sharedTypeToLabel = new(); internal static readonly Dictionary<string, string> sharedTypeToLabel = new();
void AddSuggestion(Type type) void AddSuggestion(Type type)
{ {
if (suggestedNames.Contains(type.FullName)) if (suggestedTypes.Contains(type.FullName))
return; return;
suggestedNames.Add(type.FullName); suggestedTypes.Add(type.FullName);
if (!sharedTypeToLabel.ContainsKey(type.FullName)) if (!sharedTypeToLabel.ContainsKey(type.FullName))
sharedTypeToLabel.Add(type.FullName, SignatureHighlighter.Parse(type, true)); sharedTypeToLabel.Add(type.FullName, SignatureHighlighter.Parse(type, true));

View File

@ -1,8 +1,4 @@
using System; using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.UI.Widgets.AutoComplete; using UnityExplorer.UI.Widgets.AutoComplete;
using UniverseLib.UI; using UniverseLib.UI;
@ -13,8 +9,6 @@ namespace UnityExplorer.UI.Widgets
{ {
public abstract class BaseArgumentHandler : IPooledObject public abstract class BaseArgumentHandler : IPooledObject
{ {
protected EvaluateWidget evaluator;
internal Text argNameLabel; internal Text argNameLabel;
internal InputFieldRef inputField; internal InputFieldRef inputField;
internal TypeCompleter typeCompleter; internal TypeCompleter typeCompleter;
@ -41,8 +35,10 @@ namespace UnityExplorer.UI.Widgets
inputField.Component.lineType = InputField.LineType.MultiLineNewline; inputField.Component.lineType = InputField.LineType.MultiLineNewline;
inputField.UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize; inputField.UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
typeCompleter = new TypeCompleter(typeof(object), this.inputField); typeCompleter = new TypeCompleter(typeof(object), this.inputField)
typeCompleter.Enabled = false; {
Enabled = false
};
CreateSpecialContent(); CreateSpecialContent();

View File

@ -1,16 +1,11 @@
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.UI;
using UniverseLib.UI.Models;
using UnityExplorer.UI.Widgets.AutoComplete;
using UniverseLib.UI;
using UniverseLib;
using UnityExplorer.CacheObject; using UnityExplorer.CacheObject;
using UniverseLib.UI;
using UniverseLib.UI.Models;
using UniverseLib.UI.ObjectPool; using UniverseLib.UI.ObjectPool;
using UniverseLib.Utility; using UniverseLib.Utility;
@ -48,14 +43,14 @@ namespace UnityExplorer.UI.Widgets
public void OnReturnToPool() public void OnReturnToPool()
{ {
foreach (var widget in paramHandlers) foreach (ParameterHandler widget in paramHandlers)
{ {
widget.OnReturned(); widget.OnReturned();
Pool<ParameterHandler>.Return(widget); Pool<ParameterHandler>.Return(widget);
} }
paramHandlers = null; paramHandlers = null;
foreach (var widget in genericHandlers) foreach (GenericArgumentHandler widget in genericHandlers)
{ {
widget.OnReturned(); widget.OnReturned();
Pool<GenericArgumentHandler>.Return(widget); Pool<GenericArgumentHandler>.Return(widget);
@ -111,11 +106,11 @@ namespace UnityExplorer.UI.Widgets
{ {
for (int i = 0; i < genericArguments.Length; i++) for (int i = 0; i < genericArguments.Length; i++)
{ {
var type = genericArguments[i]; Type type = genericArguments[i];
var holder = genericHandlers[i] = Pool<GenericArgumentHandler>.Borrow(); GenericArgumentHandler holder = genericHandlers[i] = Pool<GenericArgumentHandler>.Borrow();
holder.UIRoot.transform.SetParent(this.genericArgumentsHolder.transform, false); holder.UIRoot.transform.SetParent(this.genericArgumentsHolder.transform, false);
holder.OnBorrowed(this, type); holder.OnBorrowed(type);
} }
} }
@ -123,11 +118,11 @@ namespace UnityExplorer.UI.Widgets
{ {
for (int i = 0; i < parameters.Length; i++) for (int i = 0; i < parameters.Length; i++)
{ {
var param = parameters[i]; ParameterInfo param = parameters[i];
var holder = paramHandlers[i] = Pool<ParameterHandler>.Borrow(); ParameterHandler holder = paramHandlers[i] = Pool<ParameterHandler>.Borrow();
holder.UIRoot.transform.SetParent(this.parametersHolder.transform, false); holder.UIRoot.transform.SetParent(this.parametersHolder.transform, false);
holder.OnBorrowed(this, param); holder.OnBorrowed(param);
} }
} }
@ -142,7 +137,7 @@ namespace UnityExplorer.UI.Widgets
// generic args // generic args
this.genericArgumentsHolder = UIFactory.CreateUIObject("GenericHolder", UIRoot); this.genericArgumentsHolder = UIFactory.CreateUIObject("GenericHolder", UIRoot);
UIFactory.SetLayoutElement(genericArgumentsHolder, flexibleWidth: 1000); UIFactory.SetLayoutElement(genericArgumentsHolder, flexibleWidth: 1000);
var genericsTitle = UIFactory.CreateLabel(genericArgumentsHolder, "GenericsTitle", "Generic Arguments", TextAnchor.MiddleLeft); Text genericsTitle = UIFactory.CreateLabel(genericArgumentsHolder, "GenericsTitle", "Generic Arguments", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(genericsTitle.gameObject, minHeight: 25, flexibleWidth: 1000); UIFactory.SetLayoutElement(genericsTitle.gameObject, minHeight: 25, flexibleWidth: 1000);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(genericArgumentsHolder, false, false, true, true, 3); UIFactory.SetLayoutGroup<VerticalLayoutGroup>(genericArgumentsHolder, false, false, true, true, 3);
UIFactory.SetLayoutElement(genericArgumentsHolder, minHeight: 25, flexibleHeight: 750, minWidth: 50, flexibleWidth: 9999); UIFactory.SetLayoutElement(genericArgumentsHolder, minHeight: 25, flexibleHeight: 750, minWidth: 50, flexibleWidth: 9999);
@ -151,14 +146,14 @@ namespace UnityExplorer.UI.Widgets
// args // args
this.parametersHolder = UIFactory.CreateUIObject("ArgHolder", UIRoot); this.parametersHolder = UIFactory.CreateUIObject("ArgHolder", UIRoot);
UIFactory.SetLayoutElement(parametersHolder, flexibleWidth: 1000); UIFactory.SetLayoutElement(parametersHolder, flexibleWidth: 1000);
var argsTitle = UIFactory.CreateLabel(parametersHolder, "ArgsTitle", "Arguments", TextAnchor.MiddleLeft); Text argsTitle = UIFactory.CreateLabel(parametersHolder, "ArgsTitle", "Arguments", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(argsTitle.gameObject, minHeight: 25, flexibleWidth: 1000); UIFactory.SetLayoutElement(argsTitle.gameObject, minHeight: 25, flexibleWidth: 1000);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(parametersHolder, false, false, true, true, 3); UIFactory.SetLayoutGroup<VerticalLayoutGroup>(parametersHolder, false, false, true, true, 3);
UIFactory.SetLayoutElement(parametersHolder, minHeight: 25, flexibleHeight: 750, minWidth: 50, flexibleWidth: 9999); UIFactory.SetLayoutElement(parametersHolder, minHeight: 25, flexibleHeight: 750, minWidth: 50, flexibleWidth: 9999);
//argHolder.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize; //argHolder.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
// evaluate button // evaluate button
var evalButton = UIFactory.CreateButton(UIRoot, "EvaluateButton", "Evaluate", new Color(0.2f, 0.2f, 0.2f)); ButtonRef evalButton = UIFactory.CreateButton(UIRoot, "EvaluateButton", "Evaluate", new Color(0.2f, 0.2f, 0.2f));
UIFactory.SetLayoutElement(evalButton.Component.gameObject, minHeight: 25, minWidth: 150, flexibleWidth: 0); UIFactory.SetLayoutElement(evalButton.Component.gameObject, minHeight: 25, minWidth: 150, flexibleWidth: 0);
evalButton.OnClick += () => evalButton.OnClick += () =>
{ {

Some files were not shown because too many files have changed in this diff Show More