mirror of
https://github.com/GrahamKracker/UnityExplorer.git
synced 2025-07-15 15:57:52 +08:00
Adding back rest of the menu, ported most of Reflection Inspector for new UI
This commit is contained in:
193
src/UI/Inspectors/GameObjects/ChildList.cs
Normal file
193
src/UI/Inspectors/GameObjects/ChildList.cs
Normal file
@ -0,0 +1,193 @@
|
||||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using System.Text;
|
||||
//using UnityEngine;
|
||||
//using UnityEngine.UI;
|
||||
//using UnityExplorer.Core.Runtime;
|
||||
//using UnityExplorer.UI.Utility;
|
||||
|
||||
//namespace UnityExplorer.UI.Inspectors.GameObjects
|
||||
//{
|
||||
// public class ChildList
|
||||
// {
|
||||
// internal static ChildList Instance;
|
||||
|
||||
// public ChildList()
|
||||
// {
|
||||
// Instance = this;
|
||||
// }
|
||||
|
||||
// public static PageHandler s_childListPageHandler;
|
||||
// private static GameObject s_childListContent;
|
||||
|
||||
// private static GameObject[] s_allChildren = new GameObject[0];
|
||||
// private static readonly List<GameObject> s_childrenShortlist = new List<GameObject>();
|
||||
// private static int s_lastChildCount;
|
||||
|
||||
// private static readonly List<Text> s_childListTexts = new List<Text>();
|
||||
// private static readonly List<Toggle> s_childListToggles = new List<Toggle>();
|
||||
|
||||
// internal void RefreshChildObjectList()
|
||||
// {
|
||||
// var go = GameObjectInspector.ActiveInstance.TargetGO;
|
||||
|
||||
// s_allChildren = new GameObject[go.transform.childCount];
|
||||
// for (int i = 0; i < go.transform.childCount; i++)
|
||||
// {
|
||||
// var child = go.transform.GetChild(i);
|
||||
// s_allChildren[i] = child.gameObject;
|
||||
// }
|
||||
|
||||
// var objects = s_allChildren;
|
||||
// s_childListPageHandler.ListCount = objects.Length;
|
||||
|
||||
// int newCount = 0;
|
||||
|
||||
// foreach (var itemIndex in s_childListPageHandler)
|
||||
// {
|
||||
// newCount++;
|
||||
|
||||
// // normalized index starting from 0
|
||||
// var i = itemIndex - s_childListPageHandler.StartIndex;
|
||||
|
||||
// if (itemIndex >= objects.Length)
|
||||
// {
|
||||
// if (i > s_lastChildCount || i >= s_childListTexts.Count)
|
||||
// break;
|
||||
|
||||
// GameObject label = s_childListTexts[i].transform.parent.parent.gameObject;
|
||||
// if (label.activeSelf)
|
||||
// label.SetActive(false);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// GameObject obj = objects[itemIndex];
|
||||
|
||||
// if (!obj)
|
||||
// continue;
|
||||
|
||||
// if (i >= s_childrenShortlist.Count)
|
||||
// {
|
||||
// s_childrenShortlist.Add(obj);
|
||||
// AddChildListButton();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// s_childrenShortlist[i] = obj;
|
||||
// }
|
||||
|
||||
// var text = s_childListTexts[i];
|
||||
|
||||
// var name = obj.name;
|
||||
|
||||
// if (obj.transform.childCount > 0)
|
||||
// name = $"<color=grey>[{obj.transform.childCount}]</color> {name}";
|
||||
|
||||
// text.text = name;
|
||||
// text.color = obj.activeSelf ? Color.green : Color.red;
|
||||
|
||||
// var tog = s_childListToggles[i];
|
||||
// tog.isOn = obj.activeSelf;
|
||||
|
||||
// var label = text.transform.parent.parent.gameObject;
|
||||
// if (!label.activeSelf)
|
||||
// {
|
||||
// label.SetActive(true);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// s_lastChildCount = newCount;
|
||||
// }
|
||||
|
||||
// internal static void OnChildListObjectClicked(int index)
|
||||
// {
|
||||
// if (GameObjectInspector.ActiveInstance == null)
|
||||
// return;
|
||||
|
||||
// if (index >= s_childrenShortlist.Count || !s_childrenShortlist[index])
|
||||
// return;
|
||||
|
||||
// GameObjectInspector.ActiveInstance.ChangeInspectorTarget(s_childrenShortlist[index]);
|
||||
// GameObjectInspector.ActiveInstance.Update();
|
||||
// }
|
||||
|
||||
// internal static void OnChildListPageTurn()
|
||||
// {
|
||||
// if (Instance == null)
|
||||
// return;
|
||||
|
||||
// Instance.RefreshChildObjectList();
|
||||
// }
|
||||
|
||||
// internal static void OnToggleClicked(int index, bool newVal)
|
||||
// {
|
||||
// if (GameObjectInspector.ActiveInstance == null)
|
||||
// return;
|
||||
|
||||
// if (index >= s_childrenShortlist.Count || !s_childrenShortlist[index])
|
||||
// return;
|
||||
|
||||
// var obj = s_childrenShortlist[index];
|
||||
// obj.SetActive(newVal);
|
||||
// }
|
||||
|
||||
// #region UI CONSTRUCTION
|
||||
|
||||
// internal void ConstructChildList(GameObject parent)
|
||||
// {
|
||||
// var vertGroupObj = UIFactory.CreateVerticalGroup(parent, "ChildListGroup", false, true, true, true, 5, default, new Color(1, 1, 1, 0));
|
||||
// UIFactory.SetLayoutElement(vertGroupObj, minWidth: 120, flexibleWidth: 25000, minHeight: 200, flexibleHeight: 5000);
|
||||
|
||||
// var childTitle = UIFactory.CreateLabel(vertGroupObj, "ChildListTitle", "Children:", TextAnchor.MiddleLeft, Color.grey, true, 14);
|
||||
// UIFactory.SetLayoutElement(childTitle.gameObject, minHeight: 30);
|
||||
|
||||
// var childrenScrollObj = UIFactory.CreateScrollView(vertGroupObj, "ChildListScrollView", out s_childListContent,
|
||||
// out SliderScrollbar scroller, new Color(0.07f, 0.07f, 0.07f));
|
||||
// UIFactory.SetLayoutElement(childrenScrollObj, minHeight: 50);
|
||||
|
||||
// s_childListPageHandler = new PageHandler(scroller);
|
||||
// s_childListPageHandler.ConstructUI(vertGroupObj);
|
||||
// s_childListPageHandler.OnPageChanged += OnChildListPageTurn;
|
||||
// }
|
||||
|
||||
// internal void AddChildListButton()
|
||||
// {
|
||||
// int thisIndex = s_childListTexts.Count;
|
||||
|
||||
// var btnGroupObj = UIFactory.CreateHorizontalGroup(s_childListContent, "ChildButtonGroup", true, false, true, true,
|
||||
// 0, default, new Color(0.07f, 0.07f, 0.07f));
|
||||
// UIFactory.SetLayoutElement(btnGroupObj, flexibleWidth: 320, minHeight: 25, flexibleHeight: 0);
|
||||
// btnGroupObj.AddComponent<Mask>();
|
||||
|
||||
// var toggleObj = UIFactory.CreateToggle(btnGroupObj, "Toggle", out Toggle toggle, out Text toggleText, new Color(0.3f, 0.3f, 0.3f));
|
||||
// UIFactory.SetLayoutElement(toggleObj, minHeight: 25, minWidth: 25);
|
||||
// toggleText.text = "";
|
||||
// toggle.isOn = false;
|
||||
// s_childListToggles.Add(toggle);
|
||||
// toggle.onValueChanged.AddListener((bool val) => { OnToggleClicked(thisIndex, val); });
|
||||
|
||||
// var mainBtn = UIFactory.CreateButton(btnGroupObj,
|
||||
// "MainButton",
|
||||
// "",
|
||||
// () => { OnChildListObjectClicked(thisIndex); });
|
||||
|
||||
// RuntimeProvider.Instance.SetColorBlock(mainBtn, new Color(0.07f, 0.07f, 0.07f),
|
||||
// new Color(0.2f, 0.2f, 0.2f, 1), new Color(0.05f, 0.05f, 0.05f));
|
||||
|
||||
// UIFactory.SetLayoutElement(mainBtn.gameObject, minHeight: 25, flexibleHeight: 0, minWidth: 25, flexibleWidth: 9999);
|
||||
|
||||
// Text mainText = mainBtn.GetComponentInChildren<Text>();
|
||||
// mainText.alignment = TextAnchor.MiddleLeft;
|
||||
// mainText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||
// mainText.resizeTextForBestFit = true;
|
||||
// mainText.resizeTextMaxSize = 14;
|
||||
// mainText.resizeTextMinSize = 10;
|
||||
|
||||
// s_childListTexts.Add(mainText);
|
||||
// }
|
||||
|
||||
// #endregion
|
||||
// }
|
||||
//}
|
192
src/UI/Inspectors/GameObjects/ComponentList.cs
Normal file
192
src/UI/Inspectors/GameObjects/ComponentList.cs
Normal file
@ -0,0 +1,192 @@
|
||||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using System.Text;
|
||||
//using UnityEngine;
|
||||
//using UnityEngine.UI;
|
||||
//using UnityExplorer.Core;
|
||||
//using UnityExplorer.Core.Runtime;
|
||||
//using UnityExplorer.UI.Utility;
|
||||
|
||||
//namespace UnityExplorer.UI.Inspectors.GameObjects
|
||||
//{
|
||||
// public class ComponentList
|
||||
// {
|
||||
// internal static ComponentList Instance;
|
||||
|
||||
// public ComponentList()
|
||||
// {
|
||||
// Instance = this;
|
||||
// }
|
||||
|
||||
// public static PageHandler s_compListPageHandler;
|
||||
// private static Component[] s_allComps = new Component[0];
|
||||
// private static readonly List<Component> s_compShortlist = new List<Component>();
|
||||
// private static GameObject s_compListContent;
|
||||
// private static readonly List<Text> s_compListTexts = new List<Text>();
|
||||
// private static int s_lastCompCount;
|
||||
// public static readonly List<Toggle> s_compToggles = new List<Toggle>();
|
||||
|
||||
// internal void RefreshComponentList()
|
||||
// {
|
||||
// var go = GameObjectInspector.ActiveInstance.TargetGO;
|
||||
|
||||
// s_allComps = go.GetComponents<Component>().ToArray();
|
||||
|
||||
// var components = s_allComps;
|
||||
// s_compListPageHandler.ListCount = components.Length;
|
||||
|
||||
// //int startIndex = m_sceneListPageHandler.StartIndex;
|
||||
|
||||
// int newCount = 0;
|
||||
|
||||
// foreach (var itemIndex in s_compListPageHandler)
|
||||
// {
|
||||
// newCount++;
|
||||
|
||||
// // normalized index starting from 0
|
||||
// var i = itemIndex - s_compListPageHandler.StartIndex;
|
||||
|
||||
// if (itemIndex >= components.Length)
|
||||
// {
|
||||
// if (i > s_lastCompCount || i >= s_compListTexts.Count)
|
||||
// break;
|
||||
|
||||
// GameObject label = s_compListTexts[i].transform.parent.parent.gameObject;
|
||||
// if (label.activeSelf)
|
||||
// label.SetActive(false);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Component comp = components[itemIndex];
|
||||
|
||||
// if (!comp)
|
||||
// continue;
|
||||
|
||||
// if (i >= s_compShortlist.Count)
|
||||
// {
|
||||
// s_compShortlist.Add(comp);
|
||||
// AddCompListButton();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// s_compShortlist[i] = comp;
|
||||
// }
|
||||
|
||||
// var text = s_compListTexts[i];
|
||||
|
||||
// text.text = SignatureHighlighter.ParseFullSyntax(ReflectionUtility.GetActualType(comp), true);
|
||||
|
||||
// var toggle = s_compToggles[i];
|
||||
// if (comp.TryCast<Behaviour>() is Behaviour behaviour)
|
||||
// {
|
||||
// if (!toggle.gameObject.activeSelf)
|
||||
// toggle.gameObject.SetActive(true);
|
||||
|
||||
// toggle.isOn = behaviour.enabled;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (toggle.gameObject.activeSelf)
|
||||
// toggle.gameObject.SetActive(false);
|
||||
// }
|
||||
|
||||
// var label = text.transform.parent.parent.gameObject;
|
||||
// if (!label.activeSelf)
|
||||
// {
|
||||
// label.SetActive(true);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// s_lastCompCount = newCount;
|
||||
// }
|
||||
|
||||
// internal static void OnCompToggleClicked(int index, bool value)
|
||||
// {
|
||||
// var comp = s_compShortlist[index];
|
||||
// comp.TryCast<Behaviour>().enabled = value;
|
||||
// }
|
||||
|
||||
// internal static void OnCompListObjectClicked(int index)
|
||||
// {
|
||||
// if (index >= s_compShortlist.Count || !s_compShortlist[index])
|
||||
// return;
|
||||
|
||||
// InspectorManager.Instance.Inspect(s_compShortlist[index]);
|
||||
// }
|
||||
|
||||
// internal static void OnCompListPageTurn()
|
||||
// {
|
||||
// if (Instance == null)
|
||||
// return;
|
||||
|
||||
// Instance.RefreshComponentList();
|
||||
// }
|
||||
|
||||
|
||||
// #region UI CONSTRUCTION
|
||||
|
||||
// internal void ConstructCompList(GameObject parent)
|
||||
// {
|
||||
// var vertGroupObj = UIFactory.CreateVerticalGroup(parent, "ComponentList", false, true, true, true, 5, default, new Color(1, 1, 1, 0));
|
||||
// UIFactory.SetLayoutElement(vertGroupObj, minWidth: 120, flexibleWidth: 25000, minHeight: 200, flexibleHeight: 5000);
|
||||
|
||||
// var compTitle = UIFactory.CreateLabel(vertGroupObj, "ComponentsTitle", "Components:", TextAnchor.MiddleLeft, Color.grey);
|
||||
// UIFactory.SetLayoutElement(compTitle.gameObject, minHeight: 30);
|
||||
|
||||
// var compScrollObj = UIFactory.CreateScrollView(vertGroupObj, "ComponentListScrollView", out s_compListContent,
|
||||
// out SliderScrollbar scroller, new Color(0.07f, 0.07f, 0.07f));
|
||||
|
||||
// UIFactory.SetLayoutElement(compScrollObj, minHeight: 50, flexibleHeight: 5000);
|
||||
|
||||
// s_compListPageHandler = new PageHandler(scroller);
|
||||
// s_compListPageHandler.ConstructUI(vertGroupObj);
|
||||
// s_compListPageHandler.OnPageChanged += OnCompListPageTurn;
|
||||
// }
|
||||
|
||||
// internal void AddCompListButton()
|
||||
// {
|
||||
// int thisIndex = s_compListTexts.Count;
|
||||
|
||||
// GameObject groupObj = UIFactory.CreateHorizontalGroup(s_compListContent, "CompListButton", true, false, true, true, 0, default,
|
||||
// new Color(0.07f, 0.07f, 0.07f), TextAnchor.MiddleLeft);
|
||||
// UIFactory.SetLayoutElement(groupObj, minWidth: 25, flexibleWidth: 999, minHeight: 25, flexibleHeight: 0);
|
||||
// groupObj.AddComponent<Mask>();
|
||||
|
||||
// // Behaviour enabled toggle
|
||||
|
||||
// var toggleObj = UIFactory.CreateToggle(groupObj, "EnabledToggle", out Toggle toggle, out Text toggleText, new Color(0.3f, 0.3f, 0.3f));
|
||||
// UIFactory.SetLayoutElement(toggleObj, minWidth: 25, minHeight: 25);
|
||||
// toggleText.text = "";
|
||||
// toggle.isOn = true;
|
||||
// s_compToggles.Add(toggle);
|
||||
// toggle.onValueChanged.AddListener((bool val) => { OnCompToggleClicked(thisIndex, val); });
|
||||
|
||||
// // Main component button
|
||||
|
||||
// var mainBtn = UIFactory.CreateButton(groupObj,
|
||||
// "MainButton",
|
||||
// "",
|
||||
// () => { OnCompListObjectClicked(thisIndex); });
|
||||
|
||||
// RuntimeProvider.Instance.SetColorBlock(mainBtn, new Color(0.07f, 0.07f, 0.07f),
|
||||
// new Color(0.2f, 0.2f, 0.2f, 1), new Color(0.05f, 0.05f, 0.05f));
|
||||
|
||||
// UIFactory.SetLayoutElement(mainBtn.gameObject, minHeight: 25, flexibleHeight: 0, minWidth: 25, flexibleWidth: 999);
|
||||
|
||||
// // Component button text
|
||||
|
||||
// Text mainText = mainBtn.GetComponentInChildren<Text>();
|
||||
// mainText.alignment = TextAnchor.MiddleLeft;
|
||||
// mainText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||
// mainText.resizeTextForBestFit = true;
|
||||
// mainText.resizeTextMaxSize = 14;
|
||||
// mainText.resizeTextMinSize = 8;
|
||||
|
||||
// s_compListTexts.Add(mainText);
|
||||
// }
|
||||
|
||||
// #endregion
|
||||
// }
|
||||
//}
|
467
src/UI/Inspectors/GameObjects/GameObjectControls.cs
Normal file
467
src/UI/Inspectors/GameObjects/GameObjectControls.cs
Normal file
@ -0,0 +1,467 @@
|
||||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using System.Text;
|
||||
//using UnityEngine;
|
||||
//using UnityEngine.UI;
|
||||
//using UnityExplorer.Core.Input;
|
||||
//using UnityExplorer.Core.Runtime;
|
||||
|
||||
//namespace UnityExplorer.UI.Inspectors.GameObjects
|
||||
//{
|
||||
// public class GameObjectControls
|
||||
// {
|
||||
// internal static GameObjectControls Instance;
|
||||
|
||||
// public GameObjectControls()
|
||||
// {
|
||||
// Instance = this;
|
||||
// }
|
||||
|
||||
// internal static bool Showing;
|
||||
|
||||
// internal static void ToggleVisibility() => SetVisibility(!Showing);
|
||||
|
||||
// internal static void SetVisibility(bool show)
|
||||
// {
|
||||
// if (show == Showing)
|
||||
// return;
|
||||
|
||||
// Showing = show;
|
||||
|
||||
// m_hideShowLabel.text = show ? "Hide" : "Show";
|
||||
// m_contentObj.SetActive(show);
|
||||
// }
|
||||
|
||||
// internal static GameObject m_contentObj;
|
||||
// internal static Text m_hideShowLabel;
|
||||
|
||||
// private static InputField s_setParentInput;
|
||||
|
||||
// private static ControlEditor s_positionControl;
|
||||
// private static ControlEditor s_localPosControl;
|
||||
// private static ControlEditor s_rotationControl;
|
||||
// private static ControlEditor s_scaleControl;
|
||||
|
||||
// // Transform Vector editors
|
||||
|
||||
// internal struct ControlEditor
|
||||
// {
|
||||
// public InputField fullValue;
|
||||
// public Slider[] sliders;
|
||||
// public InputField[] inputs;
|
||||
// public Text[] values;
|
||||
// }
|
||||
|
||||
// internal static bool s_sliderChangedWanted;
|
||||
// private static Slider s_currentSlider;
|
||||
// private static ControlType s_currentSliderType;
|
||||
// private static VectorValue s_currentSliderValueType;
|
||||
// private static float s_currentSliderValue;
|
||||
|
||||
// internal enum ControlType
|
||||
// {
|
||||
// position,
|
||||
// localPosition,
|
||||
// eulerAngles,
|
||||
// localScale
|
||||
// }
|
||||
|
||||
// internal enum VectorValue
|
||||
// {
|
||||
// x, y, z
|
||||
// };
|
||||
|
||||
// internal void RefreshControls()
|
||||
// {
|
||||
// var go = GameObjectInspector.ActiveInstance.TargetGO;
|
||||
|
||||
// s_positionControl.fullValue.text = go.transform.position.ToStringPretty();
|
||||
// s_positionControl.values[0].text = go.transform.position.x.ToString("F3");
|
||||
// s_positionControl.values[1].text = go.transform.position.y.ToString("F3");
|
||||
// s_positionControl.values[2].text = go.transform.position.z.ToString("F3");
|
||||
|
||||
// s_localPosControl.fullValue.text = go.transform.localPosition.ToStringPretty();
|
||||
// s_localPosControl.values[0].text = go.transform.localPosition.x.ToString("F3");
|
||||
// s_localPosControl.values[1].text = go.transform.localPosition.y.ToString("F3");
|
||||
// s_localPosControl.values[2].text = go.transform.localPosition.z.ToString("F3");
|
||||
|
||||
// s_rotationControl.fullValue.text = go.transform.eulerAngles.ToStringPretty();
|
||||
// s_rotationControl.values[0].text = go.transform.eulerAngles.x.ToString("F3");
|
||||
// s_rotationControl.values[1].text = go.transform.eulerAngles.y.ToString("F3");
|
||||
// s_rotationControl.values[2].text = go.transform.eulerAngles.z.ToString("F3");
|
||||
|
||||
// s_scaleControl.fullValue.text = go.transform.localScale.ToStringPretty();
|
||||
// s_scaleControl.values[0].text = go.transform.localScale.x.ToString("F3");
|
||||
// s_scaleControl.values[1].text = go.transform.localScale.y.ToString("F3");
|
||||
// s_scaleControl.values[2].text = go.transform.localScale.z.ToString("F3");
|
||||
|
||||
// }
|
||||
|
||||
// internal static void OnSetParentClicked()
|
||||
// {
|
||||
// var go = GameObjectInspector.ActiveInstance.TargetGO;
|
||||
|
||||
// if (!go)
|
||||
// return;
|
||||
|
||||
// var input = s_setParentInput.text;
|
||||
|
||||
// if (string.IsNullOrEmpty(input))
|
||||
// {
|
||||
// go.transform.parent = null;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (GameObject.Find(input) is GameObject newParent)
|
||||
// {
|
||||
// go.transform.parent = newParent.transform;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// ExplorerCore.Log($"Could not find any GameObject from name or path '{input}'! Note: The target must be enabled.");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// internal static void OnSliderControlChanged(float value, Slider slider, ControlType controlType, VectorValue vectorValue)
|
||||
// {
|
||||
// if (value == 0)
|
||||
// s_sliderChangedWanted = false;
|
||||
// else
|
||||
// {
|
||||
// if (!s_sliderChangedWanted)
|
||||
// {
|
||||
// s_sliderChangedWanted = true;
|
||||
// s_currentSlider = slider;
|
||||
// s_currentSliderType = controlType;
|
||||
// s_currentSliderValueType = vectorValue;
|
||||
// }
|
||||
|
||||
// s_currentSliderValue = value;
|
||||
// }
|
||||
// }
|
||||
|
||||
// internal static void UpdateSliderControl()
|
||||
// {
|
||||
// if (!InputManager.GetMouseButton(0))
|
||||
// {
|
||||
// s_sliderChangedWanted = false;
|
||||
// s_currentSlider.value = 0;
|
||||
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if (GameObjectInspector.ActiveInstance == null) return;
|
||||
|
||||
// var transform = GameObjectInspector.ActiveInstance.TargetGO.transform;
|
||||
|
||||
// // get the current vector for the control type
|
||||
// Vector3 vector = Vector2.zero;
|
||||
// switch (s_currentSliderType)
|
||||
// {
|
||||
// case ControlType.position:
|
||||
// vector = transform.position; break;
|
||||
// case ControlType.localPosition:
|
||||
// vector = transform.localPosition; break;
|
||||
// case ControlType.eulerAngles:
|
||||
// vector = transform.eulerAngles; break;
|
||||
// case ControlType.localScale:
|
||||
// vector = transform.localScale; break;
|
||||
// }
|
||||
|
||||
// // apply vector value change
|
||||
// switch (s_currentSliderValueType)
|
||||
// {
|
||||
// case VectorValue.x:
|
||||
// vector.x += s_currentSliderValue; break;
|
||||
// case VectorValue.y:
|
||||
// vector.y += s_currentSliderValue; break;
|
||||
// case VectorValue.z:
|
||||
// vector.z += s_currentSliderValue; break;
|
||||
// }
|
||||
|
||||
// // set vector to transform member
|
||||
// switch (s_currentSliderType)
|
||||
// {
|
||||
// case ControlType.position:
|
||||
// transform.position = vector; break;
|
||||
// case ControlType.localPosition:
|
||||
// transform.localPosition = vector; break;
|
||||
// case ControlType.eulerAngles:
|
||||
// transform.eulerAngles = vector; break;
|
||||
// case ControlType.localScale:
|
||||
// transform.localScale = vector; break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// internal static void OnVectorControlInputApplied(ControlType controlType, VectorValue vectorValue)
|
||||
// {
|
||||
// if (!(InspectorManager.Instance.m_activeInspector is GameObjectInspector instance)) return;
|
||||
|
||||
// // get relevant input for controltype + value
|
||||
|
||||
// InputField[] inputs = null;
|
||||
// switch (controlType)
|
||||
// {
|
||||
// case ControlType.position:
|
||||
// inputs = s_positionControl.inputs; break;
|
||||
// case ControlType.localPosition:
|
||||
// inputs = s_localPosControl.inputs; break;
|
||||
// case ControlType.eulerAngles:
|
||||
// inputs = s_rotationControl.inputs; break;
|
||||
// case ControlType.localScale:
|
||||
// inputs = s_scaleControl.inputs; break;
|
||||
// }
|
||||
// InputField input = inputs[(int)vectorValue];
|
||||
|
||||
// float val = float.Parse(input.text);
|
||||
|
||||
// // apply transform value
|
||||
|
||||
// Vector3 vector = Vector3.zero;
|
||||
// var transform = instance.TargetGO.transform;
|
||||
// switch (controlType)
|
||||
// {
|
||||
// case ControlType.position:
|
||||
// vector = transform.position; break;
|
||||
// case ControlType.localPosition:
|
||||
// vector = transform.localPosition; break;
|
||||
// case ControlType.eulerAngles:
|
||||
// vector = transform.eulerAngles; break;
|
||||
// case ControlType.localScale:
|
||||
// vector = transform.localScale; break;
|
||||
// }
|
||||
|
||||
// switch (vectorValue)
|
||||
// {
|
||||
// case VectorValue.x:
|
||||
// vector.x = val; break;
|
||||
// case VectorValue.y:
|
||||
// vector.y = val; break;
|
||||
// case VectorValue.z:
|
||||
// vector.z = val; break;
|
||||
// }
|
||||
|
||||
// // set back to transform
|
||||
// switch (controlType)
|
||||
// {
|
||||
// case ControlType.position:
|
||||
// transform.position = vector; break;
|
||||
// case ControlType.localPosition:
|
||||
// transform.localPosition = vector; break;
|
||||
// case ControlType.eulerAngles:
|
||||
// transform.eulerAngles = vector; break;
|
||||
// case ControlType.localScale:
|
||||
// transform.localScale = vector; break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// //#region UI CONSTRUCTION
|
||||
|
||||
// //internal void ConstructControls(GameObject parent)
|
||||
// //{
|
||||
// // var mainGroup = UIFactory.CreateVerticalGroup(parent, "ControlsGroup", false, false, true, true, 5, new Vector4(4,4,4,4),
|
||||
// // new Color(0.07f, 0.07f, 0.07f));
|
||||
|
||||
// // // ~~~~~~ Top row ~~~~~~
|
||||
|
||||
// // var topRow = UIFactory.CreateHorizontalGroup(mainGroup, "TopRow", false, false, true, true, 5, default, new Color(1, 1, 1, 0));
|
||||
|
||||
// // var hideButton = UIFactory.CreateButton(topRow, "ToggleShowButton", "Show", ToggleVisibility, new Color(0.16f, 0.16f, 0.16f));
|
||||
// // UIFactory.SetLayoutElement(hideButton.gameObject, minWidth: 40, flexibleWidth: 0, minHeight: 25, flexibleHeight: 0);
|
||||
// // m_hideShowLabel = hideButton.GetComponentInChildren<Text>();
|
||||
|
||||
// // var topTitle = UIFactory.CreateLabel(topRow, "ControlsLabel", "Controls", TextAnchor.MiddleLeft);
|
||||
// // UIFactory.SetLayoutElement(topTitle.gameObject, minWidth: 100, flexibleWidth: 9500, minHeight: 25);
|
||||
|
||||
// // //// ~~~~~~~~ Content ~~~~~~~~ //
|
||||
|
||||
// // m_contentObj = UIFactory.CreateVerticalGroup(mainGroup, "ContentGroup", true, false, true, true, 5, default, new Color(1, 1, 1, 0));
|
||||
|
||||
// // // transform controls
|
||||
// // ConstructVector3Editor(m_contentObj, "Position", ControlType.position, out s_positionControl);
|
||||
// // ConstructVector3Editor(m_contentObj, "Local Position", ControlType.localPosition, out s_localPosControl);
|
||||
// // ConstructVector3Editor(m_contentObj, "Rotation", ControlType.eulerAngles, out s_rotationControl);
|
||||
// // ConstructVector3Editor(m_contentObj, "Scale", ControlType.localScale, out s_scaleControl);
|
||||
|
||||
// // // set parent
|
||||
// // ConstructSetParent(m_contentObj);
|
||||
|
||||
// // // bottom row buttons
|
||||
// // ConstructBottomButtons(m_contentObj);
|
||||
|
||||
// // // set controls content inactive now that content is made (otherwise TMP font size goes way too big?)
|
||||
// // m_contentObj.SetActive(false);
|
||||
// //}
|
||||
|
||||
// //internal void ConstructSetParent(GameObject contentObj)
|
||||
// //{
|
||||
// // var setParentGroupObj = UIFactory.CreateHorizontalGroup(contentObj, "SetParentRow", false, false, true, true, 5, default,
|
||||
// // new Color(1, 1, 1, 0));
|
||||
// // UIFactory.SetLayoutElement(setParentGroupObj, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
// // var title = UIFactory.CreateLabel(setParentGroupObj, "SetParentLabel", "Set Parent:", TextAnchor.MiddleLeft, Color.grey);
|
||||
// // UIFactory.SetLayoutElement(title.gameObject, minWidth: 110, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
// // var inputFieldObj = UIFactory.CreateInputField(setParentGroupObj, "SetParentInputField", "Enter a GameObject name or path...");
|
||||
// // s_setParentInput = inputFieldObj.GetComponent<InputField>();
|
||||
// // UIFactory.SetLayoutElement(inputFieldObj, minHeight: 25, preferredWidth: 400, flexibleWidth: 9999);
|
||||
|
||||
// // var applyButton = UIFactory.CreateButton(setParentGroupObj, "SetParentButton", "Apply", OnSetParentClicked);
|
||||
// // UIFactory.SetLayoutElement(applyButton.gameObject, minWidth: 55, flexibleWidth: 0, minHeight: 25, flexibleHeight: 0);
|
||||
// //}
|
||||
|
||||
// //internal void ConstructVector3Editor(GameObject parent, string titleText, ControlType type, out ControlEditor editor)
|
||||
// //{
|
||||
// // editor = new ControlEditor();
|
||||
|
||||
// // var topBarObj = UIFactory.CreateHorizontalGroup(parent, "Vector3Editor", false, false, true, true, 5, default, new Color(1, 1, 1, 0));
|
||||
// // UIFactory.SetLayoutElement(topBarObj, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
// // var title = UIFactory.CreateLabel(topBarObj, "Title", titleText, TextAnchor.MiddleLeft, Color.grey);
|
||||
// // UIFactory.SetLayoutElement(title.gameObject, minWidth: 110, flexibleWidth: 0, minHeight: 25);
|
||||
|
||||
// // // expand button
|
||||
// // var expandButton = UIFactory.CreateButton(topBarObj, "ExpandArrow", "▼");
|
||||
// // var expandText = expandButton.GetComponentInChildren<Text>();
|
||||
// // expandText.fontSize = 12;
|
||||
// // UIFactory.SetLayoutElement(expandButton.gameObject, minWidth: 35, flexibleWidth: 0, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
// // // readonly value input
|
||||
|
||||
// // var valueInputObj = UIFactory.CreateInputField(topBarObj, "ValueInput", "...");
|
||||
// // var valueInput = valueInputObj.GetComponent<InputField>();
|
||||
// // valueInput.readOnly = true;
|
||||
// // UIFactory.SetLayoutElement(valueInputObj, minHeight: 25, flexibleHeight: 0, preferredWidth: 400, flexibleWidth: 9999);
|
||||
|
||||
// // editor.fullValue = valueInput;
|
||||
|
||||
// // editor.sliders = new Slider[3];
|
||||
// // editor.inputs = new InputField[3];
|
||||
// // editor.values = new Text[3];
|
||||
|
||||
// // var xRow = ConstructEditorRow(parent, editor, type, VectorValue.x);
|
||||
// // xRow.SetActive(false);
|
||||
// // var yRow = ConstructEditorRow(parent, editor, type, VectorValue.y);
|
||||
// // yRow.SetActive(false);
|
||||
// // var zRow = ConstructEditorRow(parent, editor, type, VectorValue.z);
|
||||
// // zRow.SetActive(false);
|
||||
|
||||
// // // add expand callback now that we have group reference
|
||||
// // expandButton.onClick.AddListener(ToggleExpand);
|
||||
// // void ToggleExpand()
|
||||
// // {
|
||||
// // if (xRow.activeSelf)
|
||||
// // {
|
||||
// // xRow.SetActive(false);
|
||||
// // yRow.SetActive(false);
|
||||
// // zRow.SetActive(false);
|
||||
// // expandText.text = "▼";
|
||||
// // }
|
||||
// // else
|
||||
// // {
|
||||
// // xRow.SetActive(true);
|
||||
// // yRow.SetActive(true);
|
||||
// // zRow.SetActive(true);
|
||||
// // expandText.text = "▲";
|
||||
// // }
|
||||
// // }
|
||||
// //}
|
||||
|
||||
// //internal GameObject ConstructEditorRow(GameObject parent, ControlEditor editor, ControlType type, VectorValue vectorValue)
|
||||
// //{
|
||||
// // var rowObject = UIFactory.CreateHorizontalGroup(parent, "EditorRow", false, false, true, true, 5, default, new Color(1, 1, 1, 0));
|
||||
// // UIFactory.SetLayoutElement(rowObject, minHeight: 25, flexibleHeight: 0, minWidth: 100);
|
||||
|
||||
// // // Value labels
|
||||
|
||||
// // var valueTitle = UIFactory.CreateLabel(rowObject, "ValueTitle", $"{vectorValue.ToString().ToUpper()}:", TextAnchor.MiddleLeft, Color.cyan);
|
||||
// // UIFactory.SetLayoutElement(valueTitle.gameObject, minHeight: 25, flexibleHeight: 0, minWidth: 25, flexibleWidth: 0);
|
||||
|
||||
// // // actual value label
|
||||
// // var valueLabel = UIFactory.CreateLabel(rowObject, "ValueLabel", "", TextAnchor.MiddleLeft);
|
||||
// // editor.values[(int)vectorValue] = valueLabel;
|
||||
// // UIFactory.SetLayoutElement(valueLabel.gameObject, minWidth: 85, flexibleWidth: 0, minHeight: 25);
|
||||
|
||||
// // // input field
|
||||
|
||||
// // var inputHolder = UIFactory.CreateVerticalGroup(rowObject, "InputFieldGroup", false, false, true, true, 0, default, new Color(1, 1, 1, 0));
|
||||
|
||||
// // var inputObj = UIFactory.CreateInputField(inputHolder, "InputField", "...");
|
||||
// // var input = inputObj.GetComponent<InputField>();
|
||||
// // //input.characterValidation = InputField.CharacterValidation.Decimal;
|
||||
|
||||
// // UIFactory.SetLayoutElement(inputObj, minHeight: 25, flexibleHeight: 0, minWidth: 90, flexibleWidth: 50);
|
||||
|
||||
// // editor.inputs[(int)vectorValue] = input;
|
||||
|
||||
// // // apply button
|
||||
|
||||
// // var applyBtn = UIFactory.CreateButton(rowObject, "ApplyButton", "Apply", () => { OnVectorControlInputApplied(type, vectorValue); });
|
||||
// // UIFactory.SetLayoutElement(applyBtn.gameObject, minWidth: 60, minHeight: 25);
|
||||
|
||||
|
||||
// // // Slider
|
||||
|
||||
// // var sliderObj = UIFactory.CreateSlider(rowObject, "VectorSlider", out Slider slider);
|
||||
// // UIFactory.SetLayoutElement(sliderObj, minHeight: 20, flexibleHeight: 0, minWidth: 200, flexibleWidth: 9000);
|
||||
// // sliderObj.transform.Find("Fill Area").gameObject.SetActive(false);
|
||||
// // RuntimeProvider.Instance.SetColorBlock(slider, new Color(0.65f, 0.65f, 0.65f));
|
||||
// // slider.minValue = -2;
|
||||
// // slider.maxValue = 2;
|
||||
// // slider.value = 0;
|
||||
// // slider.onValueChanged.AddListener((float val) => { OnSliderControlChanged(val, slider, type, vectorValue); });
|
||||
// // editor.sliders[(int)vectorValue] = slider;
|
||||
|
||||
// // return rowObject;
|
||||
// //}
|
||||
|
||||
// //internal void ConstructBottomButtons(GameObject contentObj)
|
||||
// //{
|
||||
// // var bottomRow = UIFactory.CreateHorizontalGroup(contentObj, "BottomButtons", true, true, false, false, 4, default, new Color(1, 1, 1, 0));
|
||||
|
||||
// // var instantiateBtn = UIFactory.CreateButton(bottomRow, "InstantiateBtn", "Instantiate", InstantiateBtn, new Color(0.2f, 0.2f, 0.2f));
|
||||
// // UIFactory.SetLayoutElement(instantiateBtn.gameObject, minWidth: 150);
|
||||
|
||||
// // void InstantiateBtn()
|
||||
// // {
|
||||
// // var go = GameObjectInspector.ActiveInstance.TargetGO;
|
||||
// // if (!go)
|
||||
// // return;
|
||||
|
||||
// // var clone = GameObject.Instantiate(go);
|
||||
// // InspectorManager.Instance.Inspect(clone);
|
||||
// // }
|
||||
|
||||
// // var dontDestroyBtn = UIFactory.CreateButton(bottomRow, "DontDestroyButton", "Set DontDestroyOnLoad", DontDestroyOnLoadBtn,
|
||||
// // new Color(0.2f, 0.2f, 0.2f));
|
||||
// // UIFactory.SetLayoutElement(dontDestroyBtn.gameObject, flexibleWidth: 5000);
|
||||
|
||||
// // void DontDestroyOnLoadBtn()
|
||||
// // {
|
||||
// // var go = GameObjectInspector.ActiveInstance.TargetGO;
|
||||
// // if (!go)
|
||||
// // return;
|
||||
|
||||
// // GameObject.DontDestroyOnLoad(go);
|
||||
// // }
|
||||
|
||||
// // var destroyBtn = UIFactory.CreateButton(bottomRow, "DestroyButton", "Destroy", DestroyBtn, new Color(0.2f, 0.2f, 0.2f));
|
||||
// // UIFactory.SetLayoutElement(destroyBtn.gameObject, minWidth: 150);
|
||||
// // var destroyText = destroyBtn.GetComponentInChildren<Text>();
|
||||
// // destroyText.color = Color.red;
|
||||
|
||||
// // void DestroyBtn()
|
||||
// // {
|
||||
// // var go = GameObjectInspector.ActiveInstance.TargetGO;
|
||||
// // if (!go)
|
||||
// // return;
|
||||
|
||||
// // GameObject.Destroy(go);
|
||||
// // }
|
||||
// //}
|
||||
|
||||
// //#endregion
|
||||
// }
|
||||
//}
|
349
src/UI/Inspectors/GameObjects/GameObjectInspector.cs
Normal file
349
src/UI/Inspectors/GameObjects/GameObjectInspector.cs
Normal file
@ -0,0 +1,349 @@
|
||||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using System.Text;
|
||||
//using UnityEngine;
|
||||
//using UnityEngine.UI;
|
||||
//using UnityExplorer.Core.Runtime;
|
||||
|
||||
//namespace UnityExplorer.UI.Inspectors.GameObjects
|
||||
//{
|
||||
// public class GameObjectInspector : InspectorBase
|
||||
// {
|
||||
// public override string TabLabel => $" <color=cyan>[G]</color> {TargetGO?.name}";
|
||||
|
||||
// public static GameObjectInspector ActiveInstance { get; private set; }
|
||||
|
||||
// public GameObject TargetGO;
|
||||
|
||||
// //// sub modules
|
||||
// //internal static ChildList s_childList;
|
||||
// //internal static ComponentList s_compList;
|
||||
// //internal static GameObjectControls s_controls;
|
||||
|
||||
// internal static bool m_UIConstructed;
|
||||
|
||||
// public GameObjectInspector(GameObject target) : base(target)
|
||||
// {
|
||||
// ActiveInstance = this;
|
||||
|
||||
// TargetGO = target;
|
||||
|
||||
// if (!TargetGO)
|
||||
// {
|
||||
// ExplorerCore.LogWarning("Target GameObject is null!");
|
||||
// return;
|
||||
// }
|
||||
|
||||
// // one UI is used for all gameobject inspectors. no point recreating it.
|
||||
// if (!m_UIConstructed)
|
||||
// {
|
||||
// m_UIConstructed = true;
|
||||
|
||||
// //s_childList = new ChildList();
|
||||
// //s_compList = new ComponentList();
|
||||
// //s_controls = new GameObjectControls();
|
||||
|
||||
// //ConstructUI();
|
||||
// }
|
||||
// }
|
||||
|
||||
// public override void SetActive()
|
||||
// {
|
||||
// base.SetActive();
|
||||
// ActiveInstance = this;
|
||||
// }
|
||||
|
||||
// public override void SetInactive()
|
||||
// {
|
||||
// base.SetInactive();
|
||||
// ActiveInstance = null;
|
||||
// }
|
||||
|
||||
// internal void ChangeInspectorTarget(GameObject newTarget)
|
||||
// {
|
||||
// if (!newTarget)
|
||||
// return;
|
||||
|
||||
// this.Target = this.TargetGO = newTarget;
|
||||
// }
|
||||
|
||||
// // Update
|
||||
|
||||
// //public override void Update()
|
||||
// //{
|
||||
// // base.Update();
|
||||
|
||||
// // if (m_pendingDestroy || !this.IsActive)
|
||||
// // return;
|
||||
|
||||
// // RefreshTopInfo();
|
||||
|
||||
// // s_childList.RefreshChildObjectList();
|
||||
|
||||
// // s_compList.RefreshComponentList();
|
||||
|
||||
// // s_controls.RefreshControls();
|
||||
|
||||
// // if (GameObjectControls.s_sliderChangedWanted)
|
||||
// // GameObjectControls.UpdateSliderControl();
|
||||
// //}
|
||||
|
||||
// private static GameObject s_content;
|
||||
// public override GameObject Content
|
||||
// {
|
||||
// get => s_content;
|
||||
// set => s_content = value;
|
||||
// }
|
||||
|
||||
// private static string m_lastName;
|
||||
// public static InputField m_nameInput;
|
||||
|
||||
// private static string m_lastPath;
|
||||
// public static InputField m_pathInput;
|
||||
// private static RectTransform m_pathInputRect;
|
||||
// private static GameObject m_pathGroupObj;
|
||||
// private static Text m_hiddenPathText;
|
||||
// private static RectTransform m_hiddenPathRect;
|
||||
|
||||
// private static Toggle m_enabledToggle;
|
||||
// private static Text m_enabledText;
|
||||
// private static bool? m_lastEnabledState;
|
||||
|
||||
// private static Dropdown m_layerDropdown;
|
||||
// private static int m_lastLayer = -1;
|
||||
|
||||
// private static Text m_sceneText;
|
||||
// private static string m_lastScene;
|
||||
|
||||
// internal void RefreshTopInfo()
|
||||
// {
|
||||
// var target = TargetGO;
|
||||
// string name = target.name;
|
||||
|
||||
// if (m_lastName != name)
|
||||
// {
|
||||
// m_lastName = name;
|
||||
// m_nameInput.text = m_lastName;
|
||||
// }
|
||||
|
||||
// if (target.transform.parent)
|
||||
// {
|
||||
// if (!m_pathGroupObj.activeSelf)
|
||||
// m_pathGroupObj.SetActive(true);
|
||||
|
||||
// var path = target.transform.GetTransformPath(true);
|
||||
// if (m_lastPath != path)
|
||||
// {
|
||||
// m_lastPath = path;
|
||||
|
||||
// m_pathInput.text = path;
|
||||
// m_hiddenPathText.text = path;
|
||||
|
||||
// LayoutRebuilder.ForceRebuildLayoutImmediate(m_pathInputRect);
|
||||
// LayoutRebuilder.ForceRebuildLayoutImmediate(m_hiddenPathRect);
|
||||
// }
|
||||
// }
|
||||
// else if (m_pathGroupObj.activeSelf)
|
||||
// m_pathGroupObj.SetActive(false);
|
||||
|
||||
// if (m_lastEnabledState != target.activeSelf)
|
||||
// {
|
||||
// m_lastEnabledState = target.activeSelf;
|
||||
|
||||
// m_enabledToggle.isOn = target.activeSelf;
|
||||
// m_enabledText.text = target.activeSelf ? "Enabled" : "Disabled";
|
||||
// m_enabledText.color = target.activeSelf ? Color.green : Color.red;
|
||||
// }
|
||||
|
||||
// if (m_lastLayer != target.layer)
|
||||
// {
|
||||
// m_lastLayer = target.layer;
|
||||
// m_layerDropdown.value = target.layer;
|
||||
// }
|
||||
|
||||
// if (string.IsNullOrEmpty(m_lastScene) || m_lastScene != target.scene.name)
|
||||
// {
|
||||
// m_lastScene = target.scene.name;
|
||||
|
||||
// if (!string.IsNullOrEmpty(target.scene.name))
|
||||
// m_sceneText.text = m_lastScene;
|
||||
// else
|
||||
// m_sceneText.text = "None (Asset/Resource)";
|
||||
// }
|
||||
// }
|
||||
|
||||
// // UI Callbacks
|
||||
|
||||
// private static void OnApplyNameClicked()
|
||||
// {
|
||||
// if (ActiveInstance == null)
|
||||
// return;
|
||||
|
||||
// ActiveInstance.TargetGO.name = m_nameInput.text;
|
||||
// }
|
||||
|
||||
// private static void OnEnableToggled(bool enabled)
|
||||
// {
|
||||
// if (ActiveInstance == null)
|
||||
// return;
|
||||
|
||||
// ActiveInstance.TargetGO.SetActive(enabled);
|
||||
// }
|
||||
|
||||
// private static void OnLayerSelected(int layer)
|
||||
// {
|
||||
// if (ActiveInstance == null)
|
||||
// return;
|
||||
|
||||
// ActiveInstance.TargetGO.layer = layer;
|
||||
// }
|
||||
|
||||
// internal static void OnBackButtonClicked()
|
||||
// {
|
||||
// if (ActiveInstance == null)
|
||||
// return;
|
||||
|
||||
// ActiveInstance.ChangeInspectorTarget(ActiveInstance.TargetGO.transform.parent.gameObject);
|
||||
// }
|
||||
|
||||
// //#region UI CONSTRUCTION
|
||||
|
||||
// //internal void ConstructUI()
|
||||
// //{
|
||||
// // var parent = InspectorManager.m_inspectorContent;
|
||||
|
||||
// // s_content = UIFactory.CreateScrollView(parent, "GameObjectInspector_Content", out GameObject scrollContent, out _,
|
||||
// // new Color(0.1f, 0.1f, 0.1f));
|
||||
|
||||
// // UIFactory.SetLayoutGroup<VerticalLayoutGroup>(scrollContent.transform.parent.gameObject, true, true, true, true);
|
||||
|
||||
// // UIFactory.SetLayoutGroup<VerticalLayoutGroup>(scrollContent, true, true, true, true, 5);
|
||||
// // var contentFitter = scrollContent.GetComponent<ContentSizeFitter>();
|
||||
// // contentFitter.verticalFit = ContentSizeFitter.FitMode.Unconstrained;
|
||||
|
||||
// // ConstructTopArea(scrollContent);
|
||||
|
||||
// // s_controls.ConstructControls(scrollContent);
|
||||
|
||||
// // var midGroupObj = ConstructMidGroup(scrollContent);
|
||||
|
||||
// // s_childList.ConstructChildList(midGroupObj);
|
||||
// // s_compList.ConstructCompList(midGroupObj);
|
||||
|
||||
// // LayoutRebuilder.ForceRebuildLayoutImmediate(s_content.GetComponent<RectTransform>());
|
||||
// // Canvas.ForceUpdateCanvases();
|
||||
// //}
|
||||
|
||||
// //private void ConstructTopArea(GameObject scrollContent)
|
||||
// //{
|
||||
// // // path row
|
||||
|
||||
// // m_pathGroupObj = UIFactory.CreateHorizontalGroup(scrollContent, "TopArea", false, false, true, true, 5, default, new Color(0.1f, 0.1f, 0.1f));
|
||||
|
||||
// // var pathRect = m_pathGroupObj.GetComponent<RectTransform>();
|
||||
// // pathRect.sizeDelta = new Vector2(pathRect.sizeDelta.x, 20);
|
||||
// // UIFactory.SetLayoutElement(m_pathGroupObj, minHeight: 20, flexibleHeight: 75);
|
||||
|
||||
// // // Back button
|
||||
|
||||
// // var backButton = UIFactory.CreateButton(m_pathGroupObj, "BackButton", "◄", OnBackButtonClicked, new Color(0.15f, 0.15f, 0.15f));
|
||||
// // UIFactory.SetLayoutElement(backButton.gameObject, minWidth: 55, flexibleWidth: 0, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
// // m_hiddenPathText = UIFactory.CreateLabel(m_pathGroupObj, "HiddenPathText", "", TextAnchor.MiddleLeft);
|
||||
// // m_hiddenPathText.color = Color.clear;
|
||||
// // m_hiddenPathText.fontSize = 14;
|
||||
// // m_hiddenPathText.raycastTarget = false;
|
||||
|
||||
// // var hiddenFitter = m_hiddenPathText.gameObject.AddComponent<ContentSizeFitter>();
|
||||
// // hiddenFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||
|
||||
// // UIFactory.SetLayoutElement(m_hiddenPathText.gameObject, minHeight: 25, flexibleHeight: 125, minWidth: 250, flexibleWidth: 9000);
|
||||
// // UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(m_hiddenPathText.gameObject, true, true, true, true);
|
||||
|
||||
// // // Path input
|
||||
|
||||
// // var pathInputObj = UIFactory.CreateInputField(m_hiddenPathText.gameObject, "PathInputField", "...");
|
||||
// // UIFactory.SetLayoutElement(pathInputObj, minHeight: 25, flexibleHeight: 75, preferredWidth: 400, flexibleWidth: 9999);
|
||||
// // var pathInputRect = pathInputObj.GetComponent<RectTransform>();
|
||||
// // pathInputRect.sizeDelta = new Vector2(pathInputRect.sizeDelta.x, 25);
|
||||
|
||||
// // m_pathInput = pathInputObj.GetComponent<InputField>();
|
||||
// // m_pathInput.text = ActiveInstance.TargetGO.transform.GetTransformPath();
|
||||
// // m_pathInput.readOnly = true;
|
||||
// // m_pathInput.lineType = InputField.LineType.MultiLineNewline;
|
||||
// // m_pathInput.textComponent.color = new Color(0.75f, 0.75f, 0.75f);
|
||||
|
||||
// // var textRect = m_pathInput.textComponent.GetComponent<RectTransform>();
|
||||
// // textRect.offsetMin = new Vector2(3, 3);
|
||||
// // textRect.offsetMax = new Vector2(3, 3);
|
||||
|
||||
// // m_pathInputRect = m_pathInput.GetComponent<RectTransform>();
|
||||
// // m_hiddenPathRect = m_hiddenPathText.GetComponent<RectTransform>();
|
||||
|
||||
// // // name and enabled row
|
||||
|
||||
// // var nameRowObj = UIFactory.CreateHorizontalGroup(scrollContent, "NameGroup", false, false, true, true, 5, default, new Color(0.1f, 0.1f, 0.1f));
|
||||
// // UIFactory.SetLayoutElement(nameRowObj, minHeight: 25, flexibleHeight: 0);
|
||||
// // var nameRect = nameRowObj.GetComponent<RectTransform>();
|
||||
// // nameRect.sizeDelta = new Vector2(nameRect.sizeDelta.x, 25);
|
||||
|
||||
// // var nameLabel = UIFactory.CreateLabel(nameRowObj, "NameLabel", "Name:", TextAnchor.MiddleCenter, Color.grey, true, 14);
|
||||
// // UIFactory.SetLayoutElement(nameLabel.gameObject, minHeight: 25, flexibleHeight: 0, minWidth: 55, flexibleWidth: 0);
|
||||
|
||||
// // var nameInputObj = UIFactory.CreateInputField(nameRowObj, "NameInput", "...");
|
||||
// // var nameInputRect = nameInputObj.GetComponent<RectTransform>();
|
||||
// // nameInputRect.sizeDelta = new Vector2(nameInputRect.sizeDelta.x, 25);
|
||||
// // m_nameInput = nameInputObj.GetComponent<InputField>();
|
||||
// // m_nameInput.text = ActiveInstance.TargetGO.name;
|
||||
|
||||
// // var applyNameBtn = UIFactory.CreateButton(nameRowObj, "ApplyNameButton", "Apply", OnApplyNameClicked);
|
||||
// // UIFactory.SetLayoutElement(applyNameBtn.gameObject, minWidth: 65, minHeight: 25, flexibleHeight: 0);
|
||||
// // var applyNameRect = applyNameBtn.GetComponent<RectTransform>();
|
||||
// // applyNameRect.sizeDelta = new Vector2(applyNameRect.sizeDelta.x, 25);
|
||||
|
||||
// // var activeLabel = UIFactory.CreateLabel(nameRowObj, "ActiveLabel", "Active:", TextAnchor.MiddleCenter, Color.grey, true, 14);
|
||||
// // UIFactory.SetLayoutElement(activeLabel.gameObject, minWidth: 55, minHeight: 25);
|
||||
|
||||
// // var enabledToggleObj = UIFactory.CreateToggle(nameRowObj, "EnabledToggle", out m_enabledToggle, out m_enabledText);
|
||||
// // UIFactory.SetLayoutElement(enabledToggleObj, minHeight: 25, minWidth: 100, flexibleWidth: 0);
|
||||
// // m_enabledText.text = "Enabled";
|
||||
// // m_enabledText.color = Color.green;
|
||||
// // m_enabledToggle.onValueChanged.AddListener(OnEnableToggled);
|
||||
|
||||
// // // layer and scene row
|
||||
|
||||
// // var sceneLayerRow = UIFactory.CreateHorizontalGroup(scrollContent, "SceneLayerRow", false, true, true, true, 5, default, new Color(0.1f, 0.1f, 0.1f));
|
||||
|
||||
// // // layer
|
||||
|
||||
// // var layerLabel = UIFactory.CreateLabel(sceneLayerRow, "LayerLabel", "Layer:", TextAnchor.MiddleCenter, Color.grey, true, 14);
|
||||
// // UIFactory.SetLayoutElement(layerLabel.gameObject, minWidth: 55, flexibleWidth: 0);
|
||||
|
||||
// // var layerDropdownObj = UIFactory.CreateDropdown(sceneLayerRow, out m_layerDropdown, "", 14, OnLayerSelected);
|
||||
// // m_layerDropdown.options.Clear();
|
||||
// // for (int i = 0; i < 32; i++)
|
||||
// // {
|
||||
// // var layer = RuntimeProvider.Instance.LayerToName(i);
|
||||
// // m_layerDropdown.options.Add(new Dropdown.OptionData { text = $"{i}: {layer}" });
|
||||
// // }
|
||||
// // UIFactory.SetLayoutElement(layerDropdownObj, minWidth: 120, flexibleWidth: 2000, minHeight: 25);
|
||||
|
||||
// // // scene
|
||||
|
||||
// // var sceneLabel = UIFactory.CreateLabel(sceneLayerRow, "SceneLabel", "Scene:", TextAnchor.MiddleCenter, Color.grey, true, 14);
|
||||
// // UIFactory.SetLayoutElement(sceneLabel.gameObject, minWidth: 55, flexibleWidth: 0);
|
||||
|
||||
// // m_sceneText = UIFactory.CreateLabel(sceneLayerRow, "SceneText", "", TextAnchor.MiddleLeft);
|
||||
// // UIFactory.SetLayoutElement(m_sceneText.gameObject, minWidth: 120, flexibleWidth: 2000);
|
||||
// //}
|
||||
|
||||
// //private GameObject ConstructMidGroup(GameObject parent)
|
||||
// //{
|
||||
// // var midGroupObj = UIFactory.CreateHorizontalGroup(parent, "MidGroup", true, true, true, true, 5, default, new Color(1, 1, 1, 0));
|
||||
// // UIFactory.SetLayoutElement(midGroupObj, minHeight: 300, flexibleHeight: 3000);
|
||||
// // return midGroupObj;
|
||||
// //}
|
||||
// //#endregion
|
||||
// }
|
||||
//}
|
327
src/UI/Inspectors/InspectUnderMouse.cs
Normal file
327
src/UI/Inspectors/InspectUnderMouse.cs
Normal file
@ -0,0 +1,327 @@
|
||||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using System.Text;
|
||||
//using UnityEngine;
|
||||
//using UnityEngine.EventSystems;
|
||||
//using UnityEngine.UI;
|
||||
//using UnityExplorer.Core;
|
||||
//using UnityExplorer.Core.Input;
|
||||
//using UnityExplorer.Core.Runtime;
|
||||
//using UnityExplorer.UI;
|
||||
//using UnityExplorer.UI.Main;
|
||||
//using UnityExplorer.UI.Inspectors;
|
||||
|
||||
//namespace UnityExplorer.UI.Main.Home
|
||||
//{
|
||||
// public class InspectUnderMouse
|
||||
// {
|
||||
// public enum MouseInspectMode
|
||||
// {
|
||||
// World,
|
||||
// UI
|
||||
// }
|
||||
|
||||
// public static bool Inspecting { get; set; }
|
||||
|
||||
// public static MouseInspectMode Mode { get; set; }
|
||||
|
||||
// private static GameObject s_lastHit;
|
||||
// private static Vector3 s_lastMousePos;
|
||||
|
||||
// private static readonly List<Graphic> _wasDisabledGraphics = new List<Graphic>();
|
||||
// private static readonly List<CanvasGroup> _wasDisabledCanvasGroups = new List<CanvasGroup>();
|
||||
// private static readonly List<GameObject> _objectsAddedCastersTo = new List<GameObject>();
|
||||
|
||||
// internal static Camera MainCamera;
|
||||
// internal static GraphicRaycaster[] graphicRaycasters;
|
||||
|
||||
// public static void Init()
|
||||
// {
|
||||
// ConstructUI();
|
||||
// }
|
||||
|
||||
// public static void StartInspect(MouseInspectMode mode)
|
||||
// {
|
||||
// MainCamera = Camera.main;
|
||||
// if (!MainCamera)
|
||||
// return;
|
||||
|
||||
// Mode = mode;
|
||||
// Inspecting = true;
|
||||
// MainMenu.Instance.MainPanel.SetActive(false);
|
||||
|
||||
// s_UIContent.SetActive(true);
|
||||
|
||||
// if (mode == MouseInspectMode.UI)
|
||||
// SetupUIRaycast();
|
||||
// }
|
||||
|
||||
// internal static void ClearHitData()
|
||||
// {
|
||||
// s_lastHit = null;
|
||||
// s_objNameLabel.text = "No hits...";
|
||||
// s_objPathLabel.text = "";
|
||||
// }
|
||||
|
||||
// public static void StopInspect()
|
||||
// {
|
||||
// Inspecting = false;
|
||||
// MainMenu.Instance.MainPanel.SetActive(true);
|
||||
// s_UIContent.SetActive(false);
|
||||
|
||||
// if (Mode == MouseInspectMode.UI)
|
||||
// StopUIInspect();
|
||||
|
||||
// ClearHitData();
|
||||
// }
|
||||
|
||||
// public static void UpdateInspect()
|
||||
// {
|
||||
// if (InputManager.GetKeyDown(KeyCode.Escape))
|
||||
// {
|
||||
// StopInspect();
|
||||
// return;
|
||||
// }
|
||||
|
||||
// var mousePos = InputManager.MousePosition;
|
||||
|
||||
// if (mousePos != s_lastMousePos)
|
||||
// UpdatePosition(mousePos);
|
||||
|
||||
// // actual inspect raycast
|
||||
|
||||
// switch (Mode)
|
||||
// {
|
||||
// case MouseInspectMode.UI:
|
||||
// RaycastUI(mousePos); break;
|
||||
// case MouseInspectMode.World:
|
||||
// RaycastWorld(mousePos); break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// internal static void UpdatePosition(Vector2 mousePos)
|
||||
// {
|
||||
// s_lastMousePos = mousePos;
|
||||
|
||||
// var inversePos = UIManager.CanvasRoot.transform.InverseTransformPoint(mousePos);
|
||||
|
||||
// s_mousePosLabel.text = $"<color=grey>Mouse Position:</color> {mousePos.ToString()}";
|
||||
|
||||
// float yFix = mousePos.y < 120 ? 80 : -80;
|
||||
// s_UIContent.transform.localPosition = new Vector3(inversePos.x, inversePos.y + yFix, 0);
|
||||
// }
|
||||
|
||||
// internal static void OnHitGameObject(GameObject obj)
|
||||
// {
|
||||
// if (obj != s_lastHit)
|
||||
// {
|
||||
// s_lastHit = obj;
|
||||
// s_objNameLabel.text = $"<b>Click to Inspect:</b> <color=cyan>{obj.name}</color>";
|
||||
// s_objPathLabel.text = $"Path: {obj.transform.GetTransformPath(true)}";
|
||||
// }
|
||||
|
||||
// if (InputManager.GetMouseButtonDown(0))
|
||||
// {
|
||||
// StopInspect();
|
||||
// InspectorManager.Instance.Inspect(obj);
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Collider raycasting
|
||||
|
||||
// internal static void RaycastWorld(Vector2 mousePos)
|
||||
// {
|
||||
// var ray = MainCamera.ScreenPointToRay(mousePos);
|
||||
// Physics.Raycast(ray, out RaycastHit hit, 1000f);
|
||||
|
||||
// if (hit.transform)
|
||||
// {
|
||||
// var obj = hit.transform.gameObject;
|
||||
// OnHitGameObject(obj);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (s_lastHit)
|
||||
// ClearHitData();
|
||||
// }
|
||||
// }
|
||||
|
||||
// // UI Graphic raycasting
|
||||
|
||||
// private static void SetupUIRaycast()
|
||||
// {
|
||||
// foreach (var obj in RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(Canvas)))
|
||||
// {
|
||||
// var canvas = obj.Cast(typeof(Canvas)) as Canvas;
|
||||
// if (!canvas || !canvas.enabled || !canvas.gameObject.activeInHierarchy)
|
||||
// continue;
|
||||
// if (!canvas.GetComponent<GraphicRaycaster>())
|
||||
// {
|
||||
// canvas.gameObject.AddComponent<GraphicRaycaster>();
|
||||
// //ExplorerCore.Log("Added raycaster to " + canvas.name);
|
||||
// _objectsAddedCastersTo.Add(canvas.gameObject);
|
||||
// }
|
||||
// }
|
||||
|
||||
// // recache Graphic Raycasters each time we start
|
||||
// var casters = RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(GraphicRaycaster));
|
||||
// graphicRaycasters = new GraphicRaycaster[casters.Length];
|
||||
// for (int i = 0; i < casters.Length; i++)
|
||||
// {
|
||||
// graphicRaycasters[i] = casters[i].Cast(typeof(GraphicRaycaster)) as GraphicRaycaster;
|
||||
// }
|
||||
|
||||
// // enable raycastTarget on Graphics
|
||||
// foreach (var obj in RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(Graphic)))
|
||||
// {
|
||||
// var graphic = obj.Cast(typeof(Graphic)) as Graphic;
|
||||
// if (!graphic || !graphic.enabled || graphic.raycastTarget || !graphic.gameObject.activeInHierarchy)
|
||||
// continue;
|
||||
// graphic.raycastTarget = true;
|
||||
// //ExplorerCore.Log("Enabled raycastTarget on " + graphic.name);
|
||||
// _wasDisabledGraphics.Add(graphic);
|
||||
// }
|
||||
|
||||
// // enable blocksRaycasts on CanvasGroups
|
||||
// foreach (var obj in RuntimeProvider.Instance.FindObjectsOfTypeAll(typeof(CanvasGroup)))
|
||||
// {
|
||||
// var canvas = obj.Cast(typeof(CanvasGroup)) as CanvasGroup;
|
||||
// if (!canvas || !canvas.gameObject.activeInHierarchy || canvas.blocksRaycasts)
|
||||
// continue;
|
||||
// canvas.blocksRaycasts = true;
|
||||
// //ExplorerCore.Log("Enabled raycasts on " + canvas.name);
|
||||
// _wasDisabledCanvasGroups.Add(canvas);
|
||||
// }
|
||||
// }
|
||||
|
||||
// internal static void RaycastUI(Vector2 mousePos)
|
||||
// {
|
||||
// var ped = new PointerEventData(null)
|
||||
// {
|
||||
// position = mousePos
|
||||
// };
|
||||
|
||||
// //ExplorerCore.Log("~~~~~~~~~ begin raycast ~~~~~~~~");
|
||||
// GameObject hitObject = null;
|
||||
// int highestLayer = int.MinValue;
|
||||
// int highestOrder = int.MinValue;
|
||||
// int highestDepth = int.MinValue;
|
||||
// foreach (var gr in graphicRaycasters)
|
||||
// {
|
||||
// var list = new List<RaycastResult>();
|
||||
// RuntimeProvider.Instance.GraphicRaycast(gr, ped, list);
|
||||
|
||||
// //gr.Raycast(ped, list);
|
||||
|
||||
// if (list.Count > 0)
|
||||
// {
|
||||
// foreach (var hit in list)
|
||||
// {
|
||||
// // Manual trying to determine which object is "on top".
|
||||
// // Not perfect, but not terrible.
|
||||
|
||||
// if (!hit.gameObject)
|
||||
// continue;
|
||||
|
||||
// if (hit.gameObject.GetComponent<CanvasGroup>() is CanvasGroup group && group.alpha == 0)
|
||||
// continue;
|
||||
|
||||
// if (hit.gameObject.GetComponent<Graphic>() is Graphic graphic && graphic.color.a == 0f)
|
||||
// continue;
|
||||
|
||||
// if (hit.sortingLayer < highestLayer)
|
||||
// continue;
|
||||
|
||||
// if (hit.sortingLayer > highestLayer)
|
||||
// {
|
||||
// highestLayer = hit.sortingLayer;
|
||||
// highestDepth = int.MinValue;
|
||||
// }
|
||||
|
||||
// if (hit.depth < highestDepth)
|
||||
// continue;
|
||||
|
||||
// if (hit.depth > highestDepth)
|
||||
// {
|
||||
// highestDepth = hit.depth;
|
||||
// highestOrder = int.MinValue;
|
||||
// }
|
||||
|
||||
// if (hit.sortingOrder <= highestOrder)
|
||||
// continue;
|
||||
|
||||
// highestOrder = hit.sortingOrder;
|
||||
// hitObject = hit.gameObject;
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (s_lastHit)
|
||||
// ClearHitData();
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (hitObject)
|
||||
// OnHitGameObject(hitObject);
|
||||
|
||||
// //ExplorerCore.Log("~~~~~~~~~ end raycast ~~~~~~~~");
|
||||
// }
|
||||
|
||||
// private static void StopUIInspect()
|
||||
// {
|
||||
// foreach (var obj in _objectsAddedCastersTo)
|
||||
// {
|
||||
// if (obj.GetComponent<GraphicRaycaster>() is GraphicRaycaster raycaster)
|
||||
// GameObject.Destroy(raycaster);
|
||||
// }
|
||||
|
||||
// foreach (var graphic in _wasDisabledGraphics)
|
||||
// graphic.raycastTarget = false;
|
||||
|
||||
// foreach (var canvas in _wasDisabledCanvasGroups)
|
||||
// canvas.blocksRaycasts = false;
|
||||
|
||||
// _objectsAddedCastersTo.Clear();
|
||||
// _wasDisabledCanvasGroups.Clear();
|
||||
// _wasDisabledGraphics.Clear();
|
||||
// }
|
||||
|
||||
// internal static Text s_objNameLabel;
|
||||
// internal static Text s_objPathLabel;
|
||||
// internal static Text s_mousePosLabel;
|
||||
// internal static GameObject s_UIContent;
|
||||
|
||||
// internal static void ConstructUI()
|
||||
// {
|
||||
// s_UIContent = UIFactory.CreatePanel("InspectUnderMouse_UI", out GameObject content);
|
||||
|
||||
// var baseRect = s_UIContent.GetComponent<RectTransform>();
|
||||
// var half = new Vector2(0.5f, 0.5f);
|
||||
// baseRect.anchorMin = half;
|
||||
// baseRect.anchorMax = half;
|
||||
// baseRect.pivot = half;
|
||||
// baseRect.sizeDelta = new Vector2(700, 150);
|
||||
|
||||
// var group = content.GetComponent<VerticalLayoutGroup>();
|
||||
// group.childForceExpandHeight = true;
|
||||
|
||||
// // Title text
|
||||
|
||||
// UIFactory.CreateLabel(content, "InspectLabel", "<b>Mouse Inspector</b> (press <b>ESC</b> to cancel)", TextAnchor.MiddleCenter);
|
||||
|
||||
// s_mousePosLabel = UIFactory.CreateLabel(content, "MousePosLabel", "Mouse Position:", TextAnchor.MiddleCenter);
|
||||
|
||||
// s_objNameLabel = UIFactory.CreateLabel(content, "HitLabelObj", "No hits...", TextAnchor.MiddleLeft);
|
||||
// s_objNameLabel.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||
|
||||
// s_objPathLabel = UIFactory.CreateLabel(content, "PathLabel", "", TextAnchor.MiddleLeft);
|
||||
// s_objPathLabel.fontStyle = FontStyle.Italic;
|
||||
// s_objPathLabel.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||||
|
||||
// UIFactory.SetLayoutElement(s_objPathLabel.gameObject, minHeight: 75);
|
||||
|
||||
// s_UIContent.SetActive(false);
|
||||
// }
|
||||
// }
|
||||
//}
|
122
src/UI/Inspectors/InspectorBase.cs
Normal file
122
src/UI/Inspectors/InspectorBase.cs
Normal file
@ -0,0 +1,122 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.Panels;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors
|
||||
{
|
||||
public abstract class InspectorBase
|
||||
{
|
||||
public object Target;
|
||||
public bool IsActive { get; private set; }
|
||||
|
||||
public abstract string TabLabel { get; }
|
||||
|
||||
internal bool m_pendingDestroy;
|
||||
|
||||
public InspectorBase(object target)
|
||||
{
|
||||
Target = target;
|
||||
|
||||
if (Target.IsNullOrDestroyed(false))
|
||||
{
|
||||
Destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
AddInspectorTab(this);
|
||||
}
|
||||
|
||||
public virtual void SetActive()
|
||||
{
|
||||
this.IsActive = true;
|
||||
Content?.SetActive(true);
|
||||
}
|
||||
|
||||
public virtual void SetInactive()
|
||||
{
|
||||
this.IsActive = false;
|
||||
Content?.SetActive(false);
|
||||
}
|
||||
|
||||
public virtual void Update()
|
||||
{
|
||||
if (Target.IsNullOrDestroyed(false))
|
||||
{
|
||||
Destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
m_tabText.text = TabLabel;
|
||||
}
|
||||
|
||||
public virtual void Destroy()
|
||||
{
|
||||
m_pendingDestroy = true;
|
||||
|
||||
GameObject tabGroup = m_tabButton?.transform.parent.gameObject;
|
||||
|
||||
if (tabGroup)
|
||||
GameObject.Destroy(tabGroup);
|
||||
|
||||
int thisIndex = -1;
|
||||
if (InspectorManager.ActiveInspectors.Contains(this))
|
||||
{
|
||||
thisIndex = InspectorManager.ActiveInspectors.IndexOf(this);
|
||||
InspectorManager.ActiveInspectors.Remove(this);
|
||||
}
|
||||
|
||||
if (ReferenceEquals(InspectorManager.m_activeInspector, this))
|
||||
{
|
||||
InspectorManager.UnsetInspectorTab();
|
||||
|
||||
if (InspectorManager.ActiveInspectors.Count > 0)
|
||||
{
|
||||
var prevTab = InspectorManager.ActiveInspectors[thisIndex > 0 ? thisIndex - 1 : 0];
|
||||
InspectorManager.SetInspectorTab(prevTab);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region UI
|
||||
|
||||
public abstract GameObject Content { get; set; }
|
||||
public Button m_tabButton;
|
||||
public Text m_tabText;
|
||||
|
||||
public void AddInspectorTab(InspectorBase parent)
|
||||
{
|
||||
var tabContent = InspectorPanel.Instance.NavbarHolder;
|
||||
|
||||
var tabGroupObj = UIFactory.CreateHorizontalGroup(tabContent, "TabObject", true, true, true, true);
|
||||
UIFactory.SetLayoutElement(tabGroupObj, minWidth: 185, flexibleWidth: 0);
|
||||
tabGroupObj.AddComponent<Mask>();
|
||||
|
||||
m_tabButton = UIFactory.CreateButton(tabGroupObj,
|
||||
"TabButton",
|
||||
"",
|
||||
() => { InspectorManager.SetInspectorTab(parent); });
|
||||
|
||||
UIFactory.SetLayoutElement(m_tabButton.gameObject, minWidth: 165, flexibleWidth: 0);
|
||||
|
||||
m_tabText = m_tabButton.GetComponentInChildren<Text>();
|
||||
m_tabText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||
m_tabText.alignment = TextAnchor.MiddleLeft;
|
||||
|
||||
var closeBtn = UIFactory.CreateButton(tabGroupObj,
|
||||
"CloseButton",
|
||||
"X",
|
||||
parent.Destroy,
|
||||
new Color(0.2f, 0.2f, 0.2f, 1));
|
||||
|
||||
UIFactory.SetLayoutElement(closeBtn.gameObject, minWidth: 20, flexibleWidth: 0);
|
||||
|
||||
var closeBtnText = closeBtn.GetComponentInChildren<Text>();
|
||||
closeBtnText.color = new Color(1, 0, 0, 1);
|
||||
}
|
||||
|
||||
public virtual void OnPanelResized() { }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
143
src/UI/Inspectors/InspectorManager.cs
Normal file
143
src/UI/Inspectors/InspectorManager.cs
Normal file
@ -0,0 +1,143 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityExplorer.UI;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
using UnityExplorer.UI.CacheObject;
|
||||
using UnityExplorer.UI.Inspectors.Reflection;
|
||||
using UnityExplorer.UI.Panels;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors
|
||||
{
|
||||
public static class InspectorManager
|
||||
{
|
||||
public static InspectorBase m_activeInspector;
|
||||
public static readonly List<InspectorBase> ActiveInspectors = new List<InspectorBase>();
|
||||
|
||||
public static void Update()
|
||||
{
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < ActiveInspectors.Count; i++)
|
||||
ActiveInspectors[i].Update();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ExplorerCore.LogWarning(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Inspect(object obj, CacheObjectBase parentMember = null)
|
||||
{
|
||||
var type = ReflectionProvider.Instance.GetActualType(obj);
|
||||
|
||||
// only need to set parent member for structs
|
||||
if (!type.IsValueType)
|
||||
parentMember = null;
|
||||
|
||||
obj = ReflectionProvider.Instance.Cast(obj, type);
|
||||
|
||||
if (obj.IsNullOrDestroyed(false))
|
||||
return;
|
||||
|
||||
// check if currently inspecting this object
|
||||
foreach (InspectorBase tab in ActiveInspectors)
|
||||
{
|
||||
if (obj.ReferenceEqual(tab.Target))
|
||||
{
|
||||
SetInspectorTab(tab);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
InspectorBase inspector;
|
||||
if (obj is GameObject go)
|
||||
{
|
||||
ExplorerCore.Log("TODO");
|
||||
return;
|
||||
// inspector = new GameObjectInspector(go);
|
||||
}
|
||||
else
|
||||
inspector = new InstanceInspector(obj);
|
||||
|
||||
if (inspector is ReflectionInspector ri)
|
||||
ri.ParentMember = parentMember;
|
||||
|
||||
ActiveInspectors.Add(inspector);
|
||||
SetInspectorTab(inspector);
|
||||
}
|
||||
|
||||
public static void InspectType(Type type)
|
||||
{
|
||||
if (type == null)
|
||||
{
|
||||
ExplorerCore.LogWarning("The provided type was null!");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var tab in ActiveInspectors.Where(x => x is StaticInspector))
|
||||
{
|
||||
if (ReferenceEquals(tab.Target as Type, type))
|
||||
{
|
||||
SetInspectorTab(tab);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var inspector = new StaticInspector(type);
|
||||
|
||||
ActiveInspectors.Add(inspector);
|
||||
SetInspectorTab(inspector);
|
||||
}
|
||||
|
||||
public static void SetInspectorTab(InspectorBase inspector)
|
||||
{
|
||||
UIManager.SetPanelActive(UIManager.Panels.Inspector, true);
|
||||
|
||||
if (m_activeInspector == inspector)
|
||||
return;
|
||||
|
||||
UnsetInspectorTab();
|
||||
|
||||
m_activeInspector = inspector;
|
||||
inspector.SetActive();
|
||||
|
||||
OnSetInspectorTab(inspector);
|
||||
}
|
||||
|
||||
public static void UnsetInspectorTab()
|
||||
{
|
||||
if (m_activeInspector == null)
|
||||
return;
|
||||
|
||||
m_activeInspector.SetInactive();
|
||||
|
||||
OnUnsetInspectorTab();
|
||||
|
||||
m_activeInspector = null;
|
||||
}
|
||||
|
||||
public static void OnSetInspectorTab(InspectorBase inspector)
|
||||
{
|
||||
Color activeColor = new Color(0, 0.25f, 0, 1);
|
||||
RuntimeProvider.Instance.SetColorBlock(inspector.m_tabButton, activeColor, activeColor);
|
||||
}
|
||||
|
||||
public static void OnUnsetInspectorTab()
|
||||
{
|
||||
RuntimeProvider.Instance.SetColorBlock(m_activeInspector.m_tabButton,
|
||||
new Color(0.2f, 0.2f, 0.2f, 1), new Color(0.1f, 0.3f, 0.1f, 1));
|
||||
}
|
||||
|
||||
internal static void OnPanelResized()
|
||||
{
|
||||
foreach (var instance in ActiveInspectors)
|
||||
{
|
||||
instance.OnPanelResized();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
76
src/UI/Inspectors/Reflection/CacheMemberList.cs
Normal file
76
src/UI/Inspectors/Reflection/CacheMemberList.cs
Normal file
@ -0,0 +1,76 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors.Reflection
|
||||
{
|
||||
public class CacheMemberList : IPoolDataSource
|
||||
{
|
||||
public ScrollPool ScrollPool { get; }
|
||||
public ReflectionInspector Inspector { get; }
|
||||
|
||||
public CacheMemberList(ScrollPool scrollPool, ReflectionInspector inspector)
|
||||
{
|
||||
this.ScrollPool = scrollPool;
|
||||
this.Inspector = inspector;
|
||||
}
|
||||
|
||||
public int ItemCount => Inspector.filteredMembers.Count;
|
||||
|
||||
public int GetRealIndexOfTempIndex(int index)
|
||||
{
|
||||
if (index < 0 || index >= Inspector.filteredToRealIndices.Count)
|
||||
return -1;
|
||||
return Inspector.filteredToRealIndices[index];
|
||||
}
|
||||
|
||||
public ICell CreateCell(RectTransform cellTransform) => new CellViewHolder(cellTransform.gameObject);
|
||||
|
||||
public void DisableCell(ICell cell, int index)
|
||||
{
|
||||
var root = (cell as CellViewHolder).UIRoot;
|
||||
DisableContent(root);
|
||||
cell.Disable();
|
||||
}
|
||||
|
||||
public void SetCell(ICell icell, int index)
|
||||
{
|
||||
var root = (icell as CellViewHolder).UIRoot;
|
||||
|
||||
if (index < 0 || index >= ItemCount)
|
||||
{
|
||||
DisableContent(root);
|
||||
icell.Disable();
|
||||
return;
|
||||
}
|
||||
|
||||
float start = Time.realtimeSinceStartup;
|
||||
index = GetRealIndexOfTempIndex(index);
|
||||
|
||||
var cache = Inspector.allMembers[index];
|
||||
cache.Enable();
|
||||
|
||||
var content = cache.UIRoot;
|
||||
|
||||
if (content.transform.parent.ReferenceEqual(root.transform))
|
||||
return;
|
||||
|
||||
var orig = content.transform.parent;
|
||||
|
||||
DisableContent(root);
|
||||
|
||||
content.transform.SetParent(root.transform, false);
|
||||
//ExplorerCore.Log("Set cell " + index + ", took " + (Time.realtimeSinceStartup - start) + " secs");
|
||||
//ExplorerCore.Log("orig parent was " + (orig?.name ?? " <null>"));
|
||||
}
|
||||
|
||||
private void DisableContent(GameObject cellRoot)
|
||||
{
|
||||
if (cellRoot.transform.childCount > 0 && cellRoot.transform.GetChild(0) is Transform existing)
|
||||
existing.transform.SetParent(Inspector.InactiveHolder.transform, false);
|
||||
}
|
||||
}
|
||||
}
|
256
src/UI/Inspectors/Reflection/InstanceInspector.cs
Normal file
256
src/UI/Inspectors/Reflection/InstanceInspector.cs
Normal file
@ -0,0 +1,256 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Core;
|
||||
using UnityExplorer.Core.Config;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors.Reflection
|
||||
{
|
||||
public enum MemberScopes
|
||||
{
|
||||
All,
|
||||
Instance,
|
||||
Static
|
||||
}
|
||||
|
||||
public class InstanceInspector : ReflectionInspector
|
||||
{
|
||||
public override string TabLabel => $" <color=cyan>[R]</color> {base.TabLabel}";
|
||||
|
||||
internal MemberScopes m_scopeFilter;
|
||||
internal Button m_lastActiveScopeButton;
|
||||
|
||||
public InstanceInspector(object target) : base(target) { }
|
||||
|
||||
internal void OnScopeFilterClicked(MemberScopes type, Button button)
|
||||
{
|
||||
if (m_lastActiveScopeButton)
|
||||
RuntimeProvider.Instance.SetColorBlock(m_lastActiveScopeButton, new Color(0.2f, 0.2f, 0.2f));
|
||||
|
||||
m_scopeFilter = type;
|
||||
m_lastActiveScopeButton = button;
|
||||
|
||||
RuntimeProvider.Instance.SetColorBlock(m_lastActiveScopeButton, new Color(0.2f, 0.6f, 0.2f));
|
||||
|
||||
FilterMembers(null, true);
|
||||
|
||||
ScrollPool.EnableTempCache();
|
||||
ScrollPool.RefreshAndJumpToTop();
|
||||
//RefreshDisplay();
|
||||
//m_sliderScroller.m_slider.value = 1f;
|
||||
}
|
||||
|
||||
public void ConstructInstanceScopeFilters(GameObject parent)
|
||||
{
|
||||
var memberFilterRowObj = UIFactory.CreateHorizontalGroup(parent, "InstanceFilterRow", false, false, true, true, 5, default,
|
||||
new Color(1, 1, 1, 0));
|
||||
UIFactory.SetLayoutElement(memberFilterRowObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 5000);
|
||||
|
||||
var memLabel = UIFactory.CreateLabel(memberFilterRowObj, "MemberLabel", "Filter scope:", TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(memLabel.gameObject, minWidth: 100, minHeight: 25, flexibleWidth: 0);
|
||||
|
||||
AddFilterButton(memberFilterRowObj, MemberScopes.All, true);
|
||||
AddFilterButton(memberFilterRowObj, MemberScopes.Instance);
|
||||
AddFilterButton(memberFilterRowObj, MemberScopes.Static);
|
||||
}
|
||||
|
||||
private void AddFilterButton(GameObject parent, MemberScopes type, bool setEnabled = false)
|
||||
{
|
||||
var btn = UIFactory.CreateButton(parent,
|
||||
"ScopeFilterButton_" + type,
|
||||
type.ToString(),
|
||||
null,
|
||||
new Color(0.2f, 0.2f, 0.2f));
|
||||
|
||||
UIFactory.SetLayoutElement(btn.gameObject, minHeight: 25, minWidth: 70);
|
||||
|
||||
btn.onClick.AddListener(() => { OnScopeFilterClicked(type, btn); });
|
||||
|
||||
RuntimeProvider.Instance.SetColorBlock(btn, highlighted: new Color(0.3f, 0.7f, 0.3f));
|
||||
|
||||
if (setEnabled)
|
||||
{
|
||||
RuntimeProvider.Instance.SetColorBlock(btn, new Color(0.2f, 0.6f, 0.2f));
|
||||
m_scopeFilter = type;
|
||||
m_lastActiveScopeButton = btn;
|
||||
}
|
||||
}
|
||||
|
||||
public void ConstructUnityInstanceHelpers()
|
||||
{
|
||||
if (!typeof(UnityEngine.Object).IsAssignableFrom(m_targetType))
|
||||
return;
|
||||
|
||||
var rowObj = UIFactory.CreateHorizontalGroup(Content, "InstanceHelperRow", true, true, true, true, 5, new Vector4(2, 2, 2, 2),
|
||||
new Color(0.1f, 0.1f, 0.1f));
|
||||
UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleWidth: 5000);
|
||||
|
||||
if (typeof(Component).IsAssignableFrom(m_targetType))
|
||||
ConstructCompHelper(rowObj);
|
||||
|
||||
ConstructUnityObjHelper(rowObj);
|
||||
|
||||
if (m_targetType == typeof(Texture2D))
|
||||
ConstructTextureHelper();
|
||||
}
|
||||
|
||||
internal void ConstructCompHelper(GameObject rowObj)
|
||||
{
|
||||
//var gameObjectLabel = UIFactory.CreateLabel(rowObj, "GameObjectLabel", "GameObject:", TextAnchor.MiddleLeft);
|
||||
//UIFactory.SetLayoutElement(gameObjectLabel.gameObject, minWidth: 90, minHeight: 25, flexibleWidth: 0);
|
||||
|
||||
var comp = Target.TryCast(typeof(Component)) as Component;
|
||||
|
||||
var btn = UIFactory.CreateButton(rowObj,
|
||||
"GameObjectButton",
|
||||
"View GameObject",
|
||||
() => { InspectorManager.Inspect(comp.gameObject); },
|
||||
new Color(0.2f, 0.5f, 0.2f));
|
||||
UIFactory.SetLayoutElement(btn.gameObject, minHeight: 25, minWidth: 120, flexibleWidth: 0);
|
||||
}
|
||||
|
||||
internal void ConstructUnityObjHelper(GameObject rowObj)
|
||||
{
|
||||
var label = UIFactory.CreateLabel(rowObj, "NameLabel", "Name:", TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(label.gameObject, minWidth: 60, minHeight: 25, flexibleWidth: 0);
|
||||
|
||||
var uObj = Target.TryCast(typeof(UnityEngine.Object)) as UnityEngine.Object;
|
||||
|
||||
var inputObj = UIFactory.CreateInputField(rowObj, "NameInput", "...", out InputField inputField, 14, 3, 1);
|
||||
UIFactory.SetLayoutElement(inputObj, minHeight: 25, flexibleWidth: 2000);
|
||||
inputField.readOnly = true;
|
||||
inputField.text = uObj.name;
|
||||
}
|
||||
|
||||
internal bool showingTextureHelper;
|
||||
internal bool constructedTextureViewer;
|
||||
|
||||
internal GameObject m_textureViewerObj;
|
||||
|
||||
internal void ConstructTextureHelper()
|
||||
{
|
||||
var rowObj = UIFactory.CreateHorizontalGroup(Content, "TextureHelper", true, false, true, true, 5, new Vector4(3, 3, 3, 3),
|
||||
new Color(0.1f, 0.1f, 0.1f));
|
||||
UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleHeight: 0);
|
||||
|
||||
var showBtn = UIFactory.CreateButton(rowObj, "ShowButton", "Show", null, new Color(0.2f, 0.6f, 0.2f));
|
||||
UIFactory.SetLayoutElement(showBtn.gameObject, minWidth: 50, flexibleWidth: 0);
|
||||
|
||||
UIFactory.CreateLabel(rowObj, "TextureViewerLabel", "Texture Viewer", TextAnchor.MiddleLeft);
|
||||
|
||||
var textureViewerObj = UIFactory.CreateScrollView(Content, "TextureViewerContent", out GameObject scrollContent, out _,
|
||||
new Color(0.1f, 0.1f, 0.1f));
|
||||
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(textureViewerObj, false, false, true, true);
|
||||
UIFactory.SetLayoutElement(textureViewerObj, minHeight: 100, flexibleHeight: 9999, flexibleWidth: 9999);
|
||||
|
||||
textureViewerObj.SetActive(false);
|
||||
|
||||
m_textureViewerObj = textureViewerObj;
|
||||
|
||||
var showText = showBtn.GetComponentInChildren<Text>();
|
||||
showBtn.onClick.AddListener(() =>
|
||||
{
|
||||
showingTextureHelper = !showingTextureHelper;
|
||||
|
||||
if (showingTextureHelper)
|
||||
{
|
||||
if (!constructedTextureViewer)
|
||||
ConstructTextureViewerArea(scrollContent);
|
||||
|
||||
showText.text = "Hide";
|
||||
ToggleTextureViewer(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
showText.text = "Show";
|
||||
ToggleTextureViewer(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
internal void ConstructTextureViewerArea(GameObject parent)
|
||||
{
|
||||
constructedTextureViewer = true;
|
||||
|
||||
var tex = Target.TryCast(typeof(Texture2D)) as Texture2D;
|
||||
|
||||
if (!tex)
|
||||
{
|
||||
ExplorerCore.LogWarning("Could not cast the target instance to Texture2D! Maybe its null or destroyed?");
|
||||
return;
|
||||
}
|
||||
|
||||
// Save helper
|
||||
|
||||
var saveRowObj = UIFactory.CreateHorizontalGroup(parent, "SaveRow", true, true, true, true, 2, new Vector4(2, 2, 2, 2),
|
||||
new Color(0.1f, 0.1f, 0.1f));
|
||||
|
||||
var saveBtn = UIFactory.CreateButton(saveRowObj, "SaveButton", "Save .PNG", null, new Color(0.2f, 0.2f, 0.2f));
|
||||
UIFactory.SetLayoutElement(saveBtn.gameObject, minHeight: 25, minWidth: 100, flexibleWidth: 0);
|
||||
|
||||
var inputObj = UIFactory.CreateInputField(saveRowObj, "SaveInput", "...", out InputField inputField);
|
||||
UIFactory.SetLayoutElement(inputObj, minHeight: 25, minWidth: 100, flexibleWidth: 9999);
|
||||
|
||||
var name = tex.name;
|
||||
if (string.IsNullOrEmpty(name))
|
||||
name = "untitled";
|
||||
|
||||
inputField.text = Path.Combine(ConfigManager.Default_Output_Path.Value, $"{name}.png");
|
||||
|
||||
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 (!TextureUtilProvider.IsReadable(tex))
|
||||
tex = TextureUtilProvider.ForceReadTexture(tex);
|
||||
|
||||
byte[] data = TextureUtilProvider.Instance.EncodeToPNG(tex);
|
||||
|
||||
File.WriteAllBytes(path, data);
|
||||
}
|
||||
});
|
||||
|
||||
// Actual texture viewer
|
||||
|
||||
var imageObj = UIFactory.CreateUIObject("TextureViewerImage", parent);
|
||||
var image = imageObj.AddComponent<Image>();
|
||||
var sprite = TextureUtilProvider.Instance.CreateSprite(tex);
|
||||
image.sprite = sprite;
|
||||
|
||||
var fitter = imageObj.AddComponent<ContentSizeFitter>();
|
||||
fitter.verticalFit = 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);
|
||||
}
|
||||
}
|
||||
}
|
484
src/UI/Inspectors/Reflection/ReflectionInspector.cs
Normal file
484
src/UI/Inspectors/Reflection/ReflectionInspector.cs
Normal file
@ -0,0 +1,484 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.Core;
|
||||
using UnityExplorer.Core.Config;
|
||||
using UnityExplorer.Core.Runtime;
|
||||
using UnityExplorer.UI.CacheObject;
|
||||
using UnityExplorer.UI.Panels;
|
||||
using UnityExplorer.UI.Utility;
|
||||
using UnityExplorer.UI.Widgets;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors.Reflection
|
||||
{
|
||||
public class ReflectionInspector : InspectorBase
|
||||
{
|
||||
#region STATIC
|
||||
|
||||
public static ReflectionInspector ActiveInstance { get; private set; }
|
||||
|
||||
//static ReflectionInspector()
|
||||
//{
|
||||
// PanelDragger.OnFinishResize += (RectTransform _) => OnContainerResized();
|
||||
// SceneExplorer.OnToggleShow += OnContainerResized;
|
||||
//}
|
||||
|
||||
//private static void OnContainerResized(bool _ = false)
|
||||
//{
|
||||
// if (ActiveInstance == null)
|
||||
// return;
|
||||
|
||||
// ActiveInstance.m_widthUpdateWanted = true;
|
||||
//}
|
||||
|
||||
// Blacklists
|
||||
private static readonly HashSet<string> bl_typeAndMember = new HashSet<string>
|
||||
{
|
||||
#if CPP
|
||||
// these cause a crash in IL2CPP
|
||||
"Type.DeclaringMethod",
|
||||
"Rigidbody2D.Cast",
|
||||
"Collider2D.Cast",
|
||||
"Collider2D.Raycast",
|
||||
"Texture2D.SetPixelDataImpl",
|
||||
"Camera.CalculateProjectionMatrixFromPhysicalProperties",
|
||||
#endif
|
||||
};
|
||||
private static readonly HashSet<string> bl_methodNameStartsWith = new HashSet<string>
|
||||
{
|
||||
// these are redundant, just adds noise, properties are supported directly
|
||||
"get_",
|
||||
"set_",
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
#region INSTANCE
|
||||
|
||||
public override string TabLabel => m_targetTypeShortName;
|
||||
|
||||
public CacheObjectBase ParentMember { get; internal set; }
|
||||
|
||||
public ScrollPool ScrollPool { get; private set; }
|
||||
public CacheMemberList CacheMemberList { get; private set; }
|
||||
|
||||
public GameObject InactiveHolder => m_inactiveHolder;
|
||||
private GameObject m_inactiveHolder;
|
||||
|
||||
internal readonly Type m_targetType;
|
||||
internal readonly string m_targetTypeShortName;
|
||||
|
||||
// all cached members of the target
|
||||
internal CacheMember[] allMembers;
|
||||
// filtered members based on current filters
|
||||
internal readonly List<CacheMember> filteredMembers = new List<CacheMember>();
|
||||
// actual shortlist of displayed members
|
||||
internal readonly List<CacheMember> displayedMembers = new List<CacheMember>();
|
||||
|
||||
// index: Index in filter list, Value: Actual real index in allMembers list.
|
||||
internal readonly List<int> filteredToRealIndices = new List<int>();
|
||||
|
||||
internal bool autoUpdate;
|
||||
|
||||
public override void OnPanelResized()
|
||||
{
|
||||
foreach (var member in displayedMembers)
|
||||
{
|
||||
member.memberLabelElement.minWidth = 0.4f * InspectorPanel.CurrentPanelWidth;
|
||||
}
|
||||
}
|
||||
|
||||
public ReflectionInspector(object target) : base(target)
|
||||
{
|
||||
if (this is StaticInspector)
|
||||
m_targetType = target as Type;
|
||||
else
|
||||
m_targetType = ReflectionUtility.GetActualType(target);
|
||||
|
||||
m_targetTypeShortName = SignatureHighlighter.ParseFullSyntax(m_targetType, false);
|
||||
|
||||
ConstructUI();
|
||||
|
||||
CacheMembers(m_targetType);
|
||||
|
||||
FilterMembers();
|
||||
}
|
||||
|
||||
public override void SetActive()
|
||||
{
|
||||
base.SetActive();
|
||||
ActiveInstance = this;
|
||||
}
|
||||
|
||||
public override void SetInactive()
|
||||
{
|
||||
base.SetInactive();
|
||||
ActiveInstance = null;
|
||||
}
|
||||
|
||||
public override void Destroy()
|
||||
{
|
||||
base.Destroy();
|
||||
|
||||
if (this.Content)
|
||||
GameObject.Destroy(this.Content);
|
||||
}
|
||||
|
||||
internal bool IsBlacklisted(string sig) => bl_typeAndMember.Any(it => sig.Contains(it));
|
||||
internal bool IsBlacklisted(MethodInfo method) => bl_methodNameStartsWith.Any(it => method.Name.StartsWith(it));
|
||||
|
||||
internal string GetSig(MemberInfo member) => $"{member.DeclaringType.Name}.{member.Name}";
|
||||
internal string AppendArgsToSig(ParameterInfo[] args)
|
||||
{
|
||||
string ret = " (";
|
||||
foreach (var param in args)
|
||||
ret += $"{param.ParameterType.Name} {param.Name}, ";
|
||||
ret += ")";
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void CacheMembers(Type type)
|
||||
{
|
||||
var list = new List<CacheMember>();
|
||||
var cachedSigs = new HashSet<string>();
|
||||
|
||||
var types = ReflectionUtility.GetAllBaseTypes(type);
|
||||
|
||||
var flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static;
|
||||
if (this is InstanceInspector)
|
||||
flags |= BindingFlags.Instance;
|
||||
|
||||
foreach (var declaringType in types)
|
||||
{
|
||||
var target = Target;
|
||||
target = target.TryCast(declaringType);
|
||||
|
||||
IEnumerable<MemberInfo> infos = declaringType.GetMethods(flags);
|
||||
infos = infos.Concat(declaringType.GetProperties(flags));
|
||||
infos = infos.Concat(declaringType.GetFields(flags));
|
||||
|
||||
foreach (var member in infos)
|
||||
{
|
||||
try
|
||||
{
|
||||
var sig = GetSig(member);
|
||||
|
||||
//ExplorerCore.Log($"Trying to cache member {sig}...");
|
||||
//ExplorerCore.Log(member.DeclaringType.FullName + "." + member.Name);
|
||||
|
||||
var mi = member as MethodInfo;
|
||||
var pi = member as PropertyInfo;
|
||||
var fi = member as FieldInfo;
|
||||
|
||||
if (IsBlacklisted(sig) || (mi != null && IsBlacklisted(mi)))
|
||||
continue;
|
||||
|
||||
var args = mi?.GetParameters() ?? pi?.GetIndexParameters();
|
||||
if (args != null)
|
||||
{
|
||||
if (!CacheMember.CanProcessArgs(args))
|
||||
continue;
|
||||
|
||||
sig += AppendArgsToSig(args);
|
||||
}
|
||||
|
||||
if (cachedSigs.Contains(sig))
|
||||
continue;
|
||||
|
||||
cachedSigs.Add(sig);
|
||||
|
||||
if (mi != null)
|
||||
list.Add(new CacheMethod(mi, target, InactiveHolder));
|
||||
else if (pi != null)
|
||||
list.Add(new CacheProperty(pi, target, InactiveHolder));
|
||||
else
|
||||
list.Add(new CacheField(fi, target, InactiveHolder));
|
||||
|
||||
var cached = list[list.Count - 1];
|
||||
cached.ParentInspector = this;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExplorerCore.LogWarning($"Exception caching member {member.DeclaringType.FullName}.{member.Name}!");
|
||||
ExplorerCore.Log(e.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var typeList = types.ToList();
|
||||
|
||||
var sorted = new List<CacheMember>();
|
||||
sorted.AddRange(list.Where(it => it is CacheProperty)
|
||||
.OrderBy(it => typeList.IndexOf(it.DeclaringType))
|
||||
.ThenBy(it => it.NameForFiltering));
|
||||
sorted.AddRange(list.Where(it => it is CacheField)
|
||||
.OrderBy(it => typeList.IndexOf(it.DeclaringType))
|
||||
.ThenBy(it => it.NameForFiltering));
|
||||
sorted.AddRange(list.Where(it => it is CacheMethod)
|
||||
.OrderBy(it => typeList.IndexOf(it.DeclaringType))
|
||||
.ThenBy(it => it.NameForFiltering));
|
||||
|
||||
allMembers = sorted.ToArray();
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (autoUpdate)
|
||||
{
|
||||
foreach (var member in displayedMembers)
|
||||
{
|
||||
if (member == null) break;
|
||||
member.UpdateValue();
|
||||
}
|
||||
}
|
||||
|
||||
//if (m_widthUpdateWanted)
|
||||
//{
|
||||
// if (!m_widthUpdateWaiting)
|
||||
// m_widthUpdateWaiting = true;
|
||||
// else
|
||||
// {
|
||||
// UpdateWidths();
|
||||
// m_widthUpdateWaiting = false;
|
||||
// m_widthUpdateWanted = false;
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
internal void OnMemberFilterClicked(MemberTypes type, Button button)
|
||||
{
|
||||
if (m_lastActiveMemButton)
|
||||
RuntimeProvider.Instance.SetColorBlock(m_lastActiveMemButton, new Color(0.2f, 0.2f, 0.2f));
|
||||
|
||||
m_memberFilter = type;
|
||||
m_lastActiveMemButton = button;
|
||||
|
||||
RuntimeProvider.Instance.SetColorBlock(m_lastActiveMemButton, new Color(0.2f, 0.6f, 0.2f));
|
||||
|
||||
FilterMembers(null, true);
|
||||
ScrollPool.EnableTempCache();
|
||||
ScrollPool.Rebuild();
|
||||
}
|
||||
|
||||
public void FilterMembers(string nameFilter = null, bool force = false)
|
||||
{
|
||||
int lastCount = filteredMembers.Count;
|
||||
filteredMembers.Clear();
|
||||
|
||||
nameFilter = nameFilter?.ToLower() ?? m_nameFilterText.text.ToLower();
|
||||
|
||||
filteredToRealIndices.Clear();
|
||||
|
||||
for (int i = 0; i < allMembers.Length; i++)
|
||||
{
|
||||
var mem = allMembers[i];
|
||||
|
||||
// membertype filter
|
||||
if (m_memberFilter != MemberTypes.All && mem.MemInfo.MemberType != m_memberFilter)
|
||||
continue;
|
||||
|
||||
if (this is InstanceInspector ii && ii.m_scopeFilter != MemberScopes.All)
|
||||
{
|
||||
if (mem.IsStatic && ii.m_scopeFilter != MemberScopes.Static)
|
||||
continue;
|
||||
else if (!mem.IsStatic && ii.m_scopeFilter != MemberScopes.Instance)
|
||||
continue;
|
||||
}
|
||||
|
||||
// name filter
|
||||
if (!string.IsNullOrEmpty(nameFilter) && !mem.NameForFiltering.Contains(nameFilter))
|
||||
continue;
|
||||
|
||||
filteredMembers.Add(mem);
|
||||
filteredToRealIndices.Add(i);
|
||||
}
|
||||
|
||||
//if (force || lastCount != filteredMembers.Count)
|
||||
//{
|
||||
// ScrollPool.EnableTempCache();
|
||||
// ScrollPool.Rebuild();
|
||||
//}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region UI
|
||||
|
||||
private GameObject m_content;
|
||||
public override GameObject Content
|
||||
{
|
||||
get => m_content;
|
||||
set => m_content = value;
|
||||
}
|
||||
|
||||
internal Text m_nameFilterText;
|
||||
internal MemberTypes m_memberFilter;
|
||||
internal Button m_lastActiveMemButton;
|
||||
|
||||
internal GameObject m_filterAreaObj;
|
||||
internal GameObject m_updateRowObj;
|
||||
|
||||
internal void ConstructUI()
|
||||
{
|
||||
var parent = InspectorPanel.Instance.ContentHolder;
|
||||
|
||||
this.Content = UIFactory.CreateVerticalGroup(parent, "ReflectionInspector", true, false, true, true, 5, new Vector4(4, 4, 4, 4),
|
||||
new Color(0.15f, 0.15f, 0.15f));
|
||||
|
||||
this.m_inactiveHolder = new GameObject("InactiveContentHolder");
|
||||
m_inactiveHolder.transform.SetParent(parent.transform, false);
|
||||
m_inactiveHolder.SetActive(false);
|
||||
|
||||
ConstructTopArea();
|
||||
|
||||
ConstructMemberList();
|
||||
}
|
||||
|
||||
internal void ConstructTopArea()
|
||||
{
|
||||
var nameRowObj = UIFactory.CreateHorizontalGroup(Content, "NameRowObj", true, true, true, true, 2, default, new Color(1, 1, 1, 0));
|
||||
UIFactory.SetLayoutElement(nameRowObj, minHeight: 25, flexibleHeight: 0, minWidth: 200, flexibleWidth: 5000);
|
||||
|
||||
var typeLabelText = UIFactory.CreateLabel(nameRowObj, "TypeLabel", "Type:", TextAnchor.MiddleLeft);
|
||||
typeLabelText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||
UIFactory.SetLayoutElement(typeLabelText.gameObject, minWidth: 40, flexibleWidth: 0, minHeight: 25);
|
||||
|
||||
var typeDisplay = UIFactory.CreateLabel(nameRowObj, "TypeDisplayText", SignatureHighlighter.ParseFullSyntax(m_targetType, true),
|
||||
TextAnchor.MiddleLeft);
|
||||
|
||||
UIFactory.SetLayoutElement(typeDisplay.gameObject, minHeight: 25, flexibleWidth: 5000);
|
||||
|
||||
// instance helper tools
|
||||
|
||||
if (this is InstanceInspector instanceInspector)
|
||||
{
|
||||
instanceInspector.ConstructUnityInstanceHelpers();
|
||||
}
|
||||
|
||||
ConstructFilterArea();
|
||||
|
||||
ConstructUpdateRow();
|
||||
}
|
||||
|
||||
internal void ConstructFilterArea()
|
||||
{
|
||||
// Filters
|
||||
|
||||
m_filterAreaObj = UIFactory.CreateVerticalGroup(Content, "FilterGroup", true, true, true, true, 4, new Vector4(4, 4, 4, 4),
|
||||
new Color(0.1f, 0.1f, 0.1f));
|
||||
UIFactory.SetLayoutElement(m_filterAreaObj, minHeight: 60);
|
||||
|
||||
// name filter
|
||||
|
||||
var nameFilterRowObj = UIFactory.CreateHorizontalGroup(m_filterAreaObj, "NameFilterRow", false, false, true, true, 5, default,
|
||||
new Color(1, 1, 1, 0));
|
||||
UIFactory.SetLayoutElement(nameFilterRowObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 5000);
|
||||
|
||||
var nameLabel = UIFactory.CreateLabel(nameFilterRowObj, "NameLabel", "Filter names:", TextAnchor.MiddleLeft, Color.grey);
|
||||
UIFactory.SetLayoutElement(nameLabel.gameObject, minWidth: 100, minHeight: 25, flexibleWidth: 0);
|
||||
|
||||
var nameInputObj = UIFactory.CreateInputField(nameFilterRowObj, "NameInput", "...", out InputField nameInput, 14, (int)TextAnchor.MiddleLeft,
|
||||
(int)HorizontalWrapMode.Overflow);
|
||||
UIFactory.SetLayoutElement(nameInputObj, flexibleWidth: 5000, minWidth: 100, minHeight: 25);
|
||||
nameInput.onValueChanged.AddListener((string val) =>
|
||||
{
|
||||
FilterMembers(val, true);
|
||||
ScrollPool.EnableTempCache();
|
||||
ScrollPool.Rebuild();
|
||||
});
|
||||
m_nameFilterText = nameInput.textComponent;
|
||||
|
||||
// membertype filter
|
||||
|
||||
var memberFilterRowObj = UIFactory.CreateHorizontalGroup(m_filterAreaObj, "MemberFilter", false, false, true, true, 5, default,
|
||||
new Color(1, 1, 1, 0));
|
||||
UIFactory.SetLayoutElement(memberFilterRowObj, minHeight: 25, flexibleHeight: 0, flexibleWidth: 5000);
|
||||
|
||||
var memLabel = UIFactory.CreateLabel(memberFilterRowObj, "MemberFilterLabel", "Filter members:", TextAnchor.MiddleLeft, Color.grey);
|
||||
UIFactory.SetLayoutElement(memLabel.gameObject, minWidth: 100, minHeight: 25, flexibleWidth: 0);
|
||||
|
||||
AddFilterButton(memberFilterRowObj, MemberTypes.All, true);
|
||||
AddFilterButton(memberFilterRowObj, MemberTypes.Method);
|
||||
AddFilterButton(memberFilterRowObj, MemberTypes.Property);
|
||||
AddFilterButton(memberFilterRowObj, MemberTypes.Field);
|
||||
|
||||
// Instance filters
|
||||
|
||||
if (this is InstanceInspector instanceInspector)
|
||||
{
|
||||
instanceInspector.ConstructInstanceScopeFilters(m_filterAreaObj);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddFilterButton(GameObject parent, MemberTypes type, bool setEnabled = false)
|
||||
{
|
||||
var btn = UIFactory.CreateButton(parent,
|
||||
"FilterButton_" + type,
|
||||
type.ToString(),
|
||||
null,
|
||||
new Color(0.2f, 0.2f, 0.2f));
|
||||
UIFactory.SetLayoutElement(btn.gameObject, minHeight: 25, minWidth: 70);
|
||||
btn.onClick.AddListener(() => { OnMemberFilterClicked(type, btn); });
|
||||
|
||||
RuntimeProvider.Instance.SetColorBlock(btn, highlighted: new Color(0.3f, 0.7f, 0.3f));
|
||||
|
||||
if (setEnabled)
|
||||
{
|
||||
RuntimeProvider.Instance.SetColorBlock(btn, new Color(0.2f, 0.6f, 0.2f));
|
||||
m_memberFilter = type;
|
||||
m_lastActiveMemButton = btn;
|
||||
}
|
||||
}
|
||||
|
||||
internal void ConstructUpdateRow()
|
||||
{
|
||||
m_updateRowObj = UIFactory.CreateHorizontalGroup(Content, "UpdateRow", false, true, true, true, 10, default, new Color(1, 1, 1, 0));
|
||||
UIFactory.SetLayoutElement(m_updateRowObj, minHeight: 25);
|
||||
|
||||
// update button
|
||||
|
||||
var updateBtn = UIFactory.CreateButton(m_updateRowObj, "UpdateButton", "Update Values", null, new Color(0.2f, 0.2f, 0.2f));
|
||||
UIFactory.SetLayoutElement(updateBtn.gameObject, minWidth: 110, flexibleWidth: 0);
|
||||
updateBtn.onClick.AddListener(() =>
|
||||
{
|
||||
bool orig = autoUpdate;
|
||||
autoUpdate = true;
|
||||
Update();
|
||||
if (!orig)
|
||||
autoUpdate = orig;
|
||||
});
|
||||
|
||||
// auto update
|
||||
|
||||
var autoUpdateObj = UIFactory.CreateToggle(m_updateRowObj, "UpdateToggle", out Toggle autoUpdateToggle, out Text autoUpdateText);
|
||||
var autoUpdateLayout = autoUpdateObj.AddComponent<LayoutElement>();
|
||||
autoUpdateLayout.minWidth = 150;
|
||||
autoUpdateLayout.minHeight = 25;
|
||||
autoUpdateText.text = "Auto-update?";
|
||||
autoUpdateToggle.isOn = false;
|
||||
autoUpdateToggle.onValueChanged.AddListener((bool val) => { autoUpdate = val; });
|
||||
}
|
||||
|
||||
internal void ConstructMemberList()
|
||||
{
|
||||
ScrollPool = UIFactory.CreateScrollPool(Content, "MemberList", out GameObject scrollRoot, out GameObject scrollContent,
|
||||
new Color(0.05f, 0.05f, 0.05f));
|
||||
UIFactory.SetLayoutElement(scrollRoot, flexibleHeight: 9999);
|
||||
UIFactory.SetLayoutElement(scrollContent, flexibleHeight: 9999);
|
||||
|
||||
CacheMemberList = new CacheMemberList(ScrollPool, this);
|
||||
|
||||
ScrollPool.Initialize(CacheMemberList, CellViewHolder.CreatePrototypeCell(scrollRoot));
|
||||
|
||||
// ScrollPool.Viewport.GetComponent<Mask>().enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
14
src/UI/Inspectors/Reflection/StaticInspector.cs
Normal file
14
src/UI/Inspectors/Reflection/StaticInspector.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace UnityExplorer.UI.Inspectors.Reflection
|
||||
{
|
||||
public class StaticInspector : ReflectionInspector
|
||||
{
|
||||
public override string TabLabel => $" <color=cyan>[S]</color> {base.TabLabel}";
|
||||
|
||||
public StaticInspector(Type type) : base(type) { }
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user