mirror of
https://github.com/sinai-dev/UnityExplorer.git
synced 2025-06-23 00:52:31 +08:00
Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
bdf86a7448 | |||
968546d43c | |||
680556d74e | |||
f490203b10 | |||
39d9585f1d | |||
2d414e544b | |||
513fcaa534 | |||
b41f7211e5 | |||
dd6cce1df1 | |||
ad54d2c76b |
14
README.md
14
README.md
@ -78,11 +78,16 @@ There is a simple Mod Config for the Explorer. You can access the settings via t
|
||||
* Whether or not to show the Bitwise Editing helper when inspecting integers
|
||||
|
||||
`Enable Tab View` (bool) | Default: `true`
|
||||
* Whether or not all inspector windows a grouped into a single window with tabs.
|
||||
* Whether or not all inspector windows a grouped into a single window with tabs.
|
||||
|
||||
`Default Output Path` (string) | Default: `Mods\Explorer`
|
||||
* Where output is generated to, by default (for Texture PNG saving, etc).
|
||||
|
||||
## Mouse Control
|
||||
|
||||
Explorer can force the mouse to be visible and unlocked when the menu is open, if you have enabled "Force Unlock Mouse" (Left-Alt toggle). However, you may also want to prevent the mouse clicking-through onto the game behind Explorer, this is possible but it requires specific patches for that game.
|
||||
Explorer can force the mouse to be visible and unlocked when the menu is open, if you have enabled "Force Unlock Mouse" (Left-Alt toggle). Explorer also attempts to prevent clicking-through onto the game behind the Explorer menu.
|
||||
|
||||
If you need more mouse control:
|
||||
|
||||
* For VRChat, use [VRCExplorerMouseControl](https://github.com/sinai-dev/VRCExplorerMouseControl)
|
||||
* For Hellpoint, use [HPExplorerMouseControl](https://github.com/sinai-dev/Hellpoint-Mods/tree/master/HPExplorerMouseControl/HPExplorerMouseControl)
|
||||
@ -93,8 +98,9 @@ For example:
|
||||
using Explorer;
|
||||
using Harmony; // or 'using HarmonyLib;' for BepInEx
|
||||
// ...
|
||||
[HarmonyPatch(typeof(MyGame.MenuClass), nameof(MyGame.MenuClass.CursorUpdate)]
|
||||
public class MenuClass_CursorUpdate
|
||||
// You will need to figure out the relevant Class and Method for your game using dnSpy.
|
||||
[HarmonyPatch(typeof(MyGame.InputManager), nameof(MyGame.InputManager.Update))]
|
||||
public class InputManager_Update
|
||||
{
|
||||
[HarmonyPrefix]
|
||||
public static bool Prefix()
|
||||
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
using Explorer.UI;
|
||||
|
||||
namespace Explorer.CacheObject
|
||||
{
|
||||
@ -21,6 +22,15 @@ namespace Explorer.CacheObject
|
||||
|
||||
public override void UpdateValue()
|
||||
{
|
||||
if (IValue is InteractiveDictionary iDict)
|
||||
{
|
||||
if (!iDict.EnsureDictionaryIsSupported())
|
||||
{
|
||||
ReflectionException = "Not supported due to TypeInitializationException";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var fi = MemInfo as FieldInfo;
|
||||
|
@ -129,7 +129,7 @@ namespace Explorer.CacheObject
|
||||
|
||||
GUILayout.Label(i.ToString(), new GUILayoutOption[] { GUILayout.Width(15) });
|
||||
GUILayout.Label(label, new GUILayoutOption[] { GUILayout.ExpandWidth(false) });
|
||||
this.m_argumentInput[i] = GUILayout.TextField(input, new GUILayoutOption[] { GUILayout.ExpandWidth(true) });
|
||||
this.m_argumentInput[i] = GUIUnstrip.TextField(input, new GUILayoutOption[] { GUILayout.ExpandWidth(true) });
|
||||
|
||||
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
|
||||
|
||||
|
@ -73,7 +73,7 @@ namespace Explorer.CacheObject
|
||||
if (ret != null)
|
||||
{
|
||||
//m_cachedReturnValue = CacheFactory.GetTypeAndCacheObject(ret);
|
||||
m_cachedReturnValue = CacheFactory.GetCacheObject(ret, IValue.ValueType);
|
||||
m_cachedReturnValue = CacheFactory.GetCacheObject(ret);
|
||||
m_cachedReturnValue.UpdateValue();
|
||||
}
|
||||
else
|
||||
|
@ -25,12 +25,26 @@ namespace Explorer.CacheObject
|
||||
return;
|
||||
}
|
||||
|
||||
//ExplorerCore.Log("Initializing InteractiveValue of type " + valueType.FullName);
|
||||
|
||||
InteractiveValue interactive;
|
||||
|
||||
if (valueType == typeof(GameObject) || valueType == typeof(Transform))
|
||||
{
|
||||
interactive = new InteractiveGameObject();
|
||||
}
|
||||
else if (valueType == typeof(Texture2D))
|
||||
{
|
||||
interactive = new InteractiveTexture2D();
|
||||
}
|
||||
else if (valueType == typeof(Texture))
|
||||
{
|
||||
interactive = new InteractiveTexture();
|
||||
}
|
||||
else if (valueType == typeof(Sprite))
|
||||
{
|
||||
interactive = new InteractiveSprite();
|
||||
}
|
||||
else if (valueType.IsPrimitive || valueType == typeof(string))
|
||||
{
|
||||
interactive = new InteractivePrimitive();
|
||||
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
using Explorer.UI;
|
||||
|
||||
namespace Explorer.CacheObject
|
||||
{
|
||||
@ -32,14 +33,38 @@ namespace Explorer.CacheObject
|
||||
return;
|
||||
}
|
||||
|
||||
if (IValue is InteractiveDictionary iDict)
|
||||
{
|
||||
if (!iDict.EnsureDictionaryIsSupported())
|
||||
{
|
||||
ReflectionException = "Not supported due to TypeInitializationException";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var pi = MemInfo as PropertyInfo;
|
||||
var target = pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance;
|
||||
|
||||
IValue.Value = pi.GetValue(target, ParseArguments());
|
||||
if (pi.CanRead)
|
||||
{
|
||||
var target = pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance;
|
||||
|
||||
base.UpdateValue();
|
||||
IValue.Value = pi.GetValue(target, ParseArguments());
|
||||
|
||||
base.UpdateValue();
|
||||
}
|
||||
else // create a dummy value for Write-Only properties.
|
||||
{
|
||||
if (IValue.ValueType == typeof(string))
|
||||
{
|
||||
IValue.Value = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
IValue.Value = Activator.CreateInstance(IValue.ValueType);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -19,7 +19,7 @@ namespace Explorer.Config
|
||||
public int Default_Page_Limit = 20;
|
||||
public bool Bitwise_Support = false;
|
||||
public bool Tab_View = true;
|
||||
//public bool Main_Toggle_Global = true;
|
||||
public string Default_Output_Path = @"Mods\Explorer";
|
||||
|
||||
public static void OnLoad()
|
||||
{
|
||||
|
@ -208,10 +208,14 @@
|
||||
<Compile Include="CacheObject\CacheMethod.cs" />
|
||||
<Compile Include="CacheObject\CacheProperty.cs" />
|
||||
<Compile Include="CacheObject\CacheObjectBase.cs" />
|
||||
<Compile Include="Helpers\Texture2DHelpers.cs" />
|
||||
<Compile Include="UI\InteractiveValue\InteractiveValue.cs" />
|
||||
<Compile Include="UI\InteractiveValue\Object\InteractiveDictionary.cs" />
|
||||
<Compile Include="UI\InteractiveValue\Object\InteractiveEnumerable.cs" />
|
||||
<Compile Include="UI\InteractiveValue\Object\InteractiveGameObject.cs" />
|
||||
<Compile Include="UI\InteractiveValue\Object\InteractiveSprite.cs" />
|
||||
<Compile Include="UI\InteractiveValue\Object\InteractiveTexture.cs" />
|
||||
<Compile Include="UI\InteractiveValue\Object\InteractiveTexture2D.cs" />
|
||||
<Compile Include="UI\InteractiveValue\Struct\InteractiveQuaternion.cs" />
|
||||
<Compile Include="UI\InteractiveValue\Struct\InteractiveRect.cs" />
|
||||
<Compile Include="UI\InteractiveValue\Struct\InteractiveVector.cs" />
|
||||
@ -227,7 +231,7 @@
|
||||
<Compile Include="Extensions\UnityExtensions.cs" />
|
||||
<Compile Include="Helpers\ReflectionHelpers.cs" />
|
||||
<Compile Include="Helpers\UnityHelpers.cs" />
|
||||
<Compile Include="Input\AbstractInput.cs" />
|
||||
<Compile Include="Input\IAbstractInput.cs" />
|
||||
<Compile Include="Tests\TestClass.cs" />
|
||||
<Compile Include="UI\ForceUnlockCursor.cs" />
|
||||
<Compile Include="Input\InputManager.cs" />
|
||||
@ -257,6 +261,10 @@
|
||||
<Compile Include="UI\TabViewWindow.cs" />
|
||||
<Compile Include="UI\WindowBase.cs" />
|
||||
<Compile Include="UI\WindowManager.cs" />
|
||||
<Compile Include="Unstrip\ImageConversion\ImageConversionUnstrip.cs" />
|
||||
<Compile Include="Unstrip\IMGUI\Internal_GUIUtility.cs" />
|
||||
<Compile Include="Unstrip\IMGUI\Internal_TextEditor.cs" />
|
||||
<Compile Include="Unstrip\LayerMask\LayerMaskUnstrip.cs" />
|
||||
<Compile Include="Unstrip\Scene\SceneUnstrip.cs" />
|
||||
<Compile Include="Unstrip\IMGUI\GUIUnstrip.cs" />
|
||||
<Compile Include="Unstrip\IMGUI\Internal_LayoutUtility.cs" />
|
||||
|
@ -1,4 +1,6 @@
|
||||
using Explorer.Config;
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using Explorer.Config;
|
||||
using Explorer.UI;
|
||||
using Explorer.UI.Inspectors;
|
||||
using Explorer.UI.Main;
|
||||
@ -10,7 +12,7 @@ namespace Explorer
|
||||
public class ExplorerCore
|
||||
{
|
||||
public const string NAME = "Explorer " + VERSION + " (" + PLATFORM + ", " + MODLOADER + ")";
|
||||
public const string VERSION = "2.0.1";
|
||||
public const string VERSION = "2.0.6";
|
||||
public const string AUTHOR = "Sinai";
|
||||
public const string GUID = "com.sinai.explorer";
|
||||
|
||||
@ -31,6 +33,12 @@ namespace Explorer
|
||||
|
||||
public ExplorerCore()
|
||||
{
|
||||
if (Instance != null)
|
||||
{
|
||||
Log("An instance of Explorer is already active!");
|
||||
return;
|
||||
}
|
||||
|
||||
Instance = this;
|
||||
|
||||
ModConfig.OnLoad();
|
||||
@ -87,6 +95,11 @@ namespace Explorer
|
||||
WindowManager.Instance.OnGUI();
|
||||
InspectUnderMouse.OnGUI();
|
||||
|
||||
if (!ResizeDrag.IsMouseInResizeArea && WindowManager.IsMouseInWindow)
|
||||
{
|
||||
InputManager.ResetInputAxes();
|
||||
}
|
||||
|
||||
GUI.skin = origSkin;
|
||||
}
|
||||
|
||||
@ -99,27 +112,27 @@ namespace Explorer
|
||||
public static void Log(object message)
|
||||
{
|
||||
#if ML
|
||||
MelonLoader.MelonLogger.Log(message.ToString());
|
||||
MelonLoader.MelonLogger.Log(message?.ToString());
|
||||
#else
|
||||
ExplorerBepInPlugin.Logging?.LogMessage(message.ToString());
|
||||
ExplorerBepInPlugin.Logging?.LogMessage(message?.ToString());
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void LogWarning(object message)
|
||||
{
|
||||
#if ML
|
||||
MelonLoader.MelonLogger.LogWarning(message.ToString());
|
||||
MelonLoader.MelonLogger.LogWarning(message?.ToString());
|
||||
#else
|
||||
ExplorerBepInPlugin.Logging?.LogWarning(message.ToString());
|
||||
ExplorerBepInPlugin.Logging?.LogWarning(message?.ToString());
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void LogError(object message)
|
||||
{
|
||||
#if ML
|
||||
MelonLoader.MelonLogger.LogError(message.ToString());
|
||||
MelonLoader.MelonLogger.LogError(message?.ToString());
|
||||
#else
|
||||
ExplorerBepInPlugin.Logging?.LogError(message.ToString());
|
||||
ExplorerBepInPlugin.Logging?.LogError(message?.ToString());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
192
src/Helpers/Texture2DHelpers.cs
Normal file
192
src/Helpers/Texture2DHelpers.cs
Normal file
@ -0,0 +1,192 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
#if CPP
|
||||
using Explorer.Unstrip.ImageConversion;
|
||||
#endif
|
||||
|
||||
namespace Explorer.Helpers
|
||||
{
|
||||
public static class Texture2DHelpers
|
||||
{
|
||||
#if CPP // If Mono
|
||||
#else
|
||||
private static bool isNewEncodeMethod = false;
|
||||
private static MethodInfo EncodeToPNGMethod => m_encodeToPNGMethod ?? GetEncodeToPNGMethod();
|
||||
private static MethodInfo m_encodeToPNGMethod;
|
||||
|
||||
private static MethodInfo GetEncodeToPNGMethod()
|
||||
{
|
||||
if (ReflectionHelpers.GetTypeByName("UnityEngine.ImageConversion") is Type imageConversion)
|
||||
{
|
||||
isNewEncodeMethod = true;
|
||||
return m_encodeToPNGMethod = imageConversion.GetMethod("EncodeToPNG", ReflectionHelpers.CommonFlags);
|
||||
}
|
||||
|
||||
var method = typeof(Texture2D).GetMethod("EncodeToPNG", ReflectionHelpers.CommonFlags);
|
||||
if (method != null)
|
||||
{
|
||||
return m_encodeToPNGMethod = method;
|
||||
}
|
||||
|
||||
ExplorerCore.Log("ERROR: Cannot get any EncodeToPNG method!");
|
||||
return null;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
public static bool IsReadable(this Texture2D tex)
|
||||
{
|
||||
try
|
||||
{
|
||||
// This will cause an exception if it's not readable.
|
||||
// Reason for doing it this way is not all Unity versions
|
||||
// ship with the 'Texture.isReadable' property.
|
||||
|
||||
tex.GetPixel(0, 0);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static Texture2D Copy(Texture2D orig, Rect rect, bool isDTXnmNormal = false)
|
||||
{
|
||||
Color[] pixels;
|
||||
|
||||
if (!orig.IsReadable())
|
||||
{
|
||||
orig = ForceReadTexture(orig);
|
||||
}
|
||||
|
||||
pixels = orig.GetPixels((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height);
|
||||
|
||||
var _newTex = new Texture2D((int)rect.width, (int)rect.height);
|
||||
_newTex.SetPixels(pixels);
|
||||
|
||||
return _newTex;
|
||||
}
|
||||
|
||||
public static Texture2D ForceReadTexture(Texture2D tex)
|
||||
{
|
||||
try
|
||||
{
|
||||
var origFilter = tex.filterMode;
|
||||
tex.filterMode = FilterMode.Point;
|
||||
|
||||
var rt = RenderTexture.GetTemporary(tex.width, tex.height, 0, RenderTextureFormat.ARGB32);
|
||||
rt.filterMode = FilterMode.Point;
|
||||
RenderTexture.active = rt;
|
||||
Graphics.Blit(tex, rt);
|
||||
|
||||
var _newTex = new Texture2D(tex.width, tex.height, TextureFormat.ARGB32, false);
|
||||
|
||||
_newTex.ReadPixels(new Rect(0, 0, tex.width, tex.height), 0, 0);
|
||||
_newTex.Apply(false, false);
|
||||
|
||||
RenderTexture.active = null;
|
||||
tex.filterMode = origFilter;
|
||||
|
||||
return _newTex;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExplorerCore.Log("Exception on ForceReadTexture: " + e.ToString());
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SaveTextureAsPNG(Texture2D tex, string dir, string name, bool isDTXnmNormal = false)
|
||||
{
|
||||
if (!Directory.Exists(dir))
|
||||
{
|
||||
Directory.CreateDirectory(dir);
|
||||
}
|
||||
|
||||
byte[] data;
|
||||
var savepath = dir + @"\" + name + ".png";
|
||||
|
||||
// Make sure we can EncodeToPNG it.
|
||||
if (tex.format != TextureFormat.ARGB32 || !tex.IsReadable())
|
||||
{
|
||||
tex = ForceReadTexture(tex);
|
||||
}
|
||||
|
||||
if (isDTXnmNormal)
|
||||
{
|
||||
tex = DTXnmToRGBA(tex);
|
||||
tex.Apply(false, false);
|
||||
}
|
||||
|
||||
#if CPP
|
||||
data = tex.EncodeToPNG();
|
||||
#else
|
||||
if (isNewEncodeMethod)
|
||||
{
|
||||
data = (byte[])EncodeToPNGMethod.Invoke(null, new object[] { tex });
|
||||
}
|
||||
else
|
||||
{
|
||||
data = (byte[])EncodeToPNGMethod.Invoke(tex, new object[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (data == null || data.Length < 1)
|
||||
{
|
||||
ExplorerCore.LogWarning("Couldn't get any data for the texture!");
|
||||
}
|
||||
else
|
||||
{
|
||||
#if CPP
|
||||
// The Il2Cpp EncodeToPNG() method does return System.Byte[],
|
||||
// but for some reason it is not recognized or valid.
|
||||
// Simple fix is iterating into a new array manually.
|
||||
|
||||
byte[] safeData = new byte[data.Length];
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
safeData[i] = (byte)data[i]; // not sure if cast is needed
|
||||
}
|
||||
|
||||
File.WriteAllBytes(savepath, safeData);
|
||||
#else
|
||||
File.WriteAllBytes(savepath, data);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Converts DTXnm-format Normal Map to RGBA-format Normal Map.
|
||||
public static Texture2D DTXnmToRGBA(Texture2D tex)
|
||||
{
|
||||
Color[] colors = tex.GetPixels();
|
||||
|
||||
for (int i = 0; i < colors.Length; i++)
|
||||
{
|
||||
Color c = colors[i];
|
||||
|
||||
c.r = c.a * 2 - 1; // red <- alpha
|
||||
c.g = c.g * 2 - 1; // green is always the same
|
||||
|
||||
Vector2 rg = new Vector2(c.r, c.g); //this is the red-green vector
|
||||
c.b = Mathf.Sqrt(1 - Mathf.Clamp01(Vector2.Dot(rg, rg))); //recalculate the blue channel
|
||||
|
||||
colors[i] = new Color(
|
||||
(c.r * 0.5f) + 0.5f,
|
||||
(c.g * 0.5f) + 0.25f,
|
||||
(c.b * 0.5f) + 0.5f
|
||||
);
|
||||
}
|
||||
|
||||
var newtex = new Texture2D(tex.width, tex.height, TextureFormat.ARGB32, false);
|
||||
newtex.SetPixels(colors);
|
||||
|
||||
return newtex;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer.Input
|
||||
{
|
||||
public abstract class AbstractInput
|
||||
{
|
||||
public abstract void Init();
|
||||
|
||||
public abstract Vector2 MousePosition { get; }
|
||||
|
||||
public abstract bool GetKeyDown(KeyCode key);
|
||||
public abstract bool GetKey(KeyCode key);
|
||||
|
||||
public abstract bool GetMouseButtonDown(int btn);
|
||||
public abstract bool GetMouseButton(int btn);
|
||||
}
|
||||
}
|
21
src/Input/IAbstractInput.cs
Normal file
21
src/Input/IAbstractInput.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer.Input
|
||||
{
|
||||
public interface IAbstractInput
|
||||
{
|
||||
void Init();
|
||||
|
||||
Vector2 MousePosition { get; }
|
||||
|
||||
bool GetKeyDown(KeyCode key);
|
||||
bool GetKey(KeyCode key);
|
||||
|
||||
bool GetMouseButtonDown(int btn);
|
||||
bool GetMouseButton(int btn);
|
||||
}
|
||||
}
|
@ -10,65 +10,77 @@ namespace Explorer
|
||||
{
|
||||
public static class InputManager
|
||||
{
|
||||
private static AbstractInput inputModule;
|
||||
private static IAbstractInput m_inputModule;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
if (InputSystem.TKeyboard != null || TryLoadModule("Unity.InputSystem", InputSystem.TKeyboard))
|
||||
if (InputSystem.TKeyboard != null || (ReflectionHelpers.LoadModule("Unity.InputSystem") && InputSystem.TKeyboard != null))
|
||||
{
|
||||
inputModule = new InputSystem();
|
||||
m_inputModule = new InputSystem();
|
||||
}
|
||||
else if (LegacyInput.TInput != null || TryLoadModule("UnityEngine.InputLegacyModule", LegacyInput.TInput))
|
||||
else if (LegacyInput.TInput != null || (ReflectionHelpers.LoadModule("UnityEngine.InputLegacyModule") && LegacyInput.TInput != null))
|
||||
{
|
||||
inputModule = new LegacyInput();
|
||||
m_inputModule = new LegacyInput();
|
||||
}
|
||||
|
||||
if (inputModule == null)
|
||||
if (m_inputModule == null)
|
||||
{
|
||||
ExplorerCore.LogWarning("Could not find any Input module!");
|
||||
inputModule = new NoInput();
|
||||
m_inputModule = new NoInput();
|
||||
}
|
||||
|
||||
inputModule.Init();
|
||||
|
||||
bool TryLoadModule(string dll, Type check) => ReflectionHelpers.LoadModule(dll) && check != null;
|
||||
m_inputModule.Init();
|
||||
}
|
||||
|
||||
public static Vector3 MousePosition => inputModule.MousePosition;
|
||||
public static Vector3 MousePosition => m_inputModule.MousePosition;
|
||||
|
||||
public static bool GetKeyDown(KeyCode key) => inputModule.GetKeyDown(key);
|
||||
public static bool GetKey(KeyCode key) => inputModule.GetKey(key);
|
||||
public static bool GetKeyDown(KeyCode key) => m_inputModule.GetKeyDown(key);
|
||||
public static bool GetKey(KeyCode key) => m_inputModule.GetKey(key);
|
||||
|
||||
public static bool GetMouseButtonDown(int btn) => inputModule.GetMouseButtonDown(btn);
|
||||
public static bool GetMouseButton(int btn) => inputModule.GetMouseButton(btn);
|
||||
public static bool GetMouseButtonDown(int btn) => m_inputModule.GetMouseButtonDown(btn);
|
||||
public static bool GetMouseButton(int btn) => m_inputModule.GetMouseButton(btn);
|
||||
|
||||
//#if CPP
|
||||
//#pragma warning disable IDE1006
|
||||
// // public extern static string compositionString { get; }
|
||||
#if CPP
|
||||
internal delegate void d_ResetInputAxes();
|
||||
internal static d_ResetInputAxes ResetInputAxes_iCall =
|
||||
IL2CPP.ResolveICall<d_ResetInputAxes>("UnityEngine.Input::ResetInputAxes");
|
||||
|
||||
// internal delegate string get_compositionString_delegate();
|
||||
// internal static get_compositionString_delegate get_compositionString_iCall =
|
||||
// IL2CPP.ResolveICall<get_compositionString_delegate>("UnityEngine.Input::get_compositionString");
|
||||
public static void ResetInputAxes() => ResetInputAxes_iCall();
|
||||
#else
|
||||
public static void ResetInputAxes() => UnityEngine.Input.ResetInputAxes();
|
||||
#endif
|
||||
|
||||
// public static string compositionString => get_compositionString_iCall();
|
||||
#if CPP
|
||||
#pragma warning disable IDE1006
|
||||
// public extern static string compositionString { get; }
|
||||
|
||||
// // public extern static Vector2 compositionCursorPos { get; set; }
|
||||
internal delegate IntPtr d_get_compositionString();
|
||||
internal static d_get_compositionString get_compositionString_iCall =
|
||||
IL2CPP.ResolveICall<d_get_compositionString>("UnityEngine.Input::get_compositionString");
|
||||
|
||||
// internal delegate Vector2 get_compositionCursorPos_delegate();
|
||||
// internal static get_compositionCursorPos_delegate get_compositionCursorPos_iCall =
|
||||
// IL2CPP.ResolveICall<get_compositionCursorPos_delegate>("UnityEngine.Input::get_compositionCursorPos");
|
||||
public static string compositionString => IL2CPP.Il2CppStringToManaged(get_compositionString_iCall());
|
||||
|
||||
// internal delegate void set_compositionCursorPos_delegate(Vector2 value);
|
||||
// internal static set_compositionCursorPos_delegate set_compositionCursorPos_iCall =
|
||||
// IL2CPP.ResolveICall<set_compositionCursorPos_delegate>("UnityEngine.Input::set_compositionCursorPos");
|
||||
// public extern static Vector2 compositionCursorPos { get; set; }
|
||||
|
||||
// public static Vector2 compositionCursorPos
|
||||
// {
|
||||
// get => get_compositionCursorPos_iCall();
|
||||
// set => set_compositionCursorPos_iCall(value);
|
||||
// }
|
||||
internal delegate void d_get_compositionCursorPos(out Vector2 ret);
|
||||
internal static d_get_compositionCursorPos get_compositionCursorPos_iCall =
|
||||
IL2CPP.ResolveICall<d_get_compositionCursorPos>("UnityEngine.Input::get_compositionCursorPos_Injected");
|
||||
|
||||
//#pragma warning restore IDE1006
|
||||
//#endif
|
||||
internal delegate void set_compositionCursorPos_delegate(ref Vector2 value);
|
||||
internal static set_compositionCursorPos_delegate set_compositionCursorPos_iCall =
|
||||
IL2CPP.ResolveICall<set_compositionCursorPos_delegate>("UnityEngine.Input::set_compositionCursorPos_Injected");
|
||||
|
||||
public static Vector2 compositionCursorPos
|
||||
{
|
||||
get
|
||||
{
|
||||
get_compositionCursorPos_iCall(out Vector2 ret);
|
||||
return ret;
|
||||
}
|
||||
set => set_compositionCursorPos_iCall(ref value);
|
||||
}
|
||||
|
||||
#pragma warning restore IDE1006
|
||||
#endif
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ using UnityEngine;
|
||||
|
||||
namespace Explorer.Input
|
||||
{
|
||||
public class InputSystem : AbstractInput
|
||||
public class InputSystem : IAbstractInput
|
||||
{
|
||||
public static Type TKeyboard => _keyboard ?? (_keyboard = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Keyboard"));
|
||||
private static Type _keyboard;
|
||||
@ -43,9 +43,9 @@ namespace Explorer.Input
|
||||
private static PropertyInfo _positionProp;
|
||||
private static MethodInfo _readVector2InputMethod;
|
||||
|
||||
public override Vector2 MousePosition => (Vector2)_readVector2InputMethod.Invoke(MousePositionInfo, new object[0]);
|
||||
public Vector2 MousePosition => (Vector2)_readVector2InputMethod.Invoke(MousePositionInfo, new object[0]);
|
||||
|
||||
public override bool GetKeyDown(KeyCode key)
|
||||
public bool GetKeyDown(KeyCode key)
|
||||
{
|
||||
var parsedKey = Enum.Parse(TKey, key.ToString());
|
||||
var actualKey = _kbIndexer.GetValue(CurrentKeyboard, new object[] { parsedKey });
|
||||
@ -53,7 +53,7 @@ namespace Explorer.Input
|
||||
return (bool)_btnWasPressedProp.GetValue(actualKey, null);
|
||||
}
|
||||
|
||||
public override bool GetKey(KeyCode key)
|
||||
public bool GetKey(KeyCode key)
|
||||
{
|
||||
var parsed = Enum.Parse(TKey, key.ToString());
|
||||
var actualKey = _kbIndexer.GetValue(CurrentKeyboard, new object[] { parsed });
|
||||
@ -61,7 +61,7 @@ namespace Explorer.Input
|
||||
return (bool)_btnIsPressedProp.GetValue(actualKey, null);
|
||||
}
|
||||
|
||||
public override bool GetMouseButtonDown(int btn)
|
||||
public bool GetMouseButtonDown(int btn)
|
||||
{
|
||||
switch (btn)
|
||||
{
|
||||
@ -72,7 +72,7 @@ namespace Explorer.Input
|
||||
}
|
||||
}
|
||||
|
||||
public override bool GetMouseButton(int btn)
|
||||
public bool GetMouseButton(int btn)
|
||||
{
|
||||
switch (btn)
|
||||
{
|
||||
@ -83,7 +83,7 @@ namespace Explorer.Input
|
||||
}
|
||||
}
|
||||
|
||||
public override void Init()
|
||||
public void Init()
|
||||
{
|
||||
ExplorerCore.Log("Initializing new InputSystem support...");
|
||||
|
||||
|
@ -7,7 +7,7 @@ using UnityEngine;
|
||||
|
||||
namespace Explorer.Input
|
||||
{
|
||||
public class LegacyInput : AbstractInput
|
||||
public class LegacyInput : IAbstractInput
|
||||
{
|
||||
public static Type TInput => _input ?? (_input = ReflectionHelpers.GetTypeByName("UnityEngine.Input"));
|
||||
private static Type _input;
|
||||
@ -18,17 +18,17 @@ namespace Explorer.Input
|
||||
private static MethodInfo _getMouseButtonMethod;
|
||||
private static MethodInfo _getMouseButtonDownMethod;
|
||||
|
||||
public override Vector2 MousePosition => (Vector3)_mousePositionProp.GetValue(null, null);
|
||||
public Vector2 MousePosition => (Vector3)_mousePositionProp.GetValue(null, null);
|
||||
|
||||
public override bool GetKey(KeyCode key) => (bool)_getKeyMethod.Invoke(null, new object[] { key });
|
||||
public bool GetKey(KeyCode key) => (bool)_getKeyMethod.Invoke(null, new object[] { key });
|
||||
|
||||
public override bool GetKeyDown(KeyCode key) => (bool)_getKeyDownMethod.Invoke(null, new object[] { key });
|
||||
public bool GetKeyDown(KeyCode key) => (bool)_getKeyDownMethod.Invoke(null, new object[] { key });
|
||||
|
||||
public override bool GetMouseButton(int btn) => (bool)_getMouseButtonMethod.Invoke(null, new object[] { btn });
|
||||
public bool GetMouseButton(int btn) => (bool)_getMouseButtonMethod.Invoke(null, new object[] { btn });
|
||||
|
||||
public override bool GetMouseButtonDown(int btn) => (bool)_getMouseButtonDownMethod.Invoke(null, new object[] { btn });
|
||||
public bool GetMouseButtonDown(int btn) => (bool)_getMouseButtonDownMethod.Invoke(null, new object[] { btn });
|
||||
|
||||
public override void Init()
|
||||
public void Init()
|
||||
{
|
||||
ExplorerCore.Log("Initializing Legacy Input support...");
|
||||
|
||||
|
@ -8,18 +8,16 @@ namespace Explorer.Input
|
||||
{
|
||||
// Just a stub for games where no Input module was able to load at all.
|
||||
|
||||
public class NoInput : AbstractInput
|
||||
public class NoInput : IAbstractInput
|
||||
{
|
||||
public override Vector2 MousePosition => Vector2.zero;
|
||||
public Vector2 MousePosition => Vector2.zero;
|
||||
|
||||
public override bool GetKey(KeyCode key) => false;
|
||||
public bool GetKey(KeyCode key) => false;
|
||||
public bool GetKeyDown(KeyCode key) => false;
|
||||
|
||||
public override bool GetKeyDown(KeyCode key) => false;
|
||||
public bool GetMouseButton(int btn) => false;
|
||||
public bool GetMouseButtonDown(int btn) => false;
|
||||
|
||||
public override bool GetMouseButton(int btn) => false;
|
||||
|
||||
public override bool GetMouseButtonDown(int btn) => false;
|
||||
|
||||
public override void Init() { }
|
||||
public void Init() { }
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ using System;
|
||||
using UnityEngine;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using Explorer.UI.Shared;
|
||||
#if CPP
|
||||
using UnhollowerBaseLib;
|
||||
using UnityEngine.SceneManagement;
|
||||
@ -14,16 +15,13 @@ namespace Explorer.Tests
|
||||
public static class StaticTestClass
|
||||
{
|
||||
public static int StaticProperty => 5;
|
||||
|
||||
public static int StaticField = 69;
|
||||
|
||||
public static List<string> StaticList = new List<string>
|
||||
{
|
||||
"one",
|
||||
"two",
|
||||
"three",
|
||||
};
|
||||
|
||||
public static void StaticMethod() { }
|
||||
|
||||
}
|
||||
@ -33,6 +31,17 @@ namespace Explorer.Tests
|
||||
public static TestClass Instance => m_instance ?? (m_instance = new TestClass());
|
||||
private static TestClass m_instance;
|
||||
|
||||
public static bool ReadSetOnlyProperty => m_setOnlyProperty;
|
||||
|
||||
public static bool SetOnlyProperty
|
||||
{
|
||||
set => m_setOnlyProperty = value;
|
||||
}
|
||||
private static bool m_setOnlyProperty;
|
||||
|
||||
public Texture2D TestTexture = UIStyles.MakeTex(200, 200, Color.white);
|
||||
public static Sprite TestSprite;
|
||||
|
||||
public static int StaticProperty => 5;
|
||||
public static int StaticField = 5;
|
||||
public int NonStaticField;
|
||||
@ -52,6 +61,16 @@ namespace Explorer.Tests
|
||||
public TestClass()
|
||||
{
|
||||
#if CPP
|
||||
TestTexture.name = "TestTexture";
|
||||
|
||||
var r = new Rect(0, 0, TestTexture.width, TestTexture.height);
|
||||
var v2 = Vector2.zero;
|
||||
var v4 = Vector4.zero;
|
||||
TestSprite = Sprite.CreateSprite_Injected(TestTexture, ref r, ref v2, 100f, 0u, SpriteMeshType.Tight, ref v4, false);
|
||||
|
||||
GameObject.DontDestroyOnLoad(TestTexture);
|
||||
GameObject.DontDestroyOnLoad(TestSprite);
|
||||
|
||||
ILHashSetTest = new Il2CppSystem.Collections.Generic.HashSet<string>();
|
||||
ILHashSetTest.Add("1");
|
||||
ILHashSetTest.Add("2");
|
||||
|
@ -17,32 +17,25 @@ namespace Explorer.UI
|
||||
}
|
||||
private static bool m_forceUnlock;
|
||||
|
||||
private static CursorLockMode m_lastLockMode;
|
||||
private static bool m_lastVisibleState;
|
||||
private static bool m_currentlySettingCursor = false;
|
||||
|
||||
public static bool ShouldForceMouse => ExplorerCore.ShowMenu && Unlock;
|
||||
|
||||
private static Type CursorType => m_cursorType ?? (m_cursorType = ReflectionHelpers.GetTypeByName("UnityEngine.Cursor"));
|
||||
private static CursorLockMode m_lastLockMode;
|
||||
private static bool m_lastVisibleState;
|
||||
|
||||
private static bool m_currentlySettingCursor = false;
|
||||
|
||||
private static Type CursorType
|
||||
=> m_cursorType
|
||||
?? (m_cursorType = ReflectionHelpers.GetTypeByName("UnityEngine.Cursor"));
|
||||
private static Type m_cursorType;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Check if Cursor class is loaded
|
||||
if (CursorType == null)
|
||||
{
|
||||
ExplorerCore.Log("Trying to manually load Cursor module...");
|
||||
|
||||
if (ReflectionHelpers.LoadModule("UnityEngine.CoreModule") && CursorType != null)
|
||||
{
|
||||
ExplorerCore.Log("Ok!");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Could not load UnityEngine.Cursor module!");
|
||||
}
|
||||
throw new Exception("Could not find Type 'UnityEngine.Cursor'!");
|
||||
}
|
||||
|
||||
// Get current cursor state and enable cursor
|
||||
@ -91,7 +84,8 @@ namespace Explorer.UI
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExplorerCore.Log($"[NON-FATAL] Couldn't patch a method: {e.Message}");
|
||||
string s = setter ? "set_" : "get_" ;
|
||||
ExplorerCore.Log($"Unable to patch Cursor.{s}{property}: {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Explorer.UI.Shared;
|
||||
using Explorer.UI.Main;
|
||||
using Explorer.Unstrip.LayerMasks;
|
||||
#if CPP
|
||||
using UnhollowerRuntimeLib;
|
||||
#endif
|
||||
@ -17,6 +18,8 @@ namespace Explorer.UI.Inspectors
|
||||
|
||||
public GameObject TargetGO;
|
||||
|
||||
public bool pendingDestroy;
|
||||
|
||||
private static bool m_hideControls;
|
||||
|
||||
// gui element holders
|
||||
@ -43,6 +46,8 @@ namespace Explorer.UI.Inspectors
|
||||
private bool m_autoUpdateTransform;
|
||||
private bool m_localContext;
|
||||
|
||||
private int m_layer;
|
||||
|
||||
private readonly List<Component> m_cachedDestroyList = new List<Component>();
|
||||
private string m_addComponentInput = "";
|
||||
|
||||
@ -104,16 +109,16 @@ namespace Explorer.UI.Inspectors
|
||||
{
|
||||
try
|
||||
{
|
||||
if (pendingDestroy) return;
|
||||
|
||||
if (Target == null)
|
||||
{
|
||||
ExplorerCore.Log("Target is null!");
|
||||
DestroyWindow();
|
||||
DestroyOnException(new Exception("Target was destroyed."));
|
||||
return;
|
||||
}
|
||||
if (!TargetGO && !GetObjectAsGameObject())
|
||||
{
|
||||
ExplorerCore.Log("Target was destroyed!");
|
||||
DestroyWindow();
|
||||
DestroyOnException(new Exception("Target was destroyed."));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -132,6 +137,8 @@ namespace Explorer.UI.Inspectors
|
||||
TargetGO.transform.localScale = m_frozenScale;
|
||||
}
|
||||
|
||||
m_layer = TargetGO.layer;
|
||||
|
||||
// update child objects
|
||||
var childList = new List<Transform>();
|
||||
for (int i = 0; i < TargetGO.transform.childCount; i++)
|
||||
@ -162,7 +169,10 @@ namespace Explorer.UI.Inspectors
|
||||
|
||||
private void DestroyOnException(Exception e)
|
||||
{
|
||||
if (pendingDestroy) return;
|
||||
|
||||
ExplorerCore.Log($"Exception drawing GameObject Window: {e.GetType()}, {e.Message}");
|
||||
pendingDestroy = true;
|
||||
DestroyWindow();
|
||||
}
|
||||
|
||||
@ -204,6 +214,8 @@ namespace Explorer.UI.Inspectors
|
||||
|
||||
public override void WindowFunction(int windowID)
|
||||
{
|
||||
if (pendingDestroy) return;
|
||||
|
||||
try
|
||||
{
|
||||
var rect = WindowManager.TabView ? TabViewWindow.Instance.m_rect : this.m_rect;
|
||||
@ -250,6 +262,8 @@ namespace Explorer.UI.Inspectors
|
||||
GUIUnstrip.TextArea(m_name, new GUILayoutOption[0]);
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
LayerControls();
|
||||
|
||||
// --- Horizontal Columns section ---
|
||||
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||
|
||||
@ -280,6 +294,34 @@ namespace Explorer.UI.Inspectors
|
||||
}
|
||||
}
|
||||
|
||||
private void LayerControls()
|
||||
{
|
||||
GUIUnstrip.BeginHorizontal();
|
||||
GUILayout.Label("Layer:", new GUILayoutOption[] { GUILayout.Width(50) });
|
||||
|
||||
if (GUILayout.Button("<", new GUILayoutOption[] { GUILayout.Width(30) }))
|
||||
{
|
||||
if (m_layer > 0)
|
||||
{
|
||||
m_layer--;
|
||||
if (TargetGO) TargetGO.layer = m_layer;
|
||||
}
|
||||
}
|
||||
if (GUILayout.Button(">", new GUILayoutOption[] { GUILayout.Width(30) }))
|
||||
{
|
||||
if (m_layer < 32)
|
||||
{
|
||||
m_layer++;
|
||||
if (TargetGO) TargetGO.layer = m_layer;
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.Label($"{m_layer} (<color=cyan>{LayerMaskUnstrip.LayerToName(m_layer)}</color>)",
|
||||
new GUILayoutOption[] { GUILayout.Width(200) });
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
private void TransformList(Rect m_rect)
|
||||
{
|
||||
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
||||
|
@ -72,11 +72,11 @@ namespace Explorer.UI.Inspectors
|
||||
|
||||
public void DrawInstanceControls(Rect rect)
|
||||
{
|
||||
if (m_uObj)
|
||||
{
|
||||
GUILayout.Label("Name: " + m_uObj.name, new GUILayoutOption[0]);
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
//if (m_uObj)
|
||||
//{
|
||||
// GUILayout.Label("Name: " + m_uObj.name, new GUILayoutOption[0]);
|
||||
//}
|
||||
//GUILayout.EndHorizontal();
|
||||
|
||||
if (m_uObj)
|
||||
{
|
||||
@ -89,13 +89,17 @@ namespace Explorer.UI.Inspectors
|
||||
GUILayout.Label("GameObject:", new GUILayoutOption[] { GUILayout.Width(135) });
|
||||
var charWidth = obj.name.Length * 15;
|
||||
var maxWidth = rect.width - 350;
|
||||
var labelWidth = charWidth < maxWidth ? charWidth : maxWidth;
|
||||
if (GUILayout.Button("<color=#00FF00>" + obj.name + "</color>", new GUILayoutOption[] { GUILayout.Width(labelWidth) }))
|
||||
var btnWidth = charWidth < maxWidth ? charWidth : maxWidth;
|
||||
if (GUILayout.Button("<color=#00FF00>" + obj.name + "</color>", new GUILayoutOption[] { GUILayout.Width(btnWidth) }))
|
||||
{
|
||||
WindowManager.InspectObject(obj, out bool _);
|
||||
}
|
||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.Label("Name: " + m_uObj.name, new GUILayoutOption[0]);
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ namespace Explorer.UI.Inspectors
|
||||
{
|
||||
try
|
||||
{
|
||||
// make sure member type is Field, Method of Property (4 / 8 / 16)
|
||||
// make sure member type is Field, Method or Property (4 / 8 / 16)
|
||||
int m = (int)member.MemberType;
|
||||
if (m < 4 || m > 16)
|
||||
continue;
|
||||
@ -208,16 +208,19 @@ namespace Explorer.UI.Inspectors
|
||||
continue;
|
||||
}
|
||||
|
||||
//ExplorerCore.Log($"Trying to cache member {sig}...");
|
||||
|
||||
try
|
||||
{
|
||||
var cached = CacheFactory.GetCacheObject(member, target);
|
||||
|
||||
if (cached != null)
|
||||
{
|
||||
cachedSigs.Add(sig);
|
||||
list.Add(cached);
|
||||
cached.ReflectionException = exception;
|
||||
|
||||
if (string.IsNullOrEmpty(cached.ReflectionException))
|
||||
{
|
||||
cached.ReflectionException = exception;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
@ -260,15 +263,12 @@ namespace Explorer.UI.Inspectors
|
||||
? new GUILayoutOption[] { GUILayout.Width(245f) }
|
||||
: new GUILayoutOption[0];
|
||||
GUILayout.Label("<b>Type:</b> <color=cyan>" + TargetType.FullName + "</color>", labelWidth);
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
if (asInstance != null)
|
||||
{
|
||||
asInstance.DrawInstanceControls(rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
UIStyles.HorizontalLine(Color.grey);
|
||||
|
||||
|
@ -146,7 +146,7 @@ namespace Explorer.UI
|
||||
{
|
||||
GUILayout.Label($"<color=grey><i>Not yet evaluated</i></color> ({typeName})", new GUILayoutOption[0]);
|
||||
}
|
||||
else if (Value == null && !(cacheMember is CacheMethod))
|
||||
else if ((Value == null || Value is UnityEngine.Object uObj && !uObj) && !(cacheMember is CacheMethod))
|
||||
{
|
||||
GUILayout.Label($"<i>null ({typeName})</i>", new GUILayoutOption[0]);
|
||||
}
|
||||
@ -198,31 +198,51 @@ namespace Explorer.UI
|
||||
return m_toStringMethod;
|
||||
}
|
||||
|
||||
private string GetButtonLabel()
|
||||
public string GetButtonLabel()
|
||||
{
|
||||
if (Value == null) return null;
|
||||
|
||||
string label = (string)ToStringMethod?.Invoke(Value, null) ?? Value.ToString();
|
||||
var valueType = ReflectionHelpers.GetActualType(Value);
|
||||
|
||||
var classColor = ValueType.IsAbstract && ValueType.IsSealed
|
||||
? Syntax.Class_Static
|
||||
: Syntax.Class_Instance;
|
||||
string label;
|
||||
|
||||
string typeLabel = $"<color={classColor}>{ValueType.FullName}</color>";
|
||||
|
||||
if (Value is UnityEngine.Object)
|
||||
if (valueType == typeof(TextAsset))
|
||||
{
|
||||
label = label.Replace($"({ValueType.FullName})", $"({typeLabel})");
|
||||
var textAsset = Value as TextAsset;
|
||||
|
||||
label = textAsset.text;
|
||||
|
||||
if (label.Length > 10)
|
||||
{
|
||||
label = $"{label.Substring(0, 10)}...";
|
||||
}
|
||||
|
||||
label = $"\"{label}\" {textAsset.name} (<color={Syntax.Class_Instance}>UnityEngine.TextAsset</color>)";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!label.Contains(ValueType.FullName))
|
||||
label = (string)ToStringMethod?.Invoke(Value, null) ?? Value.ToString();
|
||||
|
||||
var classColor = valueType.IsAbstract && valueType.IsSealed
|
||||
? Syntax.Class_Static
|
||||
: Syntax.Class_Instance;
|
||||
|
||||
string typeLabel = $"<color={classColor}>{valueType.FullName}</color>";
|
||||
|
||||
if (Value is UnityEngine.Object)
|
||||
{
|
||||
label += $" ({typeLabel})";
|
||||
label = label.Replace($"({valueType.FullName})", $"({typeLabel})");
|
||||
}
|
||||
else
|
||||
{
|
||||
label = label.Replace(ValueType.FullName, typeLabel);
|
||||
if (!label.Contains(valueType.FullName))
|
||||
{
|
||||
label += $" ({typeLabel})";
|
||||
}
|
||||
else
|
||||
{
|
||||
label = label.Replace(valueType.FullName, typeLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,9 @@ using Explorer.CacheObject;
|
||||
|
||||
namespace Explorer.UI
|
||||
{
|
||||
// TODO: Re-work class using InteractiveEnumerable or maybe InteractiveCollection for the Keys/Value lists.
|
||||
// Make the keys and values editable.
|
||||
|
||||
public class InteractiveDictionary : InteractiveValue, IExpandHeight
|
||||
{
|
||||
public bool IsExpanded { get; set; }
|
||||
@ -158,7 +161,7 @@ namespace Explorer.UI
|
||||
m_cachedValues = values.ToArray();
|
||||
}
|
||||
|
||||
private bool EnsureDictionaryIsSupported()
|
||||
public bool EnsureDictionaryIsSupported()
|
||||
{
|
||||
if (typeof(IDictionary).IsAssignableFrom(ValueType))
|
||||
{
|
||||
@ -177,6 +180,11 @@ namespace Explorer.UI
|
||||
.GetField("NativeClassPtr")
|
||||
.GetValue(null);
|
||||
|
||||
if (ptr == IntPtr.Zero)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return Il2CppSystem.Type.internal_from_handle(IL2CPP.il2cpp_class_get_type(ptr)) is Il2CppSystem.Type;
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,10 @@ using System.Reflection;
|
||||
using UnityEngine;
|
||||
using Explorer.UI.Shared;
|
||||
using Explorer.CacheObject;
|
||||
using System.Linq;
|
||||
#if CPP
|
||||
using UnhollowerBaseLib;
|
||||
#endif
|
||||
|
||||
namespace Explorer.UI
|
||||
{
|
||||
@ -173,38 +177,20 @@ namespace Explorer.UI
|
||||
|
||||
private Type GetEntryType()
|
||||
{
|
||||
if (m_entryType == null)
|
||||
if (ValueType.IsGenericType)
|
||||
{
|
||||
if (OwnerCacheObject is CacheMember cacheMember && cacheMember.MemInfo != null)
|
||||
{
|
||||
Type memberType = null;
|
||||
switch (cacheMember.MemInfo.MemberType)
|
||||
{
|
||||
case MemberTypes.Field:
|
||||
memberType = (cacheMember.MemInfo as FieldInfo).FieldType;
|
||||
break;
|
||||
case MemberTypes.Property:
|
||||
memberType = (cacheMember.MemInfo as PropertyInfo).PropertyType;
|
||||
break;
|
||||
}
|
||||
var gArgs = ValueType.GetGenericArguments();
|
||||
|
||||
if (memberType != null && memberType.IsGenericType)
|
||||
{
|
||||
m_entryType = memberType.GetGenericArguments()[0];
|
||||
}
|
||||
}
|
||||
else if (Value != null)
|
||||
if (ValueType.FullName.Contains("ValueCollection"))
|
||||
{
|
||||
var type = Value.GetType();
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
m_entryType = type.GetGenericArguments()[0];
|
||||
}
|
||||
m_entryType = gArgs[gArgs.Length - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_entryType = gArgs[0];
|
||||
}
|
||||
}
|
||||
|
||||
// use System.Object for non-generic.
|
||||
if (m_entryType == null)
|
||||
else
|
||||
{
|
||||
m_entryType = typeof(object);
|
||||
}
|
||||
@ -255,18 +241,11 @@ namespace Explorer.UI
|
||||
}
|
||||
#endif
|
||||
|
||||
//ExplorerCore.Log("Caching enumeration entry " + obj.ToString() + " as " + EntryType.FullName);
|
||||
|
||||
var cached = new CacheEnumerated() { Index = index, RefIList = Value as IList, ParentEnumeration = this };
|
||||
cached.Init(obj, EntryType);
|
||||
list.Add(cached);
|
||||
|
||||
//if (CacheFactory.GetCacheObject(obj, t) is CacheObjectBase cached)
|
||||
//{
|
||||
// list.Add(cached);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// list.Add(null);
|
||||
//}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
51
src/UI/InteractiveValue/Object/InteractiveSprite.cs
Normal file
51
src/UI/InteractiveValue/Object/InteractiveSprite.cs
Normal file
@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Explorer.Helpers;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer.UI
|
||||
{
|
||||
public class InteractiveSprite : InteractiveTexture2D
|
||||
{
|
||||
private Sprite refSprite;
|
||||
|
||||
public override void UpdateValue()
|
||||
{
|
||||
#if CPP
|
||||
if (Value != null && Value.Il2CppCast(typeof(Sprite)) is Sprite sprite)
|
||||
{
|
||||
refSprite = sprite;
|
||||
}
|
||||
#else
|
||||
if (Value is Sprite sprite)
|
||||
{
|
||||
refSprite = sprite;
|
||||
}
|
||||
#endif
|
||||
|
||||
base.UpdateValue();
|
||||
}
|
||||
|
||||
public override void GetTexture2D()
|
||||
{
|
||||
if (refSprite)
|
||||
{
|
||||
currentTex = refSprite.texture;
|
||||
}
|
||||
}
|
||||
|
||||
public override void GetGUIContent()
|
||||
{
|
||||
// Check if the Sprite.textureRect is just the entire texture
|
||||
if (refSprite.textureRect != new Rect(0, 0, currentTex.width, currentTex.height))
|
||||
{
|
||||
// It's not, do a sub-copy.
|
||||
currentTex = Texture2DHelpers.Copy(refSprite.texture, refSprite.textureRect);
|
||||
}
|
||||
|
||||
base.GetGUIContent();
|
||||
}
|
||||
}
|
||||
}
|
30
src/UI/InteractiveValue/Object/InteractiveTexture.cs
Normal file
30
src/UI/InteractiveValue/Object/InteractiveTexture.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer.UI
|
||||
{
|
||||
// This class is possibly unnecessary.
|
||||
// It's just for CacheMembers that have 'Texture' as the value type, but is actually a Texture2D.
|
||||
|
||||
public class InteractiveTexture : InteractiveTexture2D
|
||||
{
|
||||
public override void GetTexture2D()
|
||||
{
|
||||
#if CPP
|
||||
if (Value != null && Value.Il2CppCast(typeof(Texture2D)) is Texture2D tex)
|
||||
#else
|
||||
if (Value is Texture2D tex)
|
||||
#endif
|
||||
{
|
||||
currentTex = tex;
|
||||
texContent = new GUIContent
|
||||
{
|
||||
image = currentTex
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
149
src/UI/InteractiveValue/Object/InteractiveTexture2D.cs
Normal file
149
src/UI/InteractiveValue/Object/InteractiveTexture2D.cs
Normal file
@ -0,0 +1,149 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Explorer.CacheObject;
|
||||
using Explorer.Config;
|
||||
using UnityEngine;
|
||||
using System.IO;
|
||||
using Explorer.Helpers;
|
||||
#if CPP
|
||||
using Explorer.Unstrip.ImageConversion;
|
||||
#endif
|
||||
|
||||
namespace Explorer.UI
|
||||
{
|
||||
public class InteractiveTexture2D : InteractiveValue, IExpandHeight
|
||||
{
|
||||
public bool IsExpanded { get; set; }
|
||||
public float WhiteSpace { get; set; } = 215f;
|
||||
|
||||
public Texture2D currentTex;
|
||||
public GUIContent texContent;
|
||||
|
||||
private string saveFolder = ModConfig.Instance.Default_Output_Path;
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
}
|
||||
|
||||
public override void UpdateValue()
|
||||
{
|
||||
base.UpdateValue();
|
||||
|
||||
GetTexture2D();
|
||||
}
|
||||
|
||||
public virtual void GetTexture2D()
|
||||
{
|
||||
#if CPP
|
||||
if (Value != null && Value.Il2CppCast(typeof(Texture2D)) is Texture2D tex)
|
||||
#else
|
||||
if (Value is Texture2D tex)
|
||||
#endif
|
||||
{
|
||||
currentTex = tex;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void GetGUIContent()
|
||||
{
|
||||
texContent = new GUIContent
|
||||
{
|
||||
image = currentTex
|
||||
};
|
||||
}
|
||||
|
||||
public override void DrawValue(Rect window, float width)
|
||||
{
|
||||
GUIUnstrip.BeginVertical();
|
||||
|
||||
GUIUnstrip.BeginHorizontal();
|
||||
|
||||
if (currentTex && !IsExpanded)
|
||||
{
|
||||
if (GUILayout.Button("v", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||
{
|
||||
IsExpanded = true;
|
||||
GetGUIContent();
|
||||
}
|
||||
}
|
||||
else if (currentTex)
|
||||
{
|
||||
if (GUILayout.Button("^", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||
{
|
||||
IsExpanded = false;
|
||||
}
|
||||
}
|
||||
|
||||
base.DrawValue(window, width);
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
if (currentTex && IsExpanded)
|
||||
{
|
||||
DrawTextureControls();
|
||||
DrawTexture();
|
||||
}
|
||||
|
||||
GUILayout.EndVertical();
|
||||
}
|
||||
|
||||
// Temporarily disabled in BepInEx IL2CPP.
|
||||
private void DrawTexture()
|
||||
{
|
||||
#if CPP
|
||||
#if BIE
|
||||
#else
|
||||
GUILayout.Label(texContent, new GUILayoutOption[0]);
|
||||
#endif
|
||||
#else
|
||||
GUILayout.Label(texContent, new GUILayoutOption[0]);
|
||||
#endif
|
||||
}
|
||||
|
||||
private void DrawTextureControls()
|
||||
{
|
||||
GUIUnstrip.BeginHorizontal();
|
||||
|
||||
GUILayout.Label("Save folder:", new GUILayoutOption[] { GUILayout.Width(80f) });
|
||||
saveFolder = GUIUnstrip.TextField(saveFolder, new GUILayoutOption[0]);
|
||||
GUIUnstrip.Space(10f);
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
if (GUILayout.Button("Save to PNG", new GUILayoutOption[] { GUILayout.Width(100f) }))
|
||||
{
|
||||
var name = RemoveInvalidFilenameChars(currentTex.name ?? "");
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
if (OwnerCacheObject is CacheMember cacheMember)
|
||||
{
|
||||
name = cacheMember.MemInfo.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
name = "UNTITLED";
|
||||
}
|
||||
}
|
||||
|
||||
Texture2DHelpers.SaveTextureAsPNG(currentTex, saveFolder, name, false);
|
||||
|
||||
ExplorerCore.Log($@"Saved to {saveFolder}\{name}.png!");
|
||||
}
|
||||
}
|
||||
|
||||
private string RemoveInvalidFilenameChars(string s)
|
||||
{
|
||||
var invalid = System.IO.Path.GetInvalidFileNameChars();
|
||||
foreach (var c in invalid)
|
||||
{
|
||||
s = s.Replace(c.ToString(), "");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -80,12 +80,13 @@ namespace Explorer.UI
|
||||
|
||||
if (OwnerCacheObject.CanWrite)
|
||||
{
|
||||
b = GUILayout.Toggle(b, label, new GUILayoutOption[0]);
|
||||
if (b != (bool)Value)
|
||||
{
|
||||
Value = b;
|
||||
OwnerCacheObject.SetValue();
|
||||
}
|
||||
Value = GUILayout.Toggle(b, label, new GUILayoutOption[] { GUILayout.Width(60) });
|
||||
DrawApplyButton();
|
||||
//if (b != (bool)Value)
|
||||
//{
|
||||
// Value = b;
|
||||
// OwnerCacheObject.SetValue();
|
||||
//}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -104,13 +105,8 @@ namespace Explorer.UI
|
||||
GUILayout.Label("<color=#2df7b2><i>" + ValueType.Name + "</i></color>", new GUILayoutOption[] { GUILayout.Width(50) });
|
||||
|
||||
m_valueToString = GUIUnstrip.TextArea(m_valueToString, new GUILayoutOption[] { GUILayout.ExpandWidth(true) });
|
||||
if (OwnerCacheObject.CanWrite)
|
||||
{
|
||||
if (GUILayout.Button("<color=#00FF00>Apply</color>", new GUILayoutOption[] { GUILayout.Width(60) }))
|
||||
{
|
||||
SetValueFromInput();
|
||||
}
|
||||
}
|
||||
|
||||
DrawApplyButton();
|
||||
|
||||
if (ModConfig.Instance.Bitwise_Support && m_canBitwiseOperate)
|
||||
{
|
||||
@ -129,6 +125,24 @@ namespace Explorer.UI
|
||||
GUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private void DrawApplyButton()
|
||||
{
|
||||
if (OwnerCacheObject.CanWrite)
|
||||
{
|
||||
if (GUILayout.Button("<color=#00FF00>Apply</color>", new GUILayoutOption[] { GUILayout.Width(60) }))
|
||||
{
|
||||
if (m_isBool)
|
||||
{
|
||||
OwnerCacheObject.SetValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
SetValueFromInput();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawBitwise()
|
||||
{
|
||||
if (OwnerCacheObject.CanWrite)
|
||||
|
@ -33,7 +33,7 @@ namespace Explorer.UI.Main
|
||||
public static TextEditor textEditor;
|
||||
private bool shouldRefocus;
|
||||
|
||||
public static GUIStyle AutocompleteStyle => autocompleteStyle ?? GetCompletionStyle();
|
||||
public static GUIStyle AutocompleteStyle => autocompleteStyle ?? GetAutocompleteStyle();
|
||||
private static GUIStyle autocompleteStyle;
|
||||
|
||||
public static readonly string[] DefaultUsing = new string[]
|
||||
@ -342,9 +342,9 @@ Help();";
|
||||
}
|
||||
|
||||
// Credit ManlyMarco
|
||||
private static GUIStyle GetCompletionStyle()
|
||||
private static GUIStyle GetAutocompleteStyle()
|
||||
{
|
||||
return autocompleteStyle = new GUIStyle(GUI.skin.button)
|
||||
var style = new GUIStyle
|
||||
{
|
||||
border = new RectOffset(0, 0, 0, 0),
|
||||
margin = new RectOffset(0, 0, 0, 0),
|
||||
@ -353,8 +353,10 @@ Help();";
|
||||
normal = { background = null },
|
||||
focused = { background = Texture2D.whiteTexture, textColor = Color.black },
|
||||
active = { background = Texture2D.whiteTexture, textColor = Color.black },
|
||||
alignment = TextAnchor.MiddleLeft,
|
||||
alignment = TextAnchor.MiddleLeft
|
||||
};
|
||||
|
||||
return autocompleteStyle = style;
|
||||
}
|
||||
|
||||
private class VoidType
|
||||
|
@ -18,12 +18,14 @@ namespace Explorer.UI.Main
|
||||
public int defaultPageLimit;
|
||||
public bool bitwiseSupport;
|
||||
public bool tabView;
|
||||
public string defaultOutputPath;
|
||||
|
||||
private CacheObjectBase toggleKeyInput;
|
||||
private CacheObjectBase defaultSizeInput;
|
||||
private CacheObjectBase defaultPageLimitInput;
|
||||
private CacheObjectBase bitwiseSupportInput;
|
||||
private CacheObjectBase tabViewInput;
|
||||
private CacheObjectBase defaultOutputPathInput;
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
@ -41,6 +43,9 @@ namespace Explorer.UI.Main
|
||||
|
||||
tabView = ModConfig.Instance.Tab_View;
|
||||
tabViewInput = CacheFactory.GetCacheObject(typeof(OptionsPage).GetField("tabView"), this);
|
||||
|
||||
defaultOutputPath = ModConfig.Instance.Default_Output_Path;
|
||||
defaultOutputPathInput = CacheFactory.GetCacheObject(typeof(OptionsPage).GetField("defaultOutputPath"), this);
|
||||
}
|
||||
|
||||
public override void Update() { }
|
||||
@ -58,26 +63,41 @@ namespace Explorer.UI.Main
|
||||
toggleKeyInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
UIStyles.HorizontalLine(Color.black, true);
|
||||
|
||||
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||
GUILayout.Label($"Default Window Size:", new GUILayoutOption[] { GUILayout.Width(215f) });
|
||||
defaultSizeInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
UIStyles.HorizontalLine(Color.black, true);
|
||||
|
||||
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||
GUILayout.Label($"Default Items per Page:", new GUILayoutOption[] { GUILayout.Width(215f) });
|
||||
defaultPageLimitInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
UIStyles.HorizontalLine(Color.black, true);
|
||||
|
||||
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||
GUILayout.Label($"Enable Bitwise Editing:", new GUILayoutOption[] { GUILayout.Width(215f) });
|
||||
bitwiseSupportInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
UIStyles.HorizontalLine(Color.black, true);
|
||||
|
||||
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||
GUILayout.Label($"Enable Tab View:", new GUILayoutOption[] { GUILayout.Width(215f) });
|
||||
tabViewInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
UIStyles.HorizontalLine(Color.black, true);
|
||||
|
||||
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||
GUILayout.Label($"Default Output Path:", new GUILayoutOption[] { GUILayout.Width(215f) });
|
||||
defaultOutputPathInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
if (GUILayout.Button("<color=lime><b>Apply and Save</b></color>", new GUILayoutOption[0]))
|
||||
{
|
||||
ApplyAndSave();
|
||||
|
@ -19,8 +19,6 @@ namespace Explorer.UI.Main
|
||||
private float m_timeOfLastUpdate = -1f;
|
||||
private const int PASSIVE_UPDATE_INTERVAL = 1;
|
||||
|
||||
private static bool m_getRootObjectsFailed;
|
||||
|
||||
private static string m_currentScene = "";
|
||||
|
||||
// gameobject list
|
||||
@ -50,7 +48,7 @@ namespace Explorer.UI.Main
|
||||
if (m_searching)
|
||||
CancelSearch();
|
||||
|
||||
Update_Impl(true);
|
||||
Update_Impl();
|
||||
}
|
||||
|
||||
public void TraverseUp()
|
||||
@ -75,11 +73,6 @@ namespace Explorer.UI.Main
|
||||
public void CancelSearch()
|
||||
{
|
||||
m_searching = false;
|
||||
|
||||
if (m_getRootObjectsFailed && !m_currentTransform)
|
||||
{
|
||||
GetRootObjectsManual_Impl();
|
||||
}
|
||||
}
|
||||
|
||||
public List<CacheObjectBase> SearchSceneObjects(string _search)
|
||||
@ -112,7 +105,7 @@ namespace Explorer.UI.Main
|
||||
Update_Impl();
|
||||
}
|
||||
|
||||
private void Update_Impl(bool manual = false)
|
||||
private void Update_Impl()
|
||||
{
|
||||
List<Transform> allTransforms = new List<Transform>();
|
||||
|
||||
@ -126,39 +119,23 @@ namespace Explorer.UI.Main
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m_getRootObjectsFailed)
|
||||
for (int i = 0; i < SceneManager.sceneCount; i++)
|
||||
{
|
||||
try
|
||||
var scene = SceneManager.GetSceneAt(i);
|
||||
|
||||
if (scene.name == m_currentScene)
|
||||
{
|
||||
for (int i = 0; i < SceneManager.sceneCount; i++)
|
||||
{
|
||||
var scene = SceneManager.GetSceneAt(i);
|
||||
var rootObjects =
|
||||
#if CPP
|
||||
Unstrip.Scenes.SceneUnstrip.GetRootGameObjects(scene)
|
||||
.Select(it => it.transform);
|
||||
#else
|
||||
scene.GetRootGameObjects().Select(it => it.transform);
|
||||
#endif
|
||||
allTransforms.AddRange(rootObjects);
|
||||
|
||||
if (scene.name == m_currentScene)
|
||||
{
|
||||
allTransforms.AddRange(scene.GetRootGameObjects()
|
||||
.Select(it => it.transform));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
catch
|
||||
{
|
||||
ExplorerCore.Log("Exception getting root scene objects, falling back to backup method...");
|
||||
|
||||
m_getRootObjectsFailed = true;
|
||||
allTransforms.AddRange(GetRootObjectsManual_Impl());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!manual)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
allTransforms.AddRange(GetRootObjectsManual_Impl());
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,36 +155,6 @@ namespace Explorer.UI.Main
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<Transform> GetRootObjectsManual_Impl()
|
||||
{
|
||||
try
|
||||
{
|
||||
var array = Resources.FindObjectsOfTypeAll(ReflectionHelpers.TransformType);
|
||||
|
||||
var list = new List<Transform>();
|
||||
foreach (var obj in array)
|
||||
{
|
||||
#if CPP
|
||||
var transform = obj.TryCast<Transform>();
|
||||
#else
|
||||
var transform = obj as Transform;
|
||||
#endif
|
||||
if (transform.parent == null && transform.gameObject.scene.name == m_currentScene)
|
||||
{
|
||||
list.Add(transform);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExplorerCore.Log("Exception getting root scene objects (manual): "
|
||||
+ e.GetType() + ", " + e.Message + "\r\n"
|
||||
+ e.StackTrace);
|
||||
return new Transform[0];
|
||||
}
|
||||
}
|
||||
|
||||
// --------- GUI Draw Function --------- //
|
||||
|
||||
public override void DrawWindow()
|
||||
@ -292,15 +239,12 @@ namespace Explorer.UI.Main
|
||||
{
|
||||
int index = names.IndexOf(m_currentScene);
|
||||
index += changeWanted;
|
||||
if (index > scenes.Count - 1)
|
||||
|
||||
if (index >= 0 && index < SceneManager.sceneCount)
|
||||
{
|
||||
index = 0;
|
||||
m_currentScene = scenes[index].name;
|
||||
Update_Impl();
|
||||
}
|
||||
else if (index < 0)
|
||||
{
|
||||
index = scenes.Count - 1;
|
||||
}
|
||||
m_currentScene = scenes[index].name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -317,7 +261,7 @@ namespace Explorer.UI.Main
|
||||
{
|
||||
Pages.TurnPage(Turn.Left, ref this.scroll);
|
||||
|
||||
Update_Impl(true);
|
||||
Update_Impl();
|
||||
}
|
||||
|
||||
Pages.CurrentPageLabel();
|
||||
@ -326,7 +270,7 @@ namespace Explorer.UI.Main
|
||||
{
|
||||
Pages.TurnPage(Turn.Right, ref this.scroll);
|
||||
|
||||
Update_Impl(true);
|
||||
Update_Impl();
|
||||
}
|
||||
}
|
||||
|
||||
@ -356,14 +300,6 @@ namespace Explorer.UI.Main
|
||||
else
|
||||
{
|
||||
GUILayout.Label("Scene Root GameObjects:", new GUILayoutOption[0]);
|
||||
|
||||
if (m_getRootObjectsFailed)
|
||||
{
|
||||
if (GUILayout.Button("Update Root Object List (auto-update failed!)", new GUILayoutOption[0]))
|
||||
{
|
||||
Update_Impl(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_objectList.Count > 0)
|
||||
|
@ -6,6 +6,7 @@ using System.Reflection;
|
||||
using UnityEngine;
|
||||
using Explorer.UI.Shared;
|
||||
using Explorer.CacheObject;
|
||||
using System.Threading;
|
||||
|
||||
namespace Explorer.UI.Main
|
||||
{
|
||||
@ -15,9 +16,13 @@ namespace Explorer.UI.Main
|
||||
|
||||
public override string Name { get => "Search"; }
|
||||
|
||||
private int MaxSearchResults = 5000;
|
||||
|
||||
private string m_searchInput = "";
|
||||
private string m_typeInput = "";
|
||||
|
||||
//private bool m_cachingResults;
|
||||
|
||||
private Vector2 resultsScroll = Vector2.zero;
|
||||
|
||||
public PageHelper Pages = new PageHelper();
|
||||
@ -58,6 +63,8 @@ namespace Explorer.UI.Main
|
||||
|
||||
private void CacheResults(IEnumerable results, bool isStaticClasses = false)
|
||||
{
|
||||
//m_cachingResults = true;
|
||||
|
||||
m_searchResults = new List<CacheObjectBase>();
|
||||
|
||||
foreach (var obj in results)
|
||||
@ -67,6 +74,9 @@ namespace Explorer.UI.Main
|
||||
#if CPP
|
||||
if (toCache is Il2CppSystem.Object ilObject)
|
||||
{
|
||||
var type = ReflectionHelpers.GetActualType(ilObject);
|
||||
ilObject = (Il2CppSystem.Object)ilObject.Il2CppCast(type);
|
||||
|
||||
toCache = ilObject.TryCast<GameObject>() ?? ilObject.TryCast<Transform>()?.gameObject ?? ilObject;
|
||||
}
|
||||
#else
|
||||
@ -76,6 +86,14 @@ namespace Explorer.UI.Main
|
||||
}
|
||||
#endif
|
||||
|
||||
if (toCache is TextAsset textAsset)
|
||||
{
|
||||
if (string.IsNullOrEmpty(textAsset.text))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
var cache = CacheFactory.GetCacheObject(toCache);
|
||||
cache.IsStaticClassSearchResult = isStaticClasses;
|
||||
m_searchResults.Add(cache);
|
||||
@ -83,187 +101,22 @@ namespace Explorer.UI.Main
|
||||
|
||||
Pages.ItemCount = m_searchResults.Count;
|
||||
Pages.PageOffset = 0;
|
||||
|
||||
results = null;
|
||||
|
||||
//m_cachingResults = false;
|
||||
}
|
||||
|
||||
public override void DrawWindow()
|
||||
{
|
||||
try
|
||||
{
|
||||
// helpers
|
||||
GUIUnstrip.BeginHorizontal(GUIContent.none, GUI.skin.box, null);
|
||||
GUILayout.Label("<b><color=orange>Helpers</color></b>", new GUILayoutOption[] { GUILayout.Width(70) });
|
||||
if (GUILayout.Button("Find Static Instances", new GUILayoutOption[] { GUILayout.Width(180) }))
|
||||
{
|
||||
CacheResults(GetStaticInstances());
|
||||
}
|
||||
if (GUILayout.Button("Find Static Classes", new GUILayoutOption[] { GUILayout.Width(180) }))
|
||||
{
|
||||
CacheResults(GetStaticClasses(), true);
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
// search box
|
||||
SearchBox();
|
||||
|
||||
// results
|
||||
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
||||
|
||||
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||
GUILayout.Label("<b><color=orange>Results </color></b>" + " (" + m_searchResults.Count + ")", new GUILayoutOption[0]);
|
||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||
|
||||
int count = m_searchResults.Count;
|
||||
|
||||
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||
|
||||
Pages.DrawLimitInputArea();
|
||||
|
||||
if (count > Pages.ItemsPerPage)
|
||||
{
|
||||
// prev/next page buttons
|
||||
|
||||
if (Pages.ItemCount > Pages.ItemsPerPage)
|
||||
{
|
||||
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) }))
|
||||
{
|
||||
Pages.TurnPage(Turn.Left, ref this.resultsScroll);
|
||||
}
|
||||
|
||||
Pages.CurrentPageLabel();
|
||||
|
||||
if (GUILayout.Button("Next >", new GUILayoutOption[] { GUILayout.Width(80) }))
|
||||
{
|
||||
Pages.TurnPage(Turn.Right, ref this.resultsScroll);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
resultsScroll = GUIUnstrip.BeginScrollView(resultsScroll);
|
||||
|
||||
var _temprect = new Rect(MainMenu.MainRect.x, MainMenu.MainRect.y, MainMenu.MainRect.width + 160, MainMenu.MainRect.height);
|
||||
|
||||
if (m_searchResults.Count > 0)
|
||||
{
|
||||
int offset = Pages.CalculateOffsetIndex();
|
||||
|
||||
for (int i = offset; i < offset + Pages.ItemsPerPage && i < count; i++)
|
||||
{
|
||||
m_searchResults[i].Draw(MainMenu.MainRect, 0f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.Label("<color=red><i>No results found!</i></color>", new GUILayoutOption[0]);
|
||||
}
|
||||
|
||||
GUIUnstrip.EndScrollView();
|
||||
GUILayout.EndVertical();
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_searchResults.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void SearchBox()
|
||||
{
|
||||
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
||||
|
||||
// ----- GameObject Search -----
|
||||
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||
GUILayout.Label("<b><color=orange>Search</color></b>", new GUILayoutOption[0]);
|
||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||
|
||||
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||
|
||||
GUILayout.Label("Name Contains:", new GUILayoutOption[] { GUILayout.Width(100) });
|
||||
m_searchInput = GUIUnstrip.TextField(m_searchInput, new GUILayoutOption[] { GUILayout.Width(200) });
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||
|
||||
GUILayout.Label("Class Filter:", new GUILayoutOption[] { GUILayout.Width(100) });
|
||||
ClassFilterToggle(TypeFilter.Object, "Object");
|
||||
ClassFilterToggle(TypeFilter.GameObject, "GameObject");
|
||||
ClassFilterToggle(TypeFilter.Component, "Component");
|
||||
ClassFilterToggle(TypeFilter.Custom, "Custom");
|
||||
GUILayout.EndHorizontal();
|
||||
if (TypeMode == TypeFilter.Custom)
|
||||
{
|
||||
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||
GUI.skin.label.alignment = TextAnchor.MiddleRight;
|
||||
GUILayout.Label("Custom Class:", new GUILayoutOption[] { GUILayout.Width(250) });
|
||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||
m_typeInput = GUIUnstrip.TextField(m_typeInput, new GUILayoutOption[] { GUILayout.Width(250) });
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||
GUILayout.Label("Scene Filter:", new GUILayoutOption[] { GUILayout.Width(100) });
|
||||
SceneFilterToggle(SceneFilter.Any, "Any", 60);
|
||||
SceneFilterToggle(SceneFilter.This, "This Scene", 100);
|
||||
SceneFilterToggle(SceneFilter.DontDestroy, "DontDestroyOnLoad", 140);
|
||||
SceneFilterToggle(SceneFilter.None, "No Scene", 80);
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
if (GUILayout.Button("<b><color=cyan>Search</color></b>", new GUILayoutOption[0]))
|
||||
{
|
||||
Search();
|
||||
}
|
||||
|
||||
GUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private void ClassFilterToggle(TypeFilter mode, string label)
|
||||
{
|
||||
if (TypeMode == mode)
|
||||
{
|
||||
GUI.color = Color.green;
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.color = Color.white;
|
||||
}
|
||||
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Width(100) }))
|
||||
{
|
||||
TypeMode = mode;
|
||||
}
|
||||
GUI.color = Color.white;
|
||||
}
|
||||
|
||||
private void SceneFilterToggle(SceneFilter mode, string label, float width)
|
||||
{
|
||||
if (SceneMode == mode)
|
||||
{
|
||||
GUI.color = Color.green;
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.color = Color.white;
|
||||
}
|
||||
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Width(width) }))
|
||||
{
|
||||
SceneMode = mode;
|
||||
}
|
||||
GUI.color = Color.white;
|
||||
}
|
||||
|
||||
|
||||
// -------------- ACTUAL METHODS (not Gui draw) ----------------- //
|
||||
|
||||
// ======= search functions =======
|
||||
|
||||
private void Search()
|
||||
{
|
||||
Pages.PageOffset = 0;
|
||||
CacheResults(FindAllObjectsOfType(m_searchInput, m_typeInput));
|
||||
}
|
||||
//if (m_cachingResults)
|
||||
//{
|
||||
// ExplorerCore.Log("Cannot search now, we are already caching results...");
|
||||
// return;
|
||||
//}
|
||||
|
||||
Pages.PageOffset = 0;
|
||||
|
||||
private List<object> FindAllObjectsOfType(string searchQuery, string typeName)
|
||||
{
|
||||
#if CPP
|
||||
Il2CppSystem.Type searchType = null;
|
||||
|
||||
@ -272,24 +125,18 @@ namespace Explorer.UI.Main
|
||||
#endif
|
||||
if (TypeMode == TypeFilter.Custom)
|
||||
{
|
||||
try
|
||||
if (ReflectionHelpers.GetTypeByName(m_typeInput) is Type t)
|
||||
{
|
||||
if (ReflectionHelpers.GetTypeByName(typeName) is Type t)
|
||||
{
|
||||
#if CPP
|
||||
searchType = Il2CppSystem.Type.GetType(t.AssemblyQualifiedName);
|
||||
searchType = Il2CppSystem.Type.GetType(t.AssemblyQualifiedName);
|
||||
#else
|
||||
searchType = t;
|
||||
searchType = t;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"Could not find a Type by the name of '{typeName}'!");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
else
|
||||
{
|
||||
ExplorerCore.Log("Exception getting Search Type: " + e.GetType() + ", " + e.Message);
|
||||
ExplorerCore.Log($"Could not find a Type by the name of '{m_typeInput}'!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (TypeMode == TypeFilter.Object)
|
||||
@ -311,7 +158,7 @@ namespace Explorer.UI.Main
|
||||
{
|
||||
ExplorerCore.LogWarning("Your Custom Class Type must inherit from UnityEngine.Object!");
|
||||
}
|
||||
return new List<object>();
|
||||
return;
|
||||
}
|
||||
|
||||
var matches = new List<object>();
|
||||
@ -323,9 +170,9 @@ namespace Explorer.UI.Main
|
||||
int i = 0;
|
||||
foreach (var obj in allObjectsOfType)
|
||||
{
|
||||
if (i >= 2000) break;
|
||||
if (i >= MaxSearchResults) break;
|
||||
|
||||
if (searchQuery != "" && !obj.name.ToLower().Contains(searchQuery.ToLower()))
|
||||
if (m_searchInput != "" && !obj.name.ToLower().Contains(m_searchInput.ToLower()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -355,7 +202,7 @@ namespace Explorer.UI.Main
|
||||
i++;
|
||||
}
|
||||
|
||||
return matches;
|
||||
CacheResults(matches);
|
||||
}
|
||||
|
||||
public static bool FilterScene(object obj, SceneFilter filter)
|
||||
@ -394,8 +241,6 @@ namespace Explorer.UI.Main
|
||||
return false;
|
||||
}
|
||||
|
||||
// ====== other ========
|
||||
|
||||
private static bool FilterName(string name)
|
||||
{
|
||||
// Don't really want these instances.
|
||||
@ -497,5 +342,202 @@ namespace Explorer.UI.Main
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
// =========== GUI DRAW ============= //
|
||||
|
||||
public override void DrawWindow()
|
||||
{
|
||||
try
|
||||
{
|
||||
// helpers
|
||||
GUIUnstrip.BeginHorizontal(GUIContent.none, GUI.skin.box, null);
|
||||
GUILayout.Label("<b><color=orange>Helpers</color></b>", new GUILayoutOption[] { GUILayout.Width(70) });
|
||||
if (GUILayout.Button("Find Static Instances", new GUILayoutOption[] { GUILayout.Width(180) }))
|
||||
{
|
||||
CacheResults(GetStaticInstances());
|
||||
}
|
||||
if (GUILayout.Button("Find Static Classes", new GUILayoutOption[] { GUILayout.Width(180) }))
|
||||
{
|
||||
CacheResults(GetStaticClasses(), true);
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
// search box
|
||||
SearchBox();
|
||||
|
||||
// results
|
||||
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
||||
|
||||
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||
GUILayout.Label("<b><color=orange>Results </color></b>" + " (" + m_searchResults.Count + ")", new GUILayoutOption[0]);
|
||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||
|
||||
int count = m_searchResults.Count;
|
||||
|
||||
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||
|
||||
Pages.DrawLimitInputArea();
|
||||
|
||||
if (count > Pages.ItemsPerPage)
|
||||
{
|
||||
// prev/next page buttons
|
||||
|
||||
if (Pages.ItemCount > Pages.ItemsPerPage)
|
||||
{
|
||||
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) }))
|
||||
{
|
||||
Pages.TurnPage(Turn.Left, ref this.resultsScroll);
|
||||
}
|
||||
|
||||
Pages.CurrentPageLabel();
|
||||
|
||||
if (GUILayout.Button("Next >", new GUILayoutOption[] { GUILayout.Width(80) }))
|
||||
{
|
||||
Pages.TurnPage(Turn.Right, ref this.resultsScroll);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
resultsScroll = GUIUnstrip.BeginScrollView(resultsScroll);
|
||||
|
||||
var _temprect = new Rect(MainMenu.MainRect.x, MainMenu.MainRect.y, MainMenu.MainRect.width + 160, MainMenu.MainRect.height);
|
||||
|
||||
if (m_searchResults.Count > 0)
|
||||
{
|
||||
int offset = Pages.CalculateOffsetIndex();
|
||||
|
||||
for (int i = offset; i < offset + Pages.ItemsPerPage && i < count; i++)
|
||||
{
|
||||
if (i >= m_searchResults.Count) break;
|
||||
|
||||
m_searchResults[i].Draw(MainMenu.MainRect, 0f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.Label("<color=red><i>No results found!</i></color>", new GUILayoutOption[0]);
|
||||
}
|
||||
|
||||
GUIUnstrip.EndScrollView();
|
||||
GUILayout.EndVertical();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (!e.Message.Contains("in a group with only"))
|
||||
{
|
||||
ExplorerCore.Log("Exception drawing search results!");
|
||||
while (e != null)
|
||||
{
|
||||
ExplorerCore.Log(e);
|
||||
e = e.InnerException;
|
||||
}
|
||||
m_searchResults.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SearchBox()
|
||||
{
|
||||
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
||||
|
||||
// ----- GameObject Search -----
|
||||
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||
GUILayout.Label("<b><color=orange>Search</color></b>", new GUILayoutOption[0]);
|
||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||
|
||||
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||
|
||||
GUILayout.Label("Name Contains:", new GUILayoutOption[] { GUILayout.Width(100) });
|
||||
m_searchInput = GUIUnstrip.TextField(m_searchInput, new GUILayoutOption[] { GUILayout.Width(200) });
|
||||
|
||||
GUILayout.Label("Max Results:", new GUILayoutOption[] { GUILayout.Width(100) });
|
||||
var s = MaxSearchResults.ToString();
|
||||
s = GUIUnstrip.TextField(s, new GUILayoutOption[] { GUILayout.Width(80) });
|
||||
if (int.TryParse(s, out int i))
|
||||
{
|
||||
MaxSearchResults = i;
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||
|
||||
GUILayout.Label("Class Filter:", new GUILayoutOption[] { GUILayout.Width(100) });
|
||||
ClassFilterToggle(TypeFilter.Object, "Object");
|
||||
ClassFilterToggle(TypeFilter.GameObject, "GameObject");
|
||||
ClassFilterToggle(TypeFilter.Component, "Component");
|
||||
ClassFilterToggle(TypeFilter.Custom, "Custom");
|
||||
GUILayout.EndHorizontal();
|
||||
if (TypeMode == TypeFilter.Custom)
|
||||
{
|
||||
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||
GUI.skin.label.alignment = TextAnchor.MiddleRight;
|
||||
GUILayout.Label("Custom Class:", new GUILayoutOption[] { GUILayout.Width(250) });
|
||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||
m_typeInput = GUIUnstrip.TextField(m_typeInput, new GUILayoutOption[] { GUILayout.Width(250) });
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||
GUILayout.Label("Scene Filter:", new GUILayoutOption[] { GUILayout.Width(100) });
|
||||
SceneFilterToggle(SceneFilter.Any, "Any", 60);
|
||||
SceneFilterToggle(SceneFilter.This, "This Scene", 100);
|
||||
SceneFilterToggle(SceneFilter.DontDestroy, "DontDestroyOnLoad", 140);
|
||||
SceneFilterToggle(SceneFilter.None, "No Scene", 80);
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
if (GUILayout.Button("<b><color=cyan>Search</color></b>", new GUILayoutOption[0]))
|
||||
{
|
||||
Search();
|
||||
}
|
||||
//if (m_cachingResults)
|
||||
//{
|
||||
// GUILayout.Label("Searching...", new GUILayoutOption[0]);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// if (GUILayout.Button("<b><color=cyan>Search</color></b>", new GUILayoutOption[0]))
|
||||
// {
|
||||
// Search();
|
||||
// }
|
||||
//}
|
||||
|
||||
GUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private void ClassFilterToggle(TypeFilter mode, string label)
|
||||
{
|
||||
if (TypeMode == mode)
|
||||
{
|
||||
GUI.color = Color.green;
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.color = Color.white;
|
||||
}
|
||||
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Width(100) }))
|
||||
{
|
||||
TypeMode = mode;
|
||||
}
|
||||
GUI.color = Color.white;
|
||||
}
|
||||
|
||||
private void SceneFilterToggle(SceneFilter mode, string label, float width)
|
||||
{
|
||||
if (SceneMode == mode)
|
||||
{
|
||||
GUI.color = Color.green;
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.color = Color.white;
|
||||
}
|
||||
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Width(width) }))
|
||||
{
|
||||
SceneMode = mode;
|
||||
}
|
||||
GUI.color = Color.white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,18 +8,17 @@ namespace Explorer.UI.Shared
|
||||
{
|
||||
public class ResizeDrag
|
||||
{
|
||||
#if CPP
|
||||
private static bool RESIZE_FAILED = false;
|
||||
#endif
|
||||
|
||||
public static bool IsResizing = false;
|
||||
public static bool IsMouseInResizeArea = false;
|
||||
|
||||
private static readonly GUIContent gcDrag = new GUIContent("<-- Drag to resize -->");
|
||||
private static bool isResizing = false;
|
||||
private static Rect m_currentResize;
|
||||
private static int m_currentWindow;
|
||||
|
||||
public static Rect ResizeWindow(Rect _rect, int ID)
|
||||
{
|
||||
#if CPP
|
||||
if (!RESIZE_FAILED)
|
||||
{
|
||||
var origRect = _rect;
|
||||
@ -29,31 +28,40 @@ namespace Explorer.UI.Shared
|
||||
GUIUnstrip.BeginHorizontal(GUIContent.none, GUI.skin.box, null);
|
||||
|
||||
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||
#if ML
|
||||
GUILayout.Button(gcDrag, GUI.skin.label, new GUILayoutOption[] { GUILayout.Height(15) });
|
||||
#if BIE
|
||||
#if CPP // Temporary for BepInEx IL2CPP
|
||||
GUILayout.Button("<-- Drag to resize -->", new GUILayoutOption[] { GUILayout.Height(15) });
|
||||
#else
|
||||
GUILayout.Button("<-- Drag to resize -->", new GUILayoutOption[] { GUILayout.Height(15) });
|
||||
GUILayout.Button(gcDrag, GUI.skin.label, new GUILayoutOption[] { GUILayout.Height(15) });
|
||||
#endif
|
||||
#else
|
||||
GUILayout.Button(gcDrag, GUI.skin.label, new GUILayoutOption[] { GUILayout.Height(15) });
|
||||
#endif
|
||||
|
||||
var r = GUIUnstrip.GetLastRect();
|
||||
|
||||
var resizeDragArea = GUIUnstrip.GetLastRect();
|
||||
var mousePos = InputManager.MousePosition;
|
||||
|
||||
try
|
||||
{
|
||||
var mouse = GUIUnstrip.ScreenToGUIPoint(new Vector2(mousePos.x, Screen.height - mousePos.y));
|
||||
if (r.Contains(mouse) && InputManager.GetMouseButtonDown(0))
|
||||
if (resizeDragArea.Contains(mouse))
|
||||
{
|
||||
isResizing = true;
|
||||
m_currentWindow = ID;
|
||||
m_currentResize = new Rect(mouse.x, mouse.y, _rect.width, _rect.height);
|
||||
IsMouseInResizeArea = true;
|
||||
|
||||
if (InputManager.GetMouseButtonDown(0))
|
||||
{
|
||||
IsResizing = true;
|
||||
m_currentWindow = ID;
|
||||
m_currentResize = new Rect(mouse.x, mouse.y, _rect.width, _rect.height);
|
||||
}
|
||||
}
|
||||
else if (!InputManager.GetMouseButton(0))
|
||||
{
|
||||
isResizing = false;
|
||||
IsMouseInResizeArea = false;
|
||||
IsResizing = false;
|
||||
}
|
||||
|
||||
if (isResizing && ID == m_currentWindow)
|
||||
if (IsResizing && ID == m_currentWindow)
|
||||
{
|
||||
_rect.width = Mathf.Max(100, m_currentResize.width + (mouse.x - m_currentResize.x));
|
||||
_rect.height = Mathf.Max(100, m_currentResize.height + (mouse.y - m_currentResize.y));
|
||||
@ -81,8 +89,6 @@ namespace Explorer.UI.Shared
|
||||
//ExplorerCore.Log(e.StackTrace);
|
||||
return origRect;
|
||||
}
|
||||
|
||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -111,44 +117,8 @@ namespace Explorer.UI.Shared
|
||||
}
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||
}
|
||||
|
||||
#else // mono
|
||||
|
||||
GUIUnstrip.BeginHorizontal(GUIContent.none, GUI.skin.box, null);
|
||||
|
||||
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||
GUILayout.Button(gcDrag, GUI.skin.label, new GUILayoutOption[] { GUILayout.Height(15) });
|
||||
|
||||
//var r = GUILayoutUtility.GetLastRect();
|
||||
var r = GUILayoutUtility.GetLastRect();
|
||||
|
||||
var mousePos = InputManager.MousePosition;
|
||||
|
||||
var mouse = GUIUnstrip.ScreenToGUIPoint(new Vector2(mousePos.x, Screen.height - mousePos.y));
|
||||
if (r.Contains(mouse) && InputManager.GetMouseButtonDown(0))
|
||||
{
|
||||
isResizing = true;
|
||||
m_currentWindow = ID;
|
||||
m_currentResize = new Rect(mouse.x, mouse.y, _rect.width, _rect.height);
|
||||
}
|
||||
else if (!InputManager.GetMouseButton(0))
|
||||
{
|
||||
isResizing = false;
|
||||
}
|
||||
|
||||
if (isResizing && ID == m_currentWindow)
|
||||
{
|
||||
_rect.width = Mathf.Max(100, m_currentResize.width + (mouse.x - m_currentResize.x));
|
||||
_rect.height = Mathf.Max(100, m_currentResize.height + (mouse.y - m_currentResize.y));
|
||||
_rect.xMax = Mathf.Min(Screen.width, _rect.xMax); // modifying xMax affects width, not x
|
||||
_rect.yMax = Mathf.Min(Screen.height, _rect.yMax); // modifying yMax affects height, not y
|
||||
}
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
#endif
|
||||
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
|
||||
|
||||
return _rect;
|
||||
|
@ -66,10 +66,19 @@ namespace Explorer.UI
|
||||
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
||||
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
|
||||
int tabPerRow = Mathf.FloorToInt((float)((decimal)m_rect.width / 238));
|
||||
int tabPerRow = (int)Math.Floor(m_rect.width / 238);
|
||||
int rowCount = 0;
|
||||
for (int i = 0; i < WindowManager.Windows.Count; i++)
|
||||
{
|
||||
var window = WindowManager.Windows[i];
|
||||
|
||||
// Prevent trying to draw destroyed UnityEngine.Objects
|
||||
// before the WindowManager removes them.
|
||||
if (window.Target is UnityEngine.Object uObj && !uObj)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rowCount >= tabPerRow)
|
||||
{
|
||||
rowCount = 0;
|
||||
@ -82,7 +91,6 @@ namespace Explorer.UI
|
||||
string color = focused ? "<color=lime>" : "<color=orange>";
|
||||
GUI.color = focused ? Color.green : Color.white;
|
||||
|
||||
var window = WindowManager.Windows[i];
|
||||
if (GUILayout.Button(color + window.Title + "</color>", new GUILayoutOption[] { GUILayout.Width(200) }))
|
||||
{
|
||||
TargetTabID = i;
|
||||
|
@ -11,6 +11,26 @@ namespace Explorer.UI
|
||||
|
||||
public static bool TabView = Config.ModConfig.Instance.Tab_View;
|
||||
|
||||
public static bool IsMouseInWindow
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!ExplorerCore.ShowMenu)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var window in Windows)
|
||||
{
|
||||
if (RectContainsMouse(window.m_rect))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return RectContainsMouse(MainMenu.MainRect);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<WindowBase> Windows = new List<WindowBase>();
|
||||
public static int CurrentWindowID { get; set; } = 500000;
|
||||
private static Rect m_lastWindowRect;
|
||||
@ -123,26 +143,6 @@ namespace Explorer.UI
|
||||
return new_window;
|
||||
}
|
||||
|
||||
public static bool IsMouseInWindow
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!ExplorerCore.ShowMenu)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var window in Windows)
|
||||
{
|
||||
if (RectContainsMouse(window.m_rect))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return RectContainsMouse(MainMenu.MainRect);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool RectContainsMouse(Rect rect)
|
||||
{
|
||||
var mousePos = InputManager.MousePosition;
|
||||
|
@ -53,12 +53,21 @@ namespace Explorer
|
||||
public static string TextField(string text, GUILayoutOption[] options)
|
||||
{
|
||||
#if CPP
|
||||
return Internal.TextField(text, options);
|
||||
return Internal.TextField(text, options, false);
|
||||
#else
|
||||
return GUILayout.TextField(text, options);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static string TextArea(string text, params GUILayoutOption[] options)
|
||||
{
|
||||
#if CPP
|
||||
return Internal.TextField(text, options, true);
|
||||
#else
|
||||
return GUILayout.TextArea(text, options);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static Rect Window(int id, Rect rect, GUI.WindowFunction windowFunc, string title)
|
||||
{
|
||||
#if CPP
|
||||
@ -77,15 +86,6 @@ namespace Explorer
|
||||
#endif
|
||||
}
|
||||
|
||||
public static string TextArea(string text, params GUILayoutOption[] options)
|
||||
{
|
||||
#if CPP
|
||||
return GUILayout.DoTextField(text, -1, true, GUI.skin.textArea, options);
|
||||
#else
|
||||
return GUILayout.TextArea(text, options);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void BringWindowToFront(int id)
|
||||
{
|
||||
#if CPP
|
||||
|
@ -16,12 +16,9 @@ namespace Explorer.Unstrip.IMGUI
|
||||
public static bool ScrollFailed = false;
|
||||
public static bool ManualUnstripFailed = false;
|
||||
|
||||
public static GenericStack ScrollStack => m_scrollStack ?? GetScrollStack();
|
||||
public static PropertyInfo m_scrollViewStatesInfo;
|
||||
public static GenericStack m_scrollStack;
|
||||
|
||||
public static Dictionary<int, Il2CppSystem.Object> StateCache => m_stateCacheDict ?? GetStateCacheDict();
|
||||
public static Dictionary<int, Il2CppSystem.Object> m_stateCacheDict;
|
||||
public static Stack<object> ScrollStack => m_scrollStack ?? GetScrollStack();
|
||||
public static Stack<object> m_scrollStack;
|
||||
//public static PropertyInfo m_scrollViewStatesInfo;
|
||||
|
||||
public static GUIStyle SpaceStyle => m_spaceStyle ?? GetSpaceStyle();
|
||||
public static GUIStyle m_spaceStyle;
|
||||
@ -34,53 +31,13 @@ namespace Explorer.Unstrip.IMGUI
|
||||
public static MethodInfo m_bringWindowToFrontMethod;
|
||||
public static bool m_bringWindowFrontAttempted;
|
||||
|
||||
private static GenericStack GetScrollStack()
|
||||
private static Stack<object> GetScrollStack()
|
||||
{
|
||||
if (m_scrollViewStatesInfo == null)
|
||||
{
|
||||
if (typeof(GUI).GetProperty("scrollViewStates", ReflectionHelpers.CommonFlags) is PropertyInfo scrollStatesInfo)
|
||||
{
|
||||
m_scrollViewStatesInfo = scrollStatesInfo;
|
||||
}
|
||||
else if (typeof(GUI).GetProperty("s_ScrollViewStates", ReflectionHelpers.CommonFlags) is PropertyInfo s_scrollStatesInfo)
|
||||
{
|
||||
m_scrollViewStatesInfo = s_scrollStatesInfo;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_scrollViewStatesInfo?.GetValue(null, null) is GenericStack stack)
|
||||
{
|
||||
m_scrollStack = stack;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_scrollStack = new GenericStack();
|
||||
}
|
||||
m_scrollStack = new Stack<object>();
|
||||
|
||||
return m_scrollStack;
|
||||
}
|
||||
|
||||
private static Dictionary<int, Il2CppSystem.Object> GetStateCacheDict()
|
||||
{
|
||||
if (m_stateCacheDict == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var type = ReflectionHelpers.GetTypeByName("UnityEngine.GUIStateObjects");
|
||||
m_stateCacheDict = type.GetProperty("s_StateCache")
|
||||
.GetValue(null, null)
|
||||
as Dictionary<int, Il2CppSystem.Object>;
|
||||
|
||||
if (m_stateCacheDict == null) throw new Exception();
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_stateCacheDict = new Dictionary<int, Il2CppSystem.Object>();
|
||||
}
|
||||
}
|
||||
return m_stateCacheDict;
|
||||
}
|
||||
|
||||
private static GUIStyle GetSpaceStyle()
|
||||
{
|
||||
try
|
||||
@ -115,10 +72,12 @@ namespace Explorer.Unstrip.IMGUI
|
||||
GUI.Box(g.rect, content, style);
|
||||
}
|
||||
|
||||
public static string TextField(string text, GUILayoutOption[] options)
|
||||
public static string TextField(string text, GUILayoutOption[] options, bool multiLine)
|
||||
{
|
||||
text = text ?? string.Empty;
|
||||
|
||||
var skin = multiLine ? GUI.skin.textArea : GUI.skin.textField;
|
||||
|
||||
int controlID = GUIUtility.GetControlID(FocusType.Keyboard);
|
||||
GUIContent guicontent = GUIContent.Temp(text);
|
||||
bool flag = GUIUtility.keyboardControl != controlID;
|
||||
@ -131,19 +90,19 @@ namespace Explorer.Unstrip.IMGUI
|
||||
guicontent = GUIContent.Temp(text);
|
||||
// guicontent = GUIContent.Temp(text + GUIUtility.compositionString);
|
||||
}
|
||||
Rect rect = Internal_LayoutUtility.GetRect(guicontent, GUI.skin.textField, options);
|
||||
Rect rect = Internal_LayoutUtility.GetRect(guicontent, skin, options);
|
||||
bool flag2 = GUIUtility.keyboardControl == controlID;
|
||||
if (flag2)
|
||||
{
|
||||
guicontent = GUIContent.Temp(text);
|
||||
}
|
||||
DoTextField(rect, controlID, guicontent, false, -1, GUI.skin.textField);
|
||||
DoTextField(rect, controlID, guicontent, multiLine, -1, skin);
|
||||
return guicontent.text;
|
||||
}
|
||||
|
||||
internal static void DoTextField(Rect position, int id, GUIContent content, bool multiline, int maxLength, GUIStyle style)
|
||||
{
|
||||
if (GetStateObject(Il2CppType.Of<TextEditor>(), id).TryCast<TextEditor>() is TextEditor textEditor)
|
||||
if (Internal_GUIUtility.GetMonoStateObject(typeof(Internal_TextEditor), id) is Internal_TextEditor textEditor)
|
||||
{
|
||||
if (maxLength >= 0 && content.text.Length > maxLength)
|
||||
{
|
||||
@ -156,11 +115,138 @@ namespace Explorer.Unstrip.IMGUI
|
||||
textEditor.multiline = multiline;
|
||||
textEditor.controlID = id;
|
||||
textEditor.DetectFocusChange();
|
||||
GUI.HandleTextFieldEventForDesktop(position, id, content, multiline, maxLength, style, textEditor);
|
||||
HandleTextFieldEventForDesktop(position, id, content, multiline, maxLength, style, textEditor);
|
||||
textEditor.UpdateScrollOffsetIfNeeded(Event.current);
|
||||
}
|
||||
}
|
||||
|
||||
private static void HandleTextFieldEventForDesktop(Rect position, int id, GUIContent content, bool multiline, int maxLength,
|
||||
GUIStyle style, Internal_TextEditor editor)
|
||||
{
|
||||
var evt = Event.current;
|
||||
|
||||
bool change = false;
|
||||
switch (evt.type)
|
||||
{
|
||||
case EventType.MouseDown:
|
||||
if (position.Contains(evt.mousePosition))
|
||||
{
|
||||
GUIUtility.hotControl = id;
|
||||
GUIUtility.keyboardControl = id;
|
||||
editor.m_HasFocus = true;
|
||||
editor.MoveCursorToPosition(Event.current.mousePosition);
|
||||
if (Event.current.clickCount == 2 && GUI.skin.settings.doubleClickSelectsWord)
|
||||
{
|
||||
editor.SelectCurrentWord();
|
||||
editor.DblClickSnap(Internal_TextEditor.DblClickSnapping.WORDS);
|
||||
editor.MouseDragSelectsWholeWords(true);
|
||||
}
|
||||
if (Event.current.clickCount == 3 && GUI.skin.settings.tripleClickSelectsLine)
|
||||
{
|
||||
editor.SelectCurrentParagraph();
|
||||
editor.MouseDragSelectsWholeWords(true);
|
||||
editor.DblClickSnap(Internal_TextEditor.DblClickSnapping.PARAGRAPHS);
|
||||
}
|
||||
evt.Use();
|
||||
}
|
||||
break;
|
||||
case EventType.MouseDrag:
|
||||
if (GUIUtility.hotControl == id)
|
||||
{
|
||||
if (evt.shift)
|
||||
editor.MoveCursorToPosition(Event.current.mousePosition);
|
||||
else
|
||||
editor.SelectToPosition(Event.current.mousePosition);
|
||||
evt.Use();
|
||||
}
|
||||
break;
|
||||
case EventType.MouseUp:
|
||||
if (GUIUtility.hotControl == id)
|
||||
{
|
||||
editor.MouseDragSelectsWholeWords(false);
|
||||
GUIUtility.hotControl = 0;
|
||||
evt.Use();
|
||||
}
|
||||
break;
|
||||
case EventType.KeyDown:
|
||||
if (GUIUtility.keyboardControl != id)
|
||||
return;
|
||||
|
||||
if (editor.HandleKeyEvent(evt))
|
||||
{
|
||||
evt.Use();
|
||||
change = true;
|
||||
content.text = editor.text;
|
||||
break;
|
||||
}
|
||||
|
||||
// Ignore tab & shift-tab in textfields
|
||||
if (evt.keyCode == KeyCode.Tab || evt.character == '\t')
|
||||
return;
|
||||
|
||||
char c = evt.character;
|
||||
|
||||
if (c == '\n' && !multiline && !evt.alt)
|
||||
return;
|
||||
|
||||
|
||||
// Simplest test: only allow the character if the display font supports it.
|
||||
Font font = style.font;
|
||||
if (!font)
|
||||
font = GUI.skin.font;
|
||||
|
||||
if (font.HasCharacter(c) || c == '\n')
|
||||
{
|
||||
editor.Insert(c);
|
||||
change = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// On windows, keypresses also send events with keycode but no character. Eat them up here.
|
||||
if (c == 0)
|
||||
{
|
||||
// if we have a composition string, make sure we clear the previous selection.
|
||||
if (InputManager.compositionString.Length > 0)
|
||||
{
|
||||
editor.ReplaceSelection("");
|
||||
change = true;
|
||||
}
|
||||
|
||||
evt.Use();
|
||||
}
|
||||
// else {
|
||||
// REALLY USEFUL:
|
||||
// Debug.Log ("unhandled " +evt);
|
||||
// evt.Use ();
|
||||
// }
|
||||
break;
|
||||
case EventType.Repaint:
|
||||
// If we have keyboard focus, draw the cursor
|
||||
// TODO: check if this OpenGL view has keyboard focus
|
||||
if (GUIUtility.keyboardControl != id)
|
||||
{
|
||||
style.Draw(position, content, id, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
editor.DrawCursor(content.text);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (GUIUtility.keyboardControl == id)
|
||||
GUIUtility.textFieldInput = true;
|
||||
|
||||
if (change)
|
||||
{
|
||||
GUI.changed = true;
|
||||
content.text = editor.text;
|
||||
if (maxLength >= 0 && content.text.Length > maxLength)
|
||||
content.text = content.text.Substring(0, maxLength);
|
||||
evt.Use();
|
||||
}
|
||||
}
|
||||
|
||||
public static bool DoRepeatButton(GUIContent content, GUIStyle style, GUILayoutOption[] options)
|
||||
{
|
||||
return GUI.DoRepeatButton(Internal_LayoutUtility.GetRect(content, style, options), content, style, FocusType.Passive);
|
||||
@ -279,22 +365,6 @@ namespace Explorer.Unstrip.IMGUI
|
||||
|
||||
#region Scrolling
|
||||
|
||||
private static Il2CppSystem.Object GetStateObject(Il2CppSystem.Type type, int controlID)
|
||||
{
|
||||
Il2CppSystem.Object obj;
|
||||
if (StateCache.ContainsKey(controlID))
|
||||
{
|
||||
obj = StateCache[controlID];
|
||||
}
|
||||
else
|
||||
{
|
||||
obj = Il2CppSystem.Activator.CreateInstance(type);
|
||||
StateCache.Add(controlID, obj);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
public static Vector2 BeginScrollView(Vector2 scroll, params GUILayoutOption[] options)
|
||||
{
|
||||
// First, just try normal way, may not have been stripped or was unstripped successfully.
|
||||
@ -348,10 +418,12 @@ namespace Explorer.Unstrip.IMGUI
|
||||
|
||||
if (ScrollStack.Count <= 0) return;
|
||||
|
||||
var state = ScrollStack.Peek().TryCast<ScrollViewState>();
|
||||
var scrollExt = Internal_ScrollViewState.FromPointer(state.Pointer);
|
||||
var scrollExt = ScrollStack.Peek() as Internal_ScrollViewState;
|
||||
|
||||
if (scrollExt == null) throw new Exception("Could not get scrollExt!");
|
||||
//var state = ScrollStack.Peek().TryCast<ScrollViewState>();
|
||||
//var scrollExt = Internal_ScrollViewState.FromPointer(state.Pointer);
|
||||
|
||||
//if (scrollExt == null) throw new Exception("Could not get scrollExt!");
|
||||
|
||||
GUIClip.Pop();
|
||||
|
||||
@ -419,16 +491,18 @@ namespace Explorer.Unstrip.IMGUI
|
||||
|
||||
int controlID = GUIUtility.GetControlID(GUI.s_ScrollviewHash, FocusType.Passive);
|
||||
|
||||
var scrollViewState = GetStateObject(Il2CppType.Of<ScrollViewState>(), controlID)
|
||||
.TryCast<ScrollViewState>();
|
||||
var scrollExt = (Internal_ScrollViewState)Internal_GUIUtility.GetMonoStateObject(typeof(Internal_ScrollViewState), controlID);
|
||||
|
||||
if (scrollViewState == null)
|
||||
return scrollPosition;
|
||||
//var scrollViewState = Internal_GUIUtility.GetStateObject(Il2CppType.Of<ScrollViewState>(), controlID)
|
||||
// .TryCast<ScrollViewState>();
|
||||
|
||||
var scrollExt = Internal_ScrollViewState.FromPointer(scrollViewState.Pointer);
|
||||
//if (scrollViewState == null)
|
||||
// return scrollPosition;
|
||||
|
||||
if (scrollExt == null)
|
||||
return scrollPosition;
|
||||
//var scrollExt = Internal_ScrollViewState.FromPointer(scrollViewState.Pointer);
|
||||
|
||||
//if (scrollExt == null)
|
||||
// return scrollPosition;
|
||||
|
||||
bool apply = scrollExt.apply;
|
||||
if (apply)
|
||||
@ -446,7 +520,7 @@ namespace Explorer.Unstrip.IMGUI
|
||||
rect.width = position.width;
|
||||
rect.height = position.height;
|
||||
|
||||
ScrollStack.Push(scrollViewState);
|
||||
ScrollStack.Push(scrollExt);
|
||||
|
||||
Rect screenRect = new Rect(position.x, position.y, position.width, position.height);
|
||||
EventType type = Event.current.type;
|
||||
|
66
src/Unstrip/IMGUI/Internal_GUIUtility.cs
Normal file
66
src/Unstrip/IMGUI/Internal_GUIUtility.cs
Normal file
@ -0,0 +1,66 @@
|
||||
#if CPP
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Explorer.Unstrip.IMGUI
|
||||
{
|
||||
public class Internal_GUIUtility
|
||||
{
|
||||
public static Dictionary<int, object> MonoStateCache = new Dictionary<int, object>();
|
||||
|
||||
public static object GetMonoStateObject(Type type, int controlID)
|
||||
{
|
||||
if (!MonoStateCache.ContainsKey(controlID))
|
||||
{
|
||||
MonoStateCache.Add(controlID, Activator.CreateInstance(type));
|
||||
}
|
||||
|
||||
return MonoStateCache[controlID];
|
||||
}
|
||||
|
||||
public static Dictionary<int, Il2CppSystem.Object> StateCache => m_stateCacheDict ?? GetStateCacheDict();
|
||||
public static Dictionary<int, Il2CppSystem.Object> m_stateCacheDict;
|
||||
|
||||
public static Il2CppSystem.Object GetStateObject(Il2CppSystem.Type type, int controlID)
|
||||
{
|
||||
Il2CppSystem.Object obj;
|
||||
if (StateCache.ContainsKey(controlID))
|
||||
{
|
||||
obj = StateCache[controlID];
|
||||
}
|
||||
else
|
||||
{
|
||||
obj = Il2CppSystem.Activator.CreateInstance(type);
|
||||
StateCache.Add(controlID, obj);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
private static Dictionary<int, Il2CppSystem.Object> GetStateCacheDict()
|
||||
{
|
||||
if (m_stateCacheDict == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_stateCacheDict = ReflectionHelpers.GetTypeByName("UnityEngine.GUIStateObjects")
|
||||
.GetProperty("s_StateCache")
|
||||
.GetValue(null, null)
|
||||
as Dictionary<int, Il2CppSystem.Object>;
|
||||
|
||||
if (m_stateCacheDict == null) throw new Exception();
|
||||
}
|
||||
catch
|
||||
{
|
||||
m_stateCacheDict = new Dictionary<int, Il2CppSystem.Object>();
|
||||
}
|
||||
}
|
||||
return m_stateCacheDict;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -13,17 +13,77 @@ namespace Explorer.Unstrip.IMGUI
|
||||
public Vector2 scrollPosition;
|
||||
public bool apply;
|
||||
|
||||
public static Dictionary<IntPtr, Internal_ScrollViewState> Dict = new Dictionary<IntPtr, Internal_ScrollViewState>();
|
||||
public void ScrollTo(Rect pos)
|
||||
{
|
||||
this.ScrollTowards(pos, float.PositiveInfinity);
|
||||
}
|
||||
|
||||
public static Internal_ScrollViewState FromPointer(IntPtr ptr)
|
||||
{
|
||||
if (!Dict.ContainsKey(ptr))
|
||||
{
|
||||
Dict.Add(ptr, new Internal_ScrollViewState());
|
||||
}
|
||||
public bool ScrollTowards(Rect pos, float maxDelta)
|
||||
{
|
||||
Vector2 b = this.ScrollNeeded(pos);
|
||||
bool result;
|
||||
if (b.sqrMagnitude < 0.0001f)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
else if (maxDelta == 0f)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (b.magnitude > maxDelta)
|
||||
{
|
||||
b = b.normalized * maxDelta;
|
||||
}
|
||||
this.scrollPosition += b;
|
||||
this.apply = true;
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return Dict[ptr];
|
||||
}
|
||||
}
|
||||
private Vector2 ScrollNeeded(Rect pos)
|
||||
{
|
||||
Rect rect = this.visibleRect;
|
||||
rect.x += this.scrollPosition.x;
|
||||
rect.y += this.scrollPosition.y;
|
||||
float num = pos.width - this.visibleRect.width;
|
||||
if (num > 0f)
|
||||
{
|
||||
pos.width -= num;
|
||||
pos.x += num * 0.5f;
|
||||
}
|
||||
num = pos.height - this.visibleRect.height;
|
||||
if (num > 0f)
|
||||
{
|
||||
pos.height -= num;
|
||||
pos.y += num * 0.5f;
|
||||
}
|
||||
Vector2 zero = Vector2.zero;
|
||||
if (pos.xMax > rect.xMax)
|
||||
{
|
||||
zero.x += pos.xMax - rect.xMax;
|
||||
}
|
||||
else if (pos.xMin < rect.xMin)
|
||||
{
|
||||
zero.x -= rect.xMin - pos.xMin;
|
||||
}
|
||||
if (pos.yMax > rect.yMax)
|
||||
{
|
||||
zero.y += pos.yMax - rect.yMax;
|
||||
}
|
||||
else if (pos.yMin < rect.yMin)
|
||||
{
|
||||
zero.y -= rect.yMin - pos.yMin;
|
||||
}
|
||||
Rect rect2 = this.viewRect;
|
||||
rect2.width = Mathf.Max(rect2.width, this.visibleRect.width);
|
||||
rect2.height = Mathf.Max(rect2.height, this.visibleRect.height);
|
||||
zero.x = Mathf.Clamp(zero.x, rect2.xMin - this.scrollPosition.x, rect2.xMax - this.visibleRect.width - this.scrollPosition.x);
|
||||
zero.y = Mathf.Clamp(zero.y, rect2.yMin - this.scrollPosition.y, rect2.yMax - this.visibleRect.height - this.scrollPosition.y);
|
||||
return zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@ -118,8 +118,8 @@ namespace Explorer.Unstrip.IMGUI
|
||||
GUI.changed = true;
|
||||
if (this.SupportsPageMovements())
|
||||
{
|
||||
var ext = Internal_SliderState.FromPointer(GetSliderState().Pointer);
|
||||
ext.isDragging = false;
|
||||
var state = GetSliderState();
|
||||
state.isDragging = false;
|
||||
Internal.nextScrollStepTime = DateTime.Now.AddMilliseconds(250.0);
|
||||
ScrollTroughSide = this.CurrentScrollTroughSide();
|
||||
result = this.PageMovementValue();
|
||||
@ -144,8 +144,8 @@ namespace Explorer.Unstrip.IMGUI
|
||||
}
|
||||
else
|
||||
{
|
||||
var ext = Internal_SliderState.FromPointer(GetSliderState().Pointer);
|
||||
if (!ext.isDragging)
|
||||
var state = GetSliderState();
|
||||
if (!state.isDragging)
|
||||
{
|
||||
result = this.currentValue;
|
||||
}
|
||||
@ -153,8 +153,8 @@ namespace Explorer.Unstrip.IMGUI
|
||||
{
|
||||
GUI.changed = true;
|
||||
this.CurrentEvent().Use();
|
||||
float num = this.MousePosition() - ext.dragStartPos;
|
||||
float value = ext.dragStartValue + num / this.ValuesPerPixel();
|
||||
float num = this.MousePosition() - state.dragStartPos;
|
||||
float value = state.dragStartValue + num / this.ValuesPerPixel();
|
||||
result = this.Clamp(value);
|
||||
}
|
||||
}
|
||||
@ -207,7 +207,7 @@ namespace Explorer.Unstrip.IMGUI
|
||||
Internal.nextScrollStepTime = DateTime.Now.AddMilliseconds(30.0);
|
||||
if (this.SupportsPageMovements())
|
||||
{
|
||||
Internal_SliderState.FromPointer(GetSliderState().Pointer).isDragging = false;
|
||||
GetSliderState().isDragging = false;
|
||||
GUI.changed = true;
|
||||
result = this.PageMovementValue();
|
||||
}
|
||||
@ -303,15 +303,15 @@ namespace Explorer.Unstrip.IMGUI
|
||||
|
||||
private void StartDraggingWithValue(float dragStartValue)
|
||||
{
|
||||
var ext = Internal_SliderState.FromPointer(GetSliderState().Pointer);
|
||||
ext.dragStartPos = this.MousePosition();
|
||||
ext.dragStartValue = dragStartValue;
|
||||
ext.isDragging = true;
|
||||
var state = GetSliderState();
|
||||
state.dragStartPos = this.MousePosition();
|
||||
state.dragStartValue = dragStartValue;
|
||||
state.isDragging = true;
|
||||
}
|
||||
|
||||
private SliderState GetSliderState()
|
||||
private Internal_SliderState GetSliderState()
|
||||
{
|
||||
return GUIUtility.GetStateObject(Il2CppType.Of<SliderState>(), this.id).TryCast<SliderState>();
|
||||
return (Internal_SliderState)Internal_GUIUtility.GetMonoStateObject(typeof(Internal_SliderState), this.id);
|
||||
}
|
||||
|
||||
private Rect ThumbRect()
|
||||
|
@ -10,17 +10,5 @@ namespace Explorer.Unstrip.IMGUI
|
||||
public float dragStartPos;
|
||||
public float dragStartValue;
|
||||
public bool isDragging;
|
||||
|
||||
public static Dictionary<IntPtr, Internal_SliderState> Dict = new Dictionary<IntPtr, Internal_SliderState>();
|
||||
|
||||
public static Internal_SliderState FromPointer(IntPtr ptr)
|
||||
{
|
||||
if (!Dict.ContainsKey(ptr))
|
||||
{
|
||||
Dict.Add(ptr, new Internal_SliderState());
|
||||
}
|
||||
|
||||
return Dict[ptr];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
1557
src/Unstrip/IMGUI/Internal_TextEditor.cs
Normal file
1557
src/Unstrip/IMGUI/Internal_TextEditor.cs
Normal file
File diff suppressed because it is too large
Load Diff
51
src/Unstrip/ImageConversion/ImageConversionUnstrip.cs
Normal file
51
src/Unstrip/ImageConversion/ImageConversionUnstrip.cs
Normal file
@ -0,0 +1,51 @@
|
||||
#if CPP
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnhollowerBaseLib;
|
||||
using UnityEngine;
|
||||
using System.IO;
|
||||
|
||||
namespace Explorer.Unstrip.ImageConversion
|
||||
{
|
||||
public static class ImageConversionUnstrip
|
||||
{
|
||||
// byte[] ImageConversion.EncodeToPNG(this Texture2D image);
|
||||
|
||||
public static byte[] EncodeToPNG(this Texture2D tex)
|
||||
{
|
||||
return EncodeToPNG_iCall(tex.Pointer);
|
||||
}
|
||||
|
||||
internal delegate byte[] EncodeToPNG_delegate(IntPtr tex);
|
||||
internal static EncodeToPNG_delegate EncodeToPNG_iCall =
|
||||
IL2CPP.ResolveICall<EncodeToPNG_delegate>("UnityEngine.ImageConversion::EncodeToPNG");
|
||||
|
||||
// bool ImageConversion.LoadImage(this Texture2D tex, byte[] data, bool markNonReadable);
|
||||
|
||||
public static bool LoadImage(this Texture2D tex, byte[] data, bool markNonReadable)
|
||||
{
|
||||
return LoadImage_iCall(tex.Pointer, data, markNonReadable);
|
||||
}
|
||||
|
||||
internal delegate bool LoadImage_delegate(IntPtr tex, byte[] data, bool markNonReadable);
|
||||
internal static LoadImage_delegate LoadImage_iCall =
|
||||
IL2CPP.ResolveICall<LoadImage_delegate>("UnityEngine.ImageConversion::LoadImage");
|
||||
|
||||
// Helper for LoadImage
|
||||
|
||||
public static bool LoadImage(this Texture2D tex, string filePath, bool markNonReadable)
|
||||
{
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var data = File.ReadAllBytes(filePath);
|
||||
return tex.LoadImage(data, markNonReadable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
32
src/Unstrip/LayerMask/LayerMaskUnstrip.cs
Normal file
32
src/Unstrip/LayerMask/LayerMaskUnstrip.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
#if CPP
|
||||
using UnhollowerBaseLib;
|
||||
#endif
|
||||
|
||||
namespace Explorer.Unstrip.LayerMasks
|
||||
{
|
||||
public static class LayerMaskUnstrip
|
||||
{
|
||||
#if CPP
|
||||
internal delegate IntPtr d_LayerToName(int layer);
|
||||
internal static d_LayerToName LayerToName_iCall =
|
||||
IL2CPP.ResolveICall<d_LayerToName>("UnityEngine.LayerMask::LayerToName");
|
||||
|
||||
public static string LayerToName(int layer)
|
||||
{
|
||||
var ptr = LayerToName_iCall(layer);
|
||||
|
||||
return IL2CPP.Il2CppStringToManaged(ptr);
|
||||
}
|
||||
#else
|
||||
public static string LayerToName(int layer)
|
||||
{
|
||||
return LayerMask.LayerToName(layer);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
@ -5,37 +5,35 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using UnhollowerBaseLib;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace Explorer.Unstrip.Scene
|
||||
namespace Explorer.Unstrip.Scenes
|
||||
{
|
||||
public class SceneUnstrip
|
||||
{
|
||||
internal delegate void getRootSceneObjects(int handle, IntPtr list);
|
||||
internal static getRootSceneObjects getRootSceneObjects_iCall =
|
||||
IL2CPP.ResolveICall<getRootSceneObjects>("UnityEngine.SceneManagement.Scene::GetRootGameObjectsInternal");
|
||||
|
||||
public static void GetRootGameObjects_Internal(UnityEngine.SceneManagement.Scene scene, IntPtr list)
|
||||
{
|
||||
getRootSceneObjects_iCall(scene.handle, list);
|
||||
}
|
||||
|
||||
public static GameObject[] GetRootSceneObjects(UnityEngine.SceneManagement.Scene scene)
|
||||
//Scene.GetRootGameObjects();
|
||||
public static GameObject[] GetRootGameObjects(Scene scene)
|
||||
{
|
||||
var list = new Il2CppSystem.Collections.Generic.List<GameObject>(GetRootCount_Internal(scene));
|
||||
|
||||
GetRootGameObjects_Internal(scene, list.Pointer);
|
||||
GetRootGameObjectsInternal_iCall(scene.handle, list.Pointer);
|
||||
|
||||
return list.ToArray();
|
||||
}
|
||||
|
||||
internal delegate int getRootCount(int handle);
|
||||
internal static getRootCount getRootCount_iCall =
|
||||
IL2CPP.ResolveICall<getRootCount>("UnityEngine.SceneManagement.Scene::GetRootCountInternal");
|
||||
internal delegate void GetRootGameObjectsInternal_delegate(int handle, IntPtr list);
|
||||
internal static GetRootGameObjectsInternal_delegate GetRootGameObjectsInternal_iCall =
|
||||
IL2CPP.ResolveICall<GetRootGameObjectsInternal_delegate>("UnityEngine.SceneManagement.Scene::GetRootGameObjectsInternal");
|
||||
|
||||
public static int GetRootCount_Internal(UnityEngine.SceneManagement.Scene scene)
|
||||
//Scene.rootCount;
|
||||
public static int GetRootCount_Internal(Scene scene)
|
||||
{
|
||||
return getRootCount_iCall(scene.handle);
|
||||
return GetRootCountInternal_iCall(scene.handle);
|
||||
}
|
||||
|
||||
internal delegate int GetRootCountInternal_delegate(int handle);
|
||||
internal static GetRootCountInternal_delegate GetRootCountInternal_iCall =
|
||||
IL2CPP.ResolveICall<GetRootCountInternal_delegate>("UnityEngine.SceneManagement.Scene::GetRootCountInternal");
|
||||
}
|
||||
}
|
||||
#endif
|
Reference in New Issue
Block a user