Compare commits

..

10 Commits

Author SHA1 Message Date
995e2a3e93 3.1.11: fix potential crash on scene reload 2021-03-03 22:09:14 +11:00
2c95fec646 3.1.10: Add "Hide on startup" config option 2021-02-27 17:04:47 +11:00
69912d7ea4 Prevent GC Mark Overflow on C# Console copy+paste 2021-02-26 17:54:00 +11:00
9c5596ace4 Update lib versions 2021-02-26 17:52:21 +11:00
d4dac58fc8 Fix for deobfuscated unhollowed types not being properly resolved 2021-02-20 19:39:19 +11:00
77b97cbe17 Update README.md 2021-02-03 18:31:29 +11:00
c6f0f34ac0 Update README.md 2021-01-28 02:09:40 +11:00
d1f4f74d32 some ui cleanups (minor) 2021-01-22 21:56:00 +11:00
f13068bf01 Update README.md 2021-01-20 23:05:04 +11:00
dfc288a101 Update README.md 2021-01-20 19:10:13 +11:00
17 changed files with 325 additions and 268 deletions

View File

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -32,7 +32,7 @@ namespace UnityExplorer.CSConsole
private Text inputHighlightText;
private readonly CSharpLexer highlightLexer;
private readonly StringBuilder sbHighlight;
//private readonly StringBuilder sbHighlight;
internal int m_lastCaretPos;
internal int m_fixCaretPos;
@ -68,7 +68,6 @@ The following helper methods are available:
public CodeEditor()
{
sbHighlight = new StringBuilder();
highlightLexer = new CSharpLexer();
ConstructUI();
@ -76,8 +75,24 @@ The following helper methods are available:
InputField.onValueChanged.AddListener((string s) => { OnInputChanged(s); });
}
internal static bool IsUserCopyPasting()
{
return (InputManager.GetKey(KeyCode.LeftControl) || InputManager.GetKey(KeyCode.RightControl))
&& InputManager.GetKeyDown(KeyCode.V);
}
public void Update()
{
if (s_copyPasteBuffer != null)
{
if (!IsUserCopyPasting())
{
OnInputChanged(s_copyPasteBuffer);
s_copyPasteBuffer = null;
}
}
if (EnableCtrlRShortcut)
{
if ((InputManager.GetKey(KeyCode.LeftControl) || InputManager.GetKey(KeyCode.RightControl))
@ -149,11 +164,18 @@ The following helper methods are available:
AutoCompleter.ClearAutocompletes();
}
public void OnInputChanged(string newInput, bool forceUpdate = false)
{
string newText = newInput;
internal static string s_copyPasteBuffer;
UpdateIndent(newInput);
public void OnInputChanged(string newText, bool forceUpdate = false)
{
if (IsUserCopyPasting())
{
//Console.WriteLine("Copy+Paste detected!");
s_copyPasteBuffer = newText;
return;
}
UpdateIndent(newText);
if (!forceUpdate && string.IsNullOrEmpty(newText))
inputHighlightText.text = string.Empty;
@ -203,35 +225,29 @@ The following helper methods are available:
{
int offset = 0;
sbHighlight.Length = 0;
//Console.WriteLine("Highlighting input text:\r\n" + inputText);
string ret = "";
foreach (LexerMatchInfo match in highlightLexer.GetMatches(inputText))
{
for (int i = offset; i < match.startIndex; i++)
{
sbHighlight.Append(inputText[i]);
}
ret += inputText[i];
sbHighlight.Append($"{match.htmlColor}");
ret += $"{match.htmlColor}";
for (int i = match.startIndex; i < match.endIndex; i++)
{
sbHighlight.Append(inputText[i]);
}
ret += inputText[i];
sbHighlight.Append(CLOSE_COLOR_TAG);
ret += CLOSE_COLOR_TAG;
offset = match.endIndex;
}
for (int i = offset; i < inputText.Length; i++)
{
sbHighlight.Append(inputText[i]);
}
ret += inputText[i];
inputText = sbHighlight.ToString();
return inputText;
return ret;
}
private void AutoIndentCaret()

View File

@ -24,7 +24,8 @@ namespace UnityExplorer.Config
public int Default_Page_Limit = 25;
public string Default_Output_Path = ExplorerCore.EXPLORER_FOLDER + @"\Output";
public bool Log_Unity_Debug = false;
public bool Save_Logs_To_Disk = true;
public bool Hide_On_Startup = false;
//public bool Save_Logs_To_Disk = true;
public static event Action OnConfigChanged;
@ -56,24 +57,27 @@ namespace UnityExplorer.Config
{
switch (config.KeyName)
{
case "Main_Menu_Toggle":
case nameof(Main_Menu_Toggle):
Instance.Main_Menu_Toggle = (KeyCode)Enum.Parse(typeof(KeyCode), config.Value);
break;
case "Force_Unlock_Mouse":
case nameof(Force_Unlock_Mouse):
Instance.Force_Unlock_Mouse = bool.Parse(config.Value);
break;
case "Default_Page_Limit":
case nameof(Default_Page_Limit):
Instance.Default_Page_Limit = int.Parse(config.Value);
break;
case "Log_Unity_Debug":
case nameof(Log_Unity_Debug):
Instance.Log_Unity_Debug = bool.Parse(config.Value);
break;
case "Save_Logs_To_Disk":
Instance.Save_Logs_To_Disk = bool.Parse(config.Value);
break;
case "Default_Output_Path":
case nameof(Default_Output_Path):
Instance.Default_Output_Path = config.Value;
break;
case nameof(Hide_On_Startup):
Instance.Hide_On_Startup = bool.Parse(config.Value);
break;
//case nameof(Save_Logs_To_Disk):
// Instance.Save_Logs_To_Disk = bool.Parse(config.Value);
// break;
}
}
@ -87,12 +91,13 @@ namespace UnityExplorer.Config
data.Sections.AddSection("Config");
var sec = data.Sections["Config"];
sec.AddKey("Main_Menu_Toggle", Instance.Main_Menu_Toggle.ToString());
sec.AddKey("Force_Unlock_Mouse", Instance.Force_Unlock_Mouse.ToString());
sec.AddKey("Default_Page_Limit", Instance.Default_Page_Limit.ToString());
sec.AddKey("Log_Unity_Debug", Instance.Log_Unity_Debug.ToString());
sec.AddKey("Save_Logs_To_Disk", Instance.Save_Logs_To_Disk.ToString());
sec.AddKey("Default_Output_Path", Instance.Default_Output_Path);
sec.AddKey(nameof(Main_Menu_Toggle), Instance.Main_Menu_Toggle.ToString());
sec.AddKey(nameof(Force_Unlock_Mouse), Instance.Force_Unlock_Mouse.ToString());
sec.AddKey(nameof(Default_Page_Limit), Instance.Default_Page_Limit.ToString());
sec.AddKey(nameof(Log_Unity_Debug), Instance.Log_Unity_Debug.ToString());
sec.AddKey(nameof(Default_Output_Path), Instance.Default_Output_Path);
sec.AddKey(nameof(Hide_On_Startup), Instance.Hide_On_Startup.ToString());
//sec.AddKey("Save_Logs_To_Disk", Instance.Save_Logs_To_Disk.ToString());
File.WriteAllText(INI_PATH, data.ToString());
}

View File

@ -4,27 +4,25 @@ using System.Reflection;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityExplorer.Config;
using UnityExplorer.Helpers;
using UnityExplorer.Input;
using UnityExplorer.Inspectors;
using UnityExplorer.UI;
using UnityExplorer.UI.Modules;
#if CPP
using UnityExplorer.Helpers;
#endif
namespace UnityExplorer
{
public class ExplorerCore
{
public const string NAME = "UnityExplorer";
public const string VERSION = "3.1.7";
public const string VERSION = "3.1.11";
public const string AUTHOR = "Sinai";
public const string GUID = "com.sinai.unityexplorer";
#if ML
public const string EXPLORER_FOLDER = @"Mods\UnityExplorer";
public static string EXPLORER_FOLDER = Path.Combine("Mods", NAME);
#elif BIE
public static string EXPLORER_FOLDER = Path.Combine(BepInEx.Paths.ConfigPath, "UnityExplorer");
public static string EXPLORER_FOLDER = Path.Combine(BepInEx.Paths.ConfigPath, NAME);
#elif STANDALONE
public static string EXPLORER_FOLDER
{
@ -112,6 +110,10 @@ namespace UnityExplorer
{
UIManager.Init();
Log("Initialized UnityExplorer UI.");
if (ModConfig.Instance.Hide_On_Startup)
ShowMenu = false;
// InspectorManager.Instance.Inspect(Tests.TestClass.Instance);
}
catch (Exception e)

View File

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

View File

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

View File

@ -55,16 +55,15 @@ namespace UnityExplorer.Inspectors
{
get
{
if (!m_dontDestroyObject)
if (!s_dontDestroyObject)
{
m_dontDestroyObject = new GameObject("DontDestroyMe");
GameObject.DontDestroyOnLoad(m_dontDestroyObject);
s_dontDestroyObject = new GameObject("DontDestroyMe");
GameObject.DontDestroyOnLoad(s_dontDestroyObject);
}
return m_dontDestroyObject;
return s_dontDestroyObject;
}
}
internal static GameObject m_dontDestroyObject;
internal static GameObject s_dontDestroyObject;
public void Init()
{
@ -97,22 +96,6 @@ namespace UnityExplorer.Inspectors
}
}
//#if CPP
// public int GetSceneHandle(string sceneName)
// {
// if (sceneName == "DontDestroyOnLoad")
// return DontDestroyScene;
// for (int i = 0; i < SceneManager.sceneCount; i++)
// {
// var scene = SceneManager.GetSceneAt(i);
// if (scene.name == sceneName)
// return scene.handle;
// }
// return -1;
// }
//#endif
internal void OnSceneChange()
{
m_sceneDropdown.OnCancel(null);
@ -121,8 +104,13 @@ namespace UnityExplorer.Inspectors
private void RefreshSceneSelector()
{
var names = new List<string>();
var scenes = new List<Scene>();
var newNames = new List<string>();
var newScenes = new List<Scene>();
if (m_currentScenes == null)
m_currentScenes = new Scene[0];
bool anyChange = SceneManager.sceneCount != m_currentScenes.Length - 1;
for (int i = 0; i < SceneManager.sceneCount; i++)
{
@ -131,33 +119,32 @@ namespace UnityExplorer.Inspectors
if (scene == default)
continue;
scenes.Add(scene);
names.Add(scene.name);
if (!anyChange && !m_currentScenes.Any(it => it.GetHandle() == scene.GetHandle()))
anyChange = true;
newScenes.Add(scene);
newNames.Add(scene.name);
}
names.Add("DontDestroyOnLoad");
scenes.Add(DontDestroyScene);
newNames.Add("DontDestroyOnLoad");
newScenes.Add(DontDestroyScene);
m_sceneDropdown.options.Clear();
foreach (string scene in names)
foreach (string scene in newNames)
{
m_sceneDropdown.options.Add(new Dropdown.OptionData { text = scene });
}
if (!names.Contains(m_sceneDropdownText.text))
if (anyChange)
{
m_sceneDropdownText.text = names[0];
SetTargetScene(scenes[0]);
m_sceneDropdownText.text = newNames[0];
SetTargetScene(newScenes[0]);
}
m_currentScenes = scenes.ToArray();
m_currentScenes = newScenes.ToArray();
}
//#if CPP
// public void SetTargetScene(string name) => SetTargetScene(scene.handle);
//#endif
public void SetTargetScene(Scene scene)
{
if (scene == default)
@ -167,7 +154,7 @@ namespace UnityExplorer.Inspectors
#if CPP
GameObject[] rootObjs = SceneUnstrip.GetRootGameObjects(scene.handle);
#else
GameObject[] rootObjs = SceneUnstrip.GetRootGameObjects(scene);
GameObject[] rootObjs = scene.GetRootGameObjects();
#endif
SetSceneObjectList(rootObjs);

View File

@ -16,7 +16,7 @@ namespace UnityExplorer.UI.Modules
public static DebugConsole Instance { get; private set; }
public static bool LogUnity { get; set; } = ModConfig.Instance.Log_Unity_Debug;
public static bool SaveToDisk { get; set; } = ModConfig.Instance.Save_Logs_To_Disk;
//public static bool SaveToDisk { get; set; } = ModConfig.Instance.Save_Logs_To_Disk;
internal static StreamWriter s_streamWriter;
@ -49,8 +49,8 @@ namespace UnityExplorer.UI.Modules
// set up IO
if (!SaveToDisk)
return;
//if (!SaveToDisk)
// return;
var path = ExplorerCore.EXPLORER_FOLDER + @"\Logs";

View File

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
//using TMPro;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.Config;
@ -19,6 +18,7 @@ namespace UnityExplorer.UI.Modules
private Toggle m_unlockMouseToggle;
private InputField m_pageLimitInput;
private InputField m_defaultOutputInput;
private Toggle m_hideOnStartupToggle;
public override void Init()
{
@ -27,26 +27,21 @@ namespace UnityExplorer.UI.Modules
public override void Update()
{
// not needed?
}
internal void OnApply()
{
if (!string.IsNullOrEmpty(m_keycodeInput.text) && Enum.Parse(typeof(KeyCode), m_keycodeInput.text) is KeyCode keyCode)
{
ModConfig.Instance.Main_Menu_Toggle = keyCode;
}
ModConfig.Instance.Force_Unlock_Mouse = m_unlockMouseToggle.isOn;
if (!string.IsNullOrEmpty(m_pageLimitInput.text) && int.TryParse(m_pageLimitInput.text, out int lim))
{
ModConfig.Instance.Default_Page_Limit = lim;
}
ModConfig.Instance.Default_Output_Path = m_defaultOutputInput.text;
// todo default output path
ModConfig.Instance.Hide_On_Startup = m_hideOnStartupToggle.isOn;
ModConfig.SaveSettings();
ModConfig.InvokeConfigChanged();
@ -98,6 +93,7 @@ namespace UnityExplorer.UI.Modules
ConstructMouseUnlockOpt(optionsGroupObj);
ConstructPageLimitOpt(optionsGroupObj);
ConstructOutputPathOpt(optionsGroupObj);
ConstructHideOnStartupOpt(optionsGroupObj);
var applyBtnObj = UIFactory.CreateButton(Content, new Color(0.2f, 0.2f, 0.2f));
var applyText = applyBtnObj.GetComponentInChildren<Text>();
@ -113,10 +109,34 @@ namespace UnityExplorer.UI.Modules
applyBtn.onClick.AddListener(OnApply);
}
private void ConstructHideOnStartupOpt(GameObject optionsGroupObj)
{
var rowObj = UIFactory.CreateHorizontalGroup(optionsGroupObj, new Color(1, 1, 1, 0));
var rowGroup = rowObj.GetComponent<HorizontalLayoutGroup>();
rowGroup.childControlWidth = true;
rowGroup.childForceExpandWidth = false;
rowGroup.childControlHeight = true;
rowGroup.childForceExpandHeight = true;
var groupLayout = rowObj.AddComponent<LayoutElement>();
groupLayout.minHeight = 25;
groupLayout.flexibleHeight = 0;
groupLayout.minWidth = 200;
groupLayout.flexibleWidth = 1000;
var labelObj = UIFactory.CreateLabel(rowObj, TextAnchor.MiddleLeft);
var labelText = labelObj.GetComponent<Text>();
labelText.text = "Hide UI on startup:";
var labelLayout = labelObj.AddComponent<LayoutElement>();
labelLayout.minWidth = 150;
labelLayout.minHeight = 25;
UIFactory.CreateToggle(rowObj, out m_hideOnStartupToggle, out Text toggleText);
m_hideOnStartupToggle.isOn = ModConfig.Instance.Hide_On_Startup;
toggleText.text = "";
}
internal void ConstructKeycodeOpt(GameObject parent)
{
//public KeyCode Main_Menu_Toggle = KeyCode.F7;
var rowObj = UIFactory.CreateHorizontalGroup(parent, new Color(1, 1, 1, 0));
var rowGroup = rowObj.GetComponent<HorizontalLayoutGroup>();
rowGroup.childControlWidth = true;
@ -146,8 +166,6 @@ namespace UnityExplorer.UI.Modules
internal void ConstructMouseUnlockOpt(GameObject parent)
{
//public bool Force_Unlock_Mouse = true;
var rowObj = UIFactory.CreateHorizontalGroup(parent, new Color(1, 1, 1, 0));
var rowGroup = rowObj.GetComponent<HorizontalLayoutGroup>();
rowGroup.childControlWidth = true;

View File

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

View File

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

View File

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

View File

@ -81,7 +81,7 @@ namespace UnityExplorer.UI
{
var input = InputFieldScroller.Instances[i];
if (input.sliderScroller.CheckDestroyed())
if (input.CheckDestroyed())
i--;
else
input.Update();

View File

@ -3,36 +3,25 @@ using UnityExplorer.Helpers;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityExplorer.Inspectors;
using System.Reflection;
namespace UnityExplorer.Unstrip
{
public class SceneUnstrip
public static class SceneUnstrip
{
#if MONO
public static GameObject[] GetRootGameObjects(Scene scene) => scene.GetRootGameObjects();
//public static GameObject[] GetRootGameObjects(int handle)
//{
// Scene scene = default;
// if (handle == SceneExplorer.DontDestroyHandle)
// scene = SceneExplorer.DontDestroyObject.scene;
// else
// {
// for (int i = 0; i < SceneManager.sceneCount; i++)
// {
// var iscene = SceneManager.GetSceneAt(i);
// if (iscene.handle == handle)
// scene = iscene;
// }
// }
// if (scene != default && scene.handle != -1)
// return scene.GetRootGameObjects();
// return new GameObject[0];
//}
private static readonly FieldInfo fi_Scene_handle = typeof(Scene).GetField("m_Handle", ReflectionHelpers.CommonFlags);
#endif
public static int GetHandle(this Scene scene)
{
#if CPP
return scene.handle;
#else
return (int)fi_Scene_handle.GetValue(scene);
#endif
}
#if CPP
//Scene.GetRootGameObjects();
@ -43,13 +32,16 @@ namespace UnityExplorer.Unstrip
public static GameObject[] GetRootGameObjects(int handle)
{
if (handle == -1)
{
return new GameObject[0];
}
Il2CppSystem.Collections.Generic.List<GameObject> list = new Il2CppSystem.Collections.Generic.List<GameObject>(GetRootCount(handle));
int count = GetRootCount(handle);
d_GetRootGameObjects iCall = ICallHelper.GetICall<d_GetRootGameObjects>("UnityEngine.SceneManagement.Scene::GetRootGameObjectsInternal");
if (count < 1)
return new GameObject[0];
var list = new Il2CppSystem.Collections.Generic.List<GameObject>(count);
var iCall = ICallHelper.GetICall<d_GetRootGameObjects>("UnityEngine.SceneManagement.Scene::GetRootGameObjectsInternal");
iCall.Invoke(handle, list.Pointer);
@ -58,14 +50,14 @@ namespace UnityExplorer.Unstrip
//Scene.rootCount;
internal delegate int GetRootCountInternal_delegate(int handle);
internal delegate int d_GetRootCountInternal(int handle);
public static int GetRootCount(Scene scene) => GetRootCount(scene.handle);
public static int GetRootCount(int handle)
{
GetRootCountInternal_delegate iCall = ICallHelper.GetICall<GetRootCountInternal_delegate>("UnityEngine.SceneManagement.Scene::GetRootCountInternal");
return iCall.Invoke(handle);
return ICallHelper.GetICall<d_GetRootCountInternal>("UnityEngine.SceneManagement.Scene::GetRootCountInternal")
.Invoke(handle);
}
#endif
}