using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; using UnityExplorer.Helpers; using UnityExplorer.UI; using UnityExplorer.UI.Shared; using UnityExplorer.Unstrip; namespace UnityExplorer.Inspectors.Reflection { public class InteractiveValue { public CacheObjectBase OwnerCacheObject; public object Value { get; set; } public Type ValueType; // might not need public virtual bool HasSubContent => false; public string RichTextValue => m_richValue ?? GetLabelForValue(); internal string m_richValue; internal string m_richValueType; public MethodInfo ToStringMethod => m_toStringMethod ?? GetToStringMethod(); internal MethodInfo m_toStringMethod; public virtual void Init() { UpdateValue(); } public virtual void UpdateValue() { if (!m_text) return; if (OwnerCacheObject is CacheMember ownerMember && !string.IsNullOrEmpty(ownerMember.ReflectionException)) { m_text.text = "" + ownerMember.ReflectionException + ""; return; } GetLabelForValue(); m_text.text = RichTextValue; bool shouldShowInspect = !InspectorBase.IsNullOrDestroyed(this.Value, true); if (m_inspectButton.activeSelf != shouldShowInspect) m_inspectButton.SetActive(shouldShowInspect); } public string GetLabelForValue() { if (Value != null) ValueType = Value.GetType(); m_richValueType = UISyntaxHighlight.ParseFullSyntax(ValueType, true); if (OwnerCacheObject is CacheMember cm && !cm.HasEvaluated) return $"Not yet evaluated ({m_richValueType})"; if (Value == null) return $"null ({m_richValueType})"; string label; if (ValueType == typeof(TextAsset) && Value is TextAsset textAsset) { label = textAsset.text; if (label.Length > 10) label = $"{label.Substring(0, 10)}..."; label = $"\"{label}\" {textAsset.name} ({m_richValueType})"; } else if (ValueType == typeof(EventSystem)) { label = m_richValueType; } else { var toString = (string)ToStringMethod.Invoke(Value, null); var fullnametemp = ValueType.ToString(); if (fullnametemp.StartsWith("Il2CppSystem")) fullnametemp = fullnametemp.Substring(6, fullnametemp.Length - 6); var temp = toString.Replace(fullnametemp, "").Trim(); if (string.IsNullOrEmpty(temp)) { label = m_richValueType; } else { if (toString.Length > 200) toString = toString.Substring(0, 200) + "..."; label = toString; var unityType = $"({ValueType.FullName})"; if (Value is UnityEngine.Object && label.Contains(unityType)) label = label.Replace(unityType, $"({m_richValueType})"); else label += $" ({m_richValueType})"; } } return m_richValue = label; } private MethodInfo GetToStringMethod() { try { m_toStringMethod = ReflectionHelpers.GetActualType(Value).GetMethod("ToString", new Type[0]) ?? typeof(object).GetMethod("ToString", new Type[0]); // test invoke m_toStringMethod.Invoke(Value, null); } catch { m_toStringMethod = typeof(object).GetMethod("ToString", new Type[0]); } return m_toStringMethod; } #region UI CONSTRUCTION internal GameObject m_mainContent; internal GameObject m_inspectButton; internal Text m_text; internal GameObject m_subContentParent; public virtual void ConstructUI(GameObject parent, GameObject subGroup) { m_mainContent = UIFactory.CreateHorizontalGroup(parent, new Color(1, 1, 1, 0)); var mainGroup = m_mainContent.GetComponent(); mainGroup.childForceExpandWidth = true; mainGroup.childControlWidth = true; mainGroup.childForceExpandHeight = false; mainGroup.childControlHeight = true; mainGroup.spacing = 4; mainGroup.childAlignment = TextAnchor.UpperLeft; var mainLayout = m_mainContent.AddComponent(); mainLayout.flexibleWidth = 9000; mainLayout.minWidth = 175; mainLayout.minHeight = 25; mainLayout.flexibleHeight = 0; // inspect button m_inspectButton = UIFactory.CreateButton(m_mainContent, new Color(0.3f, 0.3f, 0.3f, 0.2f)); var inspectLayout = m_inspectButton.AddComponent(); inspectLayout.minWidth = 60; inspectLayout.minHeight = 25; inspectLayout.flexibleHeight = 0; inspectLayout.flexibleWidth = 0; var inspectText = m_inspectButton.GetComponentInChildren(); inspectText.text = "Inspect"; var inspectBtn = m_inspectButton.GetComponent