Compare commits

..

11 Commits
3.3.1 ... 3.3.6

Author SHA1 Message Date
6ca117b070 Fix strings boxed as Il2CppSystem.Objects 2021-04-04 13:44:58 +10:00
113f2fd922 3.3.5 - fix Il2Cpp Hashtable, boxed strings 2021-04-04 03:41:36 +10:00
7443f6500e Update README.md 2021-04-03 17:24:28 +11:00
92566c2729 Update README.md 2021-04-02 19:56:18 +11:00
713f87f455 Update THIRDPARTY_LICENSES.md 2021-04-02 17:45:50 +11:00
4241e7e207 Include third-party licenses 2021-04-02 17:44:49 +11:00
6d479a6703 3.3.4
* Fixed Harmony patches not working properly for games which use older BepInEx releases (ie. Risk of Rain 2)
* Fixed a couple minor issues with the config settings
2021-04-02 17:06:49 +11:00
6539f818c3 Update README.md 2021-04-01 22:04:58 +11:00
bc5ffcab40 Update README.md 2021-04-01 17:15:50 +11:00
d070ded036 3.3.3
* Fix `Hide on Startup` not working
* Fix for cases when we try to `scene.GetRootGameObjects()` but the scene has not yet fully loaded.
* MelonLoader releases will no longer spam "Preferences Saved!" constantly in the Console log
* Fix mistake with UI Event System setting/releasing
* Fix some UI elements not having correct Color transition values
2021-04-01 17:13:31 +11:00
8f025622b4 3.3.2
* Added InteractiveColor UI editor to make changing a Color easier
* Added a "Scene Loader" helper which allows you to load any Scene that the game was built with. In some cases you may not find all the Scenes that the game uses, they may be loaded through AssetBundles or other means and won't show up here yet
* Adjusted the SceneExplorer UI, the "Hide" button is now always on the left of the window
*
* Handled some errors related to UI unstripping that could occur in rare cases
2021-03-31 22:58:17 +11:00
53 changed files with 1932 additions and 441 deletions

View File

