Compare commits

..

15 Commits

Author SHA1 Message Date
c88182c831 Bump version 2022-05-08 18:06:56 +10:00
02e0102041 Merge branch 'master' of https://github.com/sinai-dev/UnityExplorer 2022-05-07 05:19:46 +10:00
6adecef785 Fix generated patch code for static void methods
And always show the patch even if it failed to apply
2022-05-07 05:19:43 +10:00
ff6c03e1f3 Update README.md 2022-05-06 15:46:49 +10:00
1aedc505b2 Bump UniverseLib 2022-05-05 23:13:51 +10:00
dbe993a7c7 Fix some casts for IL2CPP 2022-05-05 22:18:19 +10:00
5a1676fb84 Update README.md 2022-05-05 19:56:29 +10:00
a7a663aefa Prevent update overwriting input field changes 2022-05-05 19:53:02 +10:00
76c77fb082 Add button to inspect scene of a GameObject 2022-05-05 19:52:25 +10:00
a25017df69 Add wider Texture2DWidget support 2022-05-05 19:52:13 +10:00
a1fab0c4a7 Add support for opening inspected Type in dnSpy 2022-05-05 19:50:52 +10:00
4599747bfe Merge branch 'master' of https://github.com/sinai-dev/UnityExplorer 2022-05-05 02:45:43 +10:00
3856e84c08 Bump version 2022-05-05 02:45:41 +10:00
104288a912 Add support for Cubemaps in Texture2DWidget 2022-05-05 02:45:24 +10:00
41e8a5ae33 Update README.md 2022-05-03 06:10:22 +10:00
16 changed files with 572 additions and 159 deletions

View File

