mirror of
https://github.com/GrahamKracker/UnityExplorer.git
synced 2025-07-14 23:56:36 +08:00
Compare commits
18 Commits
Author | SHA1 | Date | |
---|---|---|---|
fae85c2968 | |||
fc8fa9aa7a | |||
bcf9a801a9 | |||
20298aa47b | |||
e2c1c186c3 | |||
9ce6508828 | |||
506e75c5fe | |||
a2f22051f0 | |||
4e3203a91b | |||
a411ce2dba | |||
48132b3d46 | |||
e49ed3028f | |||
31dd54d25c | |||
3cfdd6fa43 | |||
1fa1283a68 | |||
afa4135b67 | |||
48d1cf574d | |||
df0abbc847 |
Binary file not shown.
@ -121,16 +121,15 @@ namespace UnityExplorer.CSConsole
|
|||||||
{
|
{
|
||||||
while (input.Length - 1 >= matchEndIdx)
|
while (input.Length - 1 >= matchEndIdx)
|
||||||
{
|
{
|
||||||
|
matchEndIdx++;
|
||||||
if (IsNewLine(input[matchEndIdx]))
|
if (IsNewLine(input[matchEndIdx]))
|
||||||
break;
|
break;
|
||||||
matchEndIdx++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check caretIdx to determine inStringOrComment state
|
// check caretIdx to determine inStringOrComment state
|
||||||
if (caretIdx >= match.startIndex && (caretIdx <= matchEndIdx || (caretIdx >= input.Length && matchEndIdx >= input.Length - 1)))
|
if (caretIdx >= match.startIndex && (caretIdx <= (matchEndIdx+1) || (caretIdx >= input.Length && matchEndIdx >= input.Length - 1)))
|
||||||
caretInStringOrComment = match.isStringOrComment;
|
caretInStringOrComment = match.isStringOrComment;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append trailing unhighlighted input
|
// Append trailing unhighlighted input
|
||||||
|
@ -12,11 +12,11 @@ namespace UnityExplorer.CacheObject
|
|||||||
public CacheConfigEntry(IConfigElement configElement)
|
public CacheConfigEntry(IConfigElement configElement)
|
||||||
{
|
{
|
||||||
this.RefConfigElement = configElement;
|
this.RefConfigElement = configElement;
|
||||||
|
this.FallbackType = configElement.ElementType;
|
||||||
|
|
||||||
this.NameLabelText = $"<color=cyan>{configElement.Name}</color>" +
|
this.NameLabelText = $"<color=cyan>{configElement.Name}</color>" +
|
||||||
$"\r\n<color=grey><i>{configElement.Description}</i></color>";
|
$"\r\n<color=grey><i>{configElement.Description}</i></color>";
|
||||||
|
this.NameLabelTextRaw = string.Empty;
|
||||||
this.FallbackType = configElement.ElementType;
|
|
||||||
|
|
||||||
configElement.OnValueChangedNotify += UpdateValueFromSource;
|
configElement.OnValueChangedNotify += UpdateValueFromSource;
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,7 @@ namespace UnityExplorer.CacheObject
|
|||||||
var kvpCell = cell as CacheKeyValuePairCell;
|
var kvpCell = cell as CacheKeyValuePairCell;
|
||||||
|
|
||||||
kvpCell.NameLabel.text = $"{DictIndex}:";
|
kvpCell.NameLabel.text = $"{DictIndex}:";
|
||||||
|
kvpCell.HiddenNameLabel.Text = "";
|
||||||
kvpCell.Image.color = DictIndex % 2 == 0 ? CacheListEntryCell.EvenColor : CacheListEntryCell.OddColor;
|
kvpCell.Image.color = DictIndex % 2 == 0 ? CacheListEntryCell.EvenColor : CacheListEntryCell.OddColor;
|
||||||
|
|
||||||
if (KeyInputWanted)
|
if (KeyInputWanted)
|
||||||
|
@ -28,6 +28,7 @@ namespace UnityExplorer.CacheObject
|
|||||||
var listCell = cell as CacheListEntryCell;
|
var listCell = cell as CacheListEntryCell;
|
||||||
|
|
||||||
listCell.NameLabel.text = $"{ListIndex}:";
|
listCell.NameLabel.text = $"{ListIndex}:";
|
||||||
|
listCell.HiddenNameLabel.Text = "";
|
||||||
listCell.Image.color = ListIndex % 2 == 0 ? CacheListEntryCell.EvenColor : CacheListEntryCell.OddColor;
|
listCell.Image.color = ListIndex % 2 == 0 ? CacheListEntryCell.EvenColor : CacheListEntryCell.OddColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@ namespace UnityExplorer.CacheObject
|
|||||||
this.Owner = inspector;
|
this.Owner = inspector;
|
||||||
this.NameLabelText = SignatureHighlighter.Parse(member.DeclaringType, false, member);
|
this.NameLabelText = SignatureHighlighter.Parse(member.DeclaringType, false, member);
|
||||||
this.NameForFiltering = $"{member.DeclaringType.Name}.{member.Name}";
|
this.NameForFiltering = $"{member.DeclaringType.Name}.{member.Name}";
|
||||||
|
this.NameLabelTextRaw = NameForFiltering;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ReleasePooledObjects()
|
public override void ReleasePooledObjects()
|
||||||
|
@ -30,15 +30,14 @@ namespace UnityExplorer.CacheObject
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var methodInfo = MethodInfo;
|
var methodInfo = MethodInfo;
|
||||||
|
|
||||||
if (methodInfo.IsGenericMethod)
|
if (methodInfo.IsGenericMethod)
|
||||||
methodInfo = MethodInfo.MakeGenericMethod(Evaluator.TryParseGenericArguments());
|
methodInfo = MethodInfo.MakeGenericMethod(Evaluator.TryParseGenericArguments());
|
||||||
|
|
||||||
if (Arguments.Length > 0)
|
object ret;
|
||||||
return methodInfo.Invoke(DeclaringInstance, Evaluator.TryParseArguments());
|
if (HasArguments)
|
||||||
|
ret = methodInfo.Invoke(DeclaringInstance, Evaluator.TryParseArguments());
|
||||||
var ret = methodInfo.Invoke(DeclaringInstance, ArgumentUtility.EmptyArgs);
|
else
|
||||||
|
ret = methodInfo.Invoke(DeclaringInstance, ArgumentUtility.EmptyArgs);
|
||||||
HadException = false;
|
HadException = false;
|
||||||
LastException = null;
|
LastException = null;
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -47,6 +47,7 @@ namespace UnityExplorer.CacheObject
|
|||||||
public bool SubContentShowWanted { get; private set; }
|
public bool SubContentShowWanted { get; private set; }
|
||||||
|
|
||||||
public string NameLabelText { get; protected set; }
|
public string NameLabelText { get; protected set; }
|
||||||
|
public string NameLabelTextRaw { get; protected set; }
|
||||||
public string ValueLabelText { get; protected set; }
|
public string ValueLabelText { get; protected set; }
|
||||||
|
|
||||||
public abstract bool ShouldAutoEvaluate { get; }
|
public abstract bool ShouldAutoEvaluate { get; }
|
||||||
@ -260,6 +261,8 @@ namespace UnityExplorer.CacheObject
|
|||||||
public virtual void SetDataToCell(CacheObjectCell cell)
|
public virtual void SetDataToCell(CacheObjectCell cell)
|
||||||
{
|
{
|
||||||
cell.NameLabel.text = NameLabelText;
|
cell.NameLabel.text = NameLabelText;
|
||||||
|
if (cell.HiddenNameLabel != null)
|
||||||
|
cell.HiddenNameLabel.Text = NameLabelTextRaw;
|
||||||
cell.ValueLabel.gameObject.SetActive(true);
|
cell.ValueLabel.gameObject.SetActive(true);
|
||||||
|
|
||||||
cell.SubContentHolder.gameObject.SetActive(SubContentShowWanted);
|
cell.SubContentHolder.gameObject.SetActive(SubContentShowWanted);
|
||||||
|
@ -45,6 +45,7 @@ namespace UnityExplorer.CacheObject.Views
|
|||||||
public LayoutElement RightGroupLayout;
|
public LayoutElement RightGroupLayout;
|
||||||
|
|
||||||
public Text NameLabel;
|
public Text NameLabel;
|
||||||
|
public InputFieldRef HiddenNameLabel;
|
||||||
public Text TypeLabel;
|
public Text TypeLabel;
|
||||||
public Text ValueLabel;
|
public Text ValueLabel;
|
||||||
public Toggle Toggle;
|
public Toggle Toggle;
|
||||||
@ -116,8 +117,19 @@ namespace UnityExplorer.CacheObject.Views
|
|||||||
|
|
||||||
NameLabel = UIFactory.CreateLabel(horiRow, "NameLabel", "<notset>", TextAnchor.MiddleLeft);
|
NameLabel = UIFactory.CreateLabel(horiRow, "NameLabel", "<notset>", TextAnchor.MiddleLeft);
|
||||||
NameLabel.horizontalOverflow = HorizontalWrapMode.Wrap;
|
NameLabel.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||||||
UIFactory.SetLayoutElement(NameLabel.gameObject, minHeight: 25, minWidth: 20, flexibleHeight: 300, flexibleWidth: 0);
|
NameLayout = UIFactory.SetLayoutElement(NameLabel.gameObject, minHeight: 25, minWidth: 20, flexibleHeight: 300, flexibleWidth: 0);
|
||||||
NameLayout = NameLabel.GetComponent<LayoutElement>();
|
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(NameLabel.gameObject, true, true, true, true);
|
||||||
|
|
||||||
|
HiddenNameLabel = UIFactory.CreateInputField(NameLabel.gameObject, "HiddenNameLabel", "");
|
||||||
|
var hiddenRect = HiddenNameLabel.Component.GetComponent<RectTransform>();
|
||||||
|
hiddenRect.anchorMin = Vector2.zero;
|
||||||
|
hiddenRect.anchorMax = Vector2.one;
|
||||||
|
HiddenNameLabel.Component.readOnly = true;
|
||||||
|
HiddenNameLabel.Component.lineType = UnityEngine.UI.InputField.LineType.MultiLineNewline;
|
||||||
|
HiddenNameLabel.Component.textComponent.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||||||
|
HiddenNameLabel.Component.gameObject.GetComponent<Image>().color = Color.clear;
|
||||||
|
HiddenNameLabel.Component.textComponent.color = Color.clear;
|
||||||
|
UIFactory.SetLayoutElement(HiddenNameLabel.Component.gameObject, minHeight: 25, minWidth: 20, flexibleHeight: 300, flexibleWidth: 0);
|
||||||
|
|
||||||
// Right vertical group
|
// Right vertical group
|
||||||
|
|
||||||
|
@ -134,6 +134,9 @@ namespace UnityExplorer
|
|||||||
var type = obj.GetType();
|
var type = obj.GetType();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (type.IsGenericType)
|
||||||
|
return type;
|
||||||
|
|
||||||
if (IsString(obj))
|
if (IsString(obj))
|
||||||
return typeof(string);
|
return typeof(string);
|
||||||
|
|
||||||
@ -178,7 +181,8 @@ namespace UnityExplorer
|
|||||||
if (fullname.StartsWith("System."))
|
if (fullname.StartsWith("System."))
|
||||||
fullname = $"Il2Cpp{fullname}";
|
fullname = $"Il2Cpp{fullname}";
|
||||||
|
|
||||||
AllTypes.TryGetValue(fullname, out Type monoType);
|
if (!AllTypes.TryGetValue(fullname, out Type monoType))
|
||||||
|
ExplorerCore.LogWarning($"Failed to get type by name '{fullname}'!");
|
||||||
return monoType;
|
return monoType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -477,60 +481,39 @@ namespace UnityExplorer
|
|||||||
|
|
||||||
#region Force-loading game modules
|
#region Force-loading game modules
|
||||||
|
|
||||||
internal static string UnhollowedFolderPath => Path.GetFullPath(
|
|
||||||
#if ML
|
|
||||||
Path.Combine("MelonLoader", "Managed")
|
|
||||||
#elif BIE
|
|
||||||
Path.Combine(BepInEx.Paths.BepInExRootPath, "unhollowed")
|
|
||||||
#else
|
|
||||||
Path.Combine(ExplorerCore.Loader.ExplorerFolder, "Modules")
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
|
|
||||||
// Helper for IL2CPP to try to make sure the Unhollowed game assemblies are actually loaded.
|
// Helper for IL2CPP to try to make sure the Unhollowed game assemblies are actually loaded.
|
||||||
|
|
||||||
// Force loading all il2cpp modules
|
// Force loading all il2cpp modules
|
||||||
|
|
||||||
internal void TryLoadGameModules()
|
internal void TryLoadGameModules()
|
||||||
{
|
{
|
||||||
if (Directory.Exists(UnhollowedFolderPath))
|
var dir = ExplorerCore.Loader.UnhollowedModulesFolder;
|
||||||
|
if (Directory.Exists(dir))
|
||||||
{
|
{
|
||||||
var files = Directory.GetFiles(UnhollowedFolderPath);
|
foreach (var filePath in Directory.GetFiles(dir, "*.dll"))
|
||||||
foreach (var filePath in files)
|
DoLoadModule(filePath);
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
DoLoadModule(filePath, true);
|
|
||||||
}
|
|
||||||
catch //(Exception ex)
|
|
||||||
{
|
|
||||||
//ExplorerCore.LogWarning($"Failed to force-load module '{name}': {ex.ReflectionExToString()}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ExplorerCore.LogWarning($"Expected Unhollowed folder path does not exist: '{UnhollowedFolderPath}'");
|
ExplorerCore.LogWarning($"Expected Unhollowed folder path does not exist: '{dir}'. " +
|
||||||
|
$"If you are using the standalone release, you can specify the Unhollowed modules path when you call CreateInstance().");
|
||||||
}
|
}
|
||||||
|
|
||||||
internal bool DoLoadModule(string fullPath, bool suppressWarning = false)
|
internal bool DoLoadModule(string fullPath)
|
||||||
{
|
{
|
||||||
if (!File.Exists(fullPath))
|
if (string.IsNullOrEmpty(fullPath) || !File.Exists(fullPath))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Assembly.LoadFile(fullPath);
|
Assembly.LoadFile(fullPath);
|
||||||
//Assembly.Load(File.ReadAllBytes(fullPath));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch //(Exception e)
|
||||||
{
|
{
|
||||||
if (!suppressWarning)
|
//ExplorerCore.LogWarning($"Failed loading module '{Path.GetFileName(fullPath)}'! {e.ReflectionExToString()}");
|
||||||
Console.WriteLine($"Failed loading module '{Path.GetFileName(fullPath)}'! {e.ReflectionExToString()}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
57
src/Core/Reflection/Patches.cs
Normal file
57
src/Core/Reflection/Patches.cs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using HarmonyLib;
|
||||||
|
|
||||||
|
namespace UnityExplorer
|
||||||
|
{
|
||||||
|
public static class ReflectionPatches
|
||||||
|
{
|
||||||
|
public static void Init()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var method = typeof(Assembly).GetMethod(nameof(Assembly.GetTypes), new Type[0]);
|
||||||
|
var processor = ExplorerCore.Harmony.CreateProcessor(method);
|
||||||
|
processor.AddFinalizer(typeof(ReflectionPatches).GetMethod(nameof(Assembly_GetTypes)));
|
||||||
|
processor.Patch();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning($"Exception setting up Reflection patch: {ex}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly Type[] emptyTypes = new Type[0];
|
||||||
|
|
||||||
|
public static Exception Assembly_GetTypes(Assembly __instance, Exception __exception, ref Type[] __result)
|
||||||
|
{
|
||||||
|
if (__exception != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
__result = __instance.GetExportedTypes();
|
||||||
|
}
|
||||||
|
catch (ReflectionTypeLoadException e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
__result = e.Types.Where(it => it != null).ToArray();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
__result = emptyTypes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
__result = emptyTypes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -27,6 +27,8 @@ namespace UnityExplorer
|
|||||||
new ReflectionUtility();
|
new ReflectionUtility();
|
||||||
#endif
|
#endif
|
||||||
Instance.Initialize();
|
Instance.Initialize();
|
||||||
|
|
||||||
|
ReflectionPatches.Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Initialize()
|
protected virtual void Initialize()
|
||||||
|
@ -98,15 +98,17 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
|||||||
|
|
||||||
internal delegate IntPtr d_FindObjectsOfTypeAll(IntPtr type);
|
internal delegate IntPtr d_FindObjectsOfTypeAll(IntPtr type);
|
||||||
|
|
||||||
public override UnityEngine.Object[] FindObjectsOfTypeAll(Type type)
|
internal static readonly string[] findObjectsOfTypeAllSignatures = new[]
|
||||||
{
|
|
||||||
var iCall = ICallManager.GetICallUnreliable<d_FindObjectsOfTypeAll>(new[]
|
|
||||||
{
|
{
|
||||||
"UnityEngine.Resources::FindObjectsOfTypeAll",
|
"UnityEngine.Resources::FindObjectsOfTypeAll",
|
||||||
"UnityEngine.ResourcesAPIInternal::FindObjectsOfTypeAll" // Unity 2020+ updated to this
|
"UnityEngine.ResourcesAPIInternal::FindObjectsOfTypeAll" // Unity 2020+ updated to this
|
||||||
});
|
};
|
||||||
|
|
||||||
return new Il2CppReferenceArray<UnityEngine.Object>(iCall.Invoke(Il2CppType.From(type).Pointer));
|
public override UnityEngine.Object[] FindObjectsOfTypeAll(Type type)
|
||||||
|
{
|
||||||
|
return new Il2CppReferenceArray<UnityEngine.Object>(
|
||||||
|
ICallManager.GetICallUnreliable<d_FindObjectsOfTypeAll>(findObjectsOfTypeAllSignatures)
|
||||||
|
.Invoke(Il2CppType.From(type).Pointer));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scene.GetRootGameObjects();
|
// Scene.GetRootGameObjects();
|
||||||
|
@ -118,7 +118,7 @@ namespace UnityExplorer.Tests
|
|||||||
|
|
||||||
ExplorerCore.Log($"5: Big list");
|
ExplorerCore.Log($"5: Big list");
|
||||||
for (int i = 0; i < ABigList.Capacity; i++)
|
for (int i = 0; i < ABigList.Capacity; i++)
|
||||||
ABigList[i] = (short)UnityEngine.Random.Range(0, short.MaxValue);
|
ABigList.Add((short)UnityEngine.Random.Range(0, short.MaxValue));
|
||||||
|
|
||||||
ExplorerCore.Log("Finished TestClass Init_Mono");
|
ExplorerCore.Log("Finished TestClass Init_Mono");
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ namespace UnityExplorer
|
|||||||
public static class ExplorerCore
|
public static class ExplorerCore
|
||||||
{
|
{
|
||||||
public const string NAME = "UnityExplorer";
|
public const string NAME = "UnityExplorer";
|
||||||
public const string VERSION = "4.2.0";
|
public const string VERSION = "4.2.1";
|
||||||
public const string AUTHOR = "Sinai";
|
public const string AUTHOR = "Sinai";
|
||||||
public const string GUID = "com.sinai.unityexplorer";
|
public const string GUID = "com.sinai.unityexplorer";
|
||||||
|
|
||||||
|
@ -9,19 +9,9 @@
|
|||||||
<InputAssemblies Include="packages\ini-parser.2.5.2\lib\net20\INIFileParser.dll" />
|
<InputAssemblies Include="packages\ini-parser.2.5.2\lib\net20\INIFileParser.dll" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<!-- MonoMod for MelonLoader 0.3.0 -->
|
|
||||||
<ItemGroup Condition="'$(IsMelonLoaderLegacy)'=='true'">
|
|
||||||
<InputAssemblies Include="packages\Mono.Cecil.0.10.4\lib\net35\Mono.Cecil.dll" />
|
|
||||||
<InputAssemblies Include="packages\Mono.Cecil.0.10.4\lib\net35\Mono.Cecil.Mdb.dll" />
|
|
||||||
<InputAssemblies Include="packages\Mono.Cecil.0.10.4\lib\net35\Mono.Cecil.Pdb.dll" />
|
|
||||||
<InputAssemblies Include="packages\Mono.Cecil.0.10.4\lib\net35\Mono.Cecil.Rocks.dll" />
|
|
||||||
<InputAssemblies Include="packages\MonoMod.RuntimeDetour.20.1.1.4\lib\net35\MonoMod.RuntimeDetour.dll" />
|
|
||||||
<InputAssemblies Include="packages\MonoMod.Utils.20.1.1.4\lib\net35\MonoMod.Utils.dll" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<!-- Required references for ILRepack -->
|
<!-- Required references for ILRepack -->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ReferenceFolders Include="packages\HarmonyX.2.4.2\lib\net35\" />
|
<ReferenceFolders Include="packages\HarmonyX.2.5.2\lib\net35\" />
|
||||||
<ReferenceFolders Include="..\lib\BepInEx.6.IL2CPP\" />
|
<ReferenceFolders Include="..\lib\BepInEx.6.IL2CPP\" />
|
||||||
<ReferenceFolders Include="..\lib\BepInEx.6.Mono\" />
|
<ReferenceFolders Include="..\lib\BepInEx.6.Mono\" />
|
||||||
<ReferenceFolders Include="..\lib\BepInEx.5\" />
|
<ReferenceFolders Include="..\lib\BepInEx.5\" />
|
||||||
|
@ -47,6 +47,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
public ScrollPool<CacheMemberCell> MemberScrollPool { get; private set; }
|
public ScrollPool<CacheMemberCell> MemberScrollPool { get; private set; }
|
||||||
|
|
||||||
|
public InputFieldRef HiddenNameText;
|
||||||
public Text NameText;
|
public Text NameText;
|
||||||
public Text AssemblyText;
|
public Text AssemblyText;
|
||||||
private Toggle autoUpdateToggle;
|
private Toggle autoUpdateToggle;
|
||||||
@ -125,6 +126,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
currentBaseTabText = $"{prefix} {SignatureHighlighter.Parse(TargetType, false)}";
|
currentBaseTabText = $"{prefix} {SignatureHighlighter.Parse(TargetType, false)}";
|
||||||
Tab.TabText.text = currentBaseTabText;
|
Tab.TabText.text = currentBaseTabText;
|
||||||
NameText.text = SignatureHighlighter.Parse(TargetType, true);
|
NameText.text = SignatureHighlighter.Parse(TargetType, true);
|
||||||
|
HiddenNameText.Text = TargetType.FullName;
|
||||||
|
|
||||||
string asmText;
|
string asmText;
|
||||||
if (TargetType.Assembly is AssemblyBuilder || string.IsNullOrEmpty(TargetType.Assembly.Location))
|
if (TargetType.Assembly is AssemblyBuilder || string.IsNullOrEmpty(TargetType.Assembly.Location))
|
||||||
@ -332,8 +334,27 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
// Class name, assembly
|
// Class name, assembly
|
||||||
|
|
||||||
NameText = UIFactory.CreateLabel(UIRoot, "Title", "not set", TextAnchor.MiddleLeft, fontSize: 17);
|
var titleHolder = UIFactory.CreateUIObject("TitleHolder", UIRoot);
|
||||||
UIFactory.SetLayoutElement(NameText.gameObject, minHeight: 25, flexibleHeight: 0);
|
UIFactory.SetLayoutElement(titleHolder, minHeight: 35, flexibleHeight: 0, flexibleWidth: 9999);
|
||||||
|
|
||||||
|
NameText = UIFactory.CreateLabel(titleHolder, "VisibleTitle", "NotSet", TextAnchor.MiddleLeft);
|
||||||
|
var namerect = NameText.GetComponent<RectTransform>();
|
||||||
|
namerect.anchorMin = new Vector2(0, 0);
|
||||||
|
namerect.anchorMax = new Vector2(1, 1);
|
||||||
|
NameText.fontSize = 17;
|
||||||
|
UIFactory.SetLayoutElement(NameText.gameObject, minHeight: 35, flexibleHeight: 0, minWidth: 300, flexibleWidth: 9999);
|
||||||
|
|
||||||
|
HiddenNameText = UIFactory.CreateInputField(titleHolder, "Title", "not set");
|
||||||
|
var hiddenrect = HiddenNameText.Component.gameObject.GetComponent<RectTransform>();
|
||||||
|
hiddenrect.anchorMin = new Vector2(0, 0);
|
||||||
|
hiddenrect.anchorMax = new Vector2(1, 1);
|
||||||
|
HiddenNameText.Component.readOnly = true;
|
||||||
|
HiddenNameText.Component.lineType = InputField.LineType.MultiLineNewline;
|
||||||
|
HiddenNameText.Component.gameObject.GetComponent<Image>().color = Color.clear;
|
||||||
|
HiddenNameText.Component.textComponent.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||||||
|
HiddenNameText.Component.textComponent.fontSize = 17;
|
||||||
|
HiddenNameText.Component.textComponent.color = Color.clear;
|
||||||
|
UIFactory.SetLayoutElement(HiddenNameText.Component.gameObject, minHeight: 35, flexibleHeight: 0, flexibleWidth: 9999);
|
||||||
|
|
||||||
AssemblyText = UIFactory.CreateLabel(UIRoot, "AssemblyLabel", "not set", TextAnchor.MiddleLeft);
|
AssemblyText = UIFactory.CreateLabel(UIRoot, "AssemblyLabel", "not set", TextAnchor.MiddleLeft);
|
||||||
UIFactory.SetLayoutElement(AssemblyText.gameObject, minHeight: 25, flexibleWidth: 9999);
|
UIFactory.SetLayoutElement(AssemblyText.gameObject, minHeight: 25, flexibleWidth: 9999);
|
||||||
|
@ -39,6 +39,8 @@ namespace UnityExplorer
|
|||||||
=> Log;
|
=> Log;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
public string UnhollowedModulesFolder => Path.Combine(Paths.BepInExRootPath, "unhollowed");
|
||||||
|
|
||||||
public ConfigHandler ConfigHandler => _configHandler;
|
public ConfigHandler ConfigHandler => _configHandler;
|
||||||
private BepInExConfigHandler _configHandler;
|
private BepInExConfigHandler _configHandler;
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ namespace UnityExplorer
|
|||||||
public interface IExplorerLoader
|
public interface IExplorerLoader
|
||||||
{
|
{
|
||||||
string ExplorerFolder { get; }
|
string ExplorerFolder { get; }
|
||||||
|
string UnhollowedModulesFolder { get; }
|
||||||
|
|
||||||
ConfigHandler ConfigHandler { get; }
|
ConfigHandler ConfigHandler { get; }
|
||||||
|
|
||||||
|
@ -24,6 +24,10 @@ namespace UnityExplorer
|
|||||||
|
|
||||||
public string ExplorerFolder => Path.Combine("Mods", ExplorerCore.NAME);
|
public string ExplorerFolder => Path.Combine("Mods", ExplorerCore.NAME);
|
||||||
|
|
||||||
|
public string UnhollowedModulesFolder => Path.Combine(
|
||||||
|
Path.GetDirectoryName(MelonHandler.ModsDirectory),
|
||||||
|
Path.Combine("MelonLoader", "Managed"));
|
||||||
|
|
||||||
public ConfigHandler ConfigHandler => _configHandler;
|
public ConfigHandler ConfigHandler => _configHandler;
|
||||||
public MelonLoaderConfigHandler _configHandler;
|
public MelonLoaderConfigHandler _configHandler;
|
||||||
|
|
||||||
|
@ -34,17 +34,34 @@ namespace UnityExplorer.Loader.ML
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void RegisterConfigElement<T>(ConfigElement<T> config)
|
// This wrapper exists to handle the arbitrary "LemonAction" delegates which ML now uses in 0.4.4+.
|
||||||
|
// Reflection is required since the delegate type changed between 0.4.3 and 0.4.4.
|
||||||
|
// A wrapper class is required to link the MelonPreferences_Entry and the delegate instance.
|
||||||
|
public class EntryDelegateWrapper<T>
|
||||||
{
|
{
|
||||||
var entry = prefCategory.CreateEntry(config.Name, config.Value, null, config.Description, config.IsInternal, false);
|
public MelonPreferences_Entry<T> entry;
|
||||||
|
public ConfigElement<T> config;
|
||||||
|
|
||||||
entry.OnValueChangedUntyped += () =>
|
public EntryDelegateWrapper(MelonPreferences_Entry<T> entry, ConfigElement<T> config)
|
||||||
|
{
|
||||||
|
this.entry = entry;
|
||||||
|
this.config = config;
|
||||||
|
var evt = entry.GetType().GetEvent("OnValueChangedUntyped");
|
||||||
|
evt.AddEventHandler(entry, Delegate.CreateDelegate(evt.EventHandlerType, this, GetType().GetMethod("OnChanged")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnChanged()
|
||||||
{
|
{
|
||||||
if ((entry.Value == null && config.Value == null) || config.Value.Equals(entry.Value))
|
if ((entry.Value == null && config.Value == null) || config.Value.Equals(entry.Value))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
config.Value = entry.Value;
|
config.Value = entry.Value;
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void RegisterConfigElement<T>(ConfigElement<T> config)
|
||||||
|
{
|
||||||
|
var entry = prefCategory.CreateEntry(config.Name, config.Value, null, config.Description, config.IsInternal, false);
|
||||||
|
new EntryDelegateWrapper<T>(entry, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void SetConfigValue<T>(ConfigElement<T> config, T value)
|
public override void SetConfigValue<T>(ConfigElement<T> config, T value)
|
||||||
|
@ -18,26 +18,43 @@ namespace UnityExplorer
|
|||||||
public class ExplorerStandalone : IExplorerLoader
|
public class ExplorerStandalone : IExplorerLoader
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Call this to initialize UnityExplorer without adding a log listener.
|
/// Call this to initialize UnityExplorer without adding a log listener or Unhollowed modules path.
|
||||||
|
/// The default Unhollowed path "UnityExplorer\Modules\" will be used.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The new (or active, if one exists) instance of ExplorerStandalone.</returns>
|
/// <returns>The new (or active, if one exists) instance of ExplorerStandalone.</returns>
|
||||||
public static ExplorerStandalone CreateInstance() => CreateInstance(null);
|
public static ExplorerStandalone CreateInstance() => CreateInstance(null, null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Call this to initialize UnityExplorer and add a listener for UnityExplorer's log messages.
|
/// Call this to initialize UnityExplorer and add a listener for UnityExplorer's log messages, without specifying an Unhollowed modules path.
|
||||||
|
/// The default Unhollowed path "UnityExplorer\Modules\" will be used.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="logListener">Your log listener to handle UnityExplorer logs.</param>
|
/// <param name="logListener">Your log listener to handle UnityExplorer logs.</param>
|
||||||
/// <returns>The new (or active, if one exists) instance of ExplorerStandalone.</returns>
|
/// <returns>The new (or active, if one exists) instance of ExplorerStandalone.</returns>
|
||||||
public static ExplorerStandalone CreateInstance(Action<string, LogType> logListener)
|
public static ExplorerStandalone CreateInstance(Action<string, LogType> logListener) => CreateInstance(logListener, null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call this to initialize UnityExplorer with the provided log listener and Unhollowed modules path.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="logListener">Your log listener to handle UnityExplorer logs.</param>
|
||||||
|
/// <param name="unhollowedModulesPath">The path of the Unhollowed modules, either relative or absolute.</param>
|
||||||
|
/// <returns>The new (or active, if one exists) instance of ExplorerStandalone.</returns>
|
||||||
|
public static ExplorerStandalone CreateInstance(Action<string, LogType> logListener, string unhollowedModulesPath)
|
||||||
{
|
{
|
||||||
if (Instance != null)
|
if (Instance != null)
|
||||||
return Instance;
|
return Instance;
|
||||||
|
|
||||||
|
var instance = new ExplorerStandalone();
|
||||||
|
instance.Init();
|
||||||
|
instance.CheckExplorerFolder();
|
||||||
|
|
||||||
if (logListener != null)
|
if (logListener != null)
|
||||||
OnLog += logListener;
|
OnLog += logListener;
|
||||||
|
|
||||||
var instance = new ExplorerStandalone();
|
if (string.IsNullOrEmpty(unhollowedModulesPath) || !Directory.Exists(unhollowedModulesPath))
|
||||||
instance.Init();
|
instance._unhollowedPath = Path.Combine(instance.ExplorerFolder, "Modules");
|
||||||
|
else
|
||||||
|
instance._unhollowedPath = unhollowedModulesPath;
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,6 +65,9 @@ namespace UnityExplorer
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static event Action<string, LogType> OnLog;
|
public static event Action<string, LogType> OnLog;
|
||||||
|
|
||||||
|
public string UnhollowedModulesFolder => _unhollowedPath;
|
||||||
|
private string _unhollowedPath;
|
||||||
|
|
||||||
public ConfigHandler ConfigHandler => _configHandler;
|
public ConfigHandler ConfigHandler => _configHandler;
|
||||||
private StandaloneConfigHandler _configHandler;
|
private StandaloneConfigHandler _configHandler;
|
||||||
|
|
||||||
|
@ -56,13 +56,7 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
else if (m_context == SearchContext.Class)
|
else if (m_context == SearchContext.Class)
|
||||||
currentResults = SearchProvider.ClassSearch(nameInputField.Text);
|
currentResults = SearchProvider.ClassSearch(nameInputField.Text);
|
||||||
else
|
else
|
||||||
{
|
currentResults = SearchProvider.UnityObjectSearch(nameInputField.Text, desiredTypeInput, m_context, m_childFilter, m_sceneFilter);
|
||||||
string compType = "";
|
|
||||||
if (m_context == SearchContext.UnityObject)
|
|
||||||
compType = this.desiredTypeInput;
|
|
||||||
|
|
||||||
currentResults = SearchProvider.UnityObjectSearch(nameInputField.Text, compType, m_context, m_childFilter, m_sceneFilter);
|
|
||||||
}
|
|
||||||
|
|
||||||
dataHandler.RefreshData();
|
dataHandler.RefreshData();
|
||||||
resultsScrollPool.Refresh(true);
|
resultsScrollPool.Refresh(true);
|
||||||
|
@ -40,14 +40,12 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The names of all scenes in the build settings, if they could be retrieved.
|
/// The names of all scenes in the build settings, if they could be retrieved.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static ReadOnlyCollection<string> AllSceneNames => new ReadOnlyCollection<string>(allScenesInBuild);
|
public static readonly List<string> AllSceneNames = new List<string>();
|
||||||
private static readonly List<string> allScenesInBuild = new List<string>();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether or not we successfuly retrieved the names of the scenes in the build settings.
|
/// Whether or not we successfuly retrieved the names of the scenes in the build settings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool WasAbleToGetScenesInBuild => gotAllScenesInBuild;
|
public static bool WasAbleToGetScenesInBuild { get; private set; }
|
||||||
private static bool gotAllScenesInBuild = true;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Invoked when the currently inspected Scene changes. The argument is the new scene.
|
/// Invoked when the currently inspected Scene changes. The argument is the new scene.
|
||||||
@ -97,12 +95,12 @@ namespace UnityExplorer.ObjectExplorer
|
|||||||
for (int i = 0; i < sceneCount; i++)
|
for (int i = 0; i < sceneCount; i++)
|
||||||
{
|
{
|
||||||
var scenePath = (string)method.Invoke(null, new object[] { i });
|
var scenePath = (string)method.Invoke(null, new object[] { i });
|
||||||
allScenesInBuild.Add(scenePath);
|
AllSceneNames.Add(scenePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
gotAllScenesInBuild = false;
|
WasAbleToGetScenesInBuild = false;
|
||||||
ExplorerCore.LogWarning($"Unable to generate list of all Scenes in the build: {ex}");
|
ExplorerCore.LogWarning($"Unable to generate list of all Scenes in the build: {ex}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -218,6 +218,7 @@
|
|||||||
<Compile Include="Core\Config\InternalConfigHandler.cs" />
|
<Compile Include="Core\Config\InternalConfigHandler.cs" />
|
||||||
<Compile Include="CacheObject\CacheConfigEntry.cs" />
|
<Compile Include="CacheObject\CacheConfigEntry.cs" />
|
||||||
<Compile Include="CacheObject\Views\CacheConfigCell.cs" />
|
<Compile Include="CacheObject\Views\CacheConfigCell.cs" />
|
||||||
|
<Compile Include="Core\Reflection\Patches.cs" />
|
||||||
<Compile Include="CSConsole\CSAutoCompleter.cs" />
|
<Compile Include="CSConsole\CSAutoCompleter.cs" />
|
||||||
<Compile Include="CSConsole\LexerBuilder.cs" />
|
<Compile Include="CSConsole\LexerBuilder.cs" />
|
||||||
<Compile Include="CSConsole\Lexers\CommentLexer.cs" />
|
<Compile Include="CSConsole\Lexers\CommentLexer.cs" />
|
||||||
|
Reference in New Issue
Block a user