mirror of
https://github.com/sinai-dev/UnityExplorer.git
synced 2025-06-23 17:02:36 +08:00
Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
0432c6d56c | |||
8c34aa2be5 | |||
4a1c54fac1 | |||
190467fa5c | |||
44f54d9190 | |||
3b4ea31b50 | |||
ad7b05f721 | |||
852ca8e9eb | |||
7386eca0c2 | |||
97325a5f3a | |||
82e52de557 | |||
28181e2266 | |||
6dfa4806ce | |||
27f6a6ca52 |
10
README.md
10
README.md
@ -28,9 +28,6 @@
|
|||||||
| [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) |
|
| [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) |
|
| [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) |
|
||||||
|
|
||||||
<b>IL2CPP Issues:</b>
|
|
||||||
* Some methods may still fail with a `MissingMethodException`, please let me know if you experience this (with full debug log please).
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
@ -52,15 +49,14 @@
|
|||||||
|
|
||||||
0. Install [BepInEx](https://github.com/BepInEx/BepInEx) for your game.
|
0. Install [BepInEx](https://github.com/BepInEx/BepInEx) for your game.
|
||||||
1. Download the UnityExplorer release for BepInEx IL2CPP or Mono above.
|
1. Download the UnityExplorer release for BepInEx IL2CPP or Mono above.
|
||||||
2. Take the `UnityExplorer.dll` file and put it in `[GameFolder]\BepInEx\plugins\`
|
2. Take the `UnityExplorer.BIE.___.dll` file and put it in `[GameFolder]\BepInEx\plugins\`
|
||||||
3. Take the `UnityExplorer\` folder (with `explorerui.bundle`) and put it in `[GameFolder]\Mods\`, so it looks like `[GameFolder]\Mods\UnityExplorer\explorerui.bundle`.
|
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.
|
||||||
4. 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.
|
|
||||||
|
|
||||||
### MelonLoader
|
### MelonLoader
|
||||||
|
|
||||||
0. Install [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) for your game.
|
0. Install [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) for your game.
|
||||||
1. Download the UnityExplorer release for MelonLoader IL2CPP or Mono above.
|
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.dll` and `[GameFolder]\Mods\UnityExplorer\explorerui.bundle`.
|
2. Take the contents of the release and put it in the `[GameFolder]\Mods\` folder. It should look like `[GameFolder]\Mods\UnityExplorer.ML.___.dll`
|
||||||
|
|
||||||
## Mod Config
|
## Mod Config
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ namespace UnityExplorer.Config
|
|||||||
public static ModConfig Instance;
|
public static ModConfig Instance;
|
||||||
|
|
||||||
internal static readonly IniDataParser _parser = new IniDataParser();
|
internal static readonly IniDataParser _parser = new IniDataParser();
|
||||||
internal const string INI_PATH = ExplorerCore.EXPLORER_FOLDER + @"\config.ini";
|
internal static readonly string INI_PATH = Path.Combine(ExplorerCore.EXPLORER_FOLDER, "config.ini");
|
||||||
|
|
||||||
static ModConfig()
|
static ModConfig()
|
||||||
{
|
{
|
||||||
@ -22,7 +22,7 @@ namespace UnityExplorer.Config
|
|||||||
public KeyCode Main_Menu_Toggle = KeyCode.F7;
|
public KeyCode Main_Menu_Toggle = KeyCode.F7;
|
||||||
public bool Force_Unlock_Mouse = true;
|
public bool Force_Unlock_Mouse = true;
|
||||||
public int Default_Page_Limit = 25;
|
public int Default_Page_Limit = 25;
|
||||||
public string Default_Output_Path = ExplorerCore.EXPLORER_FOLDER;
|
public string Default_Output_Path = ExplorerCore.EXPLORER_FOLDER + @"\Output";
|
||||||
public bool Log_Unity_Debug = false;
|
public bool Log_Unity_Debug = false;
|
||||||
public bool Save_Logs_To_Disk = true;
|
public bool Save_Logs_To_Disk = true;
|
||||||
|
|
||||||
|
@ -16,10 +16,15 @@ namespace UnityExplorer
|
|||||||
public class ExplorerCore
|
public class ExplorerCore
|
||||||
{
|
{
|
||||||
public const string NAME = "UnityExplorer";
|
public const string NAME = "UnityExplorer";
|
||||||
public const string VERSION = "3.0.6";
|
public const string VERSION = "3.1.5";
|
||||||
public const string AUTHOR = "Sinai";
|
public const string AUTHOR = "Sinai";
|
||||||
public const string GUID = "com.sinai.unityexplorer";
|
public const string GUID = "com.sinai.unityexplorer";
|
||||||
|
|
||||||
|
#if ML
|
||||||
public const string EXPLORER_FOLDER = @"Mods\UnityExplorer";
|
public const string EXPLORER_FOLDER = @"Mods\UnityExplorer";
|
||||||
|
#elif BIE
|
||||||
|
public static string EXPLORER_FOLDER = Path.Combine(BepInEx.Paths.ConfigPath, "UnityExplorer");
|
||||||
|
#endif
|
||||||
|
|
||||||
public static ExplorerCore Instance { get; private set; }
|
public static ExplorerCore Instance { get; private set; }
|
||||||
|
|
||||||
|
@ -15,6 +15,16 @@ namespace UnityExplorer.Helpers
|
|||||||
private static MethodInfo EncodeToPNGMethod => m_encodeToPNGMethod ?? GetEncodeToPNGMethod();
|
private static MethodInfo EncodeToPNGMethod => m_encodeToPNGMethod ?? GetEncodeToPNGMethod();
|
||||||
private static MethodInfo m_encodeToPNGMethod;
|
private static MethodInfo m_encodeToPNGMethod;
|
||||||
|
|
||||||
|
public static byte[] EncodeToPNGSafe(this Texture2D tex)
|
||||||
|
{
|
||||||
|
var method = EncodeToPNGMethod;
|
||||||
|
|
||||||
|
if (method.IsStatic)
|
||||||
|
return (byte[])method.Invoke(null, new object[] { tex });
|
||||||
|
else
|
||||||
|
return (byte[])method.Invoke(tex, new object[0]);
|
||||||
|
}
|
||||||
|
|
||||||
private static MethodInfo GetEncodeToPNGMethod()
|
private static MethodInfo GetEncodeToPNGMethod()
|
||||||
{
|
{
|
||||||
if (ReflectionHelpers.GetTypeByName("UnityEngine.ImageConversion") is Type imageConversion)
|
if (ReflectionHelpers.GetTypeByName("UnityEngine.ImageConversion") is Type imageConversion)
|
||||||
@ -60,7 +70,12 @@ namespace UnityExplorer.Helpers
|
|||||||
|
|
||||||
pixels = orig.GetPixels((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height);
|
pixels = orig.GetPixels((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height);
|
||||||
|
|
||||||
|
// use full constructor for better compatibility
|
||||||
|
#if CPP
|
||||||
|
var _newTex = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGBA32, Texture.GenerateAllMips, false, IntPtr.Zero);
|
||||||
|
#else
|
||||||
var _newTex = new Texture2D((int)rect.width, (int)rect.height);
|
var _newTex = new Texture2D((int)rect.width, (int)rect.height);
|
||||||
|
#endif
|
||||||
_newTex.SetPixels(pixels);
|
_newTex.SetPixels(pixels);
|
||||||
|
|
||||||
return _newTex;
|
return _newTex;
|
||||||
|
@ -111,8 +111,11 @@ namespace UnityExplorer.Inspectors.GameObjects
|
|||||||
internal static void OnCompToggleClicked(int index, bool value)
|
internal static void OnCompToggleClicked(int index, bool value)
|
||||||
{
|
{
|
||||||
var comp = s_compShortlist[index];
|
var comp = s_compShortlist[index];
|
||||||
|
#if CPP
|
||||||
|
comp.TryCast<Behaviour>().enabled = value;
|
||||||
|
#else
|
||||||
(comp as Behaviour).enabled = value;
|
(comp as Behaviour).enabled = value;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void OnCompListObjectClicked(int index)
|
internal static void OnCompListObjectClicked(int index)
|
||||||
|
@ -109,21 +109,12 @@ namespace UnityExplorer.Inspectors
|
|||||||
internal static void RaycastWorld(Vector2 mousePos)
|
internal static void RaycastWorld(Vector2 mousePos)
|
||||||
{
|
{
|
||||||
var ray = UnityHelpers.MainCamera.ScreenPointToRay(mousePos);
|
var ray = UnityHelpers.MainCamera.ScreenPointToRay(mousePos);
|
||||||
var casts = Physics.RaycastAll(ray, 1000f);
|
Physics.Raycast(ray, out RaycastHit hit, 1000f);
|
||||||
|
|
||||||
if (casts.Length > 0)
|
if (hit.transform)
|
||||||
{
|
{
|
||||||
foreach (var cast in casts)
|
var obj = hit.transform.gameObject;
|
||||||
{
|
OnHitGameObject(obj);
|
||||||
if (cast.transform)
|
|
||||||
{
|
|
||||||
var obj = cast.transform.gameObject;
|
|
||||||
|
|
||||||
OnHitGameObject(obj);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -4,6 +4,8 @@ using UnityEngine;
|
|||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Helpers;
|
||||||
using UnityExplorer.UI;
|
using UnityExplorer.UI;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
using UnityExplorer.Unstrip;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
namespace UnityExplorer.Inspectors.Reflection
|
namespace UnityExplorer.Inspectors.Reflection
|
||||||
{
|
{
|
||||||
@ -70,8 +72,8 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
|
|
||||||
// WIP
|
// WIP
|
||||||
|
|
||||||
//if (m_targetType == typeof(Texture2D))
|
if (m_targetType == typeof(Texture2D))
|
||||||
// ConstructTextureHelper();
|
ConstructTextureHelper();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void ConstructCompHelper(GameObject rowObj)
|
internal void ConstructCompHelper(GameObject rowObj)
|
||||||
@ -136,94 +138,176 @@ namespace UnityExplorer.Inspectors.Reflection
|
|||||||
//btn.onClick.AddListener(() => { InspectorManager.Instance.Inspect(comp.gameObject); });
|
//btn.onClick.AddListener(() => { InspectorManager.Instance.Inspect(comp.gameObject); });
|
||||||
}
|
}
|
||||||
|
|
||||||
//internal bool showingTextureHelper;
|
internal bool showingTextureHelper;
|
||||||
//internal bool constructedTextureViewer;
|
internal bool constructedTextureViewer;
|
||||||
|
|
||||||
//internal void ConstructTextureHelper()
|
internal GameObject m_textureViewerObj;
|
||||||
//{
|
|
||||||
// var rowObj = UIFactory.CreateHorizontalGroup(Content, new Color(0.1f, 0.1f, 0.1f));
|
|
||||||
// var rowLayout = rowObj.AddComponent<LayoutElement>();
|
|
||||||
// rowLayout.minHeight = 25;
|
|
||||||
// rowLayout.flexibleHeight = 0;
|
|
||||||
// var rowGroup = rowObj.GetComponent<HorizontalLayoutGroup>();
|
|
||||||
// rowGroup.childForceExpandHeight = true;
|
|
||||||
// rowGroup.childForceExpandWidth = false;
|
|
||||||
// rowGroup.padding.top = 3;
|
|
||||||
// rowGroup.padding.left = 3;
|
|
||||||
// rowGroup.padding.bottom = 3;
|
|
||||||
// rowGroup.padding.right = 3;
|
|
||||||
// rowGroup.spacing = 5;
|
|
||||||
|
|
||||||
// var showBtnObj = UIFactory.CreateButton(rowObj, new Color(0.2f, 0.2f, 0.2f));
|
internal void ConstructTextureHelper()
|
||||||
// var showBtnLayout = showBtnObj.AddComponent<LayoutElement>();
|
{
|
||||||
// showBtnLayout.minWidth = 50;
|
var rowObj = UIFactory.CreateHorizontalGroup(Content, new Color(0.1f, 0.1f, 0.1f));
|
||||||
// showBtnLayout.flexibleWidth = 0;
|
var rowLayout = rowObj.AddComponent<LayoutElement>();
|
||||||
// var showText = showBtnObj.GetComponentInChildren<Text>();
|
rowLayout.minHeight = 25;
|
||||||
// showText.text = "Show";
|
rowLayout.flexibleHeight = 0;
|
||||||
// var showBtn = showBtnObj.GetComponent<Button>();
|
var rowGroup = rowObj.GetComponent<HorizontalLayoutGroup>();
|
||||||
|
rowGroup.childForceExpandHeight = true;
|
||||||
|
rowGroup.childForceExpandWidth = false;
|
||||||
|
rowGroup.padding.top = 3;
|
||||||
|
rowGroup.padding.left = 3;
|
||||||
|
rowGroup.padding.bottom = 3;
|
||||||
|
rowGroup.padding.right = 3;
|
||||||
|
rowGroup.spacing = 5;
|
||||||
|
|
||||||
// var labelObj = UIFactory.CreateLabel(rowObj, TextAnchor.MiddleLeft);
|
var showBtnObj = UIFactory.CreateButton(rowObj, new Color(0.2f, 0.6f, 0.2f));
|
||||||
// var labelText = labelObj.GetComponent<Text>();
|
var showBtnLayout = showBtnObj.AddComponent<LayoutElement>();
|
||||||
// labelText.text = "Texture Viewer";
|
showBtnLayout.minWidth = 50;
|
||||||
|
showBtnLayout.flexibleWidth = 0;
|
||||||
|
var showText = showBtnObj.GetComponentInChildren<Text>();
|
||||||
|
showText.text = "Show";
|
||||||
|
var showBtn = showBtnObj.GetComponent<Button>();
|
||||||
|
|
||||||
// var textureViewerObj = UIFactory.CreateScrollView(Content, out GameObject scrollContent, out _, new Color(0.1f, 0.1f, 0.1f));
|
var labelObj = UIFactory.CreateLabel(rowObj, TextAnchor.MiddleLeft);
|
||||||
// var viewerGroup = scrollContent.GetComponent<VerticalLayoutGroup>();
|
var labelText = labelObj.GetComponent<Text>();
|
||||||
// viewerGroup.childForceExpandHeight = false;
|
labelText.text = "Texture Viewer";
|
||||||
// viewerGroup.childForceExpandWidth = false;
|
|
||||||
// viewerGroup.childControlHeight = true;
|
|
||||||
// viewerGroup.childControlWidth = true;
|
|
||||||
// var mainLayout = textureViewerObj.GetComponent<LayoutElement>();
|
|
||||||
// mainLayout.flexibleHeight = -1;
|
|
||||||
// mainLayout.flexibleWidth = 2000;
|
|
||||||
// mainLayout.minHeight = 25;
|
|
||||||
|
|
||||||
// textureViewerObj.SetActive(false);
|
var textureViewerObj = UIFactory.CreateScrollView(Content, out GameObject scrollContent, out _, new Color(0.1f, 0.1f, 0.1f));
|
||||||
|
var viewerGroup = scrollContent.GetComponent<VerticalLayoutGroup>();
|
||||||
|
viewerGroup.childForceExpandHeight = false;
|
||||||
|
viewerGroup.childForceExpandWidth = false;
|
||||||
|
viewerGroup.childControlHeight = true;
|
||||||
|
viewerGroup.childControlWidth = true;
|
||||||
|
var mainLayout = textureViewerObj.GetComponent<LayoutElement>();
|
||||||
|
mainLayout.flexibleHeight = 9999;
|
||||||
|
mainLayout.flexibleWidth = 9999;
|
||||||
|
mainLayout.minHeight = 100;
|
||||||
|
|
||||||
// showBtn.onClick.AddListener(() =>
|
textureViewerObj.SetActive(false);
|
||||||
// {
|
|
||||||
// showingTextureHelper = !showingTextureHelper;
|
|
||||||
|
|
||||||
// if (showingTextureHelper)
|
m_textureViewerObj = textureViewerObj;
|
||||||
// {
|
|
||||||
// if (!constructedTextureViewer)
|
|
||||||
// ConstructTextureViewerArea(scrollContent);
|
|
||||||
|
|
||||||
// showText.text = "Hide";
|
showBtn.onClick.AddListener(() =>
|
||||||
// textureViewerObj.SetActive(true);
|
{
|
||||||
// }
|
showingTextureHelper = !showingTextureHelper;
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// showText.text = "Show";
|
|
||||||
// textureViewerObj.SetActive(false);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
//}
|
|
||||||
|
|
||||||
//internal void ConstructTextureViewerArea(GameObject parent)
|
if (showingTextureHelper)
|
||||||
//{
|
{
|
||||||
// constructedTextureViewer = true;
|
if (!constructedTextureViewer)
|
||||||
|
ConstructTextureViewerArea(scrollContent);
|
||||||
|
|
||||||
// var tex = Target as Texture2D;
|
showText.text = "Hide";
|
||||||
|
ToggleTextureViewer(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
showText.text = "Show";
|
||||||
|
ToggleTextureViewer(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// if (!tex)
|
internal void ConstructTextureViewerArea(GameObject parent)
|
||||||
// {
|
{
|
||||||
// ExplorerCore.LogWarning("Could not cast the target instance to Texture2D!");
|
constructedTextureViewer = true;
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// var imageObj = UIFactory.CreateUIObject("TextureViewerImage", parent, new Vector2(1, 1));
|
var tex = Target as Texture2D;
|
||||||
// var image = imageObj.AddComponent<Image>();
|
#if CPP
|
||||||
// var sprite = UIManager.CreateSprite(tex);
|
if (!tex)
|
||||||
// image.sprite = sprite;
|
tex = (Target as Il2CppSystem.Object).TryCast<Texture2D>();
|
||||||
|
#endif
|
||||||
|
|
||||||
// var fitter = imageObj.AddComponent<ContentSizeFitter>();
|
if (!tex)
|
||||||
// fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
{
|
||||||
// //fitter.horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
|
ExplorerCore.LogWarning("Could not cast the target instance to Texture2D! Maybe its null or destroyed?");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// var imageLayout = imageObj.AddComponent<LayoutElement>();
|
// Save helper
|
||||||
// imageLayout.preferredHeight = sprite.rect.height;
|
|
||||||
// imageLayout.preferredWidth = sprite.rect.width;
|
var saveRowObj = UIFactory.CreateHorizontalGroup(parent, new Color(0.1f, 0.1f, 0.1f));
|
||||||
//}
|
var saveRow = saveRowObj.GetComponent<HorizontalLayoutGroup>();
|
||||||
|
saveRow.childForceExpandHeight = true;
|
||||||
|
saveRow.childForceExpandWidth = true;
|
||||||
|
saveRow.padding = new RectOffset() { left = 2, bottom = 2, right = 2, top = 2 };
|
||||||
|
saveRow.spacing = 2;
|
||||||
|
|
||||||
|
var btnObj = UIFactory.CreateButton(saveRowObj, new Color(0.2f, 0.2f, 0.2f));
|
||||||
|
var btnLayout = btnObj.AddComponent<LayoutElement>();
|
||||||
|
btnLayout.minHeight = 25;
|
||||||
|
btnLayout.minWidth = 100;
|
||||||
|
btnLayout.flexibleWidth = 0;
|
||||||
|
var saveBtn = btnObj.GetComponent<Button>();
|
||||||
|
|
||||||
|
var saveBtnText = btnObj.GetComponentInChildren<Text>();
|
||||||
|
saveBtnText.text = "Save .PNG";
|
||||||
|
|
||||||
|
var inputObj = UIFactory.CreateInputField(saveRowObj);
|
||||||
|
var inputLayout = inputObj.AddComponent<LayoutElement>();
|
||||||
|
inputLayout.minHeight = 25;
|
||||||
|
inputLayout.minWidth = 100;
|
||||||
|
inputLayout.flexibleWidth = 9999;
|
||||||
|
var inputField = inputObj.GetComponent<InputField>();
|
||||||
|
|
||||||
|
var name = tex.name;
|
||||||
|
if (string.IsNullOrEmpty(name))
|
||||||
|
name = "untitled";
|
||||||
|
|
||||||
|
var savePath = $@"{Config.ModConfig.Instance.Default_Output_Path}\{name}.png";
|
||||||
|
inputField.text = savePath;
|
||||||
|
|
||||||
|
saveBtn.onClick.AddListener(() =>
|
||||||
|
{
|
||||||
|
if (tex && !string.IsNullOrEmpty(inputField.text))
|
||||||
|
{
|
||||||
|
var path = inputField.text;
|
||||||
|
if (!path.EndsWith(".png", StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning("Desired save path must end with '.png'!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var dir = Path.GetDirectoryName(path);
|
||||||
|
if (!Directory.Exists(dir))
|
||||||
|
Directory.CreateDirectory(dir);
|
||||||
|
|
||||||
|
if (File.Exists(path))
|
||||||
|
File.Delete(path);
|
||||||
|
|
||||||
|
if (!tex.IsReadable())
|
||||||
|
tex = Texture2DHelpers.ForceReadTexture(tex);
|
||||||
|
#if CPP
|
||||||
|
byte[] data = tex.EncodeToPNG();
|
||||||
|
#else
|
||||||
|
byte[] data = tex.EncodeToPNGSafe();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
File.WriteAllBytes(path, data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Actual texture viewer
|
||||||
|
|
||||||
|
var imageObj = UIFactory.CreateUIObject("TextureViewerImage", parent);
|
||||||
|
var image = imageObj.AddComponent<Image>();
|
||||||
|
var sprite = ImageConversionUnstrip.CreateSprite(tex);
|
||||||
|
image.sprite = sprite;
|
||||||
|
|
||||||
|
var fitter = imageObj.AddComponent<ContentSizeFitter>();
|
||||||
|
fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||||
|
//fitter.horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||||
|
|
||||||
|
var imageLayout = imageObj.AddComponent<LayoutElement>();
|
||||||
|
imageLayout.preferredHeight = sprite.rect.height;
|
||||||
|
imageLayout.preferredWidth = sprite.rect.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void ToggleTextureViewer(bool enabled)
|
||||||
|
{
|
||||||
|
m_textureViewerObj.SetActive(enabled);
|
||||||
|
|
||||||
|
m_filterAreaObj.SetActive(!enabled);
|
||||||
|
m_memberListObj.SetActive(!enabled);
|
||||||
|
m_updateRowObj.SetActive(!enabled);
|
||||||
|
}
|
||||||
|
|
||||||
public void ConstructInstanceFilters(GameObject parent)
|
public void ConstructInstanceFilters(GameObject parent)
|
||||||
{
|
{
|
||||||
|
@ -363,6 +363,10 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
#region UI CONSTRUCTION
|
#region UI CONSTRUCTION
|
||||||
|
|
||||||
|
internal GameObject m_filterAreaObj;
|
||||||
|
internal GameObject m_updateRowObj;
|
||||||
|
internal GameObject m_memberListObj;
|
||||||
|
|
||||||
internal void ConstructUI()
|
internal void ConstructUI()
|
||||||
{
|
{
|
||||||
var parent = InspectorManager.Instance.m_inspectorContent;
|
var parent = InspectorManager.Instance.m_inspectorContent;
|
||||||
@ -423,7 +427,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
|
|
||||||
ConstructFilterArea();
|
ConstructFilterArea();
|
||||||
|
|
||||||
ConstructOptionsArea();
|
ConstructUpdateRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void ConstructFilterArea()
|
internal void ConstructFilterArea()
|
||||||
@ -444,6 +448,8 @@ namespace UnityExplorer.Inspectors
|
|||||||
filterGroup.padding.top = 4;
|
filterGroup.padding.top = 4;
|
||||||
filterGroup.padding.bottom = 4;
|
filterGroup.padding.bottom = 4;
|
||||||
|
|
||||||
|
m_filterAreaObj = filterAreaObj;
|
||||||
|
|
||||||
// name filter
|
// name filter
|
||||||
|
|
||||||
var nameFilterRowObj = UIFactory.CreateHorizontalGroup(filterAreaObj, new Color(1, 1, 1, 0));
|
var nameFilterRowObj = UIFactory.CreateHorizontalGroup(filterAreaObj, new Color(1, 1, 1, 0));
|
||||||
@ -540,7 +546,7 @@ namespace UnityExplorer.Inspectors
|
|||||||
btn.colors = colors;
|
btn.colors = colors;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void ConstructOptionsArea()
|
internal void ConstructUpdateRow()
|
||||||
{
|
{
|
||||||
var optionsRowObj = UIFactory.CreateHorizontalGroup(Content, new Color(1, 1, 1, 0));
|
var optionsRowObj = UIFactory.CreateHorizontalGroup(Content, new Color(1, 1, 1, 0));
|
||||||
var optionsLayout = optionsRowObj.AddComponent<LayoutElement>();
|
var optionsLayout = optionsRowObj.AddComponent<LayoutElement>();
|
||||||
@ -551,6 +557,8 @@ namespace UnityExplorer.Inspectors
|
|||||||
optionsGroup.childAlignment = TextAnchor.MiddleLeft;
|
optionsGroup.childAlignment = TextAnchor.MiddleLeft;
|
||||||
optionsGroup.spacing = 10;
|
optionsGroup.spacing = 10;
|
||||||
|
|
||||||
|
m_updateRowObj = optionsRowObj;
|
||||||
|
|
||||||
// update button
|
// update button
|
||||||
|
|
||||||
var updateButtonObj = UIFactory.CreateButton(optionsRowObj, new Color(0.2f, 0.2f, 0.2f));
|
var updateButtonObj = UIFactory.CreateButton(optionsRowObj, new Color(0.2f, 0.2f, 0.2f));
|
||||||
@ -578,11 +586,12 @@ namespace UnityExplorer.Inspectors
|
|||||||
autoUpdateToggle.isOn = false;
|
autoUpdateToggle.isOn = false;
|
||||||
autoUpdateToggle.onValueChanged.AddListener((bool val) => { m_autoUpdate = val; });
|
autoUpdateToggle.onValueChanged.AddListener((bool val) => { m_autoUpdate = val; });
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void ConstructMemberList()
|
internal void ConstructMemberList()
|
||||||
{
|
{
|
||||||
var scrollobj = UIFactory.CreateScrollView(Content, out m_scrollContent, out m_sliderScroller, new Color(0.05f, 0.05f, 0.05f));
|
var scrollobj = UIFactory.CreateScrollView(Content, out m_scrollContent, out m_sliderScroller, new Color(0.05f, 0.05f, 0.05f));
|
||||||
|
|
||||||
|
m_memberListObj = scrollobj;
|
||||||
m_scrollContentRect = m_scrollContent.GetComponent<RectTransform>();
|
m_scrollContentRect = m_scrollContent.GetComponent<RectTransform>();
|
||||||
|
|
||||||
var scrollGroup = m_scrollContent.GetComponent<VerticalLayoutGroup>();
|
var scrollGroup = m_scrollContent.GetComponent<VerticalLayoutGroup>();
|
||||||
|
@ -5,6 +5,7 @@ using UnityEngine;
|
|||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using UnityExplorer.Unstrip;
|
||||||
#if CPP
|
#if CPP
|
||||||
using UnhollowerBaseLib;
|
using UnhollowerBaseLib;
|
||||||
using UnityExplorer.Helpers;
|
using UnityExplorer.Helpers;
|
||||||
@ -121,15 +122,15 @@ namespace UnityExplorer.Tests
|
|||||||
private static bool m_setOnlyProperty;
|
private static bool m_setOnlyProperty;
|
||||||
public static bool ReadSetOnlyProperty => m_setOnlyProperty;
|
public static bool ReadSetOnlyProperty => m_setOnlyProperty;
|
||||||
|
|
||||||
public Texture TestTexture;
|
public Texture2D TestTexture;
|
||||||
public static Sprite TestSprite;
|
public static Sprite TestSprite;
|
||||||
|
|
||||||
#if CPP
|
#if CPP
|
||||||
public static Il2CppSystem.Collections.Generic.HashSet<string> CppHashSetTest;
|
public static Il2CppSystem.Collections.Generic.HashSet<string> CppHashSetTest;
|
||||||
public static Il2CppSystem.Collections.Generic.List<string> CppStringTest;
|
public static Il2CppSystem.Collections.Generic.List<string> CppStringTest;
|
||||||
public static Il2CppSystem.Collections.IList CppIList;
|
public static Il2CppSystem.Collections.IList CppIList;
|
||||||
public static Il2CppSystem.Collections.Generic.Dictionary<string, string> CppDictTest;
|
//public static Il2CppSystem.Collections.Generic.Dictionary<string, string> CppDictTest;
|
||||||
public static Il2CppSystem.Collections.Generic.Dictionary<int, float> CppDictTest2;
|
//public static Il2CppSystem.Collections.Generic.Dictionary<int, float> CppDictTest2;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public TestClass()
|
public TestClass()
|
||||||
@ -156,35 +157,35 @@ namespace UnityExplorer.Tests
|
|||||||
CppStringTest.Add("1");
|
CppStringTest.Add("1");
|
||||||
CppStringTest.Add("2");
|
CppStringTest.Add("2");
|
||||||
|
|
||||||
CppDictTest = new Il2CppSystem.Collections.Generic.Dictionary<string, string>();
|
//CppDictTest = new Il2CppSystem.Collections.Generic.Dictionary<string, string>();
|
||||||
CppDictTest.Add("key1", "value1");
|
//CppDictTest.Add("key1", "value1");
|
||||||
CppDictTest.Add("key2", "value2");
|
//CppDictTest.Add("key2", "value2");
|
||||||
CppDictTest.Add("key3", "value3");
|
//CppDictTest.Add("key3", "value3");
|
||||||
|
|
||||||
CppDictTest2 = new Il2CppSystem.Collections.Generic.Dictionary<int, float>();
|
//CppDictTest2 = new Il2CppSystem.Collections.Generic.Dictionary<int, float>();
|
||||||
CppDictTest2.Add(0, 0.5f);
|
//CppDictTest2.Add(0, 0.5f);
|
||||||
CppDictTest2.Add(1, 0.5f);
|
//CppDictTest2.Add(1, 0.5f);
|
||||||
CppDictTest2.Add(2, 0.5f);
|
//CppDictTest2.Add(2, 0.5f);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TextureSpriteTest()
|
private void TextureSpriteTest()
|
||||||
{
|
{
|
||||||
//TestTexture = UIManager.MakeSolidTexture(Color.white, 1000, 600);
|
TestTexture = new Texture2D(32, 32, TextureFormat.ARGB32, false)
|
||||||
//TestTexture = new Texture();
|
{
|
||||||
//TestTexture.name = "TestTexture";
|
name = "TestTexture"
|
||||||
|
};
|
||||||
|
TestSprite = ImageConversionUnstrip.CreateSprite(TestTexture);
|
||||||
|
|
||||||
//var r = new Rect(0, 0, TestTexture.width, TestTexture.height);
|
GameObject.DontDestroyOnLoad(TestTexture);
|
||||||
//var v2 = Vector2.zero;
|
GameObject.DontDestroyOnLoad(TestSprite);
|
||||||
//var v4 = Vector4.zero;
|
|
||||||
//TestSprite = Sprite.CreateSprite_Injected((Texture2D)TestTexture, ref r, ref v2, 100f, 0u, SpriteMeshType.Tight, ref v4, false);
|
|
||||||
|
|
||||||
//GameObject.DontDestroyOnLoad(TestTexture);
|
// test loading a tex from file
|
||||||
//GameObject.DontDestroyOnLoad(TestSprite);
|
if (System.IO.File.Exists(@"D:\Downloads\test.png"))
|
||||||
|
{
|
||||||
//// test loading a tex from file
|
var dataToLoad = System.IO.File.ReadAllBytes(@"D:\Downloads\test.png");
|
||||||
//var dataToLoad = System.IO.File.ReadAllBytes(@"Mods\UnityExplorer\Tex_Nemundis_Nebula.png");
|
ExplorerCore.Log($"Tex load success: {TestTexture.LoadImage(dataToLoad, false)}");
|
||||||
//ExplorerCore.Log($"Tex load success: {TestTexture.LoadImage(dataToLoad, false)}");
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string TestRefInOutGeneric<T>(ref string arg0, in int arg1, out string arg2) where T : Component
|
public static string TestRefInOutGeneric<T>(ref string arg0, in int arg1, out string arg2) where T : Component
|
||||||
|
@ -87,12 +87,6 @@ namespace UnityExplorer.UI
|
|||||||
new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_set_visible))),
|
new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_set_visible))),
|
||||||
true);
|
true);
|
||||||
|
|
||||||
#if BIE
|
|
||||||
#if CPP
|
|
||||||
// temporarily disabling this patch in BepInEx il2cpp as it's causing a crash in some games.
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
TryPatch(typeof(EventSystem),
|
TryPatch(typeof(EventSystem),
|
||||||
"current",
|
"current",
|
||||||
new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_EventSystem_set_current))),
|
new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_EventSystem_set_current))),
|
||||||
@ -164,9 +158,22 @@ namespace UnityExplorer.UI
|
|||||||
|
|
||||||
public static void SetEventSystem()
|
public static void SetEventSystem()
|
||||||
{
|
{
|
||||||
|
// temp disabled for new InputSystem
|
||||||
if (InputManager.CurrentType == InputType.InputSystem)
|
if (InputManager.CurrentType == InputType.InputSystem)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Disable current event system object
|
||||||
|
if (m_lastEventSystem || EventSystem.current)
|
||||||
|
{
|
||||||
|
if (!m_lastEventSystem)
|
||||||
|
m_lastEventSystem = EventSystem.current;
|
||||||
|
|
||||||
|
//ExplorerCore.Log("Disabling current event system...");
|
||||||
|
m_lastEventSystem.enabled = false;
|
||||||
|
//m_lastEventSystem.gameObject.SetActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set to our current system
|
||||||
m_settingEventSystem = true;
|
m_settingEventSystem = true;
|
||||||
EventSystem.current = UIManager.EventSys;
|
EventSystem.current = UIManager.EventSys;
|
||||||
InputManager.ActivateUIModule();
|
InputManager.ActivateUIModule();
|
||||||
@ -180,6 +187,9 @@ namespace UnityExplorer.UI
|
|||||||
|
|
||||||
if (m_lastEventSystem)
|
if (m_lastEventSystem)
|
||||||
{
|
{
|
||||||
|
m_lastEventSystem.enabled = true;
|
||||||
|
//m_lastEventSystem.gameObject.SetActive(true);
|
||||||
|
|
||||||
m_settingEventSystem = true;
|
m_settingEventSystem = true;
|
||||||
EventSystem.current = m_lastEventSystem;
|
EventSystem.current = m_lastEventSystem;
|
||||||
m_lastInputModule?.ActivateModule();
|
m_lastInputModule?.ActivateModule();
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
//using TMPro;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.SceneManagement;
|
using UnityEngine.SceneManagement;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
@ -9,6 +8,7 @@ using UnityExplorer.Helpers;
|
|||||||
using UnityExplorer.Inspectors;
|
using UnityExplorer.Inspectors;
|
||||||
using UnityExplorer.UI.Shared;
|
using UnityExplorer.UI.Shared;
|
||||||
using UnityExplorer.Unstrip;
|
using UnityExplorer.Unstrip;
|
||||||
|
using System.Reflection;
|
||||||
#if CPP
|
#if CPP
|
||||||
using UnhollowerRuntimeLib;
|
using UnhollowerRuntimeLib;
|
||||||
#endif
|
#endif
|
||||||
@ -21,7 +21,7 @@ namespace UnityExplorer.UI.Modules
|
|||||||
GameObject,
|
GameObject,
|
||||||
Component,
|
Component,
|
||||||
Custom,
|
Custom,
|
||||||
Instance,
|
Singleton,
|
||||||
StaticClass
|
StaticClass
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,11 +46,14 @@ namespace UnityExplorer.UI.Modules
|
|||||||
|
|
||||||
public static SearchPage Instance;
|
public static SearchPage Instance;
|
||||||
|
|
||||||
|
internal SearchContext m_context;
|
||||||
|
private SceneFilter m_sceneFilter;
|
||||||
|
private ChildFilter m_childFilter;
|
||||||
|
|
||||||
// ui elements
|
// ui elements
|
||||||
|
|
||||||
private Text m_resultCountText;
|
private Text m_resultCountText;
|
||||||
|
|
||||||
internal SearchContext m_context;
|
|
||||||
private InputField m_customTypeInput;
|
private InputField m_customTypeInput;
|
||||||
|
|
||||||
private InputField m_nameInput;
|
private InputField m_nameInput;
|
||||||
@ -60,9 +63,6 @@ namespace UnityExplorer.UI.Modules
|
|||||||
|
|
||||||
private Dropdown m_sceneDropdown;
|
private Dropdown m_sceneDropdown;
|
||||||
private int m_lastSceneCount = -1;
|
private int m_lastSceneCount = -1;
|
||||||
private SceneFilter m_sceneFilter;
|
|
||||||
|
|
||||||
private ChildFilter m_childFilter;
|
|
||||||
|
|
||||||
private GameObject m_extraFilterRow;
|
private GameObject m_extraFilterRow;
|
||||||
|
|
||||||
@ -132,10 +132,9 @@ namespace UnityExplorer.UI.Modules
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
var obj = m_results[itemIndex];
|
var obj = m_results[itemIndex];
|
||||||
|
var unityObj = obj as UnityEngine.Object;
|
||||||
|
|
||||||
var uObj = obj as UnityEngine.Object;
|
if (obj == null || (unityObj != null && !unityObj))
|
||||||
|
|
||||||
if (obj == null || (uObj != null && !uObj))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (i >= m_resultShortList.Count)
|
if (i >= m_resultShortList.Count)
|
||||||
@ -150,17 +149,25 @@ namespace UnityExplorer.UI.Modules
|
|||||||
|
|
||||||
var text = m_resultListTexts[i];
|
var text = m_resultListTexts[i];
|
||||||
|
|
||||||
var name = $"<color={UISyntaxHighlight.Class_Instance}>{ReflectionHelpers.GetActualType(obj).Name}</color>";
|
if (m_context != SearchContext.StaticClass)
|
||||||
|
|
||||||
if (m_context != SearchContext.Instance && m_context != SearchContext.StaticClass)
|
|
||||||
{
|
{
|
||||||
if (uObj && !string.IsNullOrEmpty(uObj.name))
|
var name = UISyntaxHighlight.ParseFullSyntax(obj.GetActualType(), true);
|
||||||
name += $": {uObj.name}";
|
|
||||||
else
|
|
||||||
name += ": <i><color=grey>untitled</color></i>";
|
|
||||||
}
|
|
||||||
|
|
||||||
text.text = name;
|
if (unityObj && m_context != SearchContext.Singleton && m_context != SearchContext.StaticClass)
|
||||||
|
{
|
||||||
|
if (unityObj && !string.IsNullOrEmpty(unityObj.name))
|
||||||
|
name += $": {unityObj.name}";
|
||||||
|
else
|
||||||
|
name += ": <i><color=grey>untitled</color></i>";
|
||||||
|
}
|
||||||
|
|
||||||
|
text.text = name;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var type = obj as Type;
|
||||||
|
text.text = UISyntaxHighlight.ParseFullSyntax(type, true);
|
||||||
|
}
|
||||||
|
|
||||||
var label = text.transform.parent.parent.gameObject;
|
var label = text.transform.parent.parent.gameObject;
|
||||||
if (!label.activeSelf)
|
if (!label.activeSelf)
|
||||||
@ -222,14 +229,127 @@ namespace UnityExplorer.UI.Modules
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_sceneDropdown.transform.Find("Label").GetComponent<Text>().text = "Any";
|
m_sceneDropdown.transform.Find("Label").GetComponent<Text>().text = "Any";
|
||||||
|
m_sceneFilter = SceneFilter.Any;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ~~~~~ UI Callbacks ~~~~~
|
// ~~~~~ UI Callbacks ~~~~~
|
||||||
|
|
||||||
internal void OnUnitySearchClicked()
|
internal void OnSearchClicked()
|
||||||
{
|
{
|
||||||
m_resultListPageHandler.CurrentPage = 0;
|
m_resultListPageHandler.CurrentPage = 0;
|
||||||
|
|
||||||
|
if (m_context == SearchContext.StaticClass)
|
||||||
|
StaticClassSearch();
|
||||||
|
else if (m_context == SearchContext.Singleton)
|
||||||
|
SingletonSearch();
|
||||||
|
else
|
||||||
|
UnityObjectSearch();
|
||||||
|
|
||||||
|
RefreshResultList();
|
||||||
|
|
||||||
|
if (m_results.Length > 0)
|
||||||
|
m_resultCountText.text = $"{m_results.Length} Results";
|
||||||
|
else
|
||||||
|
m_resultCountText.text = "No results...";
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void StaticClassSearch()
|
||||||
|
{
|
||||||
|
var list = new List<Type>();
|
||||||
|
|
||||||
|
var nameFilter = "";
|
||||||
|
if (!string.IsNullOrEmpty(m_nameInput.text))
|
||||||
|
nameFilter = m_nameInput.text.ToLower();
|
||||||
|
|
||||||
|
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
||||||
|
{
|
||||||
|
foreach (var type in asm.TryGetTypes().Where(it => it.IsSealed && it.IsAbstract))
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(nameFilter) && !type.FullName.ToLower().Contains(nameFilter))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
list.Add(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_results = list.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal string[] s_instanceNames = new string[]
|
||||||
|
{
|
||||||
|
"m_instance",
|
||||||
|
"m_Instance",
|
||||||
|
"s_instance",
|
||||||
|
"s_Instance",
|
||||||
|
"_instance",
|
||||||
|
"_Instance",
|
||||||
|
"instance",
|
||||||
|
"Instance",
|
||||||
|
"<Instance>k__BackingField",
|
||||||
|
"<instance>k__BackingField",
|
||||||
|
};
|
||||||
|
|
||||||
|
private void SingletonSearch()
|
||||||
|
{
|
||||||
|
var instances = new List<object>();
|
||||||
|
|
||||||
|
var nameFilter = "";
|
||||||
|
if (!string.IsNullOrEmpty(m_nameInput.text))
|
||||||
|
nameFilter = m_nameInput.text.ToLower();
|
||||||
|
|
||||||
|
var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
|
||||||
|
|
||||||
|
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
||||||
|
{
|
||||||
|
// All non-static classes
|
||||||
|
foreach (var type in asm.TryGetTypes().Where(it => !it.IsSealed && !it.IsAbstract))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(nameFilter) && !type.FullName.ToLower().Contains(nameFilter))
|
||||||
|
continue;
|
||||||
|
#if CPP
|
||||||
|
// Only look for Properties in IL2CPP, not for Mono.
|
||||||
|
PropertyInfo pi;
|
||||||
|
foreach (var name in s_instanceNames)
|
||||||
|
{
|
||||||
|
pi = type.GetProperty(name, flags);
|
||||||
|
if (pi != null)
|
||||||
|
{
|
||||||
|
var instance = pi.GetValue(null, null);
|
||||||
|
if (instance != null)
|
||||||
|
{
|
||||||
|
instances.Add(instance);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// Look for a typical Instance backing field.
|
||||||
|
FieldInfo fi;
|
||||||
|
foreach (var name in s_instanceNames)
|
||||||
|
{
|
||||||
|
fi = type.GetField(name, flags);
|
||||||
|
if (fi != null)
|
||||||
|
{
|
||||||
|
var instance = fi.GetValue(null);
|
||||||
|
if (instance != null)
|
||||||
|
{
|
||||||
|
instances.Add(instance);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_results = instances.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void UnityObjectSearch()
|
||||||
|
{
|
||||||
Type searchType = null;
|
Type searchType = null;
|
||||||
switch (m_context)
|
switch (m_context)
|
||||||
{
|
{
|
||||||
@ -305,12 +425,12 @@ namespace UnityExplorer.UI.Modules
|
|||||||
: obj.TryCast<Component>().gameObject;
|
: obj.TryCast<Component>().gameObject;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!go)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// scene check
|
// scene check
|
||||||
if (m_sceneFilter != SceneFilter.Any)
|
if (m_sceneFilter != SceneFilter.Any)
|
||||||
{
|
{
|
||||||
|
if (!go)
|
||||||
|
continue;
|
||||||
|
|
||||||
switch (m_context)
|
switch (m_context)
|
||||||
{
|
{
|
||||||
case SearchContext.GameObject:
|
case SearchContext.GameObject:
|
||||||
@ -325,24 +445,23 @@ namespace UnityExplorer.UI.Modules
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// root object check (no parent)
|
if (m_childFilter != ChildFilter.Any)
|
||||||
if (m_childFilter == ChildFilter.HasParent && !go.transform.parent)
|
{
|
||||||
continue;
|
if (!go)
|
||||||
else if (m_childFilter == ChildFilter.RootObject && go.transform.parent)
|
continue;
|
||||||
continue;
|
|
||||||
|
// root object check (no parent)
|
||||||
|
if (m_childFilter == ChildFilter.HasParent && !go.transform.parent)
|
||||||
|
continue;
|
||||||
|
else if (m_childFilter == ChildFilter.RootObject && go.transform.parent)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
results.Add(obj);
|
results.Add(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_results = results.ToArray();
|
m_results = results.ToArray();
|
||||||
|
|
||||||
if (m_results.Length > 0)
|
|
||||||
m_resultCountText.text = $"{m_results.Length} Results";
|
|
||||||
else
|
|
||||||
m_resultCountText.text = "No results...";
|
|
||||||
|
|
||||||
RefreshResultList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnResultPageTurn()
|
private void OnResultPageTurn()
|
||||||
@ -490,6 +609,23 @@ namespace UnityExplorer.UI.Modules
|
|||||||
m_customTypeInput = customTypeObj.GetComponent<InputField>();
|
m_customTypeInput = customTypeObj.GetComponent<InputField>();
|
||||||
m_customTypeInput.placeholder.gameObject.GetComponent<Text>().text = "eg. UnityEngine.Texture2D, etc...";
|
m_customTypeInput.placeholder.gameObject.GetComponent<Text>().text = "eg. UnityEngine.Texture2D, etc...";
|
||||||
|
|
||||||
|
// static class and singleton buttons
|
||||||
|
|
||||||
|
var secondRow = UIFactory.CreateHorizontalGroup(optionsGroupObj, new Color(1, 1, 1, 0));
|
||||||
|
var secondGroup = secondRow.GetComponent<HorizontalLayoutGroup>();
|
||||||
|
secondGroup.childForceExpandWidth = false;
|
||||||
|
secondGroup.childForceExpandHeight = false;
|
||||||
|
secondGroup.spacing = 3;
|
||||||
|
var secondLayout = secondRow.AddComponent<LayoutElement>();
|
||||||
|
secondLayout.minHeight = 25;
|
||||||
|
var spacer = UIFactory.CreateUIObject("spacer", secondRow);
|
||||||
|
var spaceLayout = spacer.AddComponent<LayoutElement>();
|
||||||
|
spaceLayout.minWidth = 125;
|
||||||
|
spaceLayout.minHeight = 25;
|
||||||
|
|
||||||
|
AddContextButton(secondRow, "Static Class", SearchContext.StaticClass);
|
||||||
|
AddContextButton(secondRow, "Singleton", SearchContext.Singleton);
|
||||||
|
|
||||||
// search input
|
// search input
|
||||||
|
|
||||||
var nameRowObj = UIFactory.CreateHorizontalGroup(optionsGroupObj, new Color(1, 1, 1, 0));
|
var nameRowObj = UIFactory.CreateHorizontalGroup(optionsGroupObj, new Color(1, 1, 1, 0));
|
||||||
@ -601,7 +737,7 @@ namespace UnityExplorer.UI.Modules
|
|||||||
searchBtnLayout.flexibleHeight = 0;
|
searchBtnLayout.flexibleHeight = 0;
|
||||||
var searchBtn = searchBtnObj.GetComponent<Button>();
|
var searchBtn = searchBtnObj.GetComponent<Button>();
|
||||||
|
|
||||||
searchBtn.onClick.AddListener(OnUnitySearchClicked);
|
searchBtn.onClick.AddListener(OnSearchClicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void AddContextButton(GameObject parent, string label, SearchContext context, float width = 110)
|
internal void AddContextButton(GameObject parent, string label, SearchContext context, float width = 110)
|
||||||
|
@ -45,7 +45,6 @@ namespace UnityExplorer.UI
|
|||||||
SceneExplorer.Instance?.OnSceneChange();
|
SceneExplorer.Instance?.OnSceneChange();
|
||||||
SearchPage.Instance?.OnSceneChange();
|
SearchPage.Instance?.OnSceneChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Update()
|
public static void Update()
|
||||||
{
|
{
|
||||||
MainMenu.Instance?.Update();
|
MainMenu.Instance?.Update();
|
||||||
@ -53,12 +52,9 @@ namespace UnityExplorer.UI
|
|||||||
if (EventSys)
|
if (EventSys)
|
||||||
{
|
{
|
||||||
if (EventSystem.current != EventSys)
|
if (EventSystem.current != EventSys)
|
||||||
{
|
|
||||||
ForceUnlockCursor.SetEventSystem();
|
ForceUnlockCursor.SetEventSystem();
|
||||||
}
|
|
||||||
|
|
||||||
#if CPP
|
#if CPP
|
||||||
// Fix for games which override the InputModule pointer events (eg, VRChat)
|
// Some IL2CPP games behave weird with multiple UI Input Systems, some fixes for them.
|
||||||
var evt = InputManager.InputPointerEvent;
|
var evt = InputManager.InputPointerEvent;
|
||||||
if (evt != null)
|
if (evt != null)
|
||||||
{
|
{
|
||||||
@ -69,9 +65,7 @@ namespace UnityExplorer.UI
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (PanelDragger.Instance != null)
|
if (PanelDragger.Instance != null)
|
||||||
{
|
|
||||||
PanelDragger.Instance.Update();
|
PanelDragger.Instance.Update();
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < SliderScrollbar.Instances.Count; i++)
|
for (int i = 0; i < SliderScrollbar.Instances.Count; i++)
|
||||||
{
|
{
|
||||||
@ -94,33 +88,66 @@ namespace UnityExplorer.UI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static AssetBundle LoadExplorerUi(string id)
|
||||||
|
{
|
||||||
|
return AssetBundle.LoadFromMemory(ReadFully(typeof(ExplorerCore).Assembly.GetManifestResourceStream($"UnityExplorer.Resources.explorerui.{id}.bundle")));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] ReadFully(this Stream input)
|
||||||
|
{
|
||||||
|
using (var ms = new MemoryStream())
|
||||||
|
{
|
||||||
|
byte[] buffer = new byte[81920];
|
||||||
|
int read;
|
||||||
|
while ((read = input.Read(buffer, 0, buffer.Length)) != 0)
|
||||||
|
ms.Write(buffer, 0, read);
|
||||||
|
|
||||||
|
return ms.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void LoadBundle()
|
private static void LoadBundle()
|
||||||
{
|
{
|
||||||
var bundlePath = ExplorerCore.EXPLORER_FOLDER + @"\explorerui.bundle";
|
AssetBundle bundle = null;
|
||||||
if (File.Exists(bundlePath))
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
var bundle = AssetBundle.LoadFromFile(bundlePath);
|
bundle = LoadExplorerUi("modern");
|
||||||
|
|
||||||
BackupShader = bundle.LoadAsset<Shader>("DefaultUI");
|
|
||||||
|
|
||||||
// Fix for games which don't ship with 'UI/Default' shader.
|
|
||||||
if (Graphic.defaultGraphicMaterial.shader?.name != "UI/Default")
|
|
||||||
{
|
|
||||||
ExplorerCore.Log("This game does not ship with the 'UI/Default' shader, using manual Default Shader...");
|
|
||||||
Graphic.defaultGraphicMaterial.shader = BackupShader;
|
|
||||||
}
|
|
||||||
|
|
||||||
ResizeCursor = bundle.LoadAsset<Sprite>("cursor");
|
|
||||||
|
|
||||||
ConsoleFont = bundle.LoadAsset<Font>("CONSOLA");
|
|
||||||
|
|
||||||
ExplorerCore.Log("Loaded UI bundle");
|
|
||||||
}
|
}
|
||||||
else
|
catch
|
||||||
{
|
{
|
||||||
ExplorerCore.LogWarning("Could not find the ExplorerUI Bundle! It should exist at '" + bundlePath + "'");
|
ExplorerCore.Log("Failed to load modern ExplorerUI Bundle, falling back to legacy");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
bundle = LoadExplorerUi("legacy");
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bundle == null)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning("Could not load the ExplorerUI Bundle!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BackupShader = bundle.LoadAsset<Shader>("DefaultUI");
|
||||||
|
|
||||||
|
// Fix for games which don't ship with 'UI/Default' shader.
|
||||||
|
if (Graphic.defaultGraphicMaterial.shader?.name != "UI/Default")
|
||||||
|
{
|
||||||
|
ExplorerCore.Log("This game does not ship with the 'UI/Default' shader, using manual Default Shader...");
|
||||||
|
Graphic.defaultGraphicMaterial.shader = BackupShader;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResizeCursor = bundle.LoadAsset<Sprite>("cursor");
|
||||||
|
|
||||||
|
ConsoleFont = bundle.LoadAsset<Font>("CONSOLA");
|
||||||
|
|
||||||
|
ExplorerCore.Log("Loaded UI bundle");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static GameObject CreateRootCanvas()
|
private static GameObject CreateRootCanvas()
|
||||||
|
@ -293,6 +293,7 @@
|
|||||||
<Compile Include="Unstrip\SceneUnstrip.cs" />
|
<Compile Include="Unstrip\SceneUnstrip.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="UI\UIFactory.cs" />
|
<Compile Include="UI\UIFactory.cs" />
|
||||||
|
<EmbeddedResource Include="Resources\*" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="ILRepack.targets" />
|
<None Include="ILRepack.targets" />
|
||||||
|
@ -24,6 +24,17 @@ namespace UnityExplorer.Unstrip
|
|||||||
|
|
||||||
return new AssetBundle(ptr);
|
return new AssetBundle(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private delegate IntPtr d_LoadFromMemory(IntPtr binary, uint crc);
|
||||||
|
|
||||||
|
public static AssetBundle LoadFromMemory(byte[] binary, uint crc = 0)
|
||||||
|
{
|
||||||
|
var iCall = ICallHelper.GetICall<d_LoadFromMemory>("UnityEngine.AssetBundle::LoadFromMemory_Internal");
|
||||||
|
|
||||||
|
var ptr = iCall(((Il2CppStructArray<byte>) binary).Pointer, crc);
|
||||||
|
|
||||||
|
return new AssetBundle(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
// ~~~~~~~~~~~~ Instance ~~~~~~~~~~~~
|
// ~~~~~~~~~~~~ Instance ~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -43,14 +43,11 @@ namespace UnityExplorer.Unstrip
|
|||||||
|
|
||||||
public static bool LoadImage(this Texture2D tex, byte[] data, bool markNonReadable)
|
public static bool LoadImage(this Texture2D tex, byte[] data, bool markNonReadable)
|
||||||
{
|
{
|
||||||
Il2CppStructArray<byte> il2cppArray = new Il2CppStructArray<byte>(data.Length);
|
var il2cppArray = (Il2CppStructArray<byte>)data;
|
||||||
for (int i = 0; i < data.Length; i++)
|
|
||||||
il2cppArray[i] = data[i];
|
|
||||||
|
|
||||||
bool ret = ICallHelper.GetICall<d_LoadImage>("UnityEngine.ImageConversion::LoadImage")
|
var iCall = ICallHelper.GetICall<d_LoadImage>("UnityEngine.ImageConversion::LoadImage");
|
||||||
.Invoke(tex.Pointer, il2cppArray.Pointer, markNonReadable);
|
|
||||||
|
return iCall.Invoke(tex.Pointer, il2cppArray.Pointer, markNonReadable);
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sprite Sprite.Create
|
// Sprite Sprite.Create
|
||||||
@ -70,5 +67,16 @@ namespace UnityExplorer.Unstrip
|
|||||||
return new Sprite(ptr);
|
return new Sprite(ptr);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Simpler CreateSprite helper
|
||||||
|
|
||||||
|
public static Sprite CreateSprite(Texture2D texture)
|
||||||
|
{
|
||||||
|
#if CPP
|
||||||
|
return CreateSprite(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero, 100f, 0u, Vector4.zero);
|
||||||
|
#else
|
||||||
|
return Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user