@ -38,10 +38,10 @@ Nightly builds can be found [here](https://github.com/sinai-dev/UnityExplorer/ac
## MelonLoader ## MelonLoader
| Release | IL2CPP | Mono | | Release | IL2CPP | Mono |
| ---------- | ------ | ---- | | ------- | ------ | ---- |
| ML 0.4/0.5 | ✅ [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) | | ML 0.5 | ✅ [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) |
| ML 0.6 | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader.IL2CPP.net6preview.zip) | ✖️ | | ML 0.6 | ✅ [link](https://github.com/sinai-dev/UnityExplorer/releases/latest/download/UnityExplorer.MelonLoader.IL2CPP.net6preview.zip) | ✖️ |
1. Unzip the release file into a folder 1. Unzip the release file into a folder
2. Copy the DLL inside the `Mods` folder into your MelonLoader `Mods` folder 2. Copy the DLL inside the `Mods` folder into your MelonLoader `Mods` folder
@ -110,7 +110,8 @@ The inspector is used to see detailed information on objects of any type and man
* Automatic updating is not enabled by default, and you must press Apply for any changes you make to take effect. * Automatic updating is not enabled by default, and you must press Apply for any changes you make to take effect.
* Press the `▼` button to expand certain values such as strings, enums, lists, dictionaries, some structs, etc * Press the `▼` button to expand certain values such as strings, enums, lists, dictionaries, some structs, etc
* Use the filters at the top to quickly find the members you are looking for * Use the filters at the top to quickly find the members you are looking for
* For `Texture2D` objects, there is a `View Texture` button at the top of the inspector which lets you view it and save it as a PNG file. Currently there are no other similar helpers yet, but I may add more at some point for Mesh, Sprite, Material, etc * For `Texture2D`, `Image`, `Sprite` and `Material` objects, there is a `View Texture` button at the top of the inspector which lets you view the Texture(s) and save them as a PNG file.
* For `AudioClip` objects there is a `Show Player` button which opens an audio player widget. For clips which are loaded as `DecompressOnLoad`, there is also a button to save them to a `.wav` file.
### C# Console ### C# Console

View File

@ -16,17 +16,17 @@ namespace UnityExplorer.Config
// Actual UE Settings // Actual UE Settings
public static ConfigElement<KeyCode> Master_Toggle; public static ConfigElement<KeyCode> Master_Toggle;
public static ConfigElement<int> Target_Display;
public static ConfigElement<UIManager.VerticalAnchor> Main_Navbar_Anchor;
public static ConfigElement<bool> Force_Unlock_Mouse;
public static ConfigElement<KeyCode> Force_Unlock_Toggle;
public static ConfigElement<bool> Aggressive_Mouse_Unlock;
public static ConfigElement<bool> Disable_EventSystem_Override;
public static ConfigElement<string> Default_Output_Path;
public static ConfigElement<bool> Log_Unity_Debug;
public static ConfigElement<bool> Hide_On_Startup; public static ConfigElement<bool> Hide_On_Startup;
public static ConfigElement<float> Startup_Delay_Time; public static ConfigElement<float> Startup_Delay_Time;
public static ConfigElement<bool> Disable_EventSystem_Override;
public static ConfigElement<int> Target_Display;
public static ConfigElement<bool> Force_Unlock_Mouse;
public static ConfigElement<KeyCode> Force_Unlock_Toggle;
public static ConfigElement<string> Default_Output_Path;
public static ConfigElement<string> DnSpy_Path;
public static ConfigElement<bool> Log_Unity_Debug;
public static ConfigElement<string> Reflection_Signature_Blacklist; public static ConfigElement<string> Reflection_Signature_Blacklist;
public static ConfigElement<UIManager.VerticalAnchor> Main_Navbar_Anchor;
public static ConfigElement<KeyCode> World_MouseInspect_Keybind; public static ConfigElement<KeyCode> World_MouseInspect_Keybind;
public static ConfigElement<KeyCode> UI_MouseInspect_Keybind; public static ConfigElement<KeyCode> UI_MouseInspect_Keybind;
@ -85,23 +85,15 @@ namespace UnityExplorer.Config
"Should UnityExplorer be hidden on startup?", "Should UnityExplorer be hidden on startup?",
false); false);
Startup_Delay_Time = new ConfigElement<float>("Startup Delay Time",
"The delay on startup before the UI is created.",
1f);
Target_Display = new ConfigElement<int>("Target Display", Target_Display = new ConfigElement<int>("Target Display",
"The monitor index for UnityExplorer to use, if you have multiple. 0 is the default display, 1 is secondary, etc. " + "The monitor index for UnityExplorer to use, if you have multiple. 0 is the default display, 1 is secondary, etc. " +
"Restart recommended when changing this setting. Make sure your extra monitors are the same resolution as your primary monitor.", "Restart recommended when changing this setting. Make sure your extra monitors are the same resolution as your primary monitor.",
0); 0);
Main_Navbar_Anchor = new ConfigElement<UIManager.VerticalAnchor>("Main Navbar Anchor",
"The vertical anchor of the main UnityExplorer Navbar, in case you want to move it.",
UIManager.VerticalAnchor.Top);
World_MouseInspect_Keybind = new("World Mouse-Inspect Keybind",
"Optional keybind to being a World-mode Mouse Inspect.",
KeyCode.None);
UI_MouseInspect_Keybind = new("UI Mouse-Inspect Keybind",
"Optional keybind to begin a UI-mode Mouse Inspect.",
KeyCode.None);
Force_Unlock_Mouse = new ConfigElement<bool>("Force Unlock Mouse", Force_Unlock_Mouse = new ConfigElement<bool>("Force Unlock Mouse",
"Force the Cursor to be unlocked (visible) when the UnityExplorer menu is open.", "Force the Cursor to be unlocked (visible) when the UnityExplorer menu is open.",
true); true);
@ -116,17 +108,29 @@ namespace UnityExplorer.Config
false); false);
Disable_EventSystem_Override.OnValueChanged += (bool value) => UniverseLib.Config.ConfigManager.Disable_EventSystem_Override = value; Disable_EventSystem_Override.OnValueChanged += (bool value) => UniverseLib.Config.ConfigManager.Disable_EventSystem_Override = value;
Log_Unity_Debug = new ConfigElement<bool>("Log Unity Debug",
"Should UnityEngine.Debug.Log messages be printed to UnityExplorer's log?",
false);
Default_Output_Path = new ConfigElement<string>("Default Output Path", Default_Output_Path = new ConfigElement<string>("Default Output Path",
"The default output path when exporting things from UnityExplorer.", "The default output path when exporting things from UnityExplorer.",
Path.Combine(ExplorerCore.ExplorerFolder, "Output")); Path.Combine(ExplorerCore.ExplorerFolder, "Output"));
Startup_Delay_Time = new ConfigElement<float>("Startup Delay Time", DnSpy_Path = new ConfigElement<string>("dnSpy Path",
"The delay on startup before the UI is created.", "The full path to dnSpy.exe (64-bit).",
1f); @"C:/Program Files/dnspy/dnSpy.exe");
Main_Navbar_Anchor = new ConfigElement<UIManager.VerticalAnchor>("Main Navbar Anchor",
"The vertical anchor of the main UnityExplorer Navbar, in case you want to move it.",
UIManager.VerticalAnchor.Top);
Log_Unity_Debug = new ConfigElement<bool>("Log Unity Debug",
"Should UnityEngine.Debug.Log messages be printed to UnityExplorer's log?",
false);
World_MouseInspect_Keybind = new("World Mouse-Inspect Keybind",
"Optional keybind to being a World-mode Mouse Inspect.",
KeyCode.None);
UI_MouseInspect_Keybind = new("UI Mouse-Inspect Keybind",
"Optional keybind to begin a UI-mode Mouse Inspect.",
KeyCode.None);
Reflection_Signature_Blacklist = new ConfigElement<string>("Member Signature Blacklist", Reflection_Signature_Blacklist = new ConfigElement<string>("Member Signature Blacklist",
"Use this to blacklist certain member signatures if they are known to cause a crash or other issues.\r\n" + "Use this to blacklist certain member signatures if they are known to cause a crash or other issues.\r\n" +

View File

@ -14,7 +14,7 @@ namespace UnityExplorer
public static class ExplorerCore public static class ExplorerCore
{ {
public const string NAME = "UnityExplorer"; public const string NAME = "UnityExplorer";
public const string VERSION = "4.7.12"; public const string VERSION = "4.8.0";
public const string AUTHOR = "Sinai"; public const string AUTHOR = "Sinai";
public const string GUID = "com.sinai.unityexplorer"; public const string GUID = "com.sinai.unityexplorer";

View File

@ -158,11 +158,8 @@ namespace UnityExplorer.Hooks
} }
HookInstance hook = new(method); HookInstance hook = new(method);
if (hook.Enabled) HookList.hookedSignatures.Add(sig);
{ HookList.currentHooks.Add(sig, hook);
HookList.hookedSignatures.Add(sig);
HookList.currentHooks.Add(sig, hook);
}
AddHooksScrollPool.Refresh(true, false); AddHooksScrollPool.Refresh(true, false);
HookList.HooksScrollPool.Refresh(true, false); HookList.HooksScrollPool.Refresh(true, false);

View File

@ -15,7 +15,6 @@ namespace UnityExplorer.Hooks
{ {
// Static // Static
//static readonly StringBuilder evalOutput = new();
static readonly StringBuilder evaluatorOutput; static readonly StringBuilder evaluatorOutput;
static readonly ScriptEvaluator scriptEvaluator = new(new StringWriter(evaluatorOutput = new StringBuilder())); static readonly ScriptEvaluator scriptEvaluator = new(new StringWriter(evaluatorOutput = new StringBuilder()));
@ -31,21 +30,22 @@ namespace UnityExplorer.Hooks
// Instance // Instance
public bool Enabled; public bool Enabled;
public MethodInfo TargetMethod; public MethodInfo TargetMethod;
public string PatchSourceCode; public string PatchSourceCode;
private readonly string shortSignature; readonly string signature;
private PatchProcessor patchProcessor; PatchProcessor patchProcessor;
private MethodInfo postfix; MethodInfo postfix;
private MethodInfo prefix; MethodInfo prefix;
private MethodInfo finalizer; MethodInfo finalizer;
private MethodInfo transpiler; MethodInfo transpiler;
public HookInstance(MethodInfo targetMethod) public HookInstance(MethodInfo targetMethod)
{ {
this.TargetMethod = targetMethod; this.TargetMethod = targetMethod;
this.shortSignature = TargetMethod.FullDescription(); this.signature = TargetMethod.FullDescription();
GenerateDefaultPatchSourceCode(targetMethod); GenerateDefaultPatchSourceCode(targetMethod);
@ -144,28 +144,29 @@ namespace UnityExplorer.Hooks
{ {
StringBuilder codeBuilder = new(); StringBuilder codeBuilder = new();
codeBuilder.Append("static void Postfix("); // System.Reflection.MethodBase __originalMethod codeBuilder.Append("static void Postfix(");
bool isStatic = targetMethod.IsStatic; bool isStatic = targetMethod.IsStatic;
List<string> arguments = new();
if (!isStatic) if (!isStatic)
codeBuilder.Append($"{FullDescriptionClean(targetMethod.DeclaringType)} __instance"); arguments.Add($"{FullDescriptionClean(targetMethod.DeclaringType)} __instance");
if (targetMethod.ReturnType != typeof(void)) if (targetMethod.ReturnType != typeof(void))
{ arguments.Add($"{FullDescriptionClean(targetMethod.ReturnType)} __result");
if (!isStatic)
codeBuilder.Append(", ");
codeBuilder.Append($"{FullDescriptionClean(targetMethod.ReturnType)} __result");
}
ParameterInfo[] parameters = targetMethod.GetParameters(); ParameterInfo[] parameters = targetMethod.GetParameters();
int paramIdx = 0; int paramIdx = 0;
foreach (ParameterInfo param in parameters) foreach (ParameterInfo param in parameters)
{ {
codeBuilder.Append($", {FullDescriptionClean(param.ParameterType)} __{paramIdx}"); arguments.Add($"{FullDescriptionClean(param.ParameterType)} __{paramIdx}");
paramIdx++; paramIdx++;
} }
codeBuilder.Append(string.Join(", ", arguments.ToArray()));
codeBuilder.Append(")\n"); codeBuilder.Append(")\n");
// Patch body // Patch body
@ -173,8 +174,8 @@ namespace UnityExplorer.Hooks
codeBuilder.AppendLine("{"); codeBuilder.AppendLine("{");
codeBuilder.AppendLine(" try {"); codeBuilder.AppendLine(" try {");
codeBuilder.AppendLine(" StringBuilder sb = new StringBuilder();"); codeBuilder.AppendLine(" StringBuilder sb = new StringBuilder();");
codeBuilder.AppendLine($" sb.AppendLine(\"---- Patched called ----\");"); codeBuilder.AppendLine($" sb.AppendLine(\"--------------------\");");
codeBuilder.AppendLine($" sb.AppendLine(\"{shortSignature}\");"); codeBuilder.AppendLine($" sb.AppendLine(\"{signature}\");");
if (!targetMethod.IsStatic) if (!targetMethod.IsStatic)
codeBuilder.AppendLine($" sb.Append(\"- __instance: \").AppendLine(__instance.ToString());"); codeBuilder.AppendLine($" sb.Append(\"- __instance: \").AppendLine(__instance.ToString());");
@ -206,15 +207,11 @@ namespace UnityExplorer.Hooks
codeBuilder.AppendLine($" UnityExplorer.ExplorerCore.Log(sb.ToString());"); codeBuilder.AppendLine($" UnityExplorer.ExplorerCore.Log(sb.ToString());");
codeBuilder.AppendLine(" }"); codeBuilder.AppendLine(" }");
codeBuilder.AppendLine(" catch (System.Exception ex) {"); codeBuilder.AppendLine(" catch (System.Exception ex) {");
codeBuilder.AppendLine($" UnityExplorer.ExplorerCore.LogWarning($\"Exception in patch of {shortSignature}:\\n{{ex}}\");"); codeBuilder.AppendLine($" UnityExplorer.ExplorerCore.LogWarning($\"Exception in patch of {signature}:\\n{{ex}}\");");
codeBuilder.AppendLine(" }"); codeBuilder.AppendLine(" }");
// End patch body
codeBuilder.AppendLine("}"); codeBuilder.AppendLine("}");
//ExplorerCore.Log(codeBuilder.ToString());
return PatchSourceCode = codeBuilder.ToString(); return PatchSourceCode = codeBuilder.ToString();
} }

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Reflection.Emit; using System.Reflection.Emit;
@ -8,6 +9,8 @@ using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.CacheObject; using UnityExplorer.CacheObject;
using UnityExplorer.CacheObject.Views; using UnityExplorer.CacheObject.Views;
using UnityExplorer.Config;
using UnityExplorer.UI;
using UnityExplorer.UI.Panels; using UnityExplorer.UI.Panels;
using UnityExplorer.UI.Widgets; using UnityExplorer.UI.Widgets;
using UniverseLib; using UniverseLib;
@ -33,7 +36,6 @@ namespace UnityExplorer.Inspectors
public class ReflectionInspector : InspectorBase, ICellPoolDataSource<CacheMemberCell>, ICacheObjectController public class ReflectionInspector : InspectorBase, ICellPoolDataSource<CacheMemberCell>, ICacheObjectController
{ {
public CacheObjectBase ParentCacheObject { get; set; } public CacheObjectBase ParentCacheObject { get; set; }
//public Type TargetType { get; private set; }
public bool StaticOnly { get; internal set; } public bool StaticOnly { get; internal set; }
public bool CanWrite => true; public bool CanWrite => true;
@ -73,6 +75,8 @@ namespace UnityExplorer.Inspectors
Text assemblyText; Text assemblyText;
Toggle autoUpdateToggle; Toggle autoUpdateToggle;
ButtonRef dnSpyButton;
ButtonRef makeGenericButton; ButtonRef makeGenericButton;
GenericConstructorWidget genericConstructor; GenericConstructorWidget genericConstructor;
@ -155,9 +159,15 @@ namespace UnityExplorer.Inspectors
string asmText; string asmText;
if (TargetType.Assembly is AssemblyBuilder || string.IsNullOrEmpty(TargetType.Assembly.Location)) if (TargetType.Assembly is AssemblyBuilder || string.IsNullOrEmpty(TargetType.Assembly.Location))
{
asmText = $"{TargetType.Assembly.GetName().Name} <color=grey><i>(in memory)</i></color>"; asmText = $"{TargetType.Assembly.GetName().Name} <color=grey><i>(in memory)</i></color>";
dnSpyButton.GameObject.SetActive(false);
}
else else
{
asmText = Path.GetFileName(TargetType.Assembly.Location); asmText = Path.GetFileName(TargetType.Assembly.Location);
dnSpyButton.GameObject.SetActive(true);
}
assemblyText.text = $"<color=grey>Assembly:</color> {asmText}"; assemblyText.text = $"<color=grey>Assembly:</color> {asmText}";
// Unity object helper widget // Unity object helper widget
@ -350,6 +360,25 @@ namespace UnityExplorer.Inspectors
ClipboardPanel.Copy(this.Target ?? this.TargetType); ClipboardPanel.Copy(this.Target ?? this.TargetType);
} }
void OnDnSpyButtonClicked()
{
string path = ConfigManager.DnSpy_Path.Value;
if (File.Exists(path) && path.EndsWith("dnspy.exe", StringComparison.OrdinalIgnoreCase))
{
Type type = TargetType;
// if constructed generic type, use the generic type definition
if (type.IsGenericType && !type.IsGenericTypeDefinition)
type = type.GetGenericTypeDefinition();
string args = $"\"{type.Assembly.Location}\" --select T:{type.FullName}";
Process.Start(path, args);
}
else
{
Notification.ShowMessage($"Please set a valid dnSpy path in UnityExplorer Settings.");
}
}
void OnMakeGenericClicked() void OnMakeGenericClicked()
{ {
ContentRoot.SetActive(false); ContentRoot.SetActive(false);
@ -425,10 +454,21 @@ namespace UnityExplorer.Inspectors
UIFactory.SetLayoutElement(copyButton.Component.gameObject, minHeight: 25, minWidth: 120, flexibleWidth: 0); UIFactory.SetLayoutElement(copyButton.Component.gameObject, minHeight: 25, minWidth: 120, flexibleWidth: 0);
copyButton.OnClick += OnCopyClicked; copyButton.OnClick += OnCopyClicked;
assemblyText = UIFactory.CreateLabel(UIRoot, "AssemblyLabel", "not set", TextAnchor.MiddleLeft); // Assembly row
GameObject asmRow = UIFactory.CreateHorizontalGroup(UIRoot, "AssemblyRow", false, false, true, true, 5, default, new(1, 1, 1, 0));
UIFactory.SetLayoutElement(asmRow, flexibleWidth: 9999, minHeight: 25);
assemblyText = UIFactory.CreateLabel(asmRow, "AssemblyLabel", "not set", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(assemblyText.gameObject, minHeight: 25, flexibleWidth: 9999); UIFactory.SetLayoutElement(assemblyText.gameObject, minHeight: 25, flexibleWidth: 9999);
ContentRoot = UIFactory.CreateVerticalGroup(UIRoot, "MemberHolder", false, false, true, true, 5, new Vector4(2, 2, 2, 2), dnSpyButton = UIFactory.CreateButton(asmRow, "DnSpyButton", "View in dnSpy");
UIFactory.SetLayoutElement(dnSpyButton.GameObject, minWidth: 120, minHeight: 25);
dnSpyButton.OnClick += OnDnSpyButtonClicked;
// Content
ContentRoot = UIFactory.CreateVerticalGroup(UIRoot, "ContentRoot", false, false, true, true, 5, new Vector4(2, 2, 2, 2),
new Color(0.12f, 0.12f, 0.12f)); new Color(0.12f, 0.12f, 0.12f));
UIFactory.SetLayoutElement(ContentRoot, flexibleWidth: 9999, flexibleHeight: 9999); UIFactory.SetLayoutElement(ContentRoot, flexibleWidth: 9999, flexibleHeight: 9999);

View File

@ -39,7 +39,6 @@ namespace UnityExplorer.UI
private static void ConstructUI() private static void ConstructUI()
{ {
popupLabel = UIFactory.CreateLabel(UIManager.UIRoot, "ClipboardNotification", "", TextAnchor.MiddleCenter); popupLabel = UIFactory.CreateLabel(UIManager.UIRoot, "ClipboardNotification", "", TextAnchor.MiddleCenter);
popupLabel.rectTransform.sizeDelta = new(500, 100); popupLabel.rectTransform.sizeDelta = new(500, 100);
popupLabel.gameObject.AddComponent<Outline>(); popupLabel.gameObject.AddComponent<Outline>();

View File

@ -171,6 +171,9 @@ namespace UnityExplorer.UI.Panels
if (!ourCamera) if (!ourCamera)
return; return;
if (positionInput.Component.isFocused)
return;
lastSetCameraPosition = ourCamera.transform.position; lastSetCameraPosition = ourCamera.transform.position;
positionInput.Text = ParseUtility.ToStringForInput<Vector3>(lastSetCameraPosition); positionInput.Text = ParseUtility.ToStringForInput<Vector3>(lastSetCameraPosition);
} }

View File

@ -33,7 +33,8 @@ namespace UnityExplorer.UI.Widgets
Text ActiveSelfText; Text ActiveSelfText;
Toggle IsStaticToggle; Toggle IsStaticToggle;
InputFieldRef SceneInput; ButtonRef SceneButton;
InputFieldRef InstanceIDInput; InputFieldRef InstanceIDInput;
InputFieldRef TagInput; InputFieldRef TagInput;
@ -100,7 +101,7 @@ namespace UnityExplorer.UI.Widgets
if (force || Target.scene.handle != lastSceneHandle) if (force || Target.scene.handle != lastSceneHandle)
{ {
lastSceneHandle = Target.scene.handle; lastSceneHandle = Target.scene.handle;
SceneInput.Text = Target.scene.IsValid() ? Target.scene.name : "None (Asset/Resource)"; SceneButton.ButtonText.text = Target.scene.IsValid() ? Target.scene.name : "None (Asset/Resource)";
} }
if (force || (!TagInput.Component.isFocused && Target.tag != lastTag)) if (force || (!TagInput.Component.isFocused && Target.tag != lastTag))
@ -228,6 +229,11 @@ namespace UnityExplorer.UI.Widgets
ExplorerCore.LogWarning($"Exception setting tag! {ex.ReflectionExToString()}"); ExplorerCore.LogWarning($"Exception setting tag! {ex.ReflectionExToString()}");
} }
} }
void OnSceneButtonClicked()
{
InspectorManager.Inspect(Target.scene);
}
void OnExploreButtonClicked() void OnExploreButtonClicked()
{ {
@ -383,10 +389,9 @@ namespace UnityExplorer.UI.Widgets
Text sceneLabel = UIFactory.CreateLabel(thirdrow, "SceneLabel", "Scene:", TextAnchor.MiddleLeft, Color.grey); Text sceneLabel = UIFactory.CreateLabel(thirdrow, "SceneLabel", "Scene:", TextAnchor.MiddleLeft, Color.grey);
UIFactory.SetLayoutElement(sceneLabel.gameObject, minHeight: 25, minWidth: 50); UIFactory.SetLayoutElement(sceneLabel.gameObject, minHeight: 25, minWidth: 50);
SceneInput = UIFactory.CreateInputField(thirdrow, "SceneInput", "untitled"); SceneButton = UIFactory.CreateButton(thirdrow, "SceneButton", "untitled");
UIFactory.SetLayoutElement(SceneInput.Component.gameObject, minHeight: 25, minWidth: 120, flexibleWidth: 999); UIFactory.SetLayoutElement(SceneButton.Component.gameObject, minHeight: 25, minWidth: 120, flexibleWidth: 999);
SceneInput.Component.readOnly = true; SceneButton.OnClick += OnSceneButtonClicked;
SceneInput.Component.textComponent.color = new Color(0.7f, 0.7f, 0.7f);
// Layer // Layer
Text layerLabel = UIFactory.CreateLabel(thirdrow, "LayerLabel", "Layer:", TextAnchor.MiddleLeft, Color.grey); Text layerLabel = UIFactory.CreateLabel(thirdrow, "LayerLabel", "Layer:", TextAnchor.MiddleLeft, Color.grey);

View File

@ -22,18 +22,18 @@ namespace UnityExplorer.UI.Widgets
static Coroutine CurrentlyPlayingCoroutine; static Coroutine CurrentlyPlayingCoroutine;
static readonly string zeroLengthString = GetLengthString(0f); static readonly string zeroLengthString = GetLengthString(0f);
public AudioClip RefAudioClip; public AudioClip audioClip;
private string fullLengthText; string fullLengthText;
private ButtonRef toggleButton; ButtonRef toggleButton;
private bool audioPlayerWanted; bool audioPlayerWanted;
private GameObject audioPlayerRoot; GameObject audioPlayerRoot;
private ButtonRef playStopButton; ButtonRef playStopButton;
private Text progressLabel; Text progressLabel;
private GameObject saveObjectRow; GameObject saveObjectRow;
private InputFieldRef savePathInput; InputFieldRef savePathInput;
private GameObject cantSaveRow; GameObject cantSaveRow;
public override void OnBorrowed(object target, Type targetType, ReflectionInspector inspector) public override void OnBorrowed(object target, Type targetType, ReflectionInspector inspector)
{ {
@ -42,10 +42,10 @@ namespace UnityExplorer.UI.Widgets
this.audioPlayerRoot.transform.SetParent(inspector.UIRoot.transform); this.audioPlayerRoot.transform.SetParent(inspector.UIRoot.transform);
this.audioPlayerRoot.transform.SetSiblingIndex(inspector.UIRoot.transform.childCount - 2); this.audioPlayerRoot.transform.SetSiblingIndex(inspector.UIRoot.transform.childCount - 2);
RefAudioClip = target.TryCast<AudioClip>(); audioClip = target.TryCast<AudioClip>();
this.fullLengthText = GetLengthString(RefAudioClip.length); this.fullLengthText = GetLengthString(audioClip.length);
if (RefAudioClip.loadType == AudioClipLoadType.DecompressOnLoad) if (audioClip.loadType == AudioClipLoadType.DecompressOnLoad)
{ {
cantSaveRow.SetActive(false); cantSaveRow.SetActive(false);
saveObjectRow.SetActive(true); saveObjectRow.SetActive(true);
@ -62,7 +62,7 @@ namespace UnityExplorer.UI.Widgets
public override void OnReturnToPool() public override void OnReturnToPool()
{ {
RefAudioClip = null; audioClip = null;
if (audioPlayerWanted) if (audioPlayerWanted)
ToggleAudioWidget(); ToggleAudioWidget();
@ -95,7 +95,7 @@ namespace UnityExplorer.UI.Widgets
void SetDefaultSavePath() void SetDefaultSavePath()
{ {
string name = RefAudioClip.name; string name = audioClip.name;
if (string.IsNullOrEmpty(name)) if (string.IsNullOrEmpty(name))
name = "untitled"; name = "untitled";
savePathInput.Text = Path.Combine(ConfigManager.Default_Output_Path.Value, $"{name}.wav"); savePathInput.Text = Path.Combine(ConfigManager.Default_Output_Path.Value, $"{name}.wav");
@ -163,7 +163,7 @@ namespace UnityExplorer.UI.Widgets
{ {
playStopButton.ButtonText.text = "Stop Clip"; playStopButton.ButtonText.text = "Stop Clip";
CurrentlyPlaying = this; CurrentlyPlaying = this;
Source.clip = this.RefAudioClip; Source.clip = this.audioClip;
Source.Play(); Source.Play();
while (Source.isPlaying) while (Source.isPlaying)
@ -191,7 +191,7 @@ namespace UnityExplorer.UI.Widgets
public void OnSaveClipClicked() public void OnSaveClipClicked()
{ {
if (!RefAudioClip) if (!audioClip)
{ {
ExplorerCore.LogWarning("AudioClip is null, maybe it was destroyed?"); ExplorerCore.LogWarning("AudioClip is null, maybe it was destroyed?");
return; return;
@ -212,7 +212,7 @@ namespace UnityExplorer.UI.Widgets
if (File.Exists(path)) if (File.Exists(path))
File.Delete(path); File.Delete(path);
SavWav.Save(RefAudioClip, path); SavWav.Save(audioClip, path);
} }
public override GameObject CreateContent(GameObject uiRoot) public override GameObject CreateContent(GameObject uiRoot)

View File

@ -0,0 +1,344 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityExplorer.Config;
using UnityExplorer.Inspectors;
using UnityExplorer.UI.Panels;
using UniverseLib;
using UniverseLib.Runtime;
using UniverseLib.UI;
using UniverseLib.UI.Models;
using UniverseLib.UI.ObjectPool;
using UniverseLib.Utility;
namespace UnityExplorer.UI.Widgets
{
public class MaterialWidget : UnityObjectWidget
{
static MaterialWidget()
{
mi_GetTexturePropertyNames = typeof(Material).GetMethod("GetTexturePropertyNames", ArgumentUtility.EmptyTypes);
MaterialWidgetSupported = mi_GetTexturePropertyNames != null;
}
internal static bool MaterialWidgetSupported { get; }
static readonly MethodInfo mi_GetTexturePropertyNames;
Material material;
Texture2D activeTexture;
readonly Dictionary<string, Texture> textures = new();
readonly HashSet<Texture2D> texturesToDestroy = new();
bool textureViewerWanted;
ButtonRef toggleButton;
GameObject textureViewerRoot;
Dropdown textureDropdown;
InputFieldRef savePathInput;
Image image;
LayoutElement imageLayout;
public override void OnBorrowed(object target, Type targetType, ReflectionInspector inspector)
{
base.OnBorrowed(target, targetType, inspector);
material = target.TryCast<Material>();
if (material.mainTexture)
SetActiveTexture(material.mainTexture);
if (mi_GetTexturePropertyNames.Invoke(material, ArgumentUtility.EmptyArgs) is IEnumerable<string> propNames)
{
foreach (string property in propNames)
{
if (material.GetTexture(property) is Texture texture)
{
if (texture.TryCast<Texture2D>() is null && texture.TryCast<Cubemap>() is null)
continue;
textures.Add(property, texture);
if (!activeTexture)
SetActiveTexture(texture);
}
}
}
if (textureViewerRoot)
{
textureViewerRoot.transform.SetParent(inspector.UIRoot.transform);
RefreshTextureDropdown();
}
InspectorPanel.Instance.Dragger.OnFinishResize += OnInspectorFinishResize;
}
void SetActiveTexture(Texture texture)
{
if (texture.TryCast<Texture2D>() is Texture2D tex2D)
activeTexture = tex2D;
else if (texture.TryCast<Cubemap>() is Cubemap cubemap)
{
activeTexture = TextureHelper.UnwrapCubemap(cubemap);
texturesToDestroy.Add(activeTexture);
}
}
public override void OnReturnToPool()
{
InspectorPanel.Instance.Dragger.OnFinishResize -= OnInspectorFinishResize;
if (texturesToDestroy.Any())
{
foreach (Texture2D tex in texturesToDestroy)
UnityEngine.Object.Destroy(tex);
texturesToDestroy.Clear();
}
material = null;
activeTexture = null;
textures.Clear();
if (image.sprite)
UnityEngine.Object.Destroy(image.sprite);
if (textureViewerWanted)
ToggleTextureViewer();
if (textureViewerRoot)
textureViewerRoot.transform.SetParent(Pool<Texture2DWidget>.Instance.InactiveHolder.transform);
base.OnReturnToPool();
}
void ToggleTextureViewer()
{
if (textureViewerWanted)
{
// disable
textureViewerWanted = false;
textureViewerRoot.SetActive(false);
toggleButton.ButtonText.text = "View Material";
owner.ContentRoot.SetActive(true);
}
else
{
// enable
if (!image.sprite)
{
RefreshTextureViewer();
RefreshTextureDropdown();
}
SetImageSize();
textureViewerWanted = true;
textureViewerRoot.SetActive(true);
toggleButton.ButtonText.text = "Hide Material";
owner.ContentRoot.gameObject.SetActive(false);
}
}
void RefreshTextureViewer()
{
if (!this.activeTexture)
{
ExplorerCore.LogWarning($"Material has no active textures!");
savePathInput.Text = string.Empty;
return;
}
if (image.sprite)
UnityEngine.Object.Destroy(image.sprite);
string name = activeTexture.name;
if (string.IsNullOrEmpty(name))
name = "untitled";
savePathInput.Text = Path.Combine(ConfigManager.Default_Output_Path.Value, $"{name}.png");
Sprite sprite = TextureHelper.CreateSprite(activeTexture);
image.sprite = sprite;
}
void RefreshTextureDropdown()
{
if (!textureDropdown)
return;
textureDropdown.options.Clear();
foreach (string key in textures.Keys)
textureDropdown.options.Add(new(key));
int i = 0;
foreach (Texture value in textures.Values)
{
if (activeTexture.ReferenceEqual(value))
{
textureDropdown.value = i;
break;
}
i++;
}
textureDropdown.RefreshShownValue();
}
void OnTextureDropdownChanged(int value)
{
Texture tex = textures.ElementAt(value).Value;
if (activeTexture.ReferenceEqual(tex))
return;
SetActiveTexture(tex);
RefreshTextureViewer();
}
void OnInspectorFinishResize()
{
SetImageSize();
}
void SetImageSize()
{
if (!imageLayout)
return;
RuntimeHelper.StartCoroutine(SetImageSizeCoro());
}
IEnumerator SetImageSizeCoro()
{
if (!activeTexture)
yield break;
// let unity rebuild layout etc
yield return null;
RectTransform imageRect = InspectorPanel.Instance.Rect;
float rectWidth = imageRect.rect.width - 25;
float rectHeight = imageRect.rect.height - 196;
// If our image is smaller than the viewport, just use 100% scaling
if (activeTexture.width < rectWidth && activeTexture.height < rectHeight)
{
imageLayout.minWidth = activeTexture.width;
imageLayout.minHeight = activeTexture.height;
}
else // we will need to scale down the image to fit
{
// get the ratio of our viewport dimensions to width and height
float viewWidthRatio = (float)((decimal)rectWidth / (decimal)activeTexture.width);
float viewHeightRatio = (float)((decimal)rectHeight / (decimal)activeTexture.height);
// if width needs to be scaled more than height
if (viewWidthRatio < viewHeightRatio)
{
imageLayout.minWidth = activeTexture.width * viewWidthRatio;
imageLayout.minHeight = activeTexture.height * viewWidthRatio;
}
else // if height needs to be scaled more than width
{
imageLayout.minWidth = activeTexture.width * viewHeightRatio;
imageLayout.minHeight = activeTexture.height * viewHeightRatio;
}
}
}
void OnSaveTextureClicked()
{
if (!activeTexture)
{
ExplorerCore.LogWarning("Texture is null, maybe it was destroyed?");
return;
}
if (string.IsNullOrEmpty(savePathInput.Text))
{
ExplorerCore.LogWarning("Save path cannot be empty!");
return;
}
string path = savePathInput.Text;
if (!path.EndsWith(".png", StringComparison.InvariantCultureIgnoreCase))
path += ".png";
path = IOUtility.EnsureValidFilePath(path);
if (File.Exists(path))
File.Delete(path);
TextureHelper.SaveTextureAsPNG(activeTexture, path);
}
public override GameObject CreateContent(GameObject uiRoot)
{
GameObject ret = base.CreateContent(uiRoot);
// Button
toggleButton = UIFactory.CreateButton(UIRoot, "MaterialButton", "View Material", new Color(0.2f, 0.3f, 0.2f));
toggleButton.Transform.SetSiblingIndex(0);
UIFactory.SetLayoutElement(toggleButton.Component.gameObject, minHeight: 25, minWidth: 150);
toggleButton.OnClick += ToggleTextureViewer;
// Texture viewer
textureViewerRoot = UIFactory.CreateVerticalGroup(uiRoot, "MaterialViewer", false, false, true, true, 2, new Vector4(5, 5, 5, 5),
new Color(0.1f, 0.1f, 0.1f), childAlignment: TextAnchor.UpperLeft);
UIFactory.SetLayoutElement(textureViewerRoot, flexibleWidth: 9999, flexibleHeight: 9999);
// Buttons holder
GameObject dropdownRow = UIFactory.CreateHorizontalGroup(textureViewerRoot, "DropdownRow", false, true, true, true, 5, new(3, 3, 3, 3));
UIFactory.SetLayoutElement(dropdownRow, minHeight: 30, flexibleWidth: 9999);
Text dropdownLabel = UIFactory.CreateLabel(dropdownRow, "DropdownLabel", "Texture:");
UIFactory.SetLayoutElement(dropdownLabel.gameObject, minWidth: 75, minHeight: 25);
GameObject dropdownObj = UIFactory.CreateDropdown(dropdownRow, "TextureDropdown", out textureDropdown, "NOT SET", 13, OnTextureDropdownChanged);
UIFactory.SetLayoutElement(dropdownObj, minWidth: 350, minHeight: 25);
// Save helper
GameObject saveRowObj = UIFactory.CreateHorizontalGroup(textureViewerRoot, "SaveRow", false, false, true, true, 2, new Vector4(2, 2, 2, 2),
new Color(0.1f, 0.1f, 0.1f));
ButtonRef saveBtn = UIFactory.CreateButton(saveRowObj, "SaveButton", "Save .PNG", new Color(0.2f, 0.25f, 0.2f));
UIFactory.SetLayoutElement(saveBtn.Component.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 0);
saveBtn.OnClick += OnSaveTextureClicked;
savePathInput = UIFactory.CreateInputField(saveRowObj, "SaveInput", "...");
UIFactory.SetLayoutElement(savePathInput.UIRoot, minHeight: 25, minWidth: 100, flexibleWidth: 9999);
// Actual texture viewer
GameObject imageViewport = UIFactory.CreateVerticalGroup(textureViewerRoot, "ImageViewport", false, false, true, true,
bgColor: new(1, 1, 1, 0), childAlignment: TextAnchor.MiddleCenter);
UIFactory.SetLayoutElement(imageViewport, flexibleWidth: 9999, flexibleHeight: 9999);
GameObject imageHolder = UIFactory.CreateUIObject("ImageHolder", imageViewport);
imageLayout = UIFactory.SetLayoutElement(imageHolder, 1, 1, 0, 0);
GameObject actualImageObj = UIFactory.CreateUIObject("ActualImage", imageHolder);
RectTransform actualRect = actualImageObj.GetComponent<RectTransform>();
actualRect.anchorMin = new(0, 0);
actualRect.anchorMax = new(1, 1);
image = actualImageObj.AddComponent<Image>();
textureViewerRoot.SetActive(false);
return ret;
}
}
}

View File

@ -17,29 +17,51 @@ namespace UnityExplorer.UI.Widgets
{ {
public class Texture2DWidget : UnityObjectWidget public class Texture2DWidget : UnityObjectWidget
{ {
private Texture2D TextureRef; Texture2D texture;
private float realWidth; bool shouldDestroyTexture;
private float realHeight;
private bool textureViewerWanted; bool textureViewerWanted;
private ButtonRef toggleButton; ButtonRef toggleButton;
private GameObject textureViewerRoot; GameObject textureViewerRoot;
private InputFieldRef savePathInput; InputFieldRef savePathInput;
private Image image; Image image;
private LayoutElement imageLayout; LayoutElement imageLayout;
public override void OnBorrowed(object target, Type targetType, ReflectionInspector inspector) public override void OnBorrowed(object target, Type targetType, ReflectionInspector inspector)
{ {
base.OnBorrowed(target, targetType, inspector); base.OnBorrowed(target, targetType, inspector);
TextureRef = target.TryCast<Texture2D>(); if (target.TryCast<Cubemap>() is Cubemap cubemap)
{
texture = TextureHelper.UnwrapCubemap(cubemap);
shouldDestroyTexture = true;
}
else if (target.TryCast<Sprite>() is Sprite sprite)
{
if (sprite.packingMode == SpritePackingMode.Tight)
texture = sprite.texture;
else
{
texture = TextureHelper.CopyTexture(sprite.texture, sprite.textureRect);
shouldDestroyTexture = true;
}
}
else if (target.TryCast<Image>() is Image image)
{
if (image.sprite.packingMode == SpritePackingMode.Tight)
texture = image.sprite.texture;
else
{
texture = TextureHelper.CopyTexture(image.sprite.texture, image.sprite.textureRect);
shouldDestroyTexture = true;
}
}
else
texture = target.TryCast<Texture2D>();
realWidth = TextureRef.width; if (textureViewerRoot)
realHeight = TextureRef.height; textureViewerRoot.transform.SetParent(inspector.UIRoot.transform);
if (this.textureViewerRoot)
this.textureViewerRoot.transform.SetParent(inspector.UIRoot.transform);
InspectorPanel.Instance.Dragger.OnFinishResize += OnInspectorFinishResize; InspectorPanel.Instance.Dragger.OnFinishResize += OnInspectorFinishResize;
} }
@ -48,21 +70,25 @@ namespace UnityExplorer.UI.Widgets
{ {
InspectorPanel.Instance.Dragger.OnFinishResize -= OnInspectorFinishResize; InspectorPanel.Instance.Dragger.OnFinishResize -= OnInspectorFinishResize;
TextureRef = null; if (shouldDestroyTexture)
UnityEngine.Object.Destroy(texture);
texture = null;
shouldDestroyTexture = false;
if (image.sprite) if (image.sprite)
GameObject.Destroy(image.sprite); UnityEngine.Object.Destroy(image.sprite);
if (textureViewerWanted) if (textureViewerWanted)
ToggleTextureViewer(); ToggleTextureViewer();
if (this.textureViewerRoot) if (textureViewerRoot)
this.textureViewerRoot.transform.SetParent(Pool<Texture2DWidget>.Instance.InactiveHolder.transform); textureViewerRoot.transform.SetParent(Pool<Texture2DWidget>.Instance.InactiveHolder.transform);
base.OnReturnToPool(); base.OnReturnToPool();
} }
private void ToggleTextureViewer() void ToggleTextureViewer()
{ {
if (textureViewerWanted) if (textureViewerWanted)
{ {
@ -71,7 +97,7 @@ namespace UnityExplorer.UI.Widgets
textureViewerRoot.SetActive(false); textureViewerRoot.SetActive(false);
toggleButton.ButtonText.text = "View Texture"; toggleButton.ButtonText.text = "View Texture";
ParentInspector.ContentRoot.SetActive(true); owner.ContentRoot.SetActive(true);
} }
else else
{ {
@ -85,30 +111,30 @@ namespace UnityExplorer.UI.Widgets
textureViewerRoot.SetActive(true); textureViewerRoot.SetActive(true);
toggleButton.ButtonText.text = "Hide Texture"; toggleButton.ButtonText.text = "Hide Texture";
ParentInspector.ContentRoot.gameObject.SetActive(false); owner.ContentRoot.gameObject.SetActive(false);
} }
} }
private void SetupTextureViewer() void SetupTextureViewer()
{ {
if (!this.TextureRef) if (!this.texture)
return; return;
string name = TextureRef.name; string name = texture.name;
if (string.IsNullOrEmpty(name)) if (string.IsNullOrEmpty(name))
name = "untitled"; name = "untitled";
savePathInput.Text = Path.Combine(ConfigManager.Default_Output_Path.Value, $"{name}.png"); savePathInput.Text = Path.Combine(ConfigManager.Default_Output_Path.Value, $"{name}.png");
Sprite sprite = TextureHelper.CreateSprite(TextureRef); Sprite sprite = TextureHelper.CreateSprite(texture);
image.sprite = sprite; image.sprite = sprite;
} }
private void OnInspectorFinishResize() void OnInspectorFinishResize()
{ {
SetImageSize(); SetImageSize();
} }
private void SetImageSize() void SetImageSize()
{ {
if (!imageLayout) if (!imageLayout)
return; return;
@ -127,34 +153,34 @@ namespace UnityExplorer.UI.Widgets
float rectHeight = imageRect.rect.height - 196; float rectHeight = imageRect.rect.height - 196;
// If our image is smaller than the viewport, just use 100% scaling // If our image is smaller than the viewport, just use 100% scaling
if (realWidth < rectWidth && realHeight < rectHeight) if (texture.width < rectWidth && texture.height < rectHeight)
{ {
imageLayout.minWidth = realWidth; imageLayout.minWidth = texture.width;
imageLayout.minHeight = realHeight; imageLayout.minHeight = texture.height;
} }
else // we will need to scale down the image to fit else // we will need to scale down the image to fit
{ {
// get the ratio of our viewport dimensions to width and height // get the ratio of our viewport dimensions to width and height
float viewWidthRatio = (float)((decimal)rectWidth / (decimal)realWidth); float viewWidthRatio = (float)((decimal)rectWidth / (decimal)texture.width);
float viewHeightRatio = (float)((decimal)rectHeight / (decimal)realHeight); float viewHeightRatio = (float)((decimal)rectHeight / (decimal)texture.height);
// if width needs to be scaled more than height // if width needs to be scaled more than height
if (viewWidthRatio < viewHeightRatio) if (viewWidthRatio < viewHeightRatio)
{ {
imageLayout.minWidth = realWidth * viewWidthRatio; imageLayout.minWidth = texture.width * viewWidthRatio;
imageLayout.minHeight = realHeight * viewWidthRatio; imageLayout.minHeight = texture.height * viewWidthRatio;
} }
else // if height needs to be scaled more than width else // if height needs to be scaled more than width
{ {
imageLayout.minWidth = realWidth * viewHeightRatio; imageLayout.minWidth = texture.width * viewHeightRatio;
imageLayout.minHeight = realHeight * viewHeightRatio; imageLayout.minHeight = texture.height * viewHeightRatio;
} }
} }
} }
private void OnSaveTextureClicked() void OnSaveTextureClicked()
{ {
if (!TextureRef) if (!texture)
{ {
ExplorerCore.LogWarning("Texture is null, maybe it was destroyed?"); ExplorerCore.LogWarning("Texture is null, maybe it was destroyed?");
return; return;
@ -175,18 +201,7 @@ namespace UnityExplorer.UI.Widgets
if (File.Exists(path)) if (File.Exists(path))
File.Delete(path); File.Delete(path);
Texture2D tex = TextureRef; TextureHelper.SaveTextureAsPNG(texture, path);
if (!TextureHelper.IsReadable(tex))
tex = TextureHelper.ForceReadTexture(tex);
byte[] data = TextureHelper.EncodeToPNG(tex);
File.WriteAllBytes(path, data);
if (tex != TextureRef)
{
// cleanup temp texture if we had to force-read it.
GameObject.Destroy(tex);
}
} }
public override GameObject CreateContent(GameObject uiRoot) public override GameObject CreateContent(GameObject uiRoot)

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityExplorer.Inspectors; using UnityExplorer.Inspectors;
@ -11,9 +12,9 @@ namespace UnityExplorer.UI.Widgets
{ {
public class UnityObjectWidget : IPooledObject public class UnityObjectWidget : IPooledObject
{ {
public UnityEngine.Object UnityObjectRef; public UnityEngine.Object unityObject;
public Component ComponentRef; public Component component;
public ReflectionInspector ParentInspector; public ReflectionInspector owner;
protected ButtonRef gameObjectButton; protected ButtonRef gameObjectButton;
protected InputFieldRef nameInput; protected InputFieldRef nameInput;
@ -30,8 +31,14 @@ namespace UnityExplorer.UI.Widgets
UnityObjectWidget widget = target switch UnityObjectWidget widget = target switch
{ {
Texture2D => Pool<Texture2DWidget>.Borrow(), Texture2D or Cubemap => Pool<Texture2DWidget>.Borrow(),
Sprite s when s.texture => Pool<Texture2DWidget>.Borrow(),
Image i when i.sprite?.texture => Pool<Texture2DWidget>.Borrow(),
Material when MaterialWidget.MaterialWidgetSupported => Pool<MaterialWidget>.Borrow(),
AudioClip => Pool<AudioClipWidget>.Borrow(), AudioClip => Pool<AudioClipWidget>.Borrow(),
_ => Pool<UnityObjectWidget>.Borrow() _ => Pool<UnityObjectWidget>.Borrow()
}; };
@ -42,7 +49,7 @@ namespace UnityExplorer.UI.Widgets
public virtual void OnBorrowed(object target, Type targetType, ReflectionInspector inspector) public virtual void OnBorrowed(object target, Type targetType, ReflectionInspector inspector)
{ {
this.ParentInspector = inspector ?? throw new ArgumentNullException(nameof(inspector)); this.owner = inspector;
if (!this.UIRoot) if (!this.UIRoot)
CreateContent(inspector.UIRoot); CreateContent(inspector.UIRoot);
@ -51,15 +58,15 @@ namespace UnityExplorer.UI.Widgets
this.UIRoot.transform.SetSiblingIndex(inspector.UIRoot.transform.childCount - 2); this.UIRoot.transform.SetSiblingIndex(inspector.UIRoot.transform.childCount - 2);
UnityObjectRef = target.TryCast<UnityEngine.Object>(); unityObject = target.TryCast<UnityEngine.Object>();
UIRoot.SetActive(true); UIRoot.SetActive(true);
nameInput.Text = UnityObjectRef.name; nameInput.Text = unityObject.name;
instanceIdInput.Text = UnityObjectRef.GetInstanceID().ToString(); instanceIdInput.Text = unityObject.GetInstanceID().ToString();
if (typeof(Component).IsAssignableFrom(targetType)) if (typeof(Component).IsAssignableFrom(targetType))
{ {
ComponentRef = (Component)target.TryCast(typeof(Component)); component = (Component)target.TryCast(typeof(Component));
gameObjectButton.Component.gameObject.SetActive(true); gameObjectButton.Component.gameObject.SetActive(true);
} }
else else
@ -68,19 +75,20 @@ namespace UnityExplorer.UI.Widgets
public virtual void OnReturnToPool() public virtual void OnReturnToPool()
{ {
UnityObjectRef = null; unityObject = null;
ComponentRef = null; component = null;
ParentInspector = null; owner = null;
} }
// Update // Update
public virtual void Update() public virtual void Update()
{ {
if (this.UnityObjectRef) if (this.unityObject)
{ {
nameInput.Text = UnityObjectRef.name; nameInput.Text = unityObject.name;
ParentInspector.Tab.TabText.text = $"{ParentInspector.TabButtonText} \"{UnityObjectRef.name}\"";
owner.Tab.TabText.text = $"{owner.TabButtonText} \"{unityObject.name}\"";
} }
} }
@ -88,13 +96,13 @@ namespace UnityExplorer.UI.Widgets
private void OnGameObjectButtonClicked() private void OnGameObjectButtonClicked()
{ {
if (!ComponentRef) if (!component)
{ {
ExplorerCore.LogWarning("Component reference is null or destroyed!"); ExplorerCore.LogWarning("Component reference is null or destroyed!");
return; return;
} }
InspectorManager.Inspect(ComponentRef.gameObject); InspectorManager.Inspect(component.gameObject);
} }
// UI construction // UI construction

View File

@ -79,11 +79,11 @@
<!-- il2cpp nuget --> <!-- il2cpp nuget -->
<ItemGroup Condition="'$(Configuration)'=='ML_Cpp_net6' or '$(Configuration)'=='ML_Cpp_net472' or '$(Configuration)'=='STANDALONE_Cpp' or '$(Configuration)'=='BIE_Cpp'"> <ItemGroup Condition="'$(Configuration)'=='ML_Cpp_net6' or '$(Configuration)'=='ML_Cpp_net472' or '$(Configuration)'=='STANDALONE_Cpp' or '$(Configuration)'=='BIE_Cpp'">
<PackageReference Include="Il2CppAssemblyUnhollower.BaseLib" Version="0.4.22" /> <PackageReference Include="Il2CppAssemblyUnhollower.BaseLib" Version="0.4.22" />
<PackageReference Include="UniverseLib.IL2CPP" Version="1.3.14" /> <PackageReference Include="UniverseLib.IL2CPP" Version="1.4.1" />
</ItemGroup> </ItemGroup>
<!-- mono nuget --> <!-- mono nuget -->
<ItemGroup Condition="'$(Configuration)'=='BIE6_Mono' or '$(Configuration)'=='BIE5_Mono' or '$(Configuration)'=='ML_Mono' or '$(Configuration)'=='STANDALONE_Mono'"> <ItemGroup Condition="'$(Configuration)'=='BIE6_Mono' or '$(Configuration)'=='BIE5_Mono' or '$(Configuration)'=='ML_Mono' or '$(Configuration)'=='STANDALONE_Mono'">
<PackageReference Include="UniverseLib.Mono" Version="1.3.14" /> <PackageReference Include="UniverseLib.Mono" Version="1.4.1" />
</ItemGroup> </ItemGroup>
<!-- ~~~~~ ASSEMBLY REFERENCES ~~~~~ --> <!-- ~~~~~ ASSEMBLY REFERENCES ~~~~~ -->