@ -6,7 +6,7 @@
An in-game explorer and a suite of debugging tools for <a href="https://docs.unity3d.com/Manual/IL2CPP.html">IL2CPP</a> and <b>Mono</b> Unity games, to aid with modding development.
</p>
## Releases [![](https://img.shields.io/github/release/sinai-dev/Explorer.svg?label=release%20notes)](../../releases/latest) [![](https://img.shields.io/github/downloads/sinai-dev/Explorer/total.svg)]() [![](https://img.shields.io/github/downloads/sinai-dev/Explorer/latest/total.svg)]()
## Releases [![](https://img.shields.io/github/release/sinai-dev/Explorer.svg?label=release%20notes)](../../releases/latest) [![](https://img.shields.io/github/downloads/sinai-dev/Explorer/total.svg)](../../releases) [![](https://img.shields.io/github/downloads/sinai-dev/Explorer/latest/total.svg)](../../releases/latest)
| Mod Loader | IL2CPP | Mono |
| ----------- | ------ | ---- |
@ -19,24 +19,54 @@
### BepInEx
0. Install [BepInEx](https://github.com/BepInEx/BepInEx) for your game. For IL2CPP you should use [BepInEx 6 (Bleeding Edge)](https://builds.bepis.io/projects/bepinex_be), for Mono you should use [BepInEx 5](https://github.com/BepInEx/BepInEx/releases) (until Mono support stabilizes in BepInEx 6).
1. Download the UnityExplorer release for BepInEx IL2CPP or Mono above.
2. Take the `UnityExplorer.BIE.___.dll` file and put it in `[GameFolder]\BepInEx\plugins\`
3. In IL2CPP, you will need to download the [Unity libs](https://github.com/LavaGang/Unity-Runtime-Libraries) for the game's Unity version and put them in the `BepInEx\unity-libs\` folder.
1. Install [BepInEx](https://github.com/BepInEx/BepInEx) for your game. For IL2CPP you should use [BepInEx 6 (Bleeding Edge)](https://builds.bepis.io/projects/bepinex_be), for Mono you should use [BepInEx 5](https://github.com/BepInEx/BepInEx/releases) (until Mono support stabilizes in BepInEx 6).
2. Download the UnityExplorer release for BepInEx IL2CPP or Mono above.
3. Take the `UnityExplorer.BIE.___.dll` file and put it in `[GameFolder]\BepInEx\plugins\`
4. In IL2CPP, you will need to download the [Unity libs](https://github.com/LavaGang/Unity-Runtime-Libraries) for the game's Unity version and put them in the `BepInEx\unity-libs\` folder.
### MelonLoader
0. Install [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) 0.3+ for your game. Version 0.3 is currently in pre-release, so you must "Enable ALPHA Releases" in your MelonLoader Installer settings to see the option for it.
1. Download the UnityExplorer release for MelonLoader IL2CPP or Mono above.
2. Take the `UnityExplorer.ML.___.dll` file and put it in the `[GameFolder]\Mods\` folder.
1. Install [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) 0.3+ for your game. Version 0.3 is currently in pre-release, so you must "Enable ALPHA Releases" in your MelonLoader Installer settings to see the option for it.
2. Download the UnityExplorer release for MelonLoader IL2CPP or Mono above.
3. Take the `UnityExplorer.ML.___.dll` file and put it in the `[GameFolder]\Mods\` folder.
### Standalone
The standalone release is based on the BepInEx build, so it requires Harmony 2.0 (or HarmonyX) to function properly.
The standalone release requires you to also load `0Harmony.dll` (HarmonyX, from the `lib\` folder) to function properly, and the IL2CPP also requires `UnhollowerBaseLib.dll` as well. The Mono release should be fairly easy to use with any loader, but the IL2CPP one may be tricky, I'd recommend just using BepInEx or MelonLoader for IL2CPP.
0. Load the DLL from your mod or inject it. You must also make sure `0Harmony.dll` is loaded, and `UnhollowerBaseLib.dll` for IL2CPP as well.
1. Create an instance of Unity Explorer with `UnityExplorer.ExplorerStandalone.CreateInstance();`
2. Optionally subscribe to the `ExplorerStandalone.OnLog` event to handle logging if you wish.
1. Load the UnityExplorer DLL from your mod or inject it, as well as `0Harmony.dll` and `UnhollowerBaseLib.dll` as required.
2. Create an instance of Unity Explorer with `UnityExplorer.ExplorerStandalone.CreateInstance();`
3. Optionally subscribe to the `ExplorerStandalone.OnLog` event to handle logging if you wish.
## Issues and contributions
Both issue reports and PR contributions are welcome in this repository.
### Issue reporting
To report an issue with UnityExplorer, please use the following template (as well as any other information / images you can provide).
Template:
```
* Game issue occurs on:
* UnityExplorer version: (eg BIE.IL2CPP v3.3.3, etc)
* Description of issue:
* Unity log link:
* Mod Loader log link:
```
Please upload your Unity log file to [Pastebin](https://pastebin.com/) (or equivalent service) and provide a link to the paste.
* The log should be found at `%userprofile%\AppData\LocalLow\[Company]\[Game]\` unless redirected by your Mod Loader.
* The file will be called either `output_log.txt` or `Player.log`
As well as the Unity log, please upload your Mod Loader's log:
* BepInEx: `BepInEx\LogOutput.log`
* MelonLoader: `MelonLoader\Latest.log`
## Features
@ -94,31 +124,6 @@ Depending on the release you are using, the config file will be found at:
* MelonLoader: `UserData\MelonPreferences.cfg`
* Standalone `{DLL_location}\UnityExplorer\config.ini`
`Main Menu Toggle` (KeyCode)
* Default: `F7`
* See [this article](https://docs.unity3d.com/ScriptReference/KeyCode.html) for a full list of all accepted KeyCodes.
`Force Unlock Mouse` (bool)
* Default: `true`
* Forces the cursor to be unlocked and visible while the UnityExplorer menu is open, and prevents anything else taking control.
`Default Page Limit` (int)
* Default: `25`
* Sets the default items per page when viewing lists or search results.
* <b>Requires a restart to take effect</b>, apart from Reflection Inspector tabs.
`Default Output Path` (string)
* Default: `Mods\UnityExplorer`
* Where output is generated to, by default (for Texture PNG saving, etc).
`Log Unity Debug` (bool)
* Default: `false`
* Listens for Unity `Debug.Log` messages and prints them to UnityExplorer's log.
`Hide on Startup` (bool)
* Default: `false`
* If true, UnityExplorer will be hidden when you start the game, you must open it via the keybind.
## Building
Building the project should be straight-forward, the references are all inside the `lib\` folder.
@ -130,10 +135,10 @@ Building the project should be straight-forward, the references are all inside t
## Acknowledgments
* [ManlyMarco](https://github.com/ManlyMarco) for [Runtime Unity Editor](https://github.com/ManlyMarco/RuntimeUnityEditor), snippets from the REPL Console were used for UnityExplorer's C# Console.
* [denikson](https://github.com/denikson) (aka Horse) for [mcs-unity](https://github.com/denikson/mcs-unity), used as the `Mono.CSharp` reference for the C# Console.
* [HerpDerpenstine](https://github.com/HerpDerpinstine) for [MelonCoroutines](https://github.com/LavaGang/MelonLoader/blob/master/MelonLoader.Support.Il2Cpp/MelonCoroutines.cs), they were included for standalone IL2CPP coroutine support.
* [InGameCodeEditor](https://assetstore.unity.com/packages/tools/gui/ingame-code-editor-144254) was used as the base for the syntax highlighting for UnityExplorer's C# console (`UnityExplorer.UI.Main.CSConsole.Lexer`).
* [ManlyMarco](https://github.com/ManlyMarco) for [Runtime Unity Editor](https://github.com/ManlyMarco/RuntimeUnityEditor) \[[license](THIRDPARTY_LICENSES.md#runtimeunityeditor-license)\], snippets from the REPL Console were used for UnityExplorer's C# Console.
* [denikson](https://github.com/denikson) (aka Horse) for [mcs-unity](https://github.com/denikson/mcs-unity) \[no license\], used as the `Mono.CSharp` reference for the C# Console.
* [HerpDerpenstine](https://github.com/HerpDerpinstine) for [MelonCoroutines](https://github.com/LavaGang/MelonLoader/blob/6cc958ec23b5e2e8453a73bc2e0d5aa353d4f0d1/MelonLoader.Support.Il2Cpp/MelonCoroutines.cs) \[[license](THIRDPARTY_LICENSES.md#melonloader-license)\], they were included for standalone IL2CPP coroutine support.
* [InGameCodeEditor](https://assetstore.unity.com/packages/tools/gui/ingame-code-editor-144254) \[[license](THIRDPARTY_LICENSES.md#ingamecodeeditor-license)\] was used as the base for the syntax highlighting for UnityExplorer's C# console (`UnityExplorer.UI.Main.CSConsole.Lexer`).
### Disclaimer

1067
THIRDPARTY_LICENSES.md Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -7,6 +7,7 @@ using System.Linq;
using UnityExplorer.Core.Runtime;
using UnityExplorer.UI.Main.CSConsole;
using UnityExplorer.UI.Main.Home;
using UnityExplorer.UI.Inspectors;
namespace UnityExplorer.Core.CSharp
{

View File

@ -46,7 +46,7 @@ namespace UnityExplorer.Core.Config
private void SetValue(T value)
{
if ((m_value == null && value == null) || m_value.Equals(value))
if ((m_value == null && value == null) || (m_value != null && m_value.Equals(value)))
return;
m_value = value;

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using UnityEngine;
using UnityExplorer.UI.Main;
@ -45,6 +46,8 @@ namespace UnityExplorer.Core.Config
PanelDragger.OnFinishDrag += PanelDragger_OnFinishDrag;
MainMenu.OnActiveTabChanged += MainMenu_OnActiveTabChanged;
DebugConsole.OnToggleShow += DebugConsole_OnToggleShow;
InitConsoleCallback();
}
internal static void RegisterConfigElement<T>(ConfigElement<T> configElement)
@ -134,6 +137,33 @@ namespace UnityExplorer.Core.Config
Last_SceneExplorer_State.Value = showing;
}
#region CONSOLE ONEXIT CALLBACK
internal static void InitConsoleCallback()
{
handler = new ConsoleEventDelegate(ConsoleEventCallback);
SetConsoleCtrlHandler(handler, true);
}
static bool ConsoleEventCallback(int eventType)
{
// 2 is Console Quit
if (eventType == 2)
Handler.SaveConfig();
return false;
}
static ConsoleEventDelegate handler;
private delegate bool ConsoleEventDelegate(int eventType);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetConsoleCtrlHandler(ConsoleEventDelegate callback, bool add);
#endregion
#region WINDOW ANCHORS / POSITION HELPERS
// Window Anchors helpers
private const string DEFAULT_WINDOW_ANCHORS = "0.25,0.10,0.78,0.95";
@ -210,5 +240,7 @@ namespace UnityExplorer.Core.Config
//ExplorerCore.LogWarning("Exception setting window position: " + ex);
}
}
#endregion
}
}

View File

@ -46,91 +46,33 @@ namespace UnityExplorer.Core.Input
UpdateCursorControl();
Unlock = true;
Unlock = ConfigManager.Force_Unlock_Mouse.Value;
ConfigManager.Force_Unlock_Mouse.OnValueChanged += (bool val) => { Unlock = val; };
}
private static void SetupPatches()
{
try
{
if (CursorType == null)
{
throw new Exception("Could not find Type 'UnityEngine.Cursor'!");
}
// Get current cursor state and enable cursor
try
{
m_lastLockMode = (CursorLockMode?)typeof(Cursor).GetProperty("lockState", BF.Public | BF.Static)?.GetValue(null, null)
?? CursorLockMode.None;
m_lastVisibleState = (bool?)typeof(Cursor).GetProperty("visible", BF.Public | BF.Static)?.GetValue(null, null)
?? false;
}
catch { }
// Setup Harmony Patches
TryPatch(typeof(Cursor),
"lockState",
new HarmonyMethod(typeof(CursorUnlocker).GetMethod(nameof(Prefix_set_lockState))),
true);
TryPatch(typeof(Cursor),
"visible",
new HarmonyMethod(typeof(CursorUnlocker).GetMethod(nameof(Prefix_set_visible))),
true);
TryPatch(typeof(EventSystem),
"current",
new HarmonyMethod(typeof(CursorUnlocker).GetMethod(nameof(Prefix_EventSystem_set_current))),
true);
}
catch (Exception e)
{
ExplorerCore.Log($"Exception on ForceUnlockCursor.Init! {e.GetType()}, {e.Message}");
}
}
private static void TryPatch(Type type, string property, HarmonyMethod patch, bool setter)
{
try
{
var harmony = ExplorerCore.Loader.HarmonyInstance;
var prop = type.GetProperty(property);
if (setter) // setter is prefix
{
harmony.Patch(prop.GetSetMethod(), prefix: patch);
}
else // getter is postfix
{
harmony.Patch(prop.GetGetMethod(), postfix: patch);
}
}
catch (Exception e)
{
string suf = setter ? "set_" : "get_";
ExplorerCore.Log($"Unable to patch {type.Name}.{suf}{property}: {e.Message}");
}
}
public static void UpdateCursorControl()
{
try
{
m_currentlySettingCursor = true;
if (ShouldActuallyUnlock)
{
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
if (UIManager.EventSys)
SetEventSystem();
}
else
{
Cursor.lockState = m_lastLockMode;
Cursor.visible = m_lastVisibleState;
if (UIManager.EventSys)
ReleaseEventSystem();
}
m_currentlySettingCursor = false;
}
catch (Exception e)
@ -157,9 +99,7 @@ namespace UnityExplorer.Core.Input
if (!m_lastEventSystem)
m_lastEventSystem = EventSystem.current;
//ExplorerCore.Log("Disabling current event system...");
m_lastEventSystem.enabled = false;
//m_lastEventSystem.gameObject.SetActive(false);
}
// Set to our current system
@ -178,7 +118,6 @@ namespace UnityExplorer.Core.Input
if (m_lastEventSystem)
{
m_lastEventSystem.enabled = true;
//m_lastEventSystem.gameObject.SetActive(true);
m_settingEventSystem = true;
EventSystem.current = m_lastEventSystem;
@ -187,7 +126,30 @@ namespace UnityExplorer.Core.Input
}
}
[HarmonyPrefix]
// Patches
private static void SetupPatches()
{
try
{
if (CursorType == null)
throw new Exception("Could not load Type 'UnityEngine.Cursor'!");
// Get current cursor state and enable cursor
m_lastLockMode = (CursorLockMode?)CursorType.GetProperty("lockState", BF.Public | BF.Static)?.GetValue(null, null)
?? CursorLockMode.None;
m_lastVisibleState = (bool?)CursorType.GetProperty("visible", BF.Public | BF.Static)?.GetValue(null, null)
?? false;
ExplorerCore.Loader.SetupPatches();
}
catch (Exception e)
{
ExplorerCore.Log($"Error on CursorUnlocker.Init! {e.GetType()}, {e.Message}");
}
}
public static void Prefix_EventSystem_set_current(ref EventSystem value)
{
if (!m_settingEventSystem)
@ -204,7 +166,6 @@ namespace UnityExplorer.Core.Input
// Also keep track of when anything else tries to set Cursor state, this will be the
// value that we set back to when we close the menu or disable force-unlock.
[HarmonyPrefix]
public static void Prefix_set_lockState(ref CursorLockMode value)
{
if (!m_currentlySettingCursor)
@ -216,7 +177,6 @@ namespace UnityExplorer.Core.Input
}
}
[HarmonyPrefix]
public static void Prefix_set_visible(ref bool value)
{
if (!m_currentlySettingCursor)

View File

@ -7,18 +7,18 @@ using System.Reflection;
using BF = System.Reflection.BindingFlags;
using UnityExplorer.Core.Runtime;
namespace UnityExplorer.Core
namespace UnityExplorer
{
public static class ReflectionUtility
{
public const BF CommonFlags = BF.Public | BF.Instance | BF.NonPublic | BF.Static;
public const BF AllFlags = BF.Public | BF.Instance | BF.NonPublic | BF.Static;
/// <summary>
/// Helper for IL2CPP to get the underlying true Type (Unhollowed) of the object.
/// </summary>
/// <param name="obj">The object to get the true Type for.</param>
/// <returns>The most accurate Type of the object which could be identified.</returns>
public static Type GetType(this object obj)
public static Type GetActualType(this object obj)
{
if (obj == null)
return null;
@ -32,7 +32,7 @@ namespace UnityExplorer.Core
/// <param name="obj">The object to cast</param>
/// <returns>The object, cast to the underlying Type if possible, otherwise the original object.</returns>
public static object Cast(this object obj)
=> ReflectionProvider.Instance.Cast(obj, GetType(obj));
=> ReflectionProvider.Instance.Cast(obj, GetActualType(obj));
/// <summary>
/// Cast an object to a Type, if possible.
@ -105,7 +105,7 @@ namespace UnityExplorer.Core
/// <summary>
/// Get all base types of the provided Type, including itself.
/// </summary>
public static Type[] GetAllBaseTypes(this object obj) => GetAllBaseTypes(GetType(obj));
public static Type[] GetAllBaseTypes(this object obj) => GetAllBaseTypes(GetActualType(obj));
/// <summary>
/// Get all base types of the provided Type, including itself.
@ -163,6 +163,32 @@ namespace UnityExplorer.Core
}
}
internal static Dictionary<Type, Dictionary<string, FieldInfo>> s_cachedFieldInfos = new Dictionary<Type, Dictionary<string, FieldInfo>>();
public static FieldInfo GetFieldInfo(Type type, string fieldName)
{
if (!s_cachedFieldInfos.ContainsKey(type))
s_cachedFieldInfos.Add(type, new Dictionary<string, FieldInfo>());
if (!s_cachedFieldInfos[type].ContainsKey(fieldName))
s_cachedFieldInfos[type].Add(fieldName, type.GetField(fieldName, AllFlags));
return s_cachedFieldInfos[type][fieldName];
}
internal static Dictionary<Type, Dictionary<string, PropertyInfo>> s_cachedPropInfos = new Dictionary<Type, Dictionary<string, PropertyInfo>>();
public static PropertyInfo GetPropertyInfo(Type type, string propertyName)
{
if (!s_cachedPropInfos.ContainsKey(type))
s_cachedPropInfos.Add(type, new Dictionary<string, PropertyInfo>());
if (!s_cachedPropInfos[type].ContainsKey(propertyName))
s_cachedPropInfos[type].Add(propertyName, type.GetProperty(propertyName, AllFlags));
return s_cachedPropInfos[type][propertyName];
}
/// <summary>
/// Helper to display a simple "{ExceptionType}: {Message}" of the exception, and optionally use the inner-most exception.
/// </summary>

View File

@ -13,6 +13,7 @@ using UnityEngine.SceneManagement;
using System.Collections;
using UnityEngine.UI;
using UnityExplorer.Core.Input;
using UnityEngine.EventSystems;
namespace UnityExplorer.Core.Runtime.Il2Cpp
{
@ -88,10 +89,13 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
internal delegate void d_GetRootGameObjects(int handle, IntPtr list);
public override GameObject[] GetRootGameObjects(Scene scene) => GetRootGameObjects(scene.handle);
public static GameObject[] GetRootGameObjects(int handle)
public override GameObject[] GetRootGameObjects(Scene scene)
{
if (!scene.isLoaded)
return new GameObject[0];
int handle = scene.handle;
if (handle == -1)
return new GameObject[0];
@ -121,17 +125,42 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
.Invoke(handle);
}
// Custom check for il2cpp input pointer event
internal static bool? s_doPropertiesExist;
public override void CheckInputPointerEvent()
public override ColorBlock SetColorBlock(ColorBlock colors, Color? normal = null, Color? highlighted = null, Color? pressed = null)
{
// Some IL2CPP games behave weird with multiple UI Input Systems, some fixes for them.
var evt = InputManager.InputPointerEvent;
if (evt != null)
if (s_doPropertiesExist == null)
{
if (!evt.eligibleForClick && evt.selectedObject)
evt.eligibleForClick = true;
var prop = ReflectionUtility.GetPropertyInfo(typeof(ColorBlock), "normalColor") as PropertyInfo;
s_doPropertiesExist = prop != null && prop.CanWrite;
}
colors.colorMultiplier = 1;
object boxed = (object)colors;
if (s_doPropertiesExist == true)
{
if (normal != null)
ReflectionUtility.GetPropertyInfo(typeof(ColorBlock), "normalColor").SetValue(boxed, (Color)normal);
if (pressed != null)
ReflectionUtility.GetPropertyInfo(typeof(ColorBlock), "pressedColor").SetValue(boxed, (Color)pressed);
if (highlighted != null)
ReflectionUtility.GetPropertyInfo(typeof(ColorBlock), "highlightedColor").SetValue(boxed, (Color)highlighted);
}
else if (s_doPropertiesExist == false)
{
if (normal != null)
ReflectionUtility.GetFieldInfo(typeof(ColorBlock), "m_NormalColor").SetValue(boxed, (Color)normal);
if (pressed != null)
ReflectionUtility.GetFieldInfo(typeof(ColorBlock), "m_PressedColor").SetValue(boxed, (Color)pressed);
if (highlighted != null)
ReflectionUtility.GetFieldInfo(typeof(ColorBlock), "m_HighlightedColor").SetValue(boxed, (Color)highlighted);
}
colors = (ColorBlock)boxed;
return colors;
}
}
}

View File

@ -154,21 +154,24 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
/// <returns>The object, as the type (or a normal C# object) if successful or the input value if not.</returns>
public static object Il2CppCast(object obj, Type castTo)
{
if (!(obj is Il2CppSystem.Object ilObj))
if (!(obj is Il2CppSystem.Object cppObj))
return obj;
if (!Il2CppTypeNotNull(castTo, out IntPtr castToPtr))
return obj;
IntPtr castFromPtr = il2cpp_object_get_class(ilObj.Pointer);
IntPtr castFromPtr = il2cpp_object_get_class(cppObj.Pointer);
if (!il2cpp_class_is_assignable_from(castToPtr, castFromPtr))
return obj;
return null;
if (RuntimeSpecificsStore.IsInjected(castToPtr))
return UnhollowerBaseLib.Runtime.ClassInjectorBase.GetMonoObjectFromIl2CppPointer(ilObj.Pointer);
return UnhollowerBaseLib.Runtime.ClassInjectorBase.GetMonoObjectFromIl2CppPointer(cppObj.Pointer);
return Activator.CreateInstance(castTo, ilObj.Pointer);
if (castTo == typeof(string))
return cppObj.ToString();
return Activator.CreateInstance(castTo, cppObj.Pointer);
}
/// <summary>
@ -319,6 +322,14 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
return false;
}
public override void BoxStringToType(ref object value, Type castTo)
{
if (castTo == typeof(Il2CppSystem.String))
value = (Il2CppSystem.String)(value as string);
else
value = (Il2CppSystem.Object)(value as string);
}
// ~~~~~~~~~~ not used ~~~~~~~~~~~~
// cached il2cpp unbox methods

View File

@ -43,7 +43,7 @@ namespace UnityExplorer.Core.Runtime.Mono
public override UnityEngine.Object[] FindObjectsOfTypeAll(Type type)
=> Resources.FindObjectsOfTypeAll(type);
private static readonly FieldInfo fi_Scene_handle = typeof(Scene).GetField("m_Handle", ReflectionUtility.CommonFlags);
private static readonly FieldInfo fi_Scene_handle = typeof(Scene).GetField("m_Handle", ReflectionUtility.AllFlags);
public override int GetSceneHandle(Scene scene)
{
@ -52,6 +52,9 @@ namespace UnityExplorer.Core.Runtime.Mono
public override GameObject[] GetRootGameObjects(Scene scene)
{
if (!scene.isLoaded)
return new GameObject[0];
return scene.GetRootGameObjects();
}
@ -60,9 +63,18 @@ namespace UnityExplorer.Core.Runtime.Mono
return scene.rootCount;
}
public override void CheckInputPointerEvent()
public override ColorBlock SetColorBlock(ColorBlock colors, Color? normal = null, Color? highlighted = null, Color? pressed = null)
{
// Not necessary afaik
if (normal != null)
colors.normalColor = (Color)normal;
if (highlighted != null)
colors.highlightedColor = (Color)highlighted;
if (pressed != null)
colors.pressedColor = (Color)pressed;
return colors;
}
}
}

View File

@ -27,6 +27,9 @@ namespace UnityExplorer.Core.Runtime.Mono
public override string ProcessTypeNameInString(Type type, string theString, ref string typeName)
=> theString;
// not necessary
public override void BoxStringToType(ref object _string, Type castTo) { }
}
}

View File

@ -52,9 +52,9 @@ namespace UnityExplorer.Core.Runtime.Mono
private static MethodInfo GetEncodeToPNGMethod()
{
if (ReflectionUtility.GetTypeByName("UnityEngine.ImageConversion") is Type imageConversion)
return m_encodeToPNGMethod = imageConversion.GetMethod("EncodeToPNG", ReflectionUtility.CommonFlags);
return m_encodeToPNGMethod = imageConversion.GetMethod("EncodeToPNG", ReflectionUtility.AllFlags);
var method = typeof(Texture2D).GetMethod("EncodeToPNG", ReflectionUtility.CommonFlags);
var method = typeof(Texture2D).GetMethod("EncodeToPNG", ReflectionUtility.AllFlags);
if (method != null)
return m_encodeToPNGMethod = method;

View File

@ -25,5 +25,7 @@ namespace UnityExplorer.Core.Runtime
public abstract string ProcessTypeNameInString(Type type, string theString, ref string typeName);
public abstract bool LoadModule(string module);
public abstract void BoxStringToType(ref object _string, Type castTo);
}
}

View File

@ -52,6 +52,6 @@ namespace UnityExplorer.Core.Runtime
public abstract int GetRootCount(Scene scene);
public abstract void CheckInputPointerEvent();
public abstract ColorBlock SetColorBlock(ColorBlock colors, Color? normal = null, Color? highlighted = null, Color? pressed = null);
}
}

27
src/Core/TestClass.cs Normal file
View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UnityExplorer
{
public static class TestClass
{
#if CPP
public static string testStringOne = "Test";
public static Il2CppSystem.Object testStringTwo = "string boxed as cpp object";
public static Il2CppSystem.String testStringThree = "string boxed as cpp string";
public static string nullString = null;
public static Il2CppSystem.Collections.Hashtable testHashset;
static TestClass()
{
testHashset = new Il2CppSystem.Collections.Hashtable();
testHashset.Add("key1", "itemOne");
testHashset.Add("key2", "itemTwo");
testHashset.Add("key3", "itemThree");
}
#endif
}
}

View File

@ -5,6 +5,7 @@ using UnityExplorer.Core.Config;
using UnityExplorer.Core.Input;
using UnityExplorer.Core.Runtime;
using UnityExplorer.UI;
using UnityExplorer.UI.Inspectors;
using UnityExplorer.UI.Main;
namespace UnityExplorer
@ -12,7 +13,7 @@ namespace UnityExplorer
public class ExplorerCore
{
public const string NAME = "UnityExplorer";
public const string VERSION = "3.3.1";
public const string VERSION = "3.3.6";
public const string AUTHOR = "Sinai";
public const string GUID = "com.sinai.unityexplorer";
@ -46,6 +47,8 @@ namespace UnityExplorer
UIManager.Init();
Log($"{NAME} {VERSION} initialized.");
// InspectorManager.Instance.Inspect(typeof(TestClass));
}
public static void Update()

View File

@ -10,6 +10,9 @@ using System.Text;
using UnityExplorer.Core.Config;
using UnityExplorer.Loader.BIE;
using UnityEngine;
using UnityExplorer.Core;
using UnityEngine.EventSystems;
using UnityExplorer.Core.Input;
#if CPP
using BepInEx.IL2CPP;
using UnhollowerRuntimeLib;
@ -75,10 +78,8 @@ namespace UnityExplorer
ClassInjector.RegisterTypeInIl2Cpp<ExplorerBehaviour>();
var obj = new GameObject(
"ExplorerBehaviour",
new Il2CppSystem.Type[] { Il2CppType.Of<ExplorerBehaviour>() }
);
var obj = new GameObject("ExplorerBehaviour");
obj.AddComponent<ExplorerBehaviour>();
obj.hideFlags = HideFlags.HideAndDontSave;
GameObject.DontDestroyOnLoad(obj);
@ -101,6 +102,48 @@ namespace UnityExplorer
}
}
#endif
public void SetupPatches()
{
try
{
this.HarmonyInstance.PatchAll();
}
catch (Exception ex)
{
ExplorerCore.Log($"Exception setting up Harmony patches:\r\n{ex.ReflectionExToString()}");
}
}
[HarmonyPatch(typeof(EventSystem), "current", MethodType.Setter)]
public class PATCH_EventSystem_current
{
[HarmonyPrefix]
public static void Prefix_EventSystem_set_current(ref EventSystem value)
{
CursorUnlocker.Prefix_EventSystem_set_current(ref value);
}
}
[HarmonyPatch(typeof(Cursor), "lockState", MethodType.Setter)]
public class PATCH_Cursor_lockState
{
[HarmonyPrefix]
public static void Prefix_set_lockState(ref CursorLockMode value)
{
CursorUnlocker.Prefix_set_lockState(ref value);
}
}
[HarmonyPatch(typeof(Cursor), "visible", MethodType.Setter)]
public class PATCH_Cursor_visible
{
[HarmonyPrefix]
public static void Prefix_set_visible(ref bool value)
{
CursorUnlocker.Prefix_set_visible(ref value);
}
}
}
}
#endif

View File

@ -17,10 +17,6 @@ namespace UnityExplorer
Action<object> OnLogWarning { get; }
Action<object> OnLogError { get; }
#if ML
Harmony.HarmonyInstance HarmonyInstance { get; }
#else
HarmonyLib.Harmony HarmonyInstance { get; }
#endif
void SetupPatches();
}
}

View File

@ -1,10 +1,14 @@
#if ML
using System;
using System.IO;
using Harmony;
using MelonLoader;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityExplorer;
using UnityExplorer.Core;
using UnityExplorer.Core.Config;
using UnityExplorer.Core.Input;
using UnityExplorer.Loader.ML;
[assembly: MelonInfo(typeof(ExplorerMelonMod), ExplorerCore.NAME, ExplorerCore.VERSION, ExplorerCore.AUTHOR)]
@ -40,6 +44,41 @@ namespace UnityExplorer
{
ExplorerCore.Update();
}
public void SetupPatches()
{
try
{
PrefixProperty(typeof(Cursor),
"lockState",
new HarmonyMethod(typeof(CursorUnlocker).GetMethod(nameof(CursorUnlocker.Prefix_set_lockState))));
PrefixProperty(typeof(Cursor),
"visible",
new HarmonyMethod(typeof(CursorUnlocker).GetMethod(nameof(CursorUnlocker.Prefix_set_visible))));
PrefixProperty(typeof(EventSystem),
"current",
new HarmonyMethod(typeof(CursorUnlocker).GetMethod(nameof(CursorUnlocker.Prefix_EventSystem_set_current))));
}
catch (Exception ex)
{
ExplorerCore.Log($"Exception setting up Harmony patches:\r\n{ex.ReflectionExToString()}");
}
}
private void PrefixProperty(Type type, string property, HarmonyMethod prefix)
{
try
{
var prop = type.GetProperty(property);
this.Harmony.Patch(prop.GetSetMethod(), prefix: prefix);
}
catch (Exception e)
{
ExplorerCore.Log($"Unable to patch {type.Name}.set_{property}: {e.Message}");
}
}
}
}
#endif

View File

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityExplorer.Core;
using UnityExplorer.Core.Config;
namespace UnityExplorer.Loader.ML
@ -20,7 +21,11 @@ namespace UnityExplorer.Loader.ML
{
prefCategory = MelonPreferences.CreateCategory(CTG_NAME, $"{CTG_NAME} Settings");
MelonPreferences.Mapper.RegisterMapper(KeycodeReader, KeycodeWriter);
try
{
MelonPreferences.Mapper.RegisterMapper(KeycodeReader, KeycodeWriter);
}
catch { }
}
public override void LoadConfig()
@ -66,6 +71,10 @@ namespace UnityExplorer.Loader.ML
return default;
}
public override void OnAnyConfigChanged()
{
}
public override void SaveConfig()
{
MelonPreferences.Save();

View File

@ -6,6 +6,9 @@ using System.Reflection;
using UnityEngine;
using UnityExplorer.Core.Config;
using UnityExplorer.Loader.STANDALONE;
using UnityEngine.EventSystems;
using UnityExplorer.Core.Input;
using UnityExplorer.Core;
#if CPP
using UnhollowerRuntimeLib;
#endif
@ -86,17 +89,9 @@ namespace UnityExplorer
#if CPP
ClassInjector.RegisterTypeInIl2Cpp<ExplorerBehaviour>();
var obj = new GameObject(
"ExplorerBehaviour",
new Il2CppSystem.Type[] { Il2CppType.Of<ExplorerBehaviour>() }
);
#else
var obj = new GameObject(
"ExplorerBehaviour",
new Type[] { typeof(ExplorerBehaviour) }
);
#endif
var obj = new GameObject("ExplorerBehaviour");
obj.AddComponent<ExplorerBehaviour>();
GameObject.DontDestroyOnLoad(obj);
obj.hideFlags = HideFlags.HideAndDontSave;
@ -114,6 +109,48 @@ namespace UnityExplorer
ExplorerCore.Update();
}
}
public void SetupPatches()
{
try
{
this.HarmonyInstance.PatchAll();
}
catch (Exception ex)
{
ExplorerCore.Log($"Exception setting up Harmony patches:\r\n{ex.ReflectionExToString()}");
}
}
[HarmonyPatch(typeof(EventSystem), "current", MethodType.Setter)]
public class PATCH_EventSystem_current
{
[HarmonyPrefix]
public static void Prefix_EventSystem_set_current(ref EventSystem value)
{
CursorUnlocker.Prefix_EventSystem_set_current(ref value);
}
}
[HarmonyPatch(typeof(Cursor), "lockState", MethodType.Setter)]
public class PATCH_Cursor_lockState
{
[HarmonyPrefix]
public static void Prefix_set_lockState(ref CursorLockMode value)
{
CursorUnlocker.Prefix_set_lockState(ref value);
}
}
[HarmonyPatch(typeof(Cursor), "visible", MethodType.Setter)]
public class PATCH_Cursor_visible
{
[HarmonyPrefix]
public static void Prefix_set_visible(ref bool value)
{
CursorUnlocker.Prefix_set_visible(ref value);
}
}
}
}
#endif

View File

@ -49,13 +49,9 @@ namespace UnityExplorer.UI.CacheObject
public override void SetValue()
{
RefConfig.BoxedValue = IValue.Value;
ConfigManager.Handler.OnAnyConfigChanged();
}
internal GameObject m_mainGroup;
//internal GameObject m_leftGroup;
//internal GameObject m_rightGroup;
//internal GameObject m_secondRow;
internal override void ConstructUI()
{
@ -66,11 +62,6 @@ namespace UnityExplorer.UI.CacheObject
var horiGroup = UIFactory.CreateHorizontalGroup(m_mainGroup, "ConfigEntryHolder", false, false, true, true, childAlignment: TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(horiGroup, minHeight: 30, flexibleHeight: 0);
//// left group
//m_leftGroup = UIFactory.CreateHorizontalGroup(horiGroup, "ConfigTitleGroup", false, false, true, true, 4, default, new Color(1, 1, 1, 0));
//UIFactory.SetLayoutElement(m_leftGroup, minHeight: 25, flexibleHeight: 0, minWidth: 200, flexibleWidth: 0);
// config entry label
var configLabel = UIFactory.CreateLabel(horiGroup, "ConfigLabel", this.RefConfig.Name, TextAnchor.MiddleLeft);
@ -91,20 +82,11 @@ namespace UnityExplorer.UI.CacheObject
new Color(0.3f, 0.3f, 0.3f));
UIFactory.SetLayoutElement(defaultButton.gameObject, minWidth: 80, minHeight: 22, flexibleWidth: 0);
//// right group
//m_rightGroup = UIFactory.CreateVerticalGroup(horiGroup, "ConfigValueGroup", false, false, true, true, 4, default, new Color(1, 1, 1, 0));
//UIFactory.SetLayoutElement(m_rightGroup, minHeight: 25, minWidth: 150, flexibleHeight: 0, flexibleWidth: 5000);
// Description label
var desc = UIFactory.CreateLabel(m_mainGroup, "Description", $"<i>{RefConfig.Description}</i>", TextAnchor.MiddleLeft, Color.grey);
UIFactory.SetLayoutElement(desc.gameObject, minWidth: 250, minHeight: 20, flexibleWidth: 9999, flexibleHeight: 0);
//// Second row (IValue)
//m_secondRow = UIFactory.CreateHorizontalGroup(m_mainGroup, "DescriptionRow", false, false, true, true, 4, new Color(0.08f, 0.08f, 0.08f));
// IValue
if (IValue != null)

View File

@ -10,7 +10,7 @@ using UnityExplorer.Core.Runtime;
using UnityExplorer.Core;
using UnityExplorer.UI.Utility;
using UnityExplorer.UI.InteractiveValues;
using UnityExplorer.UI.Main.Home.Inspectors.Reflection;
using UnityExplorer.UI.Inspectors.Reflection;
namespace UnityExplorer.UI.CacheObject
{
@ -86,7 +86,7 @@ namespace UnityExplorer.UI.CacheObject
{
try
{
Type baseType = ReflectionUtility.GetType(IValue.Value) ?? FallbackType;
Type baseType = ReflectionUtility.GetActualType(IValue.Value) ?? FallbackType;
if (!ReflectionProvider.Instance.IsReflectionSupported(baseType))
throw new Exception("Type not supported with reflection");
@ -94,7 +94,7 @@ namespace UnityExplorer.UI.CacheObject
UpdateReflection();
if (IValue.Value != null)
IValue.Value = IValue.Value.Cast(ReflectionUtility.GetType(IValue.Value));
IValue.Value = IValue.Value.Cast(ReflectionUtility.GetActualType(IValue.Value));
}
catch (Exception e)
{
@ -320,9 +320,8 @@ namespace UnityExplorer.UI.CacheObject
UIFactory.SetLayoutElement(evalGroupObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 5000);
var colors = new ColorBlock();
colors.normalColor = new Color(0.4f, 0.4f, 0.4f);
colors.highlightedColor = new Color(0.4f, 0.7f, 0.4f);
colors.pressedColor = new Color(0.3f, 0.3f, 0.3f);
colors = RuntimeProvider.Instance.SetColorBlock(colors, new Color(0.4f, 0.4f, 0.4f),
new Color(0.4f, 0.7f, 0.4f), new Color(0.3f, 0.3f, 0.3f));
var evalButton = UIFactory.CreateButton(evalGroupObj,
"EvalButton",
@ -346,9 +345,7 @@ namespace UnityExplorer.UI.CacheObject
argsHolder.SetActive(true);
m_isEvaluating = true;
evalText.text = "Evaluate";
colors = evalButton.colors;
colors.normalColor = new Color(0.3f, 0.6f, 0.3f);
evalButton.colors = colors;
evalButton.colors = RuntimeProvider.Instance.SetColorBlock(evalButton.colors, new Color(0.3f, 0.6f, 0.3f));
cancelButton.gameObject.SetActive(true);
}
@ -368,9 +365,7 @@ namespace UnityExplorer.UI.CacheObject
m_isEvaluating = false;
evalText.text = $"Evaluate ({ParamCount})";
colors = evalButton.colors;
colors.normalColor = new Color(0.4f, 0.4f, 0.4f);
evalButton.colors = colors;
evalButton.colors = RuntimeProvider.Instance.SetColorBlock(evalButton.colors, new Color(0.4f, 0.4f, 0.4f));
});
}
else if (this is CacheMethod)
@ -378,9 +373,8 @@ namespace UnityExplorer.UI.CacheObject
// simple method evaluate button
var colors = new ColorBlock();
colors.normalColor = new Color(0.4f, 0.4f, 0.4f);
colors.highlightedColor = new Color(0.4f, 0.7f, 0.4f);
colors.pressedColor = new Color(0.3f, 0.3f, 0.3f);
colors = RuntimeProvider.Instance.SetColorBlock(colors, new Color(0.4f, 0.4f, 0.4f),
new Color(0.4f, 0.7f, 0.4f), new Color(0.3f, 0.3f, 0.3f));
var evalButton = UIFactory.CreateButton(m_rightGroup, "EvalButton", "Evaluate", () => { (this as CacheMethod).Evaluate(); }, colors);
UIFactory.SetLayoutElement(evalButton.gameObject, minWidth: 100, minHeight: 22, flexibleWidth: 0);

View File

@ -55,7 +55,7 @@ namespace UnityExplorer.UI.CacheObject
// if the type has changed fundamentally, make a new interactivevalue for it
var type = value == null
? FallbackType
: ReflectionUtility.GetType(value);
: ReflectionUtility.GetActualType(value);
var ivalueType = InteractiveValue.GetIValueForType(type);

View File

@ -4,9 +4,10 @@ using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.Core.Runtime;
using UnityExplorer.UI.Utility;
namespace UnityExplorer.UI.Main.Home.Inspectors.GameObjects
namespace UnityExplorer.UI.Inspectors.GameObjects
{
public class ChildList
{
@ -168,9 +169,8 @@ namespace UnityExplorer.UI.Main.Home.Inspectors.GameObjects
toggle.onValueChanged.AddListener((bool val) => { OnToggleClicked(thisIndex, val); });
ColorBlock mainColors = new ColorBlock();
mainColors.normalColor = new Color(0.07f, 0.07f, 0.07f);
mainColors.highlightedColor = new Color(0.2f, 0.2f, 0.2f, 1);
mainColors.pressedColor = new Color(0.05f, 0.05f, 0.05f);
mainColors = RuntimeProvider.Instance.SetColorBlock(mainColors, new Color(0.07f, 0.07f, 0.07f),
new Color(0.2f, 0.2f, 0.2f, 1), new Color(0.05f, 0.05f, 0.05f));
var mainBtn = UIFactory.CreateButton(btnGroupObj,
"MainButton",

View File

@ -5,9 +5,10 @@ using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.Core;
using UnityExplorer.Core.Runtime;
using UnityExplorer.UI.Utility;
namespace UnityExplorer.UI.Main.Home.Inspectors.GameObjects
namespace UnityExplorer.UI.Inspectors.GameObjects
{
public class ComponentList
{
@ -74,7 +75,7 @@ namespace UnityExplorer.UI.Main.Home.Inspectors.GameObjects
var text = s_compListTexts[i];
text.text = SignatureHighlighter.ParseFullSyntax(ReflectionUtility.GetType(comp), true);
text.text = SignatureHighlighter.ParseFullSyntax(ReflectionUtility.GetActualType(comp), true);
var toggle = s_compToggles[i];
#if CPP
@ -175,9 +176,8 @@ namespace UnityExplorer.UI.Main.Home.Inspectors.GameObjects
// Main component button
ColorBlock mainColors = new ColorBlock();
mainColors.normalColor = new Color(0.07f, 0.07f, 0.07f);
mainColors.highlightedColor = new Color(0.2f, 0.2f, 0.2f, 1);
mainColors.pressedColor = new Color(0.05f, 0.05f, 0.05f);
mainColors = RuntimeProvider.Instance.SetColorBlock(mainColors, new Color(0.07f, 0.07f, 0.07f),
new Color(0.2f, 0.2f, 0.2f, 1), new Color(0.05f, 0.05f, 0.05f));
var mainBtn = UIFactory.CreateButton(groupObj,
"MainButton",

View File

@ -5,9 +5,10 @@ using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.Core.Input;
using UnityExplorer.Core.Runtime;
using UnityExplorer.Core.Unity;
namespace UnityExplorer.UI.Main.Home.Inspectors.GameObjects
namespace UnityExplorer.UI.Inspectors.GameObjects
{
public class GameObjectControls
{
@ -407,9 +408,7 @@ namespace UnityExplorer.UI.Main.Home.Inspectors.GameObjects
var sliderObj = UIFactory.CreateSlider(rowObject, "VectorSlider", out Slider slider);
UIFactory.SetLayoutElement(sliderObj, minHeight: 20, flexibleHeight: 0, minWidth: 200, flexibleWidth: 9000);
sliderObj.transform.Find("Fill Area").gameObject.SetActive(false);
var sliderColors = slider.colors;
sliderColors.normalColor = new Color(0.65f, 0.65f, 0.65f);
slider.colors = sliderColors;
slider.colors = RuntimeProvider.Instance.SetColorBlock(slider.colors, new Color(0.65f, 0.65f, 0.65f));
slider.minValue = -2;
slider.maxValue = 2;
slider.value = 0;

View File

@ -7,7 +7,7 @@ using UnityEngine.UI;
using UnityExplorer.Core.Runtime;
using UnityExplorer.Core.Unity;
namespace UnityExplorer.UI.Main.Home.Inspectors.GameObjects
namespace UnityExplorer.UI.Inspectors.GameObjects
{
public class GameObjectInspector : InspectorBase
{

View File

@ -11,6 +11,7 @@ using UnityExplorer.Core.Input;
using UnityExplorer.Core.Runtime;
using UnityExplorer.UI;
using UnityExplorer.UI.Main;
using UnityExplorer.UI.Inspectors;
namespace UnityExplorer.UI.Main.Home
{

View File

@ -3,7 +3,7 @@ using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.Core.Unity;
namespace UnityExplorer.UI.Main.Home.Inspectors
namespace UnityExplorer.UI.Inspectors
{
public abstract class InspectorBase
{

View File

@ -9,12 +9,11 @@ using UnityEngine.SceneManagement;
using UnityEngine.UI;
using UnityExplorer.Core.Runtime;
using UnityExplorer.UI.Main.Home;
using UnityExplorer.UI.Main.Home.Inspectors;
using UnityExplorer.UI.CacheObject;
using UnityExplorer.UI.Main.Home.Inspectors.GameObjects;
using UnityExplorer.UI.Main.Home.Inspectors.Reflection;
using UnityExplorer.UI.Inspectors.GameObjects;
using UnityExplorer.UI.Inspectors.Reflection;
namespace UnityExplorer.UI.Main.Home
namespace UnityExplorer.UI.Inspectors
{
public class InspectorManager
{
@ -141,18 +140,13 @@ namespace UnityExplorer.UI.Main.Home
public void OnSetInspectorTab(InspectorBase inspector)
{
Color activeColor = new Color(0, 0.25f, 0, 1);
ColorBlock colors = inspector.m_tabButton.colors;
colors.normalColor = activeColor;
colors.highlightedColor = activeColor;
inspector.m_tabButton.colors = colors;
inspector.m_tabButton.colors = RuntimeProvider.Instance.SetColorBlock(inspector.m_tabButton.colors, activeColor, activeColor);
}
public void OnUnsetInspectorTab()
{
ColorBlock colors = m_activeInspector.m_tabButton.colors;
colors.normalColor = new Color(0.2f, 0.2f, 0.2f, 1);
colors.highlightedColor = new Color(0.1f, 0.3f, 0.1f, 1);
m_activeInspector.m_tabButton.colors = colors;
m_activeInspector.m_tabButton.colors = RuntimeProvider.Instance.SetColorBlock(m_activeInspector.m_tabButton.colors,
new Color(0.2f, 0.2f, 0.2f, 1), new Color(0.1f, 0.3f, 0.1f, 1));
}
public void ConstructInspectorPane()

View File

@ -9,7 +9,7 @@ using UnityExplorer.Core;
using UnityExplorer.Core.Config;
using UnityExplorer.Core.Runtime;
namespace UnityExplorer.UI.Main.Home.Inspectors.Reflection
namespace UnityExplorer.UI.Inspectors.Reflection
{
public enum MemberScopes
{
@ -30,18 +30,12 @@ namespace UnityExplorer.UI.Main.Home.Inspectors.Reflection
internal void OnScopeFilterClicked(MemberScopes type, Button button)
{
if (m_lastActiveScopeButton)
{
var lastColors = m_lastActiveScopeButton.colors;
lastColors.normalColor = new Color(0.2f, 0.2f, 0.2f);
m_lastActiveScopeButton.colors = lastColors;
}
m_lastActiveScopeButton.colors = RuntimeProvider.Instance.SetColorBlock(m_lastActiveScopeButton.colors, new Color(0.2f, 0.2f, 0.2f));
m_scopeFilter = type;
m_lastActiveScopeButton = button;
var colors = m_lastActiveScopeButton.colors;
colors.normalColor = new Color(0.2f, 0.6f, 0.2f);
m_lastActiveScopeButton.colors = colors;
m_lastActiveScopeButton.colors = RuntimeProvider.Instance.SetColorBlock(m_lastActiveScopeButton.colors, new Color(0.2f, 0.6f, 0.2f));
FilterMembers(null, true);
m_sliderScroller.m_slider.value = 1f;
@ -246,17 +240,14 @@ namespace UnityExplorer.UI.Main.Home.Inspectors.Reflection
btn.onClick.AddListener(() => { OnScopeFilterClicked(type, btn); });
var colors = btn.colors;
colors.highlightedColor = new Color(0.3f, 0.7f, 0.3f);
btn.colors = RuntimeProvider.Instance.SetColorBlock(btn.colors, highlighted: new Color(0.3f, 0.7f, 0.3f));
if (setEnabled)
{
colors.normalColor = new Color(0.2f, 0.6f, 0.2f);
btn.colors = RuntimeProvider.Instance.SetColorBlock(btn.colors, new Color(0.2f, 0.6f, 0.2f));
m_scopeFilter = type;
m_lastActiveScopeButton = btn;
}
btn.colors = colors;
}
}
}

View File

@ -7,10 +7,13 @@ using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.Core;
using UnityExplorer.Core.Config;
using UnityExplorer.Core.Runtime;
using UnityExplorer.UI.CacheObject;
using UnityExplorer.UI.Main;
using UnityExplorer.UI.Main.Home;
using UnityExplorer.UI.Utility;
namespace UnityExplorer.UI.Main.Home.Inspectors.Reflection
namespace UnityExplorer.UI.Inspectors.Reflection
{
public class ReflectionInspector : InspectorBase
{
@ -77,7 +80,7 @@ namespace UnityExplorer.UI.Main.Home.Inspectors.Reflection
if (this is StaticInspector)
m_targetType = target as Type;
else
m_targetType = ReflectionUtility.GetType(target);
m_targetType = ReflectionUtility.GetActualType(target);
m_targetTypeShortName = SignatureHighlighter.ParseFullSyntax(m_targetType, false);
@ -238,18 +241,12 @@ namespace UnityExplorer.UI.Main.Home.Inspectors.Reflection
internal void OnMemberFilterClicked(MemberTypes type, Button button)
{
if (m_lastActiveMemButton)
{
var lastColors = m_lastActiveMemButton.colors;
lastColors.normalColor = new Color(0.2f, 0.2f, 0.2f);
m_lastActiveMemButton.colors = lastColors;
}
m_lastActiveMemButton.colors = RuntimeProvider.Instance.SetColorBlock(m_lastActiveMemButton.colors, new Color(0.2f, 0.2f, 0.2f));
m_memberFilter = type;
m_lastActiveMemButton = button;
var colors = m_lastActiveMemButton.colors;
colors.normalColor = new Color(0.2f, 0.6f, 0.2f);
m_lastActiveMemButton.colors = colors;
m_lastActiveMemButton.colors = RuntimeProvider.Instance.SetColorBlock(m_lastActiveMemButton.colors, new Color(0.2f, 0.6f, 0.2f));
FilterMembers(null, true);
m_sliderScroller.m_slider.value = 1f;
@ -464,17 +461,14 @@ namespace UnityExplorer.UI.Main.Home.Inspectors.Reflection
UIFactory.SetLayoutElement(btn.gameObject, minHeight: 25, minWidth: 70);
btn.onClick.AddListener(() => { OnMemberFilterClicked(type, btn); });
var colors = btn.colors;
colors.highlightedColor = new Color(0.3f, 0.7f, 0.3f);
btn.colors = RuntimeProvider.Instance.SetColorBlock(btn.colors, highlighted: new Color(0.3f, 0.7f, 0.3f));
if (setEnabled)
{
colors.normalColor = new Color(0.2f, 0.6f, 0.2f);
btn.colors = RuntimeProvider.Instance.SetColorBlock(btn.colors, new Color(0.2f, 0.6f, 0.2f));
m_memberFilter = type;
m_lastActiveMemButton = btn;
}
btn.colors = colors;
}
internal void ConstructUpdateRow()

View File

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UnityExplorer.UI.Main.Home.Inspectors.Reflection
namespace UnityExplorer.UI.Inspectors.Reflection
{
public class StaticInspector : ReflectionInspector
{

View File

@ -88,13 +88,13 @@ namespace UnityExplorer.UI.InteractiveValues
if (Owner.CanWrite)
{
var toggleObj = UIFactory.CreateToggle(m_valueContent, "InteractiveBoolToggle", out m_toggle, out _, new Color(0.1f, 0.1f, 0.1f));
var toggleObj = UIFactory.CreateToggle(m_mainContent, "InteractiveBoolToggle", out m_toggle, out _, new Color(0.1f, 0.1f, 0.1f));
UIFactory.SetLayoutElement(toggleObj, minWidth: 24);
m_toggle.onValueChanged.AddListener(OnToggleValueChanged);
m_baseLabel.transform.SetAsLastSibling();
m_applyBtn = UIFactory.CreateButton(m_valueContent,
m_applyBtn = UIFactory.CreateButton(m_mainContent,
"ApplyButton",
"Apply",
() => { Owner.SetValue(); },

View File

@ -0,0 +1,168 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
namespace UnityExplorer.UI.InteractiveValues
{
public class InteractiveColor : InteractiveValue
{
//~~~~~~~~~ Instance ~~~~~~~~~~
public InteractiveColor(object value, Type valueType) : base(value, valueType) { }
public override bool HasSubContent => true;
public override bool SubContentWanted => true;
public override bool WantInspectBtn => true;
public override void RefreshUIForValue()
{
base.RefreshUIForValue();
if (m_subContentConstructed)
RefreshUI();
}
private void RefreshUI()
{
var color = (Color)this.Value;
m_inputs[0].text = color.r.ToString();
m_inputs[1].text = color.g.ToString();
m_inputs[2].text = color.b.ToString();
m_inputs[3].text = color.a.ToString();
if (m_colorImage)
m_colorImage.color = color;
}
internal override void OnToggleSubcontent(bool toggle)
{
base.OnToggleSubcontent(toggle);
RefreshUI();
}
#region UI CONSTRUCTION
private Image m_colorImage;
private readonly InputField[] m_inputs = new InputField[4];
private readonly Slider[] m_sliders = new Slider[4];
public override void ConstructUI(GameObject parent, GameObject subGroup)
{
base.ConstructUI(parent, subGroup);
//// Limit the label width for colors, they're always about the same so make use of that space.
//UIFactory.SetLayoutElement(this.m_baseLabel.gameObject, flexibleWidth: 0, minWidth: 250);
}
public override void ConstructSubcontent()
{
base.ConstructSubcontent();
var horiGroup = UIFactory.CreateHorizontalGroup(m_subContentParent, "ColorEditor", false, false, true, true, 5,
default, default, TextAnchor.MiddleLeft);
var editorContainer = UIFactory.CreateVerticalGroup(horiGroup, "EditorContent", false, true, true, true, 2, new Vector4(4, 4, 4, 4),
new Color(0.08f, 0.08f, 0.08f));
UIFactory.SetLayoutElement(editorContainer, minWidth: 300, flexibleWidth: 0);
for (int i = 0; i < 4; i++)
AddEditorRow(i, editorContainer);
if (Owner.CanWrite)
{
var applyBtn = UIFactory.CreateButton(editorContainer, "ApplyButton", "Apply", OnSetValue, new Color(0.2f, 0.2f, 0.2f));
UIFactory.SetLayoutElement(applyBtn.gameObject, minWidth: 175, minHeight: 25, flexibleWidth: 0);
void OnSetValue()
{
Owner.SetValue();
RefreshUIForValue();
}
}
var imgHolder = UIFactory.CreateVerticalGroup(horiGroup, "ImgHolder", true, true, true, true, 0, new Vector4(1, 1, 1, 1),
new Color(0.08f, 0.08f, 0.08f));
UIFactory.SetLayoutElement(imgHolder, minWidth: 128, minHeight: 128, flexibleWidth: 0, flexibleHeight: 0);
var imgObj = UIFactory.CreateUIObject("ColorImageHelper", imgHolder, new Vector2(100, 25));
m_colorImage = imgObj.AddComponent<Image>();
m_colorImage.color = (Color)this.Value;
}
private static readonly string[] s_fieldNames = new[] { "R", "G", "B", "A" };
internal void AddEditorRow(int index, GameObject groupObj)
{
var row = UIFactory.CreateHorizontalGroup(groupObj, "EditorRow_" + s_fieldNames[index],
false, true, true, true, 5, default, new Color(1, 1, 1, 0));
var label = UIFactory.CreateLabel(row, "RowLabel", $"{s_fieldNames[index]}:", TextAnchor.MiddleRight, Color.cyan);
UIFactory.SetLayoutElement(label.gameObject, minWidth: 50, flexibleWidth: 0, minHeight: 25);
var inputFieldObj = UIFactory.CreateInputField(row, "InputField", "...", 14, 3, 1);
UIFactory.SetLayoutElement(inputFieldObj, minWidth: 120, minHeight: 25, flexibleWidth: 0);
var inputField = inputFieldObj.GetComponent<InputField>();
m_inputs[index] = inputField;
inputField.characterValidation = InputField.CharacterValidation.Decimal;
inputField.onValueChanged.AddListener((string value) =>
{
float val = float.Parse(value);
SetValueToColor(val);
m_sliders[index].value = val;
});
var sliderObj = UIFactory.CreateSlider(row, "Slider", out Slider slider);
m_sliders[index] = slider;
UIFactory.SetLayoutElement(sliderObj, minWidth: 200, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
slider.minValue = 0;
slider.maxValue = 1;
slider.value = GetValueFromColor();
slider.onValueChanged.AddListener((float value) =>
{
inputField.text = value.ToString();
SetValueToColor(value);
m_inputs[index].text = value.ToString();
});
// methods for writing to the color for this field
void SetValueToColor(float floatValue)
{
Color _color = (Color)Value;
switch (index)
{
case 0: _color.r = floatValue; break;
case 1: _color.g = floatValue; break;
case 2: _color.b = floatValue; break;
case 3: _color.a = floatValue; break;
}
Value = _color;
m_colorImage.color = _color;
}
float GetValueFromColor()
{
Color _color = (Color)Value;
switch (index)
{
case 0: return _color.r;
case 1: return _color.g;
case 2: return _color.b;
case 3: return _color.a;
default: throw new NotImplementedException();
}
}
}
#endregion
}
}

View File

@ -218,32 +218,37 @@ namespace UnityExplorer.UI.InteractiveValues
private IDictionary EnumerateWithReflection()
{
var valueType = ReflectionUtility.GetType(Value);
var valueType = ReflectionUtility.GetActualType(Value);
// get keys and values
var keys = valueType.GetProperty("Keys").GetValue(Value, null);
var values = valueType.GetProperty("Values").GetValue(Value, null);
// create lists to hold them
var keyList = new List<object>();
var valueList = new List<object>();
// store entries with reflection
EnumerateCollection(keys, keyList);
EnumerateCollection(values, valueList);
var hashtable = Value.Cast(typeof(Il2CppSystem.Collections.Hashtable)) as Il2CppSystem.Collections.Hashtable;
// make actual mono dictionary
var dict = (IDictionary)Activator.CreateInstance(typeof(Dictionary<,>)
.MakeGenericType(m_typeOfKeys, m_typeofValues));
if (hashtable != null)
{
EnumerateCppHashtable(hashtable, keyList, valueList);
}
else
{
var keys = valueType.GetProperty("Keys").GetValue(Value, null);
var values = valueType.GetProperty("Values").GetValue(Value, null);
EnumerateCppIDictionary(keys, keyList);
EnumerateCppIDictionary(values, valueList);
}
var dict = Activator.CreateInstance(typeof(Dictionary<,>)
.MakeGenericType(m_typeOfKeys, m_typeofValues))
as IDictionary;
// finally iterate into mono dictionary
for (int i = 0; i < keyList.Count; i++)
dict.Add(keyList[i], valueList[i]);
return dict;
}
private void EnumerateCollection(object collection, List<object> list)
private void EnumerateCppIDictionary(object collection, List<object> list)
{
// invoke GetEnumerator
var enumerator = collection.GetType().GetMethod("GetEnumerator").Invoke(collection, null);
@ -258,11 +263,23 @@ namespace UnityExplorer.UI.InteractiveValues
list.Add(current.GetValue(enumerator, null));
}
}
private void EnumerateCppHashtable(Il2CppSystem.Collections.Hashtable hashtable, List<object> keys, List<object> values)
{
for (int i = 0; i < hashtable.buckets.Count; i++)
{
var bucket = hashtable.buckets[i];
if (bucket == null || bucket.key == null)
continue;
keys.Add(bucket.key);
values.Add(bucket.val);
}
}
#endif
#endregion
#endregion
#region UI CONSTRUCTION
#region UI CONSTRUCTION
internal GameObject m_listContent;
internal LayoutElement m_listLayout;

View File

@ -6,6 +6,7 @@ using System.Reflection;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.Core;
using UnityExplorer.Core.Config;
using UnityExplorer.Core.Unity;
using UnityExplorer.UI;
@ -38,11 +39,11 @@ namespace UnityExplorer.UI.InteractiveValues
internal IEnumerable RefIEnumerable;
internal IList RefIList;
#if CPP
internal Il2CppSystem.Collections.ICollection CppICollection;
#else
internal ICollection CppICollection = null;
#endif
//#if CPP
// internal object CppICollection;
//#else
// internal object CppICollection = null;
//#endif
internal readonly Type m_baseEntryType;
@ -55,13 +56,17 @@ namespace UnityExplorer.UI.InteractiveValues
RefIEnumerable = Value as IEnumerable;
RefIList = Value as IList;
#if CPP
if (Value != null && RefIList == null)
{
try { CppICollection = (Value as Il2CppSystem.Object).TryCast<Il2CppSystem.Collections.ICollection>(); }
catch { }
}
#endif
//#if CPP
// if (Value != null && RefIList == null)
// {
// try
// {
// var type = typeof(Il2CppSystem.Collections.ICollection).MakeGenericType(this.m_baseEntryType);
// CppICollection = (Value as Il2CppSystem.Object).Cast(type);
// }
// catch { }
// }
//#endif
if (m_subContentParent.activeSelf)
{
@ -91,8 +96,8 @@ namespace UnityExplorer.UI.InteractiveValues
if (Value != null)
{
string count = "?";
if (m_recacheWanted && (RefIList != null || CppICollection != null))
count = RefIList?.Count.ToString() ?? CppICollection.Count.ToString();
if (m_recacheWanted && RefIList != null)// || CppICollection != null))
count = RefIList.Count.ToString();// ?? CppICollection.Count.ToString();
else if (!m_recacheWanted)
count = m_entries.Count.ToString();

View File

@ -102,7 +102,7 @@ namespace UnityExplorer.UI.InteractiveValues
labelLayout.minWidth = 50;
labelLayout.flexibleWidth = 0;
var inputObj = UIFactory.CreateInputField(m_valueContent, "InteractiveNumberInput", "...");
var inputObj = UIFactory.CreateInputField(m_mainContent, "InteractiveNumberInput", "...");
UIFactory.SetLayoutElement(inputObj, minWidth: 120, minHeight: 25, flexibleWidth: 0);
m_valueInput = inputObj.GetComponent<InputField>();
@ -110,7 +110,7 @@ namespace UnityExplorer.UI.InteractiveValues
if (Owner.CanWrite)
{
m_applyBtn = UIFactory.CreateButton(m_valueContent, "ApplyButton", "Apply", OnApplyClicked, new Color(0.2f, 0.2f, 0.2f));
m_applyBtn = UIFactory.CreateButton(m_mainContent, "ApplyButton", "Apply", OnApplyClicked, new Color(0.2f, 0.2f, 0.2f));
UIFactory.SetLayoutElement(m_applyBtn.gameObject, minWidth: 50, minHeight: 25, flexibleWidth: 0);
}
}

View File

@ -9,6 +9,7 @@ using UnityExplorer.Core.Unity;
using UnityExplorer.UI;
using UnityExplorer.UI.Utility;
using UnityExplorer.UI.CacheObject;
using UnityExplorer.Core.Runtime;
namespace UnityExplorer.UI.InteractiveValues
{
@ -23,6 +24,14 @@ namespace UnityExplorer.UI.InteractiveValues
public override void OnValueUpdated()
{
#if CPP
// strings boxed as Il2CppSystem.Objects can behave weirdly.
// GetActualType will find they are a string, but if its boxed
// then we need to unbox it like this...
if (!(Value is string) && Value is Il2CppSystem.Object cppobj)
Value = cppobj.ToString();
#endif
base.OnValueUpdated();
}
@ -88,10 +97,18 @@ namespace UnityExplorer.UI.InteractiveValues
m_labelLayout.flexibleWidth = 0;
}
internal void OnApplyClicked()
internal void SetValueFromInput()
{
Value = m_valueInput.text;
if (!typeof(string).IsAssignableFrom(Owner.FallbackType))
ReflectionProvider.Instance.BoxStringToType(ref Value, Owner.FallbackType);
Owner.SetValue();
// revert back to string now
OnValueUpdated();
RefreshUIForValue();
}
@ -115,7 +132,7 @@ namespace UnityExplorer.UI.InteractiveValues
m_labelLayout = m_baseLabel.gameObject.GetComponent<LayoutElement>();
m_readonlyInput = UIFactory.CreateLabel(m_valueContent, "ReadonlyLabel", "", TextAnchor.MiddleLeft);
m_readonlyInput = UIFactory.CreateLabel(m_mainContent, "ReadonlyLabel", "", TextAnchor.MiddleLeft);
m_readonlyInput.horizontalOverflow = HorizontalWrapMode.Overflow;
var testFitter = m_readonlyInput.gameObject.AddComponent<ContentSizeFitter>();
@ -162,7 +179,7 @@ namespace UnityExplorer.UI.InteractiveValues
if (Owner.CanWrite)
{
var apply = UIFactory.CreateButton(groupObj, "ApplyButton", "Apply", OnApplyClicked, new Color(0.2f, 0.2f, 0.2f));
var apply = UIFactory.CreateButton(groupObj, "ApplyButton", "Apply", SetValueFromInput, new Color(0.2f, 0.2f, 0.2f));
UIFactory.SetLayoutElement(apply.gameObject, minWidth: 50, minHeight: 25, flexibleWidth: 0);
}
else

View File

@ -183,7 +183,7 @@ namespace UnityExplorer.UI.InteractiveValues
typeof(Vector3),
typeof(Vector4),
typeof(Rect),
typeof(Color) // todo might make a special editor for colors
//typeof(Color) // todo might make a special editor for colors
};
//~~~~~~~~~ Instance ~~~~~~~~~~

View File

@ -12,6 +12,7 @@ using UnityExplorer.UI;
using UnityExplorer.UI.Utility;
using UnityExplorer.UI.CacheObject;
using UnityExplorer.UI.Main.Home;
using UnityExplorer.UI.Inspectors;
namespace UnityExplorer.UI.InteractiveValues
{
@ -46,6 +47,8 @@ namespace UnityExplorer.UI.InteractiveValues
return typeof(InteractiveEnum);
}
// check for unity struct types
else if (typeof(Color).IsAssignableFrom(type))
return typeof(InteractiveColor);
else if (InteractiveUnityStruct.SupportsType(type))
return typeof(InteractiveUnityStruct);
// check Transform, force InteractiveValue so they dont become InteractiveEnumerables.
@ -64,7 +67,7 @@ namespace UnityExplorer.UI.InteractiveValues
public static InteractiveValue Create(object value, Type fallbackType)
{
var type = ReflectionUtility.GetType(value) ?? fallbackType;
var type = ReflectionUtility.GetActualType(value) ?? fallbackType;
var iType = GetIValueForType(type);
return (InteractiveValue)Activator.CreateInstance(iType, new object[] { value, type });
@ -95,11 +98,11 @@ namespace UnityExplorer.UI.InteractiveValues
public virtual void OnDestroy()
{
if (this.m_valueContent)
if (this.m_mainContent)
{
m_valueContent.transform.SetParent(null, false);
m_valueContent.SetActive(false);
GameObject.Destroy(this.m_valueContent.gameObject);
m_mainContent.transform.SetParent(null, false);
m_mainContent.SetActive(false);
GameObject.Destroy(this.m_mainContent.gameObject);
}
DestroySubContent();
@ -293,7 +296,7 @@ namespace UnityExplorer.UI.InteractiveValues
internal GameObject m_mainContentParent;
internal GameObject m_subContentParent;
internal GameObject m_valueContent;
internal GameObject m_mainContent;
internal GameObject m_inspectButton;
internal Text m_baseLabel;
@ -304,24 +307,24 @@ namespace UnityExplorer.UI.InteractiveValues
{
m_UIConstructed = true;
m_valueContent = UIFactory.CreateHorizontalGroup(parent, $"InteractiveValue_{this.GetType().Name}", false, false, true, true, 4, default,
m_mainContent = UIFactory.CreateHorizontalGroup(parent, $"InteractiveValue_{this.GetType().Name}", false, false, true, true, 4, default,
new Color(1, 1, 1, 0), TextAnchor.UpperLeft);
var mainRect = m_valueContent.GetComponent<RectTransform>();
var mainRect = m_mainContent.GetComponent<RectTransform>();
mainRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 25);
UIFactory.SetLayoutElement(m_valueContent, flexibleWidth: 9000, minWidth: 175, minHeight: 25, flexibleHeight: 0);
UIFactory.SetLayoutElement(m_mainContent, flexibleWidth: 9000, minWidth: 175, minHeight: 25, flexibleHeight: 0);
// subcontent expand button
if (HasSubContent)
{
m_subExpandBtn = UIFactory.CreateButton(m_valueContent, "ExpandSubcontentButton", "▲", ToggleSubcontent, new Color(0.3f, 0.3f, 0.3f));
m_subExpandBtn = UIFactory.CreateButton(m_mainContent, "ExpandSubcontentButton", "▲", ToggleSubcontent, new Color(0.3f, 0.3f, 0.3f));
UIFactory.SetLayoutElement(m_subExpandBtn.gameObject, minHeight: 25, minWidth: 25, flexibleWidth: 0, flexibleHeight: 0);
}
// inspect button
var inspectBtn = UIFactory.CreateButton(m_valueContent,
var inspectBtn = UIFactory.CreateButton(m_mainContent,
"InspectButton",
"Inspect",
() =>
@ -338,7 +341,7 @@ namespace UnityExplorer.UI.InteractiveValues
// value label
m_baseLabel = UIFactory.CreateLabel(m_valueContent, "ValueLabel", "", TextAnchor.MiddleLeft);
m_baseLabel = UIFactory.CreateLabel(m_mainContent, "ValueLabel", "", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(m_baseLabel.gameObject, flexibleWidth: 9000, minHeight: 25);
m_subContentParent = subGroup;

View File

@ -5,6 +5,8 @@ using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using UnityExplorer.Core.CSharp;
using UnityExplorer.Core.Input;
using UnityExplorer.Core.Runtime;
using UnityExplorer.Core.Unity;
using UnityExplorer.UI;
using UnityExplorer.UI.Main;
@ -41,16 +43,12 @@ namespace UnityExplorer.UI.Main.CSConsole
public static void Update()
{
if (!m_mainObj)
{
return;
}
if (!CSharpConsole.EnableAutocompletes)
{
if (m_mainObj.activeSelf)
{
m_mainObj.SetActive(false);
}
return;
}
@ -274,8 +272,7 @@ namespace UnityExplorer.UI.Main.CSConsole
mainGroup.childForceExpandWidth = true;
ColorBlock btnColors = new ColorBlock();
btnColors.normalColor = new Color(0f, 0f, 0f, 0f);
btnColors.highlightedColor = new Color(0.2f, 0.2f, 0.2f, 1.0f);
RuntimeProvider.Instance.SetColorBlock(btnColors, new Color(0, 0, 0, 0), highlighted: new Color(0.2f, 0.2f, 0.2f, 1.0f));
for (int i = 0; i < MAX_LABELS; i++)
{

View File

@ -217,7 +217,6 @@ namespace UnityExplorer.UI.Main
{
LogUnity = val;
ConfigManager.Log_Unity_Debug.Value = val;
ConfigManager.Handler.SaveConfig();
});
ConfigManager.Log_Unity_Debug.OnValueChanged += (bool val) => { unityToggle.isOn = val; };

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.UI.Inspectors;
namespace UnityExplorer.UI.Main.Home
{

View File

@ -11,6 +11,9 @@ using UnityExplorer.UI.Main.Home;
using UnityExplorer.Core.Config;
using UnityExplorer.UI.Utility;
using UnityExplorer.UI.Main.Search;
using System.IO;
using UnityExplorer.Core;
using UnityExplorer.UI.Inspectors;
namespace UnityExplorer.UI.Main.Home
{
@ -56,11 +59,9 @@ namespace UnityExplorer.UI.Main.Home
internal readonly List<GameObject> m_shortList = new List<GameObject>();
private Text m_hideText;
private GameObject m_titleObj;
private GameObject m_sceneDropdownObj;
private GameObject m_scenePathGroupObj;
private GameObject m_scrollObj;
private LayoutElement m_leftLayout;
private GameObject m_mainContent;
internal static GameObject DontDestroyObject
{
@ -84,6 +85,30 @@ namespace UnityExplorer.UI.Main.Home
ToggleShow();
}
public void ToggleShow()
{
if (!Hiding)
{
Hiding = true;
m_hideText.text = "►";
m_mainContent.SetActive(false);
m_pageHandler.Hide();
}
else
{
Hiding = false;
m_hideText.text = "◄";
m_mainContent.SetActive(true);
m_pageHandler.Show();
Update();
}
InvokeOnToggleShow();
}
public void Update()
{
if (Hiding || Time.realtimeSinceStartup - m_timeOfLastSceneUpdate < UPDATE_INTERVAL)
@ -223,39 +248,6 @@ namespace UnityExplorer.UI.Main.Home
OnToggleShow?.Invoke(!Instance.Hiding);
}
public void ToggleShow()
{
if (!Hiding)
{
Hiding = true;
m_hideText.text = "►";
m_titleObj.SetActive(false);
m_sceneDropdownObj.SetActive(false);
m_scenePathGroupObj.SetActive(false);
m_scrollObj.SetActive(false);
m_pageHandler.Hide();
m_leftLayout.minWidth = 15;
}
else
{
Hiding = false;
m_hideText.text = "Hide Scene Explorer";
m_titleObj.SetActive(true);
m_sceneDropdownObj.SetActive(true);
m_scenePathGroupObj.SetActive(true);
m_scrollObj.SetActive(true);
m_leftLayout.minWidth = 350;
Update();
}
InvokeOnToggleShow();
}
public void OnActiveScenesChanged(List<string> newNames)
{
m_sceneDropdown.options.Clear();
@ -387,25 +379,32 @@ namespace UnityExplorer.UI.Main.Home
public void ConstructScenePane()
{
GameObject leftPane = UIFactory.CreateVerticalGroup(HomePage.Instance.Content, "SceneGroup", true, false, true, true, 0, default,
var coreGroup = UIFactory.CreateHorizontalGroup(HomePage.Instance.Content, "SceneExplorer", true, true, true, true, 4, new Vector4(2, 2, 2, 2),
new Color(0.05f, 0.05f, 0.05f));
// hide button
var hideButton = UIFactory.CreateButton(coreGroup, "HideButton", "◄", ToggleShow, new Color(0.15f, 0.15f, 0.15f));
hideButton.GetComponentInChildren<Text>().fontSize = 13;
m_hideText = hideButton.GetComponentInChildren<Text>();
UIFactory.SetLayoutElement(hideButton.gameObject, minWidth: 20, minHeight: 20, flexibleWidth: 0, flexibleHeight: 9999);
m_mainContent = UIFactory.CreateVerticalGroup(coreGroup, "SceneGroup", true, false, true, true, 0, default,
new Color(72f / 255f, 72f / 255f, 72f / 255f));
UIFactory.SetLayoutElement(m_mainContent, minWidth: 350, flexibleWidth: 0);
m_leftLayout = leftPane.AddComponent<LayoutElement>();
m_leftLayout.minWidth = 350;
m_leftLayout.flexibleWidth = 0;
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(m_mainContent, true, true, true, true, spacing: 4, padTop: 8, 4, 4, 4);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(leftPane, true, true, true, true, spacing: 4, padTop: 8, 4, 4, 4);
var titleObj = UIFactory.CreateLabel(m_mainContent, "SceneExplorerTitle", "Scene Explorer", TextAnchor.UpperLeft, default, true, 20).gameObject;
UIFactory.SetLayoutElement(titleObj, minHeight: 30, flexibleHeight: 0);
m_titleObj = UIFactory.CreateLabel(leftPane, "SceneExplorerTitle", "Scene Explorer", TextAnchor.UpperLeft, default, true, 20).gameObject;
UIFactory.SetLayoutElement(m_titleObj, minHeight: 30, flexibleHeight: 0);
m_sceneDropdownObj = UIFactory.CreateDropdown(leftPane, out m_sceneDropdown, "", 14, null);
m_sceneDropdownObj = UIFactory.CreateDropdown(m_mainContent, out m_sceneDropdown, "", 14, null);
UIFactory.SetLayoutElement(m_sceneDropdownObj, minHeight: 40, minWidth: 320, flexibleWidth: 0, flexibleHeight: 0);
m_sceneDropdownText = m_sceneDropdown.transform.Find("Label").GetComponent<Text>();
m_sceneDropdown.onValueChanged.AddListener((int val) => { SetTargetScene(val); });
m_scenePathGroupObj = UIFactory.CreateHorizontalGroup(leftPane, "ScenePathGroup", true, true, true, true, 5, default, new Color(1, 1, 1, 0f));
m_scenePathGroupObj = UIFactory.CreateHorizontalGroup(m_mainContent, "ScenePathGroup", true, true, true, true, 5, default, new Color(1, 1, 1, 0f));
UIFactory.SetLayoutElement(m_scenePathGroupObj, minHeight: 20, minWidth: 335);
var backBtnObj = UIFactory.CreateButton(m_scenePathGroupObj,
@ -439,20 +438,68 @@ namespace UnityExplorer.UI.Main.Home
m_mainInspectBtn = mainInspectButton.gameObject;
UIFactory.SetLayoutElement(m_mainInspectBtn, minWidth: 65);
m_scrollObj = UIFactory.CreateScrollView(leftPane, "SceneExplorerScrollView",
var scrollObj = UIFactory.CreateScrollView(m_mainContent, "SceneExplorerScrollView",
out m_pageContent, out SliderScrollbar scroller, new Color(0.1f, 0.1f, 0.1f));
m_pageHandler = new PageHandler(scroller);
m_pageHandler.ConstructUI(leftPane);
m_pageHandler.ConstructUI(m_mainContent);
m_pageHandler.OnPageChanged += OnSceneListPageTurn;
// hide button
// Scene Loader
try
{
Type sceneUtil = ReflectionUtility.GetTypeByName("UnityEngine.SceneManagement.SceneUtility");
if (sceneUtil == null)
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.AllFlags);
var hideButton = UIFactory.CreateButton(leftPane, "HideButton", "Hide Scene Explorer", ToggleShow, new Color(0.15f, 0.15f, 0.15f));
hideButton.GetComponentInChildren<Text>().fontSize = 13;
m_hideText = hideButton.GetComponentInChildren<Text>();
var title2 = UIFactory.CreateLabel(m_mainContent, "SceneLoaderLabel", "Scene Loader", TextAnchor.MiddleLeft, Color.white, true, 20);
UIFactory.SetLayoutElement(title2.gameObject, minHeight: 30, flexibleHeight: 0);
UIFactory.SetLayoutElement(hideButton.gameObject, minWidth: 20, minHeight: 20);
var allSceneDropObj = UIFactory.CreateDropdown(m_mainContent, out Dropdown allSceneDrop, "", 14, null);
UIFactory.SetLayoutElement(allSceneDropObj, minHeight: 40, minWidth: 320, flexibleWidth: 0, flexibleHeight: 0);
int sceneCount = SceneManager.sceneCountInBuildSettings;
for (int i = 0; i < sceneCount; i++)
{
var scenePath = (string)method.Invoke(null, new object[] { i });
allSceneDrop.options.Add(new Dropdown.OptionData(Path.GetFileNameWithoutExtension(scenePath)));
}
allSceneDrop.value = 1;
allSceneDrop.value = 0;
var buttonRow = UIFactory.CreateHorizontalGroup(m_mainContent, "LoadButtons", true, true, true, true, 4);
var loadButton = UIFactory.CreateButton(buttonRow, "LoadSceneButton", "Load (Single)", () =>
{
try
{
SceneManager.LoadScene(allSceneDrop.options[allSceneDrop.value].text);
}
catch (Exception ex)
{
ExplorerCore.LogWarning($"Unable to load the Scene! {ex.ReflectionExToString()}");
}
}, new Color(0.1f, 0.3f, 0.3f));
UIFactory.SetLayoutElement(loadButton.gameObject, minHeight: 40, minWidth: 150);
var loadAdditiveButton = UIFactory.CreateButton(buttonRow, "LoadSceneButton", "Load (Additive)", () =>
{
try
{
SceneManager.LoadScene(allSceneDrop.options[allSceneDrop.value].text, LoadSceneMode.Additive);
}
catch (Exception ex)
{
ExplorerCore.LogWarning($"Unable to load the Scene! {ex.ReflectionExToString()}");
}
}, new Color(0.1f, 0.3f, 0.3f));
UIFactory.SetLayoutElement(loadAdditiveButton.gameObject, minHeight: 40, minWidth: 150);
}
catch (Exception ex)
{
ExplorerCore.LogWarning($"Could not create the Scene Loader helper! {ex.ReflectionExToString()}");
}
}
private void AddObjectListButton()
@ -476,9 +523,8 @@ namespace UnityExplorer.UI.Main.Home
toggle.onValueChanged.AddListener((bool val) => { OnToggleClicked(thisIndex, val); });
ColorBlock mainColors = new ColorBlock();
mainColors.normalColor = new Color(0.1f, 0.1f, 0.1f);
mainColors.highlightedColor = new Color(0.2f, 0.2f, 0.2f);
mainColors.pressedColor = new Color(0.05f, 0.05f, 0.05f);
mainColors = RuntimeProvider.Instance.SetColorBlock(mainColors, new Color(0.1f, 0.1f, 0.1f),
new Color(0.2f, 0.2f, 0.2f), new Color(0.05f, 0.05f, 0.05f));
var mainButton = UIFactory.CreateButton(btnGroupObj,
"MainButton",
@ -494,9 +540,8 @@ namespace UnityExplorer.UI.Main.Home
m_shortListTexts.Add(mainText);
ColorBlock inspectColors = new ColorBlock();
inspectColors.normalColor = new Color(0.15f, 0.15f, 0.15f);
inspectColors.highlightedColor = new Color(0.2f, 0.2f, 0.2f);
inspectColors.pressedColor = new Color(0.1f, 0.1f, 0.1f);
inspectColors = RuntimeProvider.Instance.SetColorBlock(inspectColors, new Color(0.15f, 0.15f, 0.15f),
new Color(0.2f, 0.2f, 0.2f), new Color(0.1f, 0.1f, 0.1f));
var inspectButton = UIFactory.CreateButton(btnGroupObj,
"InspectButton",

View File

@ -10,6 +10,7 @@ using UnityExplorer.UI.Main.Home;
using UnityExplorer.UI.Main.Search;
using UnityExplorer.UI.Main.CSConsole;
using UnityExplorer.UI.Main.Options;
using UnityExplorer.Core.Runtime;
namespace UnityExplorer.UI.Main
{
@ -135,16 +136,12 @@ namespace UnityExplorer.UI.Main
internal void SetButtonActiveColors(Button button)
{
ColorBlock colors = button.colors;
colors.normalColor = m_navButtonSelected;
button.colors = colors;
button.colors = RuntimeProvider.Instance.SetColorBlock(button.colors, m_navButtonSelected);
}
internal void SetButtonInactiveColors(Button button)
{
ColorBlock colors = button.colors;
colors.normalColor = m_navButtonNormal;
button.colors = colors;
button.colors = RuntimeProvider.Instance.SetColorBlock(button.colors, m_navButtonNormal);
}
#region UI Construction
@ -183,9 +180,8 @@ namespace UnityExplorer.UI.Main
// Hide button
ColorBlock colorBlock = new ColorBlock();
colorBlock.normalColor = new Color(65f / 255f, 23f / 255f, 23f / 255f);
colorBlock.pressedColor = new Color(35f / 255f, 10f / 255f, 10f / 255f);
colorBlock.highlightedColor = new Color(156f / 255f, 0f, 0f);
colorBlock = RuntimeProvider.Instance.SetColorBlock(colorBlock, new Color(65f / 255f, 23f / 255f, 23f / 255f),
new Color(35f / 255f, 10f / 255f, 10f / 255f), new Color(156f / 255f, 0f, 0f));
var hideButton = UIFactory.CreateButton(titleBar,
"HideButton",
@ -213,9 +209,7 @@ namespace UnityExplorer.UI.Main
UIFactory.SetLayoutElement(navbarObj, minHeight: 25, flexibleHeight: 0);
ColorBlock colorBlock = new ColorBlock();
colorBlock.normalColor = m_navButtonNormal;
colorBlock.highlightedColor = m_navButtonHighlight;
colorBlock.pressedColor = m_navButtonSelected;
colorBlock = RuntimeProvider.Instance.SetColorBlock(colorBlock, m_navButtonNormal, m_navButtonHighlight, m_navButtonSelected);
foreach (var page in Pages)
{

View File

@ -10,6 +10,7 @@ using UnityExplorer.Core;
using UnityExplorer.UI.Utility;
using UnityExplorer.Core.Search;
using UnityExplorer.UI.Main.Home;
using UnityExplorer.UI.Inspectors;
namespace UnityExplorer.UI.Main.Search
{
@ -129,7 +130,7 @@ namespace UnityExplorer.UI.Main.Search
if (m_context != SearchContext.StaticClass)
{
var name = SignatureHighlighter.ParseFullSyntax(ReflectionUtility.GetType(obj), true);
var name = SignatureHighlighter.ParseFullSyntax(ReflectionUtility.GetActualType(obj), true);
if (unityObj && m_context != SearchContext.Singleton)
{
@ -259,10 +260,8 @@ namespace UnityExplorer.UI.Main.Search
m_selectedContextButton = button;
var colors = m_selectedContextButton.colors;
colors.normalColor = new Color(0.35f, 0.7f, 0.35f);
colors.highlightedColor = colors.normalColor;
m_selectedContextButton.colors = colors;
m_selectedContextButton.colors = RuntimeProvider.Instance.SetColorBlock(m_selectedContextButton.colors,
new Color(0.35f, 0.7f, 0.35f), new Color(0.35f, 0.7f, 0.35f));
m_context = context;
@ -439,12 +438,9 @@ namespace UnityExplorer.UI.Main.Search
UIFactory.SetLayoutElement(btnGroupObj, flexibleWidth: 320, minHeight: 25, flexibleHeight: 0);
btnGroupObj.AddComponent<Mask>();
var mainColors = new ColorBlock
{
normalColor = new Color(0.1f, 0.1f, 0.1f),
highlightedColor = new Color(0.2f, 0.2f, 0.2f, 1),
pressedColor = new Color(0.05f, 0.05f, 0.05f)
};
var mainColors = new ColorBlock();
RuntimeProvider.Instance.SetColorBlock(mainColors, new Color(0.1f, 0.1f, 0.1f),
new Color(0.2f, 0.2f, 0.2f), new Color(0.05f, 0.05f, 0.05f));
var mainButton = UIFactory.CreateButton(btnGroupObj,
"ResultButton",

View File

@ -52,27 +52,26 @@ namespace UnityExplorer.UI
internal static void SetDefaultSelectableColors(Selectable selectable)
{
ColorBlock colors = selectable.colors;
SetColorBlockValues(ref colors, new Color(0.2f, 0.2f, 0.2f), new Color(0.3f, 0.3f, 0.3f), new Color(0.15f, 0.15f, 0.15f));
selectable.colors = colors;
selectable.colors = RuntimeProvider.Instance.SetColorBlock(selectable.colors, new Color(0.2f, 0.2f, 0.2f),
new Color(0.3f, 0.3f, 0.3f), new Color(0.15f, 0.15f, 0.15f));
// Deselect all Buttons after they are clicked.
if (selectable is Button button)
button.onClick.AddListener(() => { button.OnDeselect(null); });
}
public static void SetColorBlockValues(ref this ColorBlock colorBlock, Color? normal = null, Color? highlighted = null,
Color? pressed = null)
{
if (normal != null)
colorBlock.normalColor = (Color)normal;
//public static void SetColorBlockValues(ref this ColorBlock colorBlock, Color? normal = null, Color? highlighted = null,
// Color? pressed = null)
//{
// if (normal != null)
// colorBlock.normalColor = (Color)normal;
if (highlighted != null)
colorBlock.highlightedColor = (Color)highlighted;
// if (highlighted != null)
// colorBlock.highlightedColor = (Color)highlighted;
if (pressed != null)
colorBlock.pressedColor = (Color)pressed;
}
// if (pressed != null)
// colorBlock.pressedColor = (Color)pressed;
//}
/// <summary>
/// Get and/or Add a LayoutElement component to the GameObject, and set any of the values on it.
@ -114,13 +113,15 @@ namespace UnityExplorer.UI
/// </summary>
public static T SetLayoutGroup<T>(GameObject gameObject, bool? forceWidth = null, bool? forceHeight = null,
bool? childControlWidth = null, bool? childControlHeight = null, int? spacing = null, int? padTop = null,
int? padBottom = null, int? padLeft = null, int? padRight = null, TextAnchor? childAlignment = null) where T : HorizontalOrVerticalLayoutGroup
int? padBottom = null, int? padLeft = null, int? padRight = null, TextAnchor? childAlignment = null)
where T : HorizontalOrVerticalLayoutGroup
{
var group = gameObject.GetComponent<T>();
if (!group)
group = gameObject.AddComponent<T>();
return SetLayoutGroup(group, forceWidth, forceHeight, childControlWidth, childControlHeight, spacing, padTop, padBottom, padLeft, padRight, childAlignment);
return SetLayoutGroup(group, forceWidth, forceHeight, childControlWidth, childControlHeight, spacing, padTop,
padBottom, padLeft, padRight, childAlignment);
}
/// <summary>
@ -128,7 +129,8 @@ namespace UnityExplorer.UI
/// </summary>
public static T SetLayoutGroup<T>(T group, bool? forceWidth = null, bool? forceHeight = null,
bool? childControlWidth = null, bool? childControlHeight = null, int? spacing = null, int? padTop = null,
int? padBottom = null, int? padLeft = null, int? padRight = null, TextAnchor? childAlignment = null) where T : HorizontalOrVerticalLayoutGroup
int? padBottom = null, int? padLeft = null, int? padRight = null, TextAnchor? childAlignment = null)
where T : HorizontalOrVerticalLayoutGroup
{
if (forceWidth != null)
group.childForceExpandWidth = (bool)forceWidth;
@ -273,13 +275,9 @@ namespace UnityExplorer.UI
public static Button CreateButton(GameObject parent, string name, string text, Action onClick = null, Color? normalColor = null)
{
var colors = new ColorBlock();
if (normalColor != null)
colors.normalColor = (Color)normalColor;
else
colors.normalColor = new Color(0.25f, 0.25f, 0.25f);
colors.pressedColor = new Color(0.15f, 0.15f, 0.15f);
colors.highlightedColor = new Color(0.4f, 0.4f, 0.4f);
normalColor = normalColor ?? new Color(0.25f, 0.25f, 0.25f);
colors = RuntimeProvider.Instance.SetColorBlock(colors, normalColor, new Color(0.4f, 0.4f, 0.4f),
new Color(0.15f, 0.15f, 0.15f));
return CreateButton(parent, name, text, onClick, colors);
}
@ -366,7 +364,8 @@ namespace UnityExplorer.UI
slider.targetGraphic = handleImage;
slider.direction = Slider.Direction.LeftToRight;
SetDefaultSelectableColors(slider);
slider.colors = RuntimeProvider.Instance.SetColorBlock(slider.colors, new Color(0.4f, 0.4f, 0.4f),
new Color(0.55f, 0.55f, 0.55f), new Color(0.3f, 0.3f, 0.3f));
return sliderObj;
}
@ -505,12 +504,8 @@ namespace UnityExplorer.UI
mainInput.transition = Selectable.Transition.ColorTint;
mainInput.targetGraphic = mainImage;
ColorBlock mainColors = mainInput.colors;
mainColors.normalColor = new Color(1, 1, 1, 1);
mainColors.highlightedColor = new Color(0.95f, 0.95f, 0.95f, 1.0f);
mainColors.pressedColor = new Color(0.78f, 0.78f, 0.78f, 1.0f);
mainColors.highlightedColor = new Color(0.95f, 0.95f, 0.95f, 1.0f);
mainInput.colors = mainColors;
mainInput.colors = RuntimeProvider.Instance.SetColorBlock(mainInput.colors, new Color(1, 1, 1, 1),
new Color(0.95f, 0.95f, 0.95f, 1.0f), new Color(0.78f, 0.78f, 0.78f, 1.0f));
SetLayoutGroup<VerticalLayoutGroup>(mainObj, true, true, true, true);
@ -614,10 +609,8 @@ namespace UnityExplorer.UI
Toggle itemToggle = itemObj.AddComponent<Toggle>();
itemToggle.targetGraphic = itemBgImage;
itemToggle.isOn = true;
ColorBlock colors = itemToggle.colors;
colors.normalColor = new Color(0.35f, 0.35f, 0.35f, 1.0f);
colors.highlightedColor = new Color(0.25f, 0.45f, 0.25f, 1.0f);
itemToggle.colors = colors;
itemToggle.colors = RuntimeProvider.Instance.SetColorBlock(itemToggle.colors,
new Color(0.35f, 0.35f, 0.35f, 1.0f), new Color(0.25f, 0.45f, 0.25f, 1.0f));
itemToggle.onValueChanged.AddListener((bool val) => { itemToggle.OnDeselect(null); });
Image templateImage = templateObj.AddComponent<Image>();

View File

@ -53,8 +53,7 @@ namespace UnityExplorer.UI
// Force refresh of anchors etc
Canvas.ForceUpdateCanvases();
if (!ConfigManager.Hide_On_Startup.Value)
ShowMenu = true;
ShowMenu = !ConfigManager.Hide_On_Startup.Value;
ExplorerCore.Log("UI initialized.");
}
@ -81,8 +80,6 @@ namespace UnityExplorer.UI
if (EventSystem.current != EventSys)
CursorUnlocker.SetEventSystem();
RuntimeProvider.Instance.CheckInputPointerEvent();
PanelDragger.Instance.Update();
SliderScrollbar.UpdateInstances();

View File

@ -186,7 +186,7 @@ public static class SliderExtensions
{
if (m_setMethod == null)
{
m_setMethod = typeof(Slider).GetMethod("Set", ReflectionUtility.CommonFlags, null, new[] { typeof(float), typeof(bool) }, null);
m_setMethod = typeof(Slider).GetMethod("Set", ReflectionUtility.AllFlags, null, new[] { typeof(float), typeof(bool) }, null);
}
return m_setMethod;
}

View File

@ -246,6 +246,7 @@
<Compile Include="Core\Search\SceneFilter.cs" />
<Compile Include="Core\Search\SearchContext.cs" />
<Compile Include="Core\Search\SearchProvider.cs" />
<Compile Include="Core\TestClass.cs" />
<Compile Include="Core\Unity\UnityHelpers.cs" />
<Compile Include="Loader\BIE\BepInExConfigHandler.cs" />
<Compile Include="Loader\BIE\ExplorerBepInPlugin.cs" />
@ -265,6 +266,7 @@
<Compile Include="UI\CacheObject\CachePaired.cs" />
<Compile Include="UI\CacheObject\CacheProperty.cs" />
<Compile Include="UI\InteractiveValues\InteractiveBool.cs" />
<Compile Include="UI\InteractiveValues\InteractiveColor.cs" />
<Compile Include="UI\InteractiveValues\InteractiveDictionary.cs" />
<Compile Include="UI\InteractiveValues\InteractiveEnum.cs" />
<Compile Include="UI\InteractiveValues\InteractiveEnumerable.cs" />
@ -285,16 +287,16 @@
<Compile Include="UI\Main\CSConsole\Lexer\SymbolMatch.cs" />
<Compile Include="UI\Main\DebugConsole.cs" />
<Compile Include="UI\Main\Home\HomePage.cs" />
<Compile Include="UI\Main\Home\InspectorManager.cs" />
<Compile Include="UI\Main\Home\Inspectors\GameObjects\ChildList.cs" />
<Compile Include="UI\Main\Home\Inspectors\GameObjects\ComponentList.cs" />
<Compile Include="UI\Main\Home\Inspectors\GameObjects\GameObjectControls.cs" />
<Compile Include="UI\Main\Home\Inspectors\GameObjects\GameObjectInspector.cs" />
<Compile Include="UI\Main\Home\Inspectors\InspectorBase.cs" />
<Compile Include="UI\Main\Home\Inspectors\Reflection\InstanceInspector.cs" />
<Compile Include="UI\Main\Home\Inspectors\Reflection\ReflectionInspector.cs" />
<Compile Include="UI\Main\Home\Inspectors\Reflection\StaticInspector.cs" />
<Compile Include="UI\Main\Home\InspectUnderMouse.cs" />
<Compile Include="UI\Inspectors\InspectorManager.cs" />
<Compile Include="UI\Inspectors\GameObjects\ChildList.cs" />
<Compile Include="UI\Inspectors\GameObjects\ComponentList.cs" />
<Compile Include="UI\Inspectors\GameObjects\GameObjectControls.cs" />
<Compile Include="UI\Inspectors\GameObjects\GameObjectInspector.cs" />
<Compile Include="UI\Inspectors\InspectorBase.cs" />
<Compile Include="UI\Inspectors\Reflection\InstanceInspector.cs" />
<Compile Include="UI\Inspectors\Reflection\ReflectionInspector.cs" />
<Compile Include="UI\Inspectors\Reflection\StaticInspector.cs" />
<Compile Include="UI\Inspectors\InspectUnderMouse.cs" />
<Compile Include="UI\Main\Home\SceneExplorer.cs" />
<Compile Include="UI\Main\MainMenu.cs" />
<Compile Include="UI\Main\Options\OptionsPage.cs" />