mirror of
https://github.com/sinai-dev/UnityExplorer.git
synced 2025-06-23 08:53:05 +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)
|
||||
{
|
||||
matchEndIdx++;
|
||||
if (IsNewLine(input[matchEndIdx]))
|
||||
break;
|
||||
matchEndIdx++;
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
}
|
||||
|
||||
// Append trailing unhighlighted input
|
||||
|
@ -12,11 +12,11 @@ namespace UnityExplorer.CacheObject
|
||||
public CacheConfigEntry(IConfigElement configElement)
|
||||
{
|
||||
this.RefConfigElement = configElement;
|
||||
this.FallbackType = configElement.ElementType;
|
||||
|
||||
this.NameLabelText = $"<color=cyan>{configElement.Name}</color>" +
|
||||
$"\r\n<color=grey><i>{configElement.Description}</i></color>";
|
||||
|
||||
this.FallbackType = configElement.ElementType;
|
||||
this.NameLabelTextRaw = string.Empty;
|
||||
|
||||
configElement.OnValueChangedNotify += UpdateValueFromSource;
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ namespace UnityExplorer.CacheObject
|
||||
var kvpCell = cell as CacheKeyValuePairCell;
|
||||
|
||||
kvpCell.NameLabel.text = $"{DictIndex}:";
|
||||
kvpCell.HiddenNameLabel.Text = "";
|
||||
kvpCell.Image.color = DictIndex % 2 == 0 ? CacheListEntryCell.EvenColor : CacheListEntryCell.OddColor;
|
||||
|
||||
if (KeyInputWanted)
|
||||
|
@ -28,6 +28,7 @@ namespace UnityExplorer.CacheObject
|
||||
var listCell = cell as CacheListEntryCell;
|
||||
|
||||
listCell.NameLabel.text = $"{ListIndex}:";
|
||||
listCell.HiddenNameLabel.Text = "";
|
||||
listCell.Image.color = ListIndex % 2 == 0 ? CacheListEntryCell.EvenColor : CacheListEntryCell.OddColor;
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@ namespace UnityExplorer.CacheObject
|
||||
this.Owner = inspector;
|
||||
this.NameLabelText = SignatureHighlighter.Parse(member.DeclaringType, false, member);
|
||||
this.NameForFiltering = $"{member.DeclaringType.Name}.{member.Name}";
|
||||
this.NameLabelTextRaw = NameForFiltering;
|
||||
}
|
||||
|
||||
public override void ReleasePooledObjects()
|
||||
|
@ -30,15 +30,14 @@ namespace UnityExplorer.CacheObject
|
||||
try
|
||||
{
|
||||
var methodInfo = MethodInfo;
|
||||
|
||||
if (methodInfo.IsGenericMethod)
|
||||
methodInfo = MethodInfo.MakeGenericMethod(Evaluator.TryParseGenericArguments());
|
||||
|
||||
if (Arguments.Length > 0)
|
||||
return methodInfo.Invoke(DeclaringInstance, Evaluator.TryParseArguments());
|
||||
|
||||
var ret = methodInfo.Invoke(DeclaringInstance, ArgumentUtility.EmptyArgs);
|
||||
|
||||
object ret;
|
||||
if (HasArguments)
|
||||
ret = methodInfo.Invoke(DeclaringInstance, Evaluator.TryParseArguments());
|
||||
else
|
||||
ret = methodInfo.Invoke(DeclaringInstance, ArgumentUtility.EmptyArgs);
|
||||
HadException = false;
|
||||
LastException = null;
|
||||
return ret;
|
||||
|
@ -47,6 +47,7 @@ namespace UnityExplorer.CacheObject
|
||||
public bool SubContentShowWanted { get; private set; }
|
||||
|
||||
public string NameLabelText { get; protected set; }
|
||||
public string NameLabelTextRaw { get; protected set; }
|
||||
public string ValueLabelText { get; protected set; }
|
||||
|
||||
public abstract bool ShouldAutoEvaluate { get; }
|
||||
@ -260,6 +261,8 @@ namespace UnityExplorer.CacheObject
|
||||
public virtual void SetDataToCell(CacheObjectCell cell)
|
||||
{
|
||||
cell.NameLabel.text = NameLabelText;
|
||||
if (cell.HiddenNameLabel != null)
|
||||
cell.HiddenNameLabel.Text = NameLabelTextRaw;
|
||||
cell.ValueLabel.gameObject.SetActive(true);
|
||||
|
||||
cell.SubContentHolder.gameObject.SetActive(SubContentShowWanted);
|
||||
|
@ -45,6 +45,7 @@ namespace UnityExplorer.CacheObject.Views
|
||||
public LayoutElement RightGroupLayout;
|
||||
|
||||
public Text NameLabel;
|
||||
public InputFieldRef HiddenNameLabel;
|
||||
public Text TypeLabel;
|
||||
public Text ValueLabel;
|
||||
public Toggle Toggle;
|
||||
@ -116,8 +117,19 @@ namespace UnityExplorer.CacheObject.Views
|
||||
|
||||
NameLabel = UIFactory.CreateLabel(horiRow, "NameLabel", "<notset>", TextAnchor.MiddleLeft);
|
||||
NameLabel.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||||
UIFactory.SetLayoutElement(NameLabel.gameObject, minHeight: 25, minWidth: 20, flexibleHeight: 300, flexibleWidth: 0);
|
||||
NameLayout = NameLabel.GetComponent<LayoutElement>();
|
||||
NameLayout = UIFactory.SetLayoutElement(NameLabel.gameObject, minHeight: 25, minWidth: 20, flexibleHeight: 300, flexibleWidth: 0);
|
||||
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
|
||||
|
||||
|
@ -134,6 +134,9 @@ namespace UnityExplorer
|
||||
var type = obj.GetType();
|
||||
try
|
||||
{
|
||||
if (type.IsGenericType)
|
||||
return type;
|
||||
|
||||
if (IsString(obj))
|
||||
return typeof(string);
|
||||
|
||||
@ -178,7 +181,8 @@ namespace UnityExplorer
|
||||
if (fullname.StartsWith("System."))
|
||||
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;
|
||||
}
|
||||
|
||||
@ -477,59 +481,38 @@ namespace UnityExplorer
|
||||
|
||||
#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.
|
||||
|
||||
// Force loading all il2cpp modules
|
||||
|
||||
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 files)
|
||||
{
|
||||
try
|
||||
{
|
||||
DoLoadModule(filePath, true);
|
||||
}
|
||||
catch //(Exception ex)
|
||||
{
|
||||
//ExplorerCore.LogWarning($"Failed to force-load module '{name}': {ex.ReflectionExToString()}");
|
||||
}
|
||||
}
|
||||
foreach (var filePath in Directory.GetFiles(dir, "*.dll"))
|
||||
DoLoadModule(filePath);
|
||||
}
|
||||
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;
|
||||
|
||||
try
|
||||
{
|
||||
Assembly.LoadFile(fullPath);
|
||||
//Assembly.Load(File.ReadAllBytes(fullPath));
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
catch //(Exception e)
|
||||
{
|
||||
if (!suppressWarning)
|
||||
Console.WriteLine($"Failed loading module '{Path.GetFileName(fullPath)}'! {e.ReflectionExToString()}");
|
||||
//ExplorerCore.LogWarning($"Failed loading module '{Path.GetFileName(fullPath)}'! {e.ReflectionExToString()}");
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#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();
|
||||
#endif
|
||||
Instance.Initialize();
|
||||
|
||||
ReflectionPatches.Init();
|
||||
}
|
||||
|
||||
protected virtual void Initialize()
|
||||
|
@ -98,15 +98,17 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||
|
||||
internal delegate IntPtr d_FindObjectsOfTypeAll(IntPtr type);
|
||||
|
||||
internal static readonly string[] findObjectsOfTypeAllSignatures = new[]
|
||||
{
|
||||
"UnityEngine.Resources::FindObjectsOfTypeAll",
|
||||
"UnityEngine.ResourcesAPIInternal::FindObjectsOfTypeAll" // Unity 2020+ updated to this
|
||||
};
|
||||
|
||||
public override UnityEngine.Object[] FindObjectsOfTypeAll(Type type)
|
||||
{
|
||||
var iCall = ICallManager.GetICallUnreliable<d_FindObjectsOfTypeAll>(new[]
|
||||
{
|
||||
"UnityEngine.Resources::FindObjectsOfTypeAll",
|
||||
"UnityEngine.ResourcesAPIInternal::FindObjectsOfTypeAll" // Unity 2020+ updated to this
|
||||
});
|
||||
|
||||
return new Il2CppReferenceArray<UnityEngine.Object>(iCall.Invoke(Il2CppType.From(type).Pointer));
|
||||
return new Il2CppReferenceArray<UnityEngine.Object>(
|
||||
ICallManager.GetICallUnreliable<d_FindObjectsOfTypeAll>(findObjectsOfTypeAllSignatures)
|
||||
.Invoke(Il2CppType.From(type).Pointer));
|
||||
}
|
||||
|
||||
// Scene.GetRootGameObjects();
|
||||
|
@ -118,7 +118,7 @@ namespace UnityExplorer.Tests
|
||||
|
||||
ExplorerCore.Log($"5: Big list");
|
||||
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");
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ namespace UnityExplorer
|
||||
public static class ExplorerCore
|
||||
{
|
||||
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 GUID = "com.sinai.unityexplorer";
|
||||
|
||||
|
@ -8,20 +8,10 @@
|
||||
<InputAssemblies Include="..\lib\mcs-unity\mcs\bin\Release\mcs.dll" />
|
||||
<InputAssemblies Include="packages\ini-parser.2.5.2\lib\net20\INIFileParser.dll" />
|
||||
</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 -->
|
||||
<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.Mono\" />
|
||||
<ReferenceFolders Include="..\lib\BepInEx.5\" />
|
||||
|
@ -47,6 +47,7 @@ namespace UnityExplorer.Inspectors
|
||||
|
||||
public ScrollPool<CacheMemberCell> MemberScrollPool { get; private set; }
|
||||
|
||||
public InputFieldRef HiddenNameText;
|
||||
public Text NameText;
|
||||
public Text AssemblyText;
|
||||
private Toggle autoUpdateToggle;
|
||||
@ -125,6 +126,7 @@ namespace UnityExplorer.Inspectors
|
||||
currentBaseTabText = $"{prefix} {SignatureHighlighter.Parse(TargetType, false)}";
|
||||
Tab.TabText.text = currentBaseTabText;
|
||||
NameText.text = SignatureHighlighter.Parse(TargetType, true);
|
||||
HiddenNameText.Text = TargetType.FullName;
|
||||
|
||||
string asmText;
|
||||
if (TargetType.Assembly is AssemblyBuilder || string.IsNullOrEmpty(TargetType.Assembly.Location))
|
||||
@ -332,8 +334,27 @@ namespace UnityExplorer.Inspectors
|
||||
|
||||
// Class name, assembly
|
||||
|
||||
NameText = UIFactory.CreateLabel(UIRoot, "Title", "not set", TextAnchor.MiddleLeft, fontSize: 17);
|
||||
UIFactory.SetLayoutElement(NameText.gameObject, minHeight: 25, flexibleHeight: 0);
|
||||
var titleHolder = UIFactory.CreateUIObject("TitleHolder", UIRoot);
|
||||
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);
|
||||
UIFactory.SetLayoutElement(AssemblyText.gameObject, minHeight: 25, flexibleWidth: 9999);
|
||||
|
@ -39,6 +39,8 @@ namespace UnityExplorer
|
||||
=> Log;
|
||||
#endif
|
||||
|
||||
public string UnhollowedModulesFolder => Path.Combine(Paths.BepInExRootPath, "unhollowed");
|
||||
|
||||
public ConfigHandler ConfigHandler => _configHandler;
|
||||
private BepInExConfigHandler _configHandler;
|
||||
|
||||
|
@ -9,6 +9,7 @@ namespace UnityExplorer
|
||||
public interface IExplorerLoader
|
||||
{
|
||||
string ExplorerFolder { get; }
|
||||
string UnhollowedModulesFolder { get; }
|
||||
|
||||
ConfigHandler ConfigHandler { get; }
|
||||
|
||||
|
@ -24,6 +24,10 @@ namespace UnityExplorer
|
||||
|
||||
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 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);
|
||||
|
||||
entry.OnValueChangedUntyped += () =>
|
||||
public MelonPreferences_Entry<T> entry;
|
||||
public ConfigElement<T> config;
|
||||
|
||||
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))
|
||||
return;
|
||||
|
||||
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)
|
||||
|
@ -18,26 +18,43 @@ namespace UnityExplorer
|
||||
public class ExplorerStandalone : IExplorerLoader
|
||||
{
|
||||
/// <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>
|
||||
/// <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>
|
||||
/// 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>
|
||||
/// <param name="logListener">Your log listener to handle UnityExplorer logs.</param>
|
||||
/// <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)
|
||||
return Instance;
|
||||
|
||||
var instance = new ExplorerStandalone();
|
||||
instance.Init();
|
||||
instance.CheckExplorerFolder();
|
||||
|
||||
if (logListener != null)
|
||||
OnLog += logListener;
|
||||
|
||||
var instance = new ExplorerStandalone();
|
||||
instance.Init();
|
||||
if (string.IsNullOrEmpty(unhollowedModulesPath) || !Directory.Exists(unhollowedModulesPath))
|
||||
instance._unhollowedPath = Path.Combine(instance.ExplorerFolder, "Modules");
|
||||
else
|
||||
instance._unhollowedPath = unhollowedModulesPath;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
@ -48,6 +65,9 @@ namespace UnityExplorer
|
||||
/// </summary>
|
||||
public static event Action<string, LogType> OnLog;
|
||||
|
||||
public string UnhollowedModulesFolder => _unhollowedPath;
|
||||
private string _unhollowedPath;
|
||||
|
||||
public ConfigHandler ConfigHandler => _configHandler;
|
||||
private StandaloneConfigHandler _configHandler;
|
||||
|
||||
|
@ -56,13 +56,7 @@ namespace UnityExplorer.ObjectExplorer
|
||||
else if (m_context == SearchContext.Class)
|
||||
currentResults = SearchProvider.ClassSearch(nameInputField.Text);
|
||||
else
|
||||
{
|
||||
string compType = "";
|
||||
if (m_context == SearchContext.UnityObject)
|
||||
compType = this.desiredTypeInput;
|
||||
|
||||
currentResults = SearchProvider.UnityObjectSearch(nameInputField.Text, compType, m_context, m_childFilter, m_sceneFilter);
|
||||
}
|
||||
currentResults = SearchProvider.UnityObjectSearch(nameInputField.Text, desiredTypeInput, m_context, m_childFilter, m_sceneFilter);
|
||||
|
||||
dataHandler.RefreshData();
|
||||
resultsScrollPool.Refresh(true);
|
||||
|
@ -40,14 +40,12 @@ namespace UnityExplorer.ObjectExplorer
|
||||
/// <summary>
|
||||
/// The names of all scenes in the build settings, if they could be retrieved.
|
||||
/// </summary>
|
||||
public static ReadOnlyCollection<string> AllSceneNames => new ReadOnlyCollection<string>(allScenesInBuild);
|
||||
private static readonly List<string> allScenesInBuild = new List<string>();
|
||||
public static readonly List<string> AllSceneNames = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not we successfuly retrieved the names of the scenes in the build settings.
|
||||
/// </summary>
|
||||
public static bool WasAbleToGetScenesInBuild => gotAllScenesInBuild;
|
||||
private static bool gotAllScenesInBuild = true;
|
||||
public static bool WasAbleToGetScenesInBuild { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 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++)
|
||||
{
|
||||
var scenePath = (string)method.Invoke(null, new object[] { i });
|
||||
allScenesInBuild.Add(scenePath);
|
||||
AllSceneNames.Add(scenePath);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
gotAllScenesInBuild = false;
|
||||
WasAbleToGetScenesInBuild = false;
|
||||
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="CacheObject\CacheConfigEntry.cs" />
|
||||
<Compile Include="CacheObject\Views\CacheConfigCell.cs" />
|
||||
<Compile Include="Core\Reflection\Patches.cs" />
|
||||
<Compile Include="CSConsole\CSAutoCompleter.cs" />
|
||||
<Compile Include="CSConsole\LexerBuilder.cs" />
|
||||
<Compile Include="CSConsole\Lexers\CommentLexer.cs" />
|
||||
|
Reference in New Issue
Block a user