mirror of
https://github.com/GrahamKracker/UnityExplorer.git
synced 2025-07-03 03:52:28 +08:00
Compare commits
20 Commits
Author | SHA1 | Date | |
---|---|---|---|
d4dac58fc8 | |||
77b97cbe17 | |||
c6f0f34ac0 | |||
d1f4f74d32 | |||
f13068bf01 | |||
dfc288a101 | |||
544009dc21 | |||
fdfaaadd89 | |||
58d60a10d4 | |||
0432c6d56c | |||
8c34aa2be5 | |||
4a1c54fac1 | |||
190467fa5c | |||
44f54d9190 | |||
3b4ea31b50 | |||
ad7b05f721 | |||
852ca8e9eb | |||
7386eca0c2 | |||
97325a5f3a | |||
82e52de557 |
20
README.md
20
README.md
@ -17,7 +17,6 @@
|
|||||||
- [Features](#features)
|
- [Features](#features)
|
||||||
- [How to install](#how-to-install)
|
- [How to install](#how-to-install)
|
||||||
- [Mod Config](#mod-config)
|
- [Mod Config](#mod-config)
|
||||||
- [Mouse Control](#mouse-control)
|
|
||||||
- [Building](#building)
|
- [Building](#building)
|
||||||
- [Credits](#credits)
|
- [Credits](#credits)
|
||||||
|
|
||||||
@ -25,8 +24,9 @@
|
|||||||
|
|
||||||
| Mod Loader | IL2CPP | Mono |
|
| Mod Loader | IL2CPP | Mono |
|
||||||
| ----------- | ------ | ---- |
|
| ----------- | ------ | ---- |
|
||||||
| [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) | ✔️ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader.Il2Cpp.zip) | ✔️ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader.Mono.zip) |
|
|
||||||
| [BepInEx](https://github.com/BepInEx/BepInEx) | ✔️ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.BepInEx.Il2Cpp.zip) | ✔️ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.BepInEx.Mono.zip) |
|
| [BepInEx](https://github.com/BepInEx/BepInEx) | ✔️ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.BepInEx.Il2Cpp.zip) | ✔️ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.BepInEx.Mono.zip) |
|
||||||
|
| [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) | ✔️ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader.Il2Cpp.zip) | ✔️ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader.Mono.zip) |
|
||||||
|
| Standalone | ✔️ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Standalone.Il2Cpp.zip) | ✔️ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.Standalone.Mono.zip) |
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
@ -49,15 +49,21 @@
|
|||||||
|
|
||||||
0. Install [BepInEx](https://github.com/BepInEx/BepInEx) for your game.
|
0. Install [BepInEx](https://github.com/BepInEx/BepInEx) for your game.
|
||||||
1. Download the UnityExplorer release for BepInEx IL2CPP or Mono above.
|
1. Download the UnityExplorer release for BepInEx IL2CPP or Mono above.
|
||||||
2. Take the `UnityExplorer.dll` file and put it in `[GameFolder]\BepInEx\plugins\`
|
2. Take the `UnityExplorer.BIE.___.dll` file and put it in `[GameFolder]\BepInEx\plugins\`
|
||||||
3. Take the `UnityExplorer\` folder (with `explorerui.bundle`) and put it in `[GameFolder]\Mods\`, so it looks like `[GameFolder]\Mods\UnityExplorer\explorerui.bundle`.
|
3. In IL2CPP, it is highly recommended to get the base Unity libs for the game's Unity version and put them in the `BepInEx\unity-libs\` folder.
|
||||||
4. In IL2CPP, it is highly recommended to get the base Unity libs for the game's Unity version and put them in the `BepInEx\unhollowed\base\` folder.
|
|
||||||
|
|
||||||
### MelonLoader
|
### MelonLoader
|
||||||
|
|
||||||
0. Install [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) for your game.
|
0. Install [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) for your game.
|
||||||
1. Download the UnityExplorer release for MelonLoader IL2CPP or Mono above.
|
1. Download the UnityExplorer release for MelonLoader IL2CPP or Mono above.
|
||||||
2. Take the contents of the release and put it in the `[GameFolder]\Mods\` folder. It should look like `[GameFolder]\Mods\UnityExplorer.dll` and `[GameFolder]\Mods\UnityExplorer\explorerui.bundle`.
|
2. Take the contents of the release and put it in the `[GameFolder]\Mods\` folder. It should look like `[GameFolder]\Mods\UnityExplorer.ML.___.dll`
|
||||||
|
|
||||||
|
### Standalone
|
||||||
|
|
||||||
|
0. Load the DLL from your mod or inject it.
|
||||||
|
1. Create an instance of Unity Explorer with `new ExplorerCore();`
|
||||||
|
2. You will need to call ExplorerCore.Update() (static method) from your Update method.
|
||||||
|
3. Subscribe to the `ExplorerCore.OnLog__` methods for logging.
|
||||||
|
|
||||||
## Mod Config
|
## Mod Config
|
||||||
|
|
||||||
@ -89,7 +95,7 @@ You can access the settings via the "Options" page of the main menu, or directly
|
|||||||
|
|
||||||
If you'd like to build this yourself, you will need to have installed BepInEx and/or MelonLoader for at least one Unity game. If you want to build all 4 versions, you will need at least one IL2CPP and one Mono game, with BepInEx and MelonLoader installed for both.
|
If you'd like to build this yourself, you will need to have installed BepInEx and/or MelonLoader for at least one Unity game. If you want to build all 4 versions, you will need at least one IL2CPP and one Mono game, with BepInEx and MelonLoader installed for both.
|
||||||
|
|
||||||
1. Install BepInEx or MelonLoader for your game.
|
1. Install BepInEx or MelonLoader for your game, or use the standalone build.
|
||||||
2. Open the `src\UnityExplorer.csproj` file in a text editor.
|
2. Open the `src\UnityExplorer.csproj` file in a text editor.
|
||||||
3. For IL2CPP builds, make sure you set `BIECppGameFolder` (for BepInEx) and/or `MLCppGameFolder` (for MelonLoader) so the project can locate the necessary references.
|
3. For IL2CPP builds, make sure you set `BIECppGameFolder` (for BepInEx) and/or `MLCppGameFolder` (for MelonLoader) so the project can locate the necessary references.
|
||||||
4. Open the `src\UnityExplorer.sln` project.
|
4. Open the `src\UnityExplorer.sln` project.
|
||||||
|
@ -11,7 +11,7 @@ namespace UnityExplorer.Config
|
|||||||
public static ModConfig Instance;
|
public static ModConfig Instance;
|
||||||
|
|
||||||
internal static readonly IniDataParser _parser = new IniDataParser();
|
internal static readonly IniDataParser _parser = new IniDataParser();
|
||||||
internal const string INI_PATH = ExplorerCore.EXPLORER_FOLDER + @"\config.ini";
|
internal static readonly string INI_PATH = Path.Combine(ExplorerCore.EXPLORER_FOLDER, "config.ini");
|
||||||
|
|
||||||
static ModConfig()
|
static ModConfig()
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.SceneManagement;
|
using UnityEngine.SceneManagement;
|
||||||
using UnityExplorer.Config;
|
using UnityExplorer.Config;
|
||||||
@ -16,10 +17,31 @@ namespace UnityExplorer
|
|||||||
public class ExplorerCore
|
public class ExplorerCore
|
||||||
{
|
{
|
||||||
public const string NAME = "UnityExplorer";
|
public const string NAME = "UnityExplorer";
|
||||||
public const string VERSION = "3.1.0";
|
public const string VERSION = "3.1.8";
|
||||||
public const string AUTHOR = "Sinai";
|
public const string AUTHOR = "Sinai";
|
||||||
public const string GUID = "com.sinai.unityexplorer";
|
public const string GUID = "com.sinai.unityexplorer";
|
||||||
|
|
||||||
|
#if ML
|
||||||
public const string EXPLORER_FOLDER = @"Mods\UnityExplorer";
|
public const string EXPLORER_FOLDER = @"Mods\UnityExplorer";
|
||||||
|
#elif BIE
|
||||||
|
public static string EXPLORER_FOLDER = Path.Combine(BepInEx.Paths.ConfigPath, "UnityExplorer");
|
||||||
|
#elif STANDALONE
|
||||||
|
public static string EXPLORER_FOLDER
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (s_explorerFolder == null)
|
||||||
|
{
|
||||||
|
s_explorerFolder = (new Uri(Assembly.GetExecutingAssembly().CodeBase)).AbsolutePath;
|
||||||
|
s_explorerFolder = Uri.UnescapeDataString(s_explorerFolder);
|
||||||
|
s_explorerFolder = Path.GetDirectoryName(s_explorerFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
return s_explorerFolder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static string s_explorerFolder;
|
||||||
|
#endif
|
||||||
|
|
||||||
public static ExplorerCore Instance { get; private set; }
|
public static ExplorerCore Instance { get; private set; }
|
||||||
|
|
||||||
@ -161,6 +183,12 @@ namespace UnityExplorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if STANDALONE
|
||||||
|
public static Action<string> OnLogMessage;
|
||||||
|
public static Action<string> OnLogWarning;
|
||||||
|
public static Action<string> OnLogError;
|
||||||
|
#endif
|
||||||
|
|
||||||
public static void Log(object message, bool unity = false)
|
public static void Log(object message, bool unity = false)
|
||||||
{
|
{
|
||||||
DebugConsole.Log(message?.ToString());
|
DebugConsole.Log(message?.ToString());
|
||||||
@ -170,8 +198,10 @@ namespace UnityExplorer
|
|||||||
|
|
||||||
#if ML
|
#if ML
|
||||||
MelonLoader.MelonLogger.Log(message?.ToString());
|
MelonLoader.MelonLogger.Log(message?.ToString());
|
||||||
#else
|
#elif BIE
|
||||||
ExplorerBepInPlugin.Logging?.LogMessage(message?.ToString());
|
ExplorerBepInPlugin.Logging?.LogMessage(message?.ToString());
|
||||||
|
#elif STANDALONE
|
||||||
|
OnLogMessage?.Invoke(message?.ToString());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,8 +214,10 @@ namespace UnityExplorer
|
|||||||
|
|
||||||
#if ML
|
#if ML
|
||||||
MelonLoader.MelonLogger.LogWarning(message?.ToString());
|
MelonLoader.MelonLogger.LogWarning(message?.ToString());
|
||||||
#else
|
#elif BIE
|
||||||
ExplorerBepInPlugin.Logging?.LogWarning(message?.ToString());
|
ExplorerBepInPlugin.Logging?.LogWarning(message?.ToString());
|
||||||
|
#elif STANDALONE
|
||||||
|
OnLogWarning?.Invoke(message?.ToString());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,8 +230,10 @@ namespace UnityExplorer
|
|||||||
|
|
||||||
#if ML
|
#if ML
|
||||||
MelonLoader.MelonLogger.LogError(message?.ToString());
|
MelonLoader.MelonLogger.LogError(message?.ToString());
|
||||||
#else
|
#elif BIE
|
||||||
ExplorerBepInPlugin.Logging?.LogError(message?.ToString());
|
ExplorerBepInPlugin.Logging?.LogError(message?.ToString());
|
||||||
|
#elif STANDALONE
|
||||||
|
OnLogError?.Invoke(message?.ToString());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
11
src/ExplorerStandalone.cs
Normal file
11
src/ExplorerStandalone.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#if STANDALONE
|
||||||
|
using HarmonyLib;
|
||||||
|
|
||||||
|
namespace UnityExplorer
|
||||||
|
{
|
||||||
|
public class ExplorerStandalone
|
||||||
|
{
|
||||||
|
public static readonly Harmony HarmonyInstance = new Harmony(ExplorerCore.GUID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
@ -101,8 +101,24 @@ namespace UnityExplorer.Helpers
|
|||||||
return Il2CppToMonoType[cppType];
|
return Il2CppToMonoType[cppType];
|
||||||
|
|
||||||
var getType = Type.GetType(cppType.AssemblyQualifiedName);
|
var getType = Type.GetType(cppType.AssemblyQualifiedName);
|
||||||
Il2CppToMonoType.Add(cppType, getType);
|
|
||||||
return getType;
|
if (getType != null)
|
||||||
|
{
|
||||||
|
Il2CppToMonoType.Add(cppType, getType);
|
||||||
|
return getType;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string baseName = cppType.FullName;
|
||||||
|
string baseAssembly = cppType.Assembly.GetName().name;
|
||||||
|
|
||||||
|
Type unhollowedType = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.GetName().Name == baseAssembly)?.GetTypes().FirstOrDefault(t =>
|
||||||
|
t.CustomAttributes.Any(ca =>
|
||||||
|
ca.AttributeType.Name == "ObfuscatedNameAttribute" && (string)ca.ConstructorArguments[0].Value == baseName));
|
||||||
|
|
||||||
|
Il2CppToMonoType.Add(cppType, unhollowedType);
|
||||||
|
return unhollowedType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Dictionary<Type, IntPtr> CppClassPointers = new Dictionary<Type, IntPtr>();
|
private static readonly Dictionary<Type, IntPtr> CppClassPointers = new Dictionary<Type, IntPtr>();
|
||||||
|
@ -15,6 +15,16 @@ namespace UnityExplorer.Helpers
|
|||||||
private static MethodInfo EncodeToPNGMethod => m_encodeToPNGMethod ?? GetEncodeToPNGMethod();
|
private static MethodInfo EncodeToPNGMethod => m_encodeToPNGMethod ?? GetEncodeToPNGMethod();
|
||||||
private static MethodInfo m_encodeToPNGMethod;
|
private static MethodInfo m_encodeToPNGMethod;
|
||||||
|
|
||||||
|
public static byte[] EncodeToPNGSafe(this Texture2D tex)
|
||||||
|
{
|
||||||
|
var method = EncodeToPNGMethod;
|
||||||
|
|
||||||
|
if (method.IsStatic)
|
||||||
|
return (byte[])method.Invoke(null, new object[] { tex });
|
||||||
|
else
|
||||||
|
return (byte[])method.Invoke(tex, new object[0]);
|
||||||
|
}
|
||||||
|
|
||||||
private static MethodInfo GetEncodeToPNGMethod()
|
private static MethodInfo GetEncodeToPNGMethod()
|
||||||
{
|
{
|
||||||
if (ReflectionHelpers.GetTypeByName("UnityEngine.ImageConversion") is Type imageConversion)
|
if (ReflectionHelpers.GetTypeByName("UnityEngine.ImageConversion") is Type imageConversion)
|
||||||
@ -60,7 +70,12 @@ namespace UnityExplorer.Helpers
|
|||||||
|
|
||||||
pixels = orig.GetPixels((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height);
|
pixels = orig.GetPixels((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height);
|
||||||
|
|
||||||
|
// use full constructor for better compatibility
|
||||||
|
#if CPP
|
||||||
|
var _newTex = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGBA32, Texture.GenerateAllMips, false, IntPtr.Zero);
|
||||||
|
#else
|
||||||
var _newTex = new Texture2D((int)rect.width, (int)rect.height);
|
var _newTex = new Texture2D((int)rect.width, (int)rect.height);
|
||||||
|
#endif
|
||||||
_newTex.SetPixels(pixels);
|
_newTex.SetPixels(pixels);
|
||||||
|
|
||||||
return _newTex;
|
return _newTex;
|
||||||
|
@ -111,8 +111,11 @@ namespace UnityExplorer.Inspectors.GameObjects
|
|||||||
internal static void OnCompToggleClicked(int index, bool value)
|
internal static void OnCompToggleClicked(int index, bool value)
|
||||||
{
|
{
|
||||||
var comp = s_compShortlist[index];
|
var comp = s_compShortlist[index];
|
||||||
|
#if CPP
|
||||||
|
comp.TryCast<Behaviour>().enabled = value;
|
||||||
|
#else
|
||||||
(comp as Behaviour).enabled = value;
|
(comp as Behaviour).enabled = value;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void OnCompListObjectClicked(int index)
|
internal static void OnCompListObjectClicked(int index)
|
||||||
|
@ -38,7 +38,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Inspect(object obj)
|
public void Inspect(object obj, CacheObjectBase parentMember = null)
|
||||||
{
|
{
|
||||||
#if CPP
|
#if CPP
|
||||||
obj = obj.Il2CppCast(ReflectionHelpers.GetActualType(obj));
|
obj = obj.Il2CppCast(ReflectionHelpers.GetActualType(obj));
|
||||||
@ -76,6 +76,9 @@ namespace UnityExplorer.Inspectors
|
|||||||
else
|
else
|
||||||
inspector = new InstanceInspector(obj);
|
inspector = new InstanceInspector(obj);
|
||||||
|
|
||||||
|
if (inspector is ReflectionInspector ri)
|
||||||
|
ri.ParentMember = parentMember;
|
||||||
|
|
||||||
m_currentInspectors.Add(inspector);
|
m_currentInspectors.Add(inspector);
|
||||||
SetInspectorTab(inspector);
|
SetInspectorTab(inspector);
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,9 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
{
|
{
|
||||||
var fi = MemInfo as FieldInfo;
|
var fi = MemInfo as FieldInfo;
|
||||||
fi.SetValue(fi.IsStatic ? null : DeclaringInstance, IValue.Value);
|
fi.SetValue(fi.IsStatic ? null : DeclaringInstance, IValue.Value);
|
||||||
|
|
||||||
|
if (this.ParentInspector?.ParentMember != null)
|
||||||
|
this.ParentInspector.ParentMember.SetValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
|
|
||||||
public override Type FallbackType { get; }
|
public override Type FallbackType { get; }
|
||||||
|
|
||||||
|
public ReflectionInspector ParentInspector { get; set; }
|
||||||
public MemberInfo MemInfo { get; set; }
|
public MemberInfo MemInfo { get; set; }
|
||||||
public Type DeclaringType { get; set; }
|
public Type DeclaringType { get; set; }
|
||||||
public object DeclaringInstance { get; set; }
|
public object DeclaringInstance { get; set; }
|
||||||
|
@ -63,6 +63,9 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
var target = pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance;
|
var target = pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance;
|
||||||
|
|
||||||
pi.SetValue(target, IValue.Value, ParseArguments());
|
pi.SetValue(target, IValue.Value, ParseArguments());
|
||||||
|
|
||||||
|
if (this.ParentInspector?.ParentMember != null)
|
||||||
|
this.ParentInspector.ParentMember.SetValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -272,7 +272,14 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
if (File.Exists(path))
|
if (File.Exists(path))
|
||||||
File.Delete(path);
|
File.Delete(path);
|
||||||
|
|
||||||
var data = tex.EncodeToPNG();
|
if (!tex.IsReadable())
|
||||||
|
tex = Texture2DHelpers.ForceReadTexture(tex);
|
||||||
|
#if CPP
|
||||||
|
byte[] data = tex.EncodeToPNG();
|
||||||
|
#else
|
||||||
|
byte[] data = tex.EncodeToPNGSafe();
|
||||||
|
#endif
|
||||||
|
|
||||||
File.WriteAllBytes(path, data);
|
File.WriteAllBytes(path, data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -176,6 +176,10 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
ConstructSubcontent();
|
ConstructSubcontent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal MethodInfo m_toStringMethod;
|
||||||
|
internal MethodInfo m_toStringFormatMethod;
|
||||||
|
internal bool m_gotToStringMethods;
|
||||||
|
|
||||||
public string GetDefaultLabel(bool updateType = true)
|
public string GetDefaultLabel(bool updateType = true)
|
||||||
{
|
{
|
||||||
var valueType = Value?.GetType() ?? this.FallbackType;
|
var valueType = Value?.GetType() ?? this.FallbackType;
|
||||||
@ -205,8 +209,29 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var toString = (string)valueType.GetMethod("ToString", new Type[0])?.Invoke(Value, null)
|
if (!m_gotToStringMethods)
|
||||||
?? Value.ToString();
|
{
|
||||||
|
m_gotToStringMethods = true;
|
||||||
|
|
||||||
|
m_toStringMethod = valueType.GetMethod("ToString", new Type[0]);
|
||||||
|
m_toStringFormatMethod = valueType.GetMethod("ToString", new Type[] { typeof(string) });
|
||||||
|
|
||||||
|
// test format method actually works
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_toStringFormatMethod.Invoke(Value, new object[] { "F3" });
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
m_toStringFormatMethod = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string toString;
|
||||||
|
if (m_toStringFormatMethod != null)
|
||||||
|
toString = (string)m_toStringFormatMethod.Invoke(Value, new object[] { "F3" });
|
||||||
|
else
|
||||||
|
toString = (string)m_toStringMethod.Invoke(Value, new object[0]);
|
||||||
|
|
||||||
var fullnametemp = valueType.ToString();
|
var fullnametemp = valueType.ToString();
|
||||||
if (fullnametemp.StartsWith("Il2CppSystem"))
|
if (fullnametemp.StartsWith("Il2CppSystem"))
|
||||||
@ -303,7 +328,7 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
void OnInspectClicked()
|
void OnInspectClicked()
|
||||||
{
|
{
|
||||||
if (!Value.IsNullOrDestroyed(false))
|
if (!Value.IsNullOrDestroyed(false))
|
||||||
InspectorManager.Instance.Inspect(this.Value);
|
InspectorManager.Instance.Inspect(this.Value, this.Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_inspectButton.SetActive(false);
|
m_inspectButton.SetActive(false);
|
||||||
|
@ -58,6 +58,8 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
public override string TabLabel => m_targetTypeShortName;
|
public override string TabLabel => m_targetTypeShortName;
|
||||||
|
|
||||||
|
internal CacheObjectBase ParentMember { get; set; }
|
||||||
|
|
||||||
internal readonly Type m_targetType;
|
internal readonly Type m_targetType;
|
||||||
internal readonly string m_targetTypeShortName;
|
internal readonly string m_targetTypeShortName;
|
||||||
|
|
||||||
@ -202,6 +204,8 @@ namespace UnityExplorer.Inspectors
|
|||||||
list.Add(new CacheProperty(pi, target, m_scrollContent));
|
list.Add(new CacheProperty(pi, target, m_scrollContent));
|
||||||
else
|
else
|
||||||
list.Add(new CacheField(fi, target, m_scrollContent));
|
list.Add(new CacheField(fi, target, m_scrollContent));
|
||||||
|
|
||||||
|
list.Last().ParentInspector = this;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -87,12 +87,6 @@ namespace UnityExplorer.UI
|
|||||||
new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_set_visible))),
|
new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_set_visible))),
|
||||||
true);
|
true);
|
||||||
|
|
||||||
#if BIE
|
|
||||||
#if CPP
|
|
||||||
// temporarily disabling this patch in BepInEx il2cpp as it's causing a crash in some games.
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
TryPatch(typeof(EventSystem),
|
TryPatch(typeof(EventSystem),
|
||||||
"current",
|
"current",
|
||||||
new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_EventSystem_set_current))),
|
new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_EventSystem_set_current))),
|
||||||
@ -111,8 +105,10 @@ namespace UnityExplorer.UI
|
|||||||
var harmony =
|
var harmony =
|
||||||
#if ML
|
#if ML
|
||||||
ExplorerMelonMod.Instance.harmonyInstance;
|
ExplorerMelonMod.Instance.harmonyInstance;
|
||||||
#else
|
#elif BIE
|
||||||
ExplorerBepInPlugin.HarmonyInstance;
|
ExplorerBepInPlugin.HarmonyInstance;
|
||||||
|
#elif STANDALONE
|
||||||
|
ExplorerStandalone.HarmonyInstance;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
System.Reflection.PropertyInfo prop = type.GetProperty(property);
|
System.Reflection.PropertyInfo prop = type.GetProperty(property);
|
||||||
@ -164,11 +160,25 @@ namespace UnityExplorer.UI
|
|||||||
|
|
||||||
public static void SetEventSystem()
|
public static void SetEventSystem()
|
||||||
{
|
{
|
||||||
|
// temp disabled for new InputSystem
|
||||||
if (InputManager.CurrentType == InputType.InputSystem)
|
if (InputManager.CurrentType == InputType.InputSystem)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Disable current event system object
|
||||||
|
if (m_lastEventSystem || EventSystem.current)
|
||||||
|
{
|
||||||
|
if (!m_lastEventSystem)
|
||||||
|
m_lastEventSystem = EventSystem.current;
|
||||||
|
|
||||||
|
//ExplorerCore.Log("Disabling current event system...");
|
||||||
|
m_lastEventSystem.enabled = false;
|
||||||
|
//m_lastEventSystem.gameObject.SetActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set to our current system
|
||||||
m_settingEventSystem = true;
|
m_settingEventSystem = true;
|
||||||
EventSystem.current = UIManager.EventSys;
|
EventSystem.current = UIManager.EventSys;
|
||||||
|
UIManager.EventSys.enabled = true;
|
||||||
InputManager.ActivateUIModule();
|
InputManager.ActivateUIModule();
|
||||||
m_settingEventSystem = false;
|
m_settingEventSystem = false;
|
||||||
}
|
}
|
||||||
@ -180,6 +190,9 @@ namespace UnityExplorer.UI
|
|||||||
|
|
||||||
if (m_lastEventSystem)
|
if (m_lastEventSystem)
|
||||||
{
|
{
|
||||||
|
m_lastEventSystem.enabled = true;
|
||||||
|
//m_lastEventSystem.gameObject.SetActive(true);
|
||||||
|
|
||||||
m_settingEventSystem = true;
|
m_settingEventSystem = true;
|
||||||
EventSystem.current = m_lastEventSystem;
|
EventSystem.current = m_lastEventSystem;
|
||||||
m_lastInputModule?.ActivateModule();
|
m_lastInputModule?.ActivateModule();
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
//using TMPro;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.SceneManagement;
|
using UnityEngine.SceneManagement;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
@ -51,8 +50,6 @@ namespace UnityExplorer.UI.Modules
|
|||||||
private SceneFilter m_sceneFilter;
|
private SceneFilter m_sceneFilter;
|
||||||
private ChildFilter m_childFilter;
|
private ChildFilter m_childFilter;
|
||||||
|
|
||||||
internal bool m_isStaticClassSearching;
|
|
||||||
|
|
||||||
// ui elements
|
// ui elements
|
||||||
|
|
||||||
private Text m_resultCountText;
|
private Text m_resultCountText;
|
||||||
@ -156,7 +153,7 @@ namespace UnityExplorer.UI.Modules
|
|||||||
{
|
{
|
||||||
var name = UISyntaxHighlight.ParseFullSyntax(obj.GetActualType(), true);
|
var name = UISyntaxHighlight.ParseFullSyntax(obj.GetActualType(), true);
|
||||||
|
|
||||||
if (unityObj && m_context != SearchContext.Singleton && m_context != SearchContext.StaticClass)
|
if (unityObj && m_context != SearchContext.Singleton)
|
||||||
{
|
{
|
||||||
if (unityObj && !string.IsNullOrEmpty(unityObj.name))
|
if (unityObj && !string.IsNullOrEmpty(unityObj.name))
|
||||||
name += $": {unityObj.name}";
|
name += $": {unityObj.name}";
|
||||||
@ -232,6 +229,7 @@ namespace UnityExplorer.UI.Modules
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_sceneDropdown.transform.Find("Label").GetComponent<Text>().text = "Any";
|
m_sceneDropdown.transform.Find("Label").GetComponent<Text>().text = "Any";
|
||||||
|
m_sceneFilter = SceneFilter.Any;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~~~~~ UI Callbacks ~~~~~
|
// ~~~~~ UI Callbacks ~~~~~
|
||||||
@ -248,12 +246,15 @@ namespace UnityExplorer.UI.Modules
|
|||||||
UnityObjectSearch();
|
UnityObjectSearch();
|
||||||
|
|
||||||
RefreshResultList();
|
RefreshResultList();
|
||||||
|
|
||||||
|
if (m_results.Length > 0)
|
||||||
|
m_resultCountText.text = $"{m_results.Length} Results";
|
||||||
|
else
|
||||||
|
m_resultCountText.text = "No results...";
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void StaticClassSearch()
|
internal void StaticClassSearch()
|
||||||
{
|
{
|
||||||
m_isStaticClassSearching = true;
|
|
||||||
|
|
||||||
var list = new List<Type>();
|
var list = new List<Type>();
|
||||||
|
|
||||||
var nameFilter = "";
|
var nameFilter = "";
|
||||||
@ -274,50 +275,69 @@ namespace UnityExplorer.UI.Modules
|
|||||||
m_results = list.ToArray();
|
m_results = list.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal string[] s_instanceNames = new string[]
|
||||||
|
{
|
||||||
|
"m_instance",
|
||||||
|
"m_Instance",
|
||||||
|
"s_instance",
|
||||||
|
"s_Instance",
|
||||||
|
"_instance",
|
||||||
|
"_Instance",
|
||||||
|
"instance",
|
||||||
|
"Instance",
|
||||||
|
"<Instance>k__BackingField",
|
||||||
|
"<instance>k__BackingField",
|
||||||
|
};
|
||||||
|
|
||||||
private void SingletonSearch()
|
private void SingletonSearch()
|
||||||
{
|
{
|
||||||
m_isStaticClassSearching = false;
|
|
||||||
|
|
||||||
var instances = new List<object>();
|
var instances = new List<object>();
|
||||||
|
|
||||||
var nameFilter = "";
|
var nameFilter = "";
|
||||||
if (!string.IsNullOrEmpty(m_nameInput.text))
|
if (!string.IsNullOrEmpty(m_nameInput.text))
|
||||||
nameFilter = m_nameInput.text.ToLower();
|
nameFilter = m_nameInput.text.ToLower();
|
||||||
|
|
||||||
|
var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
|
||||||
|
|
||||||
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
||||||
{
|
{
|
||||||
// All non-static classes
|
// Search all non-static, non-enum classes.
|
||||||
foreach (var type in asm.TryGetTypes().Where(it => !it.IsSealed && !it.IsAbstract))
|
foreach (var type in asm.TryGetTypes().Where(it => !(it.IsSealed && it.IsAbstract) && !it.IsEnum))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(nameFilter) && !type.FullName.ToLower().Contains(nameFilter))
|
if (!string.IsNullOrEmpty(nameFilter) && !type.FullName.ToLower().Contains(nameFilter))
|
||||||
continue;
|
continue;
|
||||||
|
#if CPP
|
||||||
// First look for an "Instance" Property
|
// Only look for Properties in IL2CPP, not for Mono.
|
||||||
if (type.GetProperty("Instance", ReflectionHelpers.CommonFlags) is PropertyInfo pi
|
PropertyInfo pi;
|
||||||
&& pi.CanRead
|
foreach (var name in s_instanceNames)
|
||||||
&& pi.GetGetMethod(true).IsStatic)
|
|
||||||
{
|
{
|
||||||
var instance = pi.GetValue(null, null);
|
pi = type.GetProperty(name, flags);
|
||||||
if (instance != null)
|
if (pi != null)
|
||||||
instances.Add(instance);
|
{
|
||||||
|
var instance = pi.GetValue(null, null);
|
||||||
|
if (instance != null)
|
||||||
|
{
|
||||||
|
instances.Add(instance);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
#endif
|
||||||
|
// Look for a typical Instance backing field.
|
||||||
|
FieldInfo fi;
|
||||||
|
foreach (var name in s_instanceNames)
|
||||||
{
|
{
|
||||||
// Otherwise, look for a typical Instance backing field.
|
fi = type.GetField(name, flags);
|
||||||
FieldInfo fi;
|
if (fi != null)
|
||||||
fi = type.GetField("m_instance", ReflectionHelpers.CommonFlags);
|
|
||||||
if (fi == null)
|
|
||||||
fi = type.GetField("s_instance", ReflectionHelpers.CommonFlags);
|
|
||||||
if (fi == null)
|
|
||||||
fi = type.GetField("_instance", ReflectionHelpers.CommonFlags);
|
|
||||||
if (fi == null)
|
|
||||||
fi = type.GetField("instance", ReflectionHelpers.CommonFlags);
|
|
||||||
|
|
||||||
if (fi != null && fi.IsStatic)
|
|
||||||
{
|
{
|
||||||
var instance = fi.GetValue(null);
|
var instance = fi.GetValue(null);
|
||||||
|
if (instance != null)
|
||||||
|
{
|
||||||
|
instances.Add(instance);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -330,8 +350,6 @@ namespace UnityExplorer.UI.Modules
|
|||||||
|
|
||||||
internal void UnityObjectSearch()
|
internal void UnityObjectSearch()
|
||||||
{
|
{
|
||||||
m_isStaticClassSearching = false;
|
|
||||||
|
|
||||||
Type searchType = null;
|
Type searchType = null;
|
||||||
switch (m_context)
|
switch (m_context)
|
||||||
{
|
{
|
||||||
@ -444,11 +462,6 @@ namespace UnityExplorer.UI.Modules
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_results = results.ToArray();
|
m_results = results.ToArray();
|
||||||
|
|
||||||
if (m_results.Length > 0)
|
|
||||||
m_resultCountText.text = $"{m_results.Length} Results";
|
|
||||||
else
|
|
||||||
m_resultCountText.text = "No results...";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnResultPageTurn()
|
private void OnResultPageTurn()
|
||||||
|
@ -33,6 +33,8 @@ namespace UnityExplorer.UI.Shared
|
|||||||
this.sliderScroller = sliderScroller;
|
this.sliderScroller = sliderScroller;
|
||||||
this.inputField = inputField;
|
this.inputField = inputField;
|
||||||
|
|
||||||
|
sliderScroller.m_parentInputScroller = this;
|
||||||
|
|
||||||
inputField.onValueChanged.AddListener(OnTextChanged);
|
inputField.onValueChanged.AddListener(OnTextChanged);
|
||||||
|
|
||||||
inputRect = inputField.GetComponent<RectTransform>();
|
inputRect = inputField.GetComponent<RectTransform>();
|
||||||
@ -68,6 +70,17 @@ namespace UnityExplorer.UI.Shared
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal bool CheckDestroyed()
|
||||||
|
{
|
||||||
|
if (sliderScroller == null || sliderScroller.CheckDestroyed())
|
||||||
|
{
|
||||||
|
Instances.Remove(this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
internal void OnTextChanged(string text)
|
internal void OnTextChanged(string text)
|
||||||
{
|
{
|
||||||
m_lastText = text;
|
m_lastText = text;
|
||||||
|
@ -8,150 +8,154 @@ using UnityExplorer;
|
|||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Helpers;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
|
|
||||||
// Basically just to fix an issue with Scrollbars, instead we use a Slider as the scrollbar.
|
namespace UnityExplorer.UI.Shared
|
||||||
public class SliderScrollbar
|
|
||||||
{
|
{
|
||||||
internal static readonly List<SliderScrollbar> Instances = new List<SliderScrollbar>();
|
// Basically just to fix an issue with Scrollbars, instead we use a Slider as the scrollbar.
|
||||||
|
public class SliderScrollbar
|
||||||
public bool IsActive { get; private set; }
|
|
||||||
|
|
||||||
internal readonly Scrollbar m_scrollbar;
|
|
||||||
internal readonly Slider m_slider;
|
|
||||||
internal readonly RectTransform m_scrollRect;
|
|
||||||
|
|
||||||
public SliderScrollbar(Scrollbar scrollbar, Slider slider)
|
|
||||||
{
|
{
|
||||||
Instances.Add(this);
|
internal static readonly List<SliderScrollbar> Instances = new List<SliderScrollbar>();
|
||||||
|
|
||||||
this.m_scrollbar = scrollbar;
|
public bool IsActive { get; private set; }
|
||||||
this.m_slider = slider;
|
|
||||||
this.m_scrollRect = scrollbar.transform.parent.GetComponent<RectTransform>();
|
|
||||||
|
|
||||||
this.m_scrollbar.onValueChanged.AddListener(this.OnScrollbarValueChanged);
|
internal readonly Scrollbar m_scrollbar;
|
||||||
this.m_slider.onValueChanged.AddListener(this.OnSliderValueChanged);
|
internal readonly Slider m_slider;
|
||||||
|
internal readonly RectTransform m_scrollRect;
|
||||||
|
|
||||||
this.RefreshVisibility();
|
internal InputFieldScroller m_parentInputScroller;
|
||||||
this.m_slider.Set(1f, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal bool CheckDestroyed()
|
public SliderScrollbar(Scrollbar scrollbar, Slider slider)
|
||||||
{
|
|
||||||
if (!m_slider || !m_scrollbar)
|
|
||||||
{
|
{
|
||||||
Instances.Remove(this);
|
Instances.Add(this);
|
||||||
return true;
|
|
||||||
|
this.m_scrollbar = scrollbar;
|
||||||
|
this.m_slider = slider;
|
||||||
|
this.m_scrollRect = scrollbar.transform.parent.GetComponent<RectTransform>();
|
||||||
|
|
||||||
|
this.m_scrollbar.onValueChanged.AddListener(this.OnScrollbarValueChanged);
|
||||||
|
this.m_slider.onValueChanged.AddListener(this.OnSliderValueChanged);
|
||||||
|
|
||||||
|
this.RefreshVisibility();
|
||||||
|
this.m_slider.Set(1f, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
internal bool CheckDestroyed()
|
||||||
}
|
|
||||||
|
|
||||||
internal void Update()
|
|
||||||
{
|
|
||||||
this.RefreshVisibility();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void RefreshVisibility()
|
|
||||||
{
|
|
||||||
if (!m_slider.gameObject.activeInHierarchy)
|
|
||||||
{
|
{
|
||||||
IsActive = false;
|
if (!m_slider || !m_scrollbar)
|
||||||
return;
|
{
|
||||||
|
Instances.Remove(this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool shouldShow = !Mathf.Approximately(this.m_scrollbar.size, 1);
|
internal void Update()
|
||||||
var obj = this.m_slider.handleRect.gameObject;
|
|
||||||
|
|
||||||
if (IsActive != shouldShow)
|
|
||||||
{
|
{
|
||||||
IsActive = shouldShow;
|
this.RefreshVisibility();
|
||||||
obj.SetActive(IsActive);
|
|
||||||
|
|
||||||
if (IsActive)
|
|
||||||
this.m_slider.Set(this.m_scrollbar.value, false);
|
|
||||||
else
|
|
||||||
m_slider.Set(1f, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void RefreshVisibility()
|
||||||
|
{
|
||||||
|
if (!m_slider.gameObject.activeInHierarchy)
|
||||||
|
{
|
||||||
|
IsActive = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool shouldShow = !Mathf.Approximately(this.m_scrollbar.size, 1);
|
||||||
|
var obj = this.m_slider.handleRect.gameObject;
|
||||||
|
|
||||||
|
if (IsActive != shouldShow)
|
||||||
|
{
|
||||||
|
IsActive = shouldShow;
|
||||||
|
obj.SetActive(IsActive);
|
||||||
|
|
||||||
|
if (IsActive)
|
||||||
|
this.m_slider.Set(this.m_scrollbar.value, false);
|
||||||
|
else
|
||||||
|
m_slider.Set(1f, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnScrollbarValueChanged(float _value)
|
||||||
|
{
|
||||||
|
if (this.m_slider.value != _value)
|
||||||
|
this.m_slider.Set(_value, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnSliderValueChanged(float _value)
|
||||||
|
{
|
||||||
|
this.m_scrollbar.value = _value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region UI CONSTRUCTION
|
||||||
|
|
||||||
|
public static GameObject CreateSliderScrollbar(GameObject parent, out Slider slider)
|
||||||
|
{
|
||||||
|
GameObject sliderObj = UIFactory.CreateUIObject("Slider", parent, UIFactory.thinSize);
|
||||||
|
|
||||||
|
GameObject bgObj = UIFactory.CreateUIObject("Background", sliderObj);
|
||||||
|
GameObject fillAreaObj = UIFactory.CreateUIObject("Fill Area", sliderObj);
|
||||||
|
GameObject fillObj = UIFactory.CreateUIObject("Fill", fillAreaObj);
|
||||||
|
GameObject handleSlideAreaObj = UIFactory.CreateUIObject("Handle Slide Area", sliderObj);
|
||||||
|
GameObject handleObj = UIFactory.CreateUIObject("Handle", handleSlideAreaObj);
|
||||||
|
|
||||||
|
Image bgImage = bgObj.AddComponent<Image>();
|
||||||
|
bgImage.type = Image.Type.Sliced;
|
||||||
|
bgImage.color = new Color(0.05f, 0.05f, 0.05f, 1.0f);
|
||||||
|
|
||||||
|
RectTransform bgRect = bgObj.GetComponent<RectTransform>();
|
||||||
|
bgRect.anchorMin = Vector2.zero;
|
||||||
|
bgRect.anchorMax = Vector2.one;
|
||||||
|
bgRect.sizeDelta = Vector2.zero;
|
||||||
|
bgRect.offsetMax = new Vector2(-10f, 0f);
|
||||||
|
|
||||||
|
RectTransform fillAreaRect = fillAreaObj.GetComponent<RectTransform>();
|
||||||
|
fillAreaRect.anchorMin = new Vector2(0f, 0.25f);
|
||||||
|
fillAreaRect.anchorMax = new Vector2(1f, 0.75f);
|
||||||
|
fillAreaRect.anchoredPosition = new Vector2(-5f, 0f);
|
||||||
|
fillAreaRect.sizeDelta = new Vector2(-20f, 0f);
|
||||||
|
|
||||||
|
Image fillImage = fillObj.AddComponent<Image>();
|
||||||
|
fillImage.type = Image.Type.Sliced;
|
||||||
|
fillImage.color = Color.clear;
|
||||||
|
|
||||||
|
fillObj.GetComponent<RectTransform>().sizeDelta = new Vector2(10f, 0f);
|
||||||
|
|
||||||
|
RectTransform handleSlideRect = handleSlideAreaObj.GetComponent<RectTransform>();
|
||||||
|
handleSlideRect.anchorMin = new Vector2(0f, 0f);
|
||||||
|
handleSlideRect.anchorMax = new Vector2(1f, 1f);
|
||||||
|
handleSlideRect.offsetMin = new Vector2(15f, 30f);
|
||||||
|
handleSlideRect.offsetMax = new Vector2(-15f, 0f);
|
||||||
|
handleSlideRect.sizeDelta = new Vector2(-30f, -30f);
|
||||||
|
|
||||||
|
Image handleImage = handleObj.AddComponent<Image>();
|
||||||
|
handleImage.color = new Color(0.5f, 0.5f, 0.5f, 1.0f);
|
||||||
|
|
||||||
|
var handleRect = handleObj.GetComponent<RectTransform>();
|
||||||
|
handleRect.sizeDelta = new Vector2(15f, 30f);
|
||||||
|
handleRect.offsetMin = new Vector2(-13f, -28f);
|
||||||
|
handleRect.offsetMax = new Vector2(3f, -2f);
|
||||||
|
|
||||||
|
var sliderBarLayout = sliderObj.AddComponent<LayoutElement>();
|
||||||
|
sliderBarLayout.minWidth = 25;
|
||||||
|
sliderBarLayout.flexibleWidth = 0;
|
||||||
|
sliderBarLayout.minHeight = 30;
|
||||||
|
sliderBarLayout.flexibleHeight = 5000;
|
||||||
|
|
||||||
|
slider = sliderObj.AddComponent<Slider>();
|
||||||
|
slider.fillRect = fillObj.GetComponent<RectTransform>();
|
||||||
|
slider.handleRect = handleObj.GetComponent<RectTransform>();
|
||||||
|
slider.targetGraphic = handleImage;
|
||||||
|
slider.direction = Slider.Direction.BottomToTop;
|
||||||
|
UIFactory.SetDefaultColorTransitionValues(slider);
|
||||||
|
|
||||||
|
return sliderObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnScrollbarValueChanged(float _value)
|
|
||||||
{
|
|
||||||
if (this.m_slider.value != _value)
|
|
||||||
this.m_slider.Set(_value, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnSliderValueChanged(float _value)
|
|
||||||
{
|
|
||||||
this.m_scrollbar.value = _value;
|
|
||||||
}
|
|
||||||
|
|
||||||
#region UI CONSTRUCTION
|
|
||||||
|
|
||||||
public static GameObject CreateSliderScrollbar(GameObject parent, out Slider slider)
|
|
||||||
{
|
|
||||||
GameObject sliderObj = UIFactory.CreateUIObject("Slider", parent, UIFactory.thinSize);
|
|
||||||
|
|
||||||
GameObject bgObj = UIFactory.CreateUIObject("Background", sliderObj);
|
|
||||||
GameObject fillAreaObj = UIFactory.CreateUIObject("Fill Area", sliderObj);
|
|
||||||
GameObject fillObj = UIFactory.CreateUIObject("Fill", fillAreaObj);
|
|
||||||
GameObject handleSlideAreaObj = UIFactory.CreateUIObject("Handle Slide Area", sliderObj);
|
|
||||||
GameObject handleObj = UIFactory.CreateUIObject("Handle", handleSlideAreaObj);
|
|
||||||
|
|
||||||
Image bgImage = bgObj.AddComponent<Image>();
|
|
||||||
bgImage.type = Image.Type.Sliced;
|
|
||||||
bgImage.color = new Color(0.05f, 0.05f, 0.05f, 1.0f);
|
|
||||||
|
|
||||||
RectTransform bgRect = bgObj.GetComponent<RectTransform>();
|
|
||||||
bgRect.anchorMin = Vector2.zero;
|
|
||||||
bgRect.anchorMax = Vector2.one;
|
|
||||||
bgRect.sizeDelta = Vector2.zero;
|
|
||||||
bgRect.offsetMax = new Vector2(-10f, 0f);
|
|
||||||
|
|
||||||
RectTransform fillAreaRect = fillAreaObj.GetComponent<RectTransform>();
|
|
||||||
fillAreaRect.anchorMin = new Vector2(0f, 0.25f);
|
|
||||||
fillAreaRect.anchorMax = new Vector2(1f, 0.75f);
|
|
||||||
fillAreaRect.anchoredPosition = new Vector2(-5f, 0f);
|
|
||||||
fillAreaRect.sizeDelta = new Vector2(-20f, 0f);
|
|
||||||
|
|
||||||
Image fillImage = fillObj.AddComponent<Image>();
|
|
||||||
fillImage.type = Image.Type.Sliced;
|
|
||||||
fillImage.color = Color.clear;
|
|
||||||
|
|
||||||
fillObj.GetComponent<RectTransform>().sizeDelta = new Vector2(10f, 0f);
|
|
||||||
|
|
||||||
RectTransform handleSlideRect = handleSlideAreaObj.GetComponent<RectTransform>();
|
|
||||||
handleSlideRect.anchorMin = new Vector2(0f, 0f);
|
|
||||||
handleSlideRect.anchorMax = new Vector2(1f, 1f);
|
|
||||||
handleSlideRect.offsetMin = new Vector2(15f, 30f);
|
|
||||||
handleSlideRect.offsetMax = new Vector2(-15f, 0f);
|
|
||||||
handleSlideRect.sizeDelta = new Vector2(-30f, -30f);
|
|
||||||
|
|
||||||
Image handleImage = handleObj.AddComponent<Image>();
|
|
||||||
handleImage.color = new Color(0.5f, 0.5f, 0.5f, 1.0f);
|
|
||||||
|
|
||||||
var handleRect = handleObj.GetComponent<RectTransform>();
|
|
||||||
handleRect.sizeDelta = new Vector2(15f, 30f);
|
|
||||||
handleRect.offsetMin = new Vector2(-13f, -28f);
|
|
||||||
handleRect.offsetMax = new Vector2(3f, -2f);
|
|
||||||
|
|
||||||
var sliderBarLayout = sliderObj.AddComponent<LayoutElement>();
|
|
||||||
sliderBarLayout.minWidth = 25;
|
|
||||||
sliderBarLayout.flexibleWidth = 0;
|
|
||||||
sliderBarLayout.minHeight = 30;
|
|
||||||
sliderBarLayout.flexibleHeight = 5000;
|
|
||||||
|
|
||||||
slider = sliderObj.AddComponent<Slider>();
|
|
||||||
slider.fillRect = fillObj.GetComponent<RectTransform>();
|
|
||||||
slider.handleRect = handleObj.GetComponent<RectTransform>();
|
|
||||||
slider.targetGraphic = handleImage;
|
|
||||||
slider.direction = Slider.Direction.BottomToTop;
|
|
||||||
UIFactory.SetDefaultColorTransitionValues(slider);
|
|
||||||
|
|
||||||
return sliderObj;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
|
|
||||||
#if MONO
|
#if MONO
|
||||||
public static class SliderExtensions
|
public static class SliderExtensions
|
||||||
{
|
{
|
||||||
@ -175,4 +179,5 @@ public static class SliderExtensions
|
|||||||
SetMethod.Invoke(slider, new object[] { value, invokeCallback });
|
SetMethod.Invoke(slider, new object[] { value, invokeCallback });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
@ -45,7 +45,6 @@ namespace UnityExplorer.UI
|
|||||||
SceneExplorer.Instance?.OnSceneChange();
|
SceneExplorer.Instance?.OnSceneChange();
|
||||||
SearchPage.Instance?.OnSceneChange();
|
SearchPage.Instance?.OnSceneChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Update()
|
public static void Update()
|
||||||
{
|
{
|
||||||
MainMenu.Instance?.Update();
|
MainMenu.Instance?.Update();
|
||||||
@ -53,12 +52,9 @@ namespace UnityExplorer.UI
|
|||||||
if (EventSys)
|
if (EventSys)
|
||||||
{
|
{
|
||||||
if (EventSystem.current != EventSys)
|
if (EventSystem.current != EventSys)
|
||||||
{
|
|
||||||
ForceUnlockCursor.SetEventSystem();
|
ForceUnlockCursor.SetEventSystem();
|
||||||
}
|
|
||||||
|
|
||||||
#if CPP
|
#if CPP
|
||||||
// Fix for games which override the InputModule pointer events (eg, VRChat)
|
// Some IL2CPP games behave weird with multiple UI Input Systems, some fixes for them.
|
||||||
var evt = InputManager.InputPointerEvent;
|
var evt = InputManager.InputPointerEvent;
|
||||||
if (evt != null)
|
if (evt != null)
|
||||||
{
|
{
|
||||||
@ -69,9 +65,7 @@ namespace UnityExplorer.UI
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (PanelDragger.Instance != null)
|
if (PanelDragger.Instance != null)
|
||||||
{
|
|
||||||
PanelDragger.Instance.Update();
|
PanelDragger.Instance.Update();
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < SliderScrollbar.Instances.Count; i++)
|
for (int i = 0; i < SliderScrollbar.Instances.Count; i++)
|
||||||
{
|
{
|
||||||
@ -87,40 +81,73 @@ namespace UnityExplorer.UI
|
|||||||
{
|
{
|
||||||
var input = InputFieldScroller.Instances[i];
|
var input = InputFieldScroller.Instances[i];
|
||||||
|
|
||||||
if (input.sliderScroller.CheckDestroyed())
|
if (input.CheckDestroyed())
|
||||||
i--;
|
i--;
|
||||||
else
|
else
|
||||||
input.Update();
|
input.Update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static AssetBundle LoadExplorerUi(string id)
|
||||||
|
{
|
||||||
|
return AssetBundle.LoadFromMemory(ReadFully(typeof(ExplorerCore).Assembly.GetManifestResourceStream($"UnityExplorer.Resources.explorerui.{id}.bundle")));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] ReadFully(this Stream input)
|
||||||
|
{
|
||||||
|
using (var ms = new MemoryStream())
|
||||||
|
{
|
||||||
|
byte[] buffer = new byte[81920];
|
||||||
|
int read;
|
||||||
|
while ((read = input.Read(buffer, 0, buffer.Length)) != 0)
|
||||||
|
ms.Write(buffer, 0, read);
|
||||||
|
|
||||||
|
return ms.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void LoadBundle()
|
private static void LoadBundle()
|
||||||
{
|
{
|
||||||
var bundlePath = ExplorerCore.EXPLORER_FOLDER + @"\explorerui.bundle";
|
AssetBundle bundle = null;
|
||||||
if (File.Exists(bundlePath))
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
var bundle = AssetBundle.LoadFromFile(bundlePath);
|
bundle = LoadExplorerUi("modern");
|
||||||
|
|
||||||
BackupShader = bundle.LoadAsset<Shader>("DefaultUI");
|
|
||||||
|
|
||||||
// Fix for games which don't ship with 'UI/Default' shader.
|
|
||||||
if (Graphic.defaultGraphicMaterial.shader?.name != "UI/Default")
|
|
||||||
{
|
|
||||||
ExplorerCore.Log("This game does not ship with the 'UI/Default' shader, using manual Default Shader...");
|
|
||||||
Graphic.defaultGraphicMaterial.shader = BackupShader;
|
|
||||||
}
|
|
||||||
|
|
||||||
ResizeCursor = bundle.LoadAsset<Sprite>("cursor");
|
|
||||||
|
|
||||||
ConsoleFont = bundle.LoadAsset<Font>("CONSOLA");
|
|
||||||
|
|
||||||
ExplorerCore.Log("Loaded UI bundle");
|
|
||||||
}
|
}
|
||||||
else
|
catch
|
||||||
{
|
{
|
||||||
ExplorerCore.LogWarning("Could not find the ExplorerUI Bundle! It should exist at '" + bundlePath + "'");
|
ExplorerCore.Log("Failed to load modern ExplorerUI Bundle, falling back to legacy");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
bundle = LoadExplorerUi("legacy");
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bundle == null)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning("Could not load the ExplorerUI Bundle!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BackupShader = bundle.LoadAsset<Shader>("DefaultUI");
|
||||||
|
|
||||||
|
// Fix for games which don't ship with 'UI/Default' shader.
|
||||||
|
if (Graphic.defaultGraphicMaterial.shader?.name != "UI/Default")
|
||||||
|
{
|
||||||
|
ExplorerCore.Log("This game does not ship with the 'UI/Default' shader, using manual Default Shader...");
|
||||||
|
Graphic.defaultGraphicMaterial.shader = BackupShader;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResizeCursor = bundle.LoadAsset<Sprite>("cursor");
|
||||||
|
|
||||||
|
ConsoleFont = bundle.LoadAsset<Font>("CONSOLA");
|
||||||
|
|
||||||
|
ExplorerCore.Log("Loaded UI bundle");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static GameObject CreateRootCanvas()
|
private static GameObject CreateRootCanvas()
|
||||||
@ -139,7 +166,7 @@ namespace UnityExplorer.UI
|
|||||||
canvas.renderMode = RenderMode.ScreenSpaceCamera;
|
canvas.renderMode = RenderMode.ScreenSpaceCamera;
|
||||||
canvas.referencePixelsPerUnit = 100;
|
canvas.referencePixelsPerUnit = 100;
|
||||||
canvas.sortingOrder = 999;
|
canvas.sortingOrder = 999;
|
||||||
canvas.pixelPerfect = false;
|
//canvas.pixelPerfect = false;
|
||||||
|
|
||||||
CanvasScaler scaler = rootObj.AddComponent<CanvasScaler>();
|
CanvasScaler scaler = rootObj.AddComponent<CanvasScaler>();
|
||||||
scaler.referenceResolution = new Vector2(1920, 1080);
|
scaler.referenceResolution = new Vector2(1920, 1080);
|
||||||
|
@ -25,9 +25,9 @@
|
|||||||
<Prefer32Bit>false</Prefer32Bit>
|
<Prefer32Bit>false</Prefer32Bit>
|
||||||
<RootNamespace>UnityExplorer</RootNamespace>
|
<RootNamespace>UnityExplorer</RootNamespace>
|
||||||
<!-- Set this to the BepInEx Il2Cpp Game folder, without the ending '\' character. -->
|
<!-- Set this to the BepInEx Il2Cpp Game folder, without the ending '\' character. -->
|
||||||
<BIECppGameFolder>D:\source\Unity Projects\Test\_BUILD</BIECppGameFolder>
|
<BIECppGameFolder>E:\source\Unity Projects\Test\_BUILD</BIECppGameFolder>
|
||||||
<!-- Set this to the MelonLoader Il2Cpp Game folder, without the ending '\' character. -->
|
<!-- Set this to the MelonLoader Il2Cpp Game folder, without the ending '\' character. -->
|
||||||
<MLCppGameFolder>D:\source\Unity Projects\Test\_BUILD</MLCppGameFolder>
|
<MLCppGameFolder>E:\source\Unity Projects\Test\_BUILD</MLCppGameFolder>
|
||||||
<NuGetPackageImportStamp>
|
<NuGetPackageImportStamp>
|
||||||
</NuGetPackageImportStamp>
|
</NuGetPackageImportStamp>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@ -68,6 +68,24 @@
|
|||||||
<IsMelonLoader>false</IsMelonLoader>
|
<IsMelonLoader>false</IsMelonLoader>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release_STANDALONE_Mono|AnyCPU'">
|
||||||
|
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||||
|
<OutputPath>..\Release\UnityExplorer.Standalone.Mono\</OutputPath>
|
||||||
|
<DefineConstants>MONO,STANDALONE</DefineConstants>
|
||||||
|
<AssemblyName>UnityExplorer.STANDALONE.Mono</AssemblyName>
|
||||||
|
<IsCpp>false</IsCpp>
|
||||||
|
<IsMelonLoader>false</IsMelonLoader>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release_STANDALONE_Cpp|AnyCPU'">
|
||||||
|
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||||
|
<OutputPath>..\Release\UnityExplorer.Standalone.Il2Cpp\</OutputPath>
|
||||||
|
<DefineConstants>CPP,STANDALONE</DefineConstants>
|
||||||
|
<AssemblyName>UnityExplorer.STANDALONE.IL2CPP</AssemblyName>
|
||||||
|
<IsCpp>true</IsCpp>
|
||||||
|
<IsMelonLoader>false</IsMelonLoader>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="INIFileParser, Version=2.5.2.0, Culture=neutral, PublicKeyToken=79af7b307b65cf3c, processorArchitecture=MSIL">
|
<Reference Include="INIFileParser, Version=2.5.2.0, Culture=neutral, PublicKeyToken=79af7b307b65cf3c, processorArchitecture=MSIL">
|
||||||
<HintPath>packages\ini-parser.2.5.2\lib\net20\INIFileParser.dll</HintPath>
|
<HintPath>packages\ini-parser.2.5.2\lib\net20\INIFileParser.dll</HintPath>
|
||||||
@ -217,6 +235,7 @@
|
|||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="ExplorerStandalone.cs" />
|
||||||
<Compile Include="Helpers\EventHelper.cs" />
|
<Compile Include="Helpers\EventHelper.cs" />
|
||||||
<Compile Include="Inspectors\MouseInspector.cs" />
|
<Compile Include="Inspectors\MouseInspector.cs" />
|
||||||
<Compile Include="Inspectors\Reflection\CacheObject\CacheEnumerated.cs" />
|
<Compile Include="Inspectors\Reflection\CacheObject\CacheEnumerated.cs" />
|
||||||
@ -293,6 +312,7 @@
|
|||||||
<Compile Include="Unstrip\SceneUnstrip.cs" />
|
<Compile Include="Unstrip\SceneUnstrip.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="UI\UIFactory.cs" />
|
<Compile Include="UI\UIFactory.cs" />
|
||||||
|
<EmbeddedResource Include="Resources\*" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="ILRepack.targets" />
|
<None Include="ILRepack.targets" />
|
||||||
|
@ -11,6 +11,8 @@ Global
|
|||||||
Release_BIE_Mono|Any CPU = Release_BIE_Mono|Any CPU
|
Release_BIE_Mono|Any CPU = Release_BIE_Mono|Any CPU
|
||||||
Release_ML_Cpp|Any CPU = Release_ML_Cpp|Any CPU
|
Release_ML_Cpp|Any CPU = Release_ML_Cpp|Any CPU
|
||||||
Release_ML_Mono|Any CPU = Release_ML_Mono|Any CPU
|
Release_ML_Mono|Any CPU = Release_ML_Mono|Any CPU
|
||||||
|
Release_STANDALONE_Cpp|Any CPU = Release_STANDALONE_Cpp|Any CPU
|
||||||
|
Release_STANDALONE_Mono|Any CPU = Release_STANDALONE_Mono|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_BIE_Cpp|Any CPU.ActiveCfg = Release_BIE_Cpp|Any CPU
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_BIE_Cpp|Any CPU.ActiveCfg = Release_BIE_Cpp|Any CPU
|
||||||
@ -21,6 +23,10 @@ Global
|
|||||||
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Cpp|Any CPU.Build.0 = Release_ML_Cpp|Any CPU
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Cpp|Any CPU.Build.0 = Release_ML_Cpp|Any CPU
|
||||||
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Mono|Any CPU.ActiveCfg = Release_ML_Mono|Any CPU
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Mono|Any CPU.ActiveCfg = Release_ML_Mono|Any CPU
|
||||||
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Mono|Any CPU.Build.0 = Release_ML_Mono|Any CPU
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Mono|Any CPU.Build.0 = Release_ML_Mono|Any CPU
|
||||||
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_STANDALONE_Cpp|Any CPU.ActiveCfg = Release_STANDALONE_Cpp|Any CPU
|
||||||
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_STANDALONE_Cpp|Any CPU.Build.0 = Release_STANDALONE_Cpp|Any CPU
|
||||||
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_STANDALONE_Mono|Any CPU.ActiveCfg = Release_STANDALONE_Mono|Any CPU
|
||||||
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_STANDALONE_Mono|Any CPU.Build.0 = Release_STANDALONE_Mono|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@ -24,6 +24,17 @@ namespace UnityExplorer.Unstrip
|
|||||||
|
|
||||||
return new AssetBundle(ptr);
|
return new AssetBundle(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private delegate IntPtr d_LoadFromMemory(IntPtr binary, uint crc);
|
||||||
|
|
||||||
|
public static AssetBundle LoadFromMemory(byte[] binary, uint crc = 0)
|
||||||
|
{
|
||||||
|
var iCall = ICallHelper.GetICall<d_LoadFromMemory>("UnityEngine.AssetBundle::LoadFromMemory_Internal");
|
||||||
|
|
||||||
|
var ptr = iCall(((Il2CppStructArray<byte>) binary).Pointer, crc);
|
||||||
|
|
||||||
|
return new AssetBundle(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
// ~~~~~~~~~~~~ Instance ~~~~~~~~~~~~
|
// ~~~~~~~~~~~~ Instance ~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user