mirror of
https://github.com/sinai-dev/UnityExplorer.git
synced 2025-06-23 08:53:05 +08:00
Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
d4dac58fc8 | |||
77b97cbe17 | |||
c6f0f34ac0 | |||
d1f4f74d32 | |||
f13068bf01 | |||
dfc288a101 |
15
README.md
15
README.md
@ -17,7 +17,6 @@
|
||||
- [Features](#features)
|
||||
- [How to install](#how-to-install)
|
||||
- [Mod Config](#mod-config)
|
||||
- [Mouse Control](#mouse-control)
|
||||
- [Building](#building)
|
||||
- [Credits](#credits)
|
||||
|
||||
@ -25,8 +24,9 @@
|
||||
|
||||
| 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) |
|
||||
| [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
|
||||
|
||||
@ -50,7 +50,7 @@
|
||||
0. Install [BepInEx](https://github.com/BepInEx/BepInEx) for your game.
|
||||
1. Download the UnityExplorer release for BepInEx IL2CPP or Mono above.
|
||||
2. Take the `UnityExplorer.BIE.___.dll` file and put it in `[GameFolder]\BepInEx\plugins\`
|
||||
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\unhollowed\base\` folder.
|
||||
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.
|
||||
|
||||
### MelonLoader
|
||||
|
||||
@ -58,6 +58,13 @@
|
||||
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.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
|
||||
|
||||
You can access the settings via the "Options" page of the main menu, or directly from the config at `Mods\UnityExplorer\config.ini` (generated after first launch).
|
||||
@ -88,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.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
@ -17,7 +17,7 @@ namespace UnityExplorer
|
||||
public class ExplorerCore
|
||||
{
|
||||
public const string NAME = "UnityExplorer";
|
||||
public const string VERSION = "3.1.7";
|
||||
public const string VERSION = "3.1.8";
|
||||
public const string AUTHOR = "Sinai";
|
||||
public const string GUID = "com.sinai.unityexplorer";
|
||||
|
||||
|
@ -101,8 +101,24 @@ namespace UnityExplorer.Helpers
|
||||
return Il2CppToMonoType[cppType];
|
||||
|
||||
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>();
|
||||
|
@ -229,13 +229,9 @@ namespace UnityExplorer.Inspectors.Reflection
|
||||
|
||||
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();
|
||||
if (fullnametemp.StartsWith("Il2CppSystem"))
|
||||
|
@ -153,7 +153,7 @@ namespace UnityExplorer.UI.Modules
|
||||
{
|
||||
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))
|
||||
name += $": {unityObj.name}";
|
||||
@ -301,8 +301,8 @@ namespace UnityExplorer.UI.Modules
|
||||
|
||||
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
// All non-static classes
|
||||
foreach (var type in asm.TryGetTypes().Where(it => !it.IsSealed && !it.IsAbstract))
|
||||
// Search all non-static, non-enum classes.
|
||||
foreach (var type in asm.TryGetTypes().Where(it => !(it.IsSealed && it.IsAbstract) && !it.IsEnum))
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -336,7 +336,7 @@ namespace UnityExplorer.UI.Modules
|
||||
if (instance != null)
|
||||
{
|
||||
instances.Add(instance);
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,8 @@ namespace UnityExplorer.UI.Shared
|
||||
this.sliderScroller = sliderScroller;
|
||||
this.inputField = inputField;
|
||||
|
||||
sliderScroller.m_parentInputScroller = this;
|
||||
|
||||
inputField.onValueChanged.AddListener(OnTextChanged);
|
||||
|
||||
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)
|
||||
{
|
||||
m_lastText = text;
|
||||
|
@ -8,150 +8,154 @@ using UnityExplorer;
|
||||
using UnityExplorer.Helpers;
|
||||
using UnityExplorer.UI;
|
||||
|
||||
// Basically just to fix an issue with Scrollbars, instead we use a Slider as the scrollbar.
|
||||
public class SliderScrollbar
|
||||
namespace UnityExplorer.UI.Shared
|
||||
{
|
||||
internal static readonly List<SliderScrollbar> Instances = new List<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)
|
||||
// Basically just to fix an issue with Scrollbars, instead we use a Slider as the scrollbar.
|
||||
public class SliderScrollbar
|
||||
{
|
||||
Instances.Add(this);
|
||||
internal static readonly List<SliderScrollbar> Instances = new List<SliderScrollbar>();
|
||||
|
||||
this.m_scrollbar = scrollbar;
|
||||
this.m_slider = slider;
|
||||
this.m_scrollRect = scrollbar.transform.parent.GetComponent<RectTransform>();
|
||||
public bool IsActive { get; private set; }
|
||||
|
||||
this.m_scrollbar.onValueChanged.AddListener(this.OnScrollbarValueChanged);
|
||||
this.m_slider.onValueChanged.AddListener(this.OnSliderValueChanged);
|
||||
internal readonly Scrollbar m_scrollbar;
|
||||
internal readonly Slider m_slider;
|
||||
internal readonly RectTransform m_scrollRect;
|
||||
|
||||
this.RefreshVisibility();
|
||||
this.m_slider.Set(1f, false);
|
||||
}
|
||||
internal InputFieldScroller m_parentInputScroller;
|
||||
|
||||
internal bool CheckDestroyed()
|
||||
{
|
||||
if (!m_slider || !m_scrollbar)
|
||||
public SliderScrollbar(Scrollbar scrollbar, Slider slider)
|
||||
{
|
||||
Instances.Remove(this);
|
||||
return true;
|
||||
Instances.Add(this);
|
||||
|
||||
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 void Update()
|
||||
{
|
||||
this.RefreshVisibility();
|
||||
}
|
||||
|
||||
internal void RefreshVisibility()
|
||||
{
|
||||
if (!m_slider.gameObject.activeInHierarchy)
|
||||
internal bool CheckDestroyed()
|
||||
{
|
||||
IsActive = false;
|
||||
return;
|
||||
if (!m_slider || !m_scrollbar)
|
||||
{
|
||||
Instances.Remove(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool shouldShow = !Mathf.Approximately(this.m_scrollbar.size, 1);
|
||||
var obj = this.m_slider.handleRect.gameObject;
|
||||
|
||||
if (IsActive != shouldShow)
|
||||
internal void Update()
|
||||
{
|
||||
IsActive = shouldShow;
|
||||
obj.SetActive(IsActive);
|
||||
|
||||
if (IsActive)
|
||||
this.m_slider.Set(this.m_scrollbar.value, false);
|
||||
else
|
||||
m_slider.Set(1f, false);
|
||||
this.RefreshVisibility();
|
||||
}
|
||||
|
||||
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
|
||||
public static class SliderExtensions
|
||||
{
|
||||
@ -175,4 +179,5 @@ public static class SliderExtensions
|
||||
SetMethod.Invoke(slider, new object[] { value, invokeCallback });
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
@ -81,7 +81,7 @@ namespace UnityExplorer.UI
|
||||
{
|
||||
var input = InputFieldScroller.Instances[i];
|
||||
|
||||
if (input.sliderScroller.CheckDestroyed())
|
||||
if (input.CheckDestroyed())
|
||||
i--;
|
||||
else
|
||||
input.Update();
|
||||
|
Reference in New Issue
Block a user