Compare commits

..

18 Commits
4.2.0 ... 4.2.1

25 changed files with 201 additions and 93 deletions

Binary file not shown.

View File

@ -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

View File

@ -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;
} }

View File

@ -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)

View File

@ -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;
} }

View File

@ -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()

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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

View 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;
}
}
}

View File

@ -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()

View File

@ -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();

View File

@ -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");
} }

View File

@ -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";

View File

@ -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\" />

View File

@ -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);

View File

@ -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;

View File

@ -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; }

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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);

View File

@ -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}");
} }
} }

View File

@ -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" />