同步操作将从 jobily/UnityExplorer 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
using System.Collections;using UnityExplorer.CacheObject.IValues;using UnityExplorer.CacheObject.Views;using UniverseLib.UI;using UniverseLib.UI.ObjectPool;namespace UnityExplorer.CacheObject{public enum ValueState{NotEvaluated,Exception,Boolean,Number,String,Enum,Collection,Dictionary,ValueStruct,Color,Unsupported}public abstract class CacheObjectBase{public ICacheObjectController Owner { get; set; }public CacheObjectCell CellView { get; internal set; }public object Value { get; protected set; }public Type FallbackType { get; protected set; }public ValueState State { get; set; }public Exception LastException { get; protected set; }bool valueIsNull;Type currentValueType;// InteractiveValuespublic InteractiveValue IValue { get; private set; }public Type CurrentIValueType { get; private set; }public bool SubContentShowWanted { get; private set; }// UIpublic string NameLabelText { get; protected set; }public string NameLabelTextRaw { get; protected set; }public string ValueLabelText { get; protected set; }// Abstractpublic abstract bool ShouldAutoEvaluate { get; }public abstract bool HasArguments { get; }public abstract bool CanWrite { get; }protected const string NOT_YET_EVAL = "<color=grey>Not yet evaluated</color>";public virtual void SetFallbackType(Type fallbackType){this.FallbackType = fallbackType;this.ValueLabelText = GetValueLabel();}public virtual void SetView(CacheObjectCell cellView){this.CellView = cellView;cellView.Occupant = this;}public virtual void UnlinkFromView(){if (this.CellView == null)return;this.CellView.Occupant = null;this.CellView = null;if (this.IValue != null)this.IValue.UIRoot.transform.SetParent(InactiveIValueHolder.transform, false);}public virtual void ReleasePooledObjects(){if (this.IValue != null)ReleaseIValue();if (this.CellView != null)UnlinkFromView();}// Updating and applying values// The only method which sets the CacheObjectBase.Valuepublic virtual void SetValueFromSource(object value){this.Value = value;if (!Value.IsNullOrDestroyed())Value = Value.TryCast();ProcessOnEvaluate();if (this.IValue != null){if (SubContentShowWanted)this.IValue.SetValue(Value);elseIValue.PendingValueWanted = true;}}public void SetUserValue(object value){value = value.TryCast(FallbackType);TrySetUserValue(value);if (CellView != null)SetDataToCell(CellView);// If the owner's ParentCacheObject is set, we are setting the value of an inspected struct.// Set the inspector target as the value back to that parent.if (Owner.ParentCacheObject != null)Owner.ParentCacheObject.SetUserValue(Owner.Target);}public abstract void TrySetUserValue(object value);protected virtual void ProcessOnEvaluate(){ValueState prevState = State;if (LastException != null){valueIsNull = true;currentValueType = FallbackType;State = ValueState.Exception;}else if (Value.IsNullOrDestroyed()){valueIsNull = true;State = GetStateForType(FallbackType);}else{valueIsNull = false;State = GetStateForType(Value.GetActualType());}if (IValue != null){// If we changed states (always needs IValue change)// or if the value is null, and the fallback type isnt string (we always want to edit strings).if (State != prevState || (State != ValueState.String && State != ValueState.Exception && Value.IsNullOrDestroyed())){// need to return IValueReleaseIValue();SubContentShowWanted = false;}}// Set label textthis.ValueLabelText = GetValueLabel();}public ValueState GetStateForType(Type type){if (currentValueType == type && (State != ValueState.Exception || LastException != null))return State;currentValueType = type;if (type == typeof(bool))return ValueState.Boolean;else if (type.IsPrimitive || type == typeof(decimal))return ValueState.Number;else if (type == typeof(string))return ValueState.String;else if (type.IsEnum)return ValueState.Enum;else if (type == typeof(Color) || type == typeof(Color32))return ValueState.Color;else if (InteractiveValueStruct.SupportsType(type))return ValueState.ValueStruct;else if (ReflectionUtility.IsDictionary(type))return ValueState.Dictionary;else if (!typeof(Transform).IsAssignableFrom(type) && ReflectionUtility.IsEnumerable(type))return ValueState.Collection;elsereturn ValueState.Unsupported;}protected string GetValueLabel(){string label = string.Empty;switch (State){case ValueState.NotEvaluated:return $"<i>{NOT_YET_EVAL} ({SignatureHighlighter.Parse(FallbackType, true)})</i>";case ValueState.Exception:return $"<i><color=#eb4034>{LastException.ReflectionExToString()}</color></i>";// bool and number dont want the label for the value at allcase ValueState.Boolean:case ValueState.Number:return null;// and valuestruct also doesnt want it if we can parse itcase ValueState.ValueStruct:if (ParseUtility.CanParse(currentValueType))return null;break;// string wants it trimmed to max 200 charscase ValueState.String:if (!valueIsNull)return $"\"{ToStringUtility.PruneString(Value as string, 200, 5)}\"";break;// try to prefix the count of the collection for lists and dictscase ValueState.Collection:if (!valueIsNull){if (Value is IList iList)label = $"[{iList.Count}] ";else if (Value is ICollection iCol)label = $"[{iCol.Count}] ";elselabel = "[?] ";}break;case ValueState.Dictionary:if (!valueIsNull){if (Value is IDictionary iDict)label = $"[{iDict.Count}] ";elselabel = "[?] ";}break;}// Cases which dont return will append to ToStringWithTypereturn label += ToStringUtility.ToStringWithType(Value, FallbackType, true);}// Setting cell state from our model/// <summary>Return false if SetCell should abort, true if it should continue.</summary>protected abstract bool TryAutoEvaluateIfUnitialized(CacheObjectCell cell);public virtual void SetDataToCell(CacheObjectCell cell){cell.NameLabel.text = NameLabelText;if (cell.HiddenNameLabel != null)cell.HiddenNameLabel.Text = NameLabelTextRaw ?? string.Empty;cell.ValueLabel.gameObject.SetActive(true);cell.SubContentHolder.gameObject.SetActive(SubContentShowWanted);if (IValue != null){IValue.UIRoot.transform.SetParent(cell.SubContentHolder.transform, false);IValue.SetLayout();}bool evaluated = TryAutoEvaluateIfUnitialized(cell);if (cell.CopyButton != null){bool canCopy = State != ValueState.NotEvaluated && State != ValueState.Exception;cell.CopyButton.Component.gameObject.SetActive(canCopy);cell.PasteButton.Component.gameObject.SetActive(canCopy && this.CanWrite);}if (!evaluated)return;// The following only executes if the object has evaluated.// For members and properties with args, they will return by default now.switch (State){case ValueState.Exception:SetValueState(cell, new(true, subContentButtonActive: true));break;case ValueState.Boolean:SetValueState(cell, new(false, toggleActive: true, applyActive: CanWrite));break;case ValueState.Number:SetValueState(cell, new(false, typeLabelActive: true, inputActive: true, applyActive: CanWrite));break;case ValueState.String:if (valueIsNull)SetValueState(cell, new(true, subContentButtonActive: true));elseSetValueState(cell, new(true, false, SignatureHighlighter.StringOrange, subContentButtonActive: true));break;case ValueState.Enum:SetValueState(cell, new(true, subContentButtonActive: CanWrite));break;case ValueState.Color:case ValueState.ValueStruct:if (ParseUtility.CanParse(currentValueType))SetValueState(cell, new(false, false, null, true, false, true, CanWrite, true, true));elseSetValueState(cell, new(true, inspectActive: true, subContentButtonActive: true));break;case ValueState.Collection:case ValueState.Dictionary:SetValueState(cell, new(true, inspectActive: !valueIsNull, subContentButtonActive: !valueIsNull));break;case ValueState.Unsupported:SetValueState(cell, new(true, inspectActive: !valueIsNull));break;}cell.RefreshSubcontentButton();}protected virtual void SetValueState(CacheObjectCell cell, ValueStateArgs args){// main value labelif (args.valueActive){cell.ValueLabel.text = ValueLabelText;cell.ValueLabel.supportRichText = args.valueRichText;cell.ValueLabel.color = args.valueColor;}elsecell.ValueLabel.text = "";// Type label (for primitives)cell.TypeLabel.gameObject.SetActive(args.typeLabelActive);if (args.typeLabelActive)cell.TypeLabel.text = SignatureHighlighter.Parse(currentValueType, false);// toggle for boolscell.Toggle.gameObject.SetActive(args.toggleActive);if (args.toggleActive){cell.Toggle.interactable = CanWrite;cell.Toggle.isOn = (bool)Value;cell.ToggleText.text = Value.ToString();}// inputfield for numberscell.InputField.UIRoot.SetActive(args.inputActive);if (args.inputActive){cell.InputField.Text = ParseUtility.ToStringForInput(Value, currentValueType);cell.InputField.Component.readOnly = !CanWrite;}// apply for bool and numberscell.ApplyButton.Component.gameObject.SetActive(args.applyActive);// Inspect button only if last value not null.if (cell.InspectButton != null)cell.InspectButton.Component.gameObject.SetActive(args.inspectActive && !valueIsNull);// set subcontent button if needed, and for null strings and exceptionscell.SubContentButton.Component.gameObject.SetActive(args.subContentButtonActive&& (!valueIsNull || State == ValueState.String || State == ValueState.Exception));}// CacheObjectCell Applypublic virtual void OnCellApplyClicked(){if (State == ValueState.Boolean)SetUserValue(this.CellView.Toggle.isOn);else{if (ParseUtility.TryParse(CellView.InputField.Text, currentValueType, out object value, out Exception ex)){SetUserValue(value);}else{ExplorerCore.LogWarning("Unable to parse input!");if (ex != null)ExplorerCore.Log(ex.ReflectionExToString());}}SetDataToCell(this.CellView);}// IValuespublic virtual void OnCellSubContentToggle(){if (this.IValue == null){Type ivalueType = InteractiveValue.GetIValueTypeForState(State);if (ivalueType == null)return;IValue = (InteractiveValue)Pool.Borrow(ivalueType);CurrentIValueType = ivalueType;IValue.OnBorrowed(this);IValue.SetValue(this.Value);IValue.UIRoot.transform.SetParent(CellView.SubContentHolder.transform, false);CellView.SubContentHolder.SetActive(true);SubContentShowWanted = true;// update our cell after creating the ivalue (the value may have updated, make sure its consistent)this.ProcessOnEvaluate();this.SetDataToCell(this.CellView);}else{SubContentShowWanted = !SubContentShowWanted;CellView.SubContentHolder.SetActive(SubContentShowWanted);if (SubContentShowWanted && IValue.PendingValueWanted){IValue.PendingValueWanted = false;this.ProcessOnEvaluate();this.SetDataToCell(this.CellView);IValue.SetValue(this.Value);}}CellView.RefreshSubcontentButton();}public virtual void ReleaseIValue(){if (IValue == null)return;IValue.ReleaseFromOwner();Pool.Return(CurrentIValueType, IValue);IValue = null;}internal static GameObject InactiveIValueHolder{get{if (!inactiveIValueHolder){inactiveIValueHolder = new GameObject("Temp_IValue_Holder");GameObject.DontDestroyOnLoad(inactiveIValueHolder);inactiveIValueHolder.hideFlags = HideFlags.HideAndDontSave;inactiveIValueHolder.transform.parent = UniversalUI.PoolHolder.transform;inactiveIValueHolder.SetActive(false);}return inactiveIValueHolder;}}private static GameObject inactiveIValueHolder;// Value state args helperpublic struct ValueStateArgs{public static ValueStateArgs Default { get; } = new(true);public Color valueColor;public bool valueActive, valueRichText, typeLabelActive, toggleActive, inputActive, applyActive, inspectActive, subContentButtonActive;public ValueStateArgs(bool valueActive = true,bool valueRichText = true,Color? valueColor = null,bool typeLabelActive = false,bool toggleActive = false,bool inputActive = false,bool applyActive = false,bool inspectActive = false,bool subContentButtonActive = false){this.valueActive = valueActive;this.valueRichText = valueRichText;this.valueColor = valueColor == null ? Color.white : (Color)valueColor;this.typeLabelActive = typeLabelActive;this.toggleActive = toggleActive;this.inputActive = inputActive;this.applyActive = applyActive;this.inspectActive = inspectActive;this.subContentButtonActive = subContentButtonActive;}}}}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。