More progress, and change Aggressive Mouse Unlock behaviour

This commit is contained in:
Sinai 2021-04-29 21:01:08 +10:00
parent a2a2b09d33
commit dba9bdbdc2
22 changed files with 365 additions and 233 deletions

View File

@ -29,10 +29,8 @@ namespace UnityExplorer.Core.Config
// internal configs
internal static InternalConfigHandler InternalHandler { get; private set; }
public static ConfigElement<string> SceneExplorerData;
public static ConfigElement<string> GameObjectInspectorData;
public static ConfigElement<string> MainWindowData;
public static ConfigElement<string> DebugConsoleData;
public static ConfigElement<string> ObjectExplorerData;
public static ConfigElement<string> InspectorData;
internal static readonly Dictionary<string, IConfigElement> ConfigElements = new Dictionary<string, IConfigElement>();
internal static readonly Dictionary<string, IConfigElement> InternalConfigs = new Dictionary<string, IConfigElement>();
@ -86,13 +84,9 @@ namespace UnityExplorer.Core.Config
KeyCode.None);
Aggressive_Force_Unlock = new ConfigElement<bool>("Aggressive Mouse Unlock",
"Use Camera.onPostRender callback to aggressively force the Mouse to be unlocked (requires game restart).",
"Use WaitForEndOfFrame to aggressively force the Mouse to be unlocked (requires game restart).",
false);
//Default_Tab = new ConfigElement<MenuPages>("Default Tab",
// "The default menu page when starting the game.",
// MenuPages.Home);
Log_Unity_Debug = new ConfigElement<bool>("Log Unity Debug",
"Should UnityEngine.Debug.Log messages be printed to UnityExplorer's log?",
false);
@ -111,10 +105,8 @@ namespace UnityExplorer.Core.Config
// Internal configs
SceneExplorerData = new ConfigElement<string>("SceneExplorer", "", "", true);
GameObjectInspectorData = new ConfigElement<string>("GameObjectInspector", "", "", true);
MainWindowData = new ConfigElement<string>("MainWindow", "", "", true);
DebugConsoleData = new ConfigElement<string>("DebugConsole", "", "", true);
ObjectExplorerData = new ConfigElement<string>("ObjectExplorer", "", "", true);
InspectorData = new ConfigElement<string>("Inspector", "", "", true);
}
}
}

View File

@ -5,6 +5,7 @@ using System.IO;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityExplorer.UI;
namespace UnityExplorer.Core.Config
{
@ -33,8 +34,7 @@ namespace UnityExplorer.Core.Config
public override void SetConfigValue<T>(ConfigElement<T> element, T value)
{
// Not necessary, just save.
SaveConfig();
// Not necessary
}
public override T GetConfigValue<T>(ConfigElement<T> element)
@ -43,10 +43,17 @@ namespace UnityExplorer.Core.Config
return element.Value;
}
public override void OnAnyConfigChanged()
{
SaveConfig();
}
public bool TryLoadConfig()
{
try
{
ExplorerCore.Log("Loading internal data");
if (!File.Exists(INI_PATH))
return false;
@ -60,33 +67,22 @@ namespace UnityExplorer.Core.Config
configElement.BoxedValue = StringToConfigValue(config.Value, configElement.ElementType);
}
ExplorerCore.Log("Loaded");
return true;
}
catch
catch (Exception ex)
{
ExplorerCore.LogWarning("Error loading internal data: " + ex.ToString());
return false;
}
}
public object StringToConfigValue(string value, Type elementType)
{
if (elementType.IsEnum)
return Enum.Parse(elementType, value);
else if (elementType == typeof(bool))
return bool.Parse(value);
else if (elementType == typeof(int))
return int.Parse(value);
else
return value;
}
public override void OnAnyConfigChanged()
{
SaveConfig();
}
public override void SaveConfig()
{
if (UIManager.Initializing)
return;
var data = new IniParser.Model.IniData();
data.Sections.AddSection("Config");
@ -100,5 +96,17 @@ namespace UnityExplorer.Core.Config
File.WriteAllText(INI_PATH, data.ToString());
}
public object StringToConfigValue(string value, Type elementType)
{
if (elementType.IsEnum)
return Enum.Parse(elementType, value);
else if (elementType == typeof(bool))
return bool.Parse(value);
else if (elementType == typeof(int))
return int.Parse(value);
else
return value;
}
}
}

View File

@ -6,6 +6,7 @@ using BF = System.Reflection.BindingFlags;
using UnityExplorer.Core.Config;
using UnityExplorer.Core;
using UnityExplorer.UI;
using System.Collections;
#if ML
using Harmony;
#else
@ -42,7 +43,7 @@ namespace UnityExplorer.Core.Input
public static void Init()
{
if (ConfigManager.Aggressive_Force_Unlock.Value)
RuntimeProvider.Instance.SetupCameraDelegate();
SetupAggressiveUnlock();
SetupPatches();
@ -52,11 +53,29 @@ namespace UnityExplorer.Core.Input
ConfigManager.Force_Unlock_Mouse.OnValueChanged += (bool val) => { Unlock = val; };
}
public static void OnCameraPostRender(Camera _)
public static void SetupAggressiveUnlock()
{
if (!UIManager.ShowMenu)
return;
UpdateIfNeeded();
try
{
RuntimeProvider.Instance.StartCoroutine(AggressiveUnlockCoroutine());
}
catch (Exception ex)
{
ExplorerCore.LogWarning($"Exception setting up Camera.onPostRender callback: {ex}");
}
}
private static readonly WaitForEndOfFrame _waitForEndOfFrame = new WaitForEndOfFrame();
private static IEnumerator AggressiveUnlockCoroutine()
{
while (true)
{
yield return _waitForEndOfFrame;
if (UIManager.ShowMenu)
UpdateCursorControl();
}
}
public static void UpdateIfNeeded()

View File

@ -26,24 +26,6 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
TextureUtil = new Il2CppTextureUtil();
}
public override void SetupCameraDelegate()
{
try
{
var action = new Action<Camera>(CursorUnlocker.OnCameraPostRender);
var _delegate = DelegateSupport.ConvertDelegate<Camera.CameraCallback>(action);
if (Camera.onPostRender == null)
Camera.onPostRender = _delegate;
else
Camera.onPostRender = Camera.onPostRender.CombineImpl(_delegate).TryCast<Camera.CameraCallback>();
}
catch (Exception ex)
{
ExplorerCore.LogWarning($"Exception setting up Camera.onPostRender callback: {ex}");
}
}
public override void SetupEvents()
{
try

View File

@ -27,11 +27,6 @@ namespace UnityExplorer.Core.Runtime.Mono
DummyBehaviour.Setup();
}
public override void SetupCameraDelegate()
{
Camera.onPostRender += CursorUnlocker.OnCameraPostRender;
}
public override void SetupEvents()
{
Application.logMessageReceived += Application_logMessageReceived;

View File

@ -35,8 +35,6 @@ namespace UnityExplorer
public abstract void Initialize();
public abstract void SetupCameraDelegate();
public abstract void SetupEvents();
public abstract void StartCoroutine(IEnumerator routine);

View File

@ -17,7 +17,7 @@ namespace UnityExplorer
public static class ExplorerCore
{
public const string NAME = "UnityExplorer";
public const string VERSION = "3.4.0";
public const string VERSION = "4.0.0";
public const string AUTHOR = "Sinai";
public const string GUID = "com.sinai.unityexplorer";
@ -35,6 +35,22 @@ namespace UnityExplorer
return;
}
// TEMP DEBUG TEST FOR TRANSFORM TREE
var stressTest = new GameObject("StressTest");
for (int i = 0; i < 100; i++)
{
var obj = new GameObject($"Parent_{i}");
obj.transform.parent = stressTest.transform;
for (int j = 0; j < 100; j++)
{
var obj2 = new GameObject($"Child_{j}");
obj2.transform.parent = obj.transform;
}
}
// END
Loader = loader;
if (!Directory.Exists(Loader.ExplorerFolder))

View File

@ -32,5 +32,17 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
LastException = ex;
}
}
protected override void TrySetValue(object value)
{
try
{
FieldInfo.SetValue(FieldInfo.IsStatic ? null : ParentInspector.Target, value);
}
catch (Exception ex)
{
ExplorerCore.LogWarning(ex);
}
}
}
}

View File

@ -15,6 +15,8 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
public abstract class CacheMember : CacheObjectBase
{
public ReflectionInspector ParentInspector { get; internal set; }
public CacheMemberCell CurrentView { get; internal set; }
public bool AutoUpdateWanted { get; internal set; }
public Type DeclaringType { get; private set; }
public string NameForFiltering { get; private set; }
@ -34,6 +36,8 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
public string TypeLabelText { get; protected set; }
public string ValueLabelText { get; protected set; }
private static readonly Dictionary<string, MethodInfo> numberParseMethods = new Dictionary<string, MethodInfo>();
public enum ValueState
{
NotEvaluated, Exception, NullValue,
@ -66,6 +70,43 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
protected abstract void TryEvaluate();
public void SetValue(object value)
{
// TODO unbox string, cast, etc
TrySetValue(value);
Evaluate();
}
protected abstract void TrySetValue(object value);
public void OnCellApplyClicked()
{
if (CurrentView == null)
{
ExplorerCore.LogWarning("Trying to apply CacheMember but current cell reference is null!");
return;
}
if (State == ValueState.Boolean)
SetValue(this.CurrentView.Toggle.isOn);
else
{
if (!numberParseMethods.ContainsKey(FallbackType.AssemblyQualifiedName))
{
var method = FallbackType.GetMethod("Parse", new Type[] { typeof(string) });
numberParseMethods.Add(FallbackType.AssemblyQualifiedName, method);
}
var val = numberParseMethods[FallbackType.AssemblyQualifiedName]
.Invoke(null, new object[] { CurrentView.InputField.text });
SetValue(val);
}
SetCell(this.CurrentView);
}
/// <summary>
/// Evaluate when first shown (if ShouldAutoEvaluate), or else when Evaluate button is clicked.
/// </summary>
@ -156,17 +197,23 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
cell.EvaluateHolder.SetActive(!ShouldAutoEvaluate);
if (!ShouldAutoEvaluate)
{
cell.UpdateToggle.gameObject.SetActive(false);
cell.EvaluateButton.Button.gameObject.SetActive(true);
if (HasArguments)
cell.EvaluateButton.ButtonText.text = $"Evaluate ({Arguments.Length})";
else
cell.EvaluateButton.ButtonText.text = "Evaluate";
}
else
{
cell.UpdateToggle.gameObject.SetActive(true);
cell.UpdateToggle.isOn = AutoUpdateWanted;
}
if (State == ValueState.NotEvaluated && !ShouldAutoEvaluate)
{
// todo evaluate buttons etc
SetCellState(cell, true, true, Color.white, false, false, false, false, false, false);
SetValueState(cell, true, true, Color.white, false, false, false, false, false, false);
return;
}
@ -178,31 +225,31 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
{
case ValueState.Exception:
case ValueState.NullValue:
SetCellState(cell, true, true, Color.white, false, false, false, false, false, false);
SetValueState(cell, true, true, Color.white, false, false, false, false, false, false);
break;
case ValueState.Boolean:
SetCellState(cell, false, false, default, true, toggleActive: true, false, CanWrite, false, false);
SetValueState(cell, false, false, default, true, toggleActive: true, false, CanWrite, false, false);
break;
case ValueState.Number:
SetCellState(cell, false, true, Color.white, true, false, inputActive: true, CanWrite, false, false);
SetValueState(cell, false, true, Color.white, true, false, inputActive: true, CanWrite, false, false);
break;
case ValueState.String:
SetCellState(cell, true, false, SignatureHighlighter.StringOrange, false, false, false, false, false, true);
SetValueState(cell, true, false, SignatureHighlighter.StringOrange, false, false, false, false, false, true);
break;
case ValueState.Enum:
SetCellState(cell, true, true, Color.white, false, false, false, false, false, true);
SetValueState(cell, true, true, Color.white, false, false, false, false, false, true);
break;
case ValueState.Collection:
case ValueState.ValueStruct:
SetCellState(cell, true, true, Color.white, false, false, false, false, true, true);
SetValueState(cell, true, true, Color.white, false, false, false, false, true, true);
break;
case ValueState.Unsupported:
SetCellState(cell, true, true, Color.white, false, false, false, false, true, false);
SetValueState(cell, true, true, Color.white, false, false, false, false, true, false);
break;
}
}
private void SetCellState(CacheMemberCell cell, bool valueActive, bool valueRichText, Color valueColor,
private void SetValueState(CacheMemberCell cell, bool valueActive, bool valueRichText, Color valueColor,
bool typeLabelActive, bool toggleActive, bool inputActive, bool applyActive, bool inspectActive, bool subContentActive)
{
//cell.ValueLabel.gameObject.SetActive(valueActive);
@ -228,13 +275,16 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
cell.InputField.gameObject.SetActive(inputActive);
if (inputActive)
{
cell.InputField.text = Value.ToString();
cell.InputField.readOnly = !CanWrite;
}
cell.ApplyButton.Button.gameObject.SetActive(applyActive);
cell.InspectButton.Button.gameObject.SetActive(inspectActive);
cell.SubContentButton.Button.gameObject.SetActive(subContentActive);
cell.UpdateButton.Button.gameObject.SetActive(ShouldAutoEvaluate);
cell.UpdateToggle.gameObject.SetActive(ShouldAutoEvaluate);
}

View File

@ -31,5 +31,7 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
LastException = ex;
}
}
protected override void TrySetValue(object value) => throw new NotImplementedException("You can't set a method");
}
}

View File

@ -32,5 +32,22 @@ namespace UnityExplorer.UI.Inspectors.CacheObject
LastException = ex;
}
}
protected override void TrySetValue(object value)
{
if (!CanWrite)
return;
try
{
// TODO property indexers
PropertyInfo.SetValue(PropertyInfo.GetSetMethod().IsStatic ? null : ParentInspector.Target, value, null);
}
catch (Exception ex)
{
ExplorerCore.LogWarning(ex);
}
}
}
}

View File

@ -9,8 +9,6 @@ using UnityExplorer.UI.Widgets;
namespace UnityExplorer.UI.Inspectors.CacheObject.Views
{
// Todo add C# events for the unity UI listeners
public class CacheMemberCell : ICell
{
#region ICell
@ -43,18 +41,10 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
public ReflectionInspector CurrentOwner { get; set; }
public CacheMember CurrentOccupant { get; set; }
public Action<CacheMember> OnApplyClicked;
public Action<CacheMember> OnInspectClicked;
public Action<CacheMember> OnSubContentClicked;
public Action<CacheMember> OnUpdateClicked;
public Action<CacheMember> OnEvaluateClicked;
public LayoutElement MemberLayout;
public LayoutElement RightGroupLayout;
public Text MemberLabel;
//public GameObject RightGroupHolder;
public Text TypeLabel;
public Text ValueLabel;
public Toggle Toggle;
@ -67,45 +57,41 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
public ButtonRef InspectButton;
public ButtonRef SubContentButton;
public ButtonRef ApplyButton;
public ButtonRef UpdateButton;
public Toggle UpdateToggle;
public GameObject SubContentHolder;
public void OnReturnToPool()
{
// remove listeners
OnApplyClicked = null;
OnInspectClicked = null;
OnSubContentClicked = null;
OnUpdateClicked = null;
OnEvaluateClicked = null;
if (CurrentOccupant != null)
{
// TODO
CurrentOccupant = null;
}
CurrentOwner = null;
}
private void ApplyClicked()
{
OnApplyClicked?.Invoke(CurrentOccupant);
CurrentOccupant.OnCellApplyClicked();
}
private void InspectClicked()
{
OnInspectClicked?.Invoke(CurrentOccupant);
}
private void SubContentClicked()
{
OnSubContentClicked?.Invoke(CurrentOccupant);
}
private void UpdateClicked()
{
OnUpdateClicked?.Invoke(CurrentOccupant);
InspectorManager.Inspect(CurrentOccupant.Value);
}
private void EvaluateClicked()
{
OnEvaluateClicked?.Invoke(CurrentOccupant);
// TODO
}
private void SubContentClicked()
{
// TODO
}
private void ToggleClicked(bool value)
@ -113,8 +99,12 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
ToggleText.text = value.ToString();
}
// Todo could create these as needed maybe, just need to make sure the transform order is correct.
public GameObject CreateContent(GameObject parent)
{
// Main layout
uiRoot = UIFactory.CreateUIObject("CacheMemberCell", parent, new Vector2(100, 30));
m_rect = uiRoot.GetComponent<RectTransform>();
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(uiRoot, true, false, true, true, 2, 0);
@ -130,16 +120,22 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(horiRow, false, false, true, true, 5, 2, childAlignment: TextAnchor.UpperLeft);
horiRow.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
// Left member label
MemberLabel = UIFactory.CreateLabel(horiRow, "MemberLabel", "<notset>", TextAnchor.MiddleLeft);
MemberLabel.horizontalOverflow = HorizontalWrapMode.Wrap;
UIFactory.SetLayoutElement(MemberLabel.gameObject, minHeight: 25, minWidth: 20, flexibleHeight: 300, flexibleWidth: 0);
MemberLayout = MemberLabel.GetComponent<LayoutElement>();
// Right vertical group
var rightGroupHolder = UIFactory.CreateUIObject("RightGroup", horiRow);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(rightGroupHolder, false, false, true, true, 4, childAlignment: TextAnchor.UpperLeft);
UIFactory.SetLayoutElement(rightGroupHolder, minHeight: 25, minWidth: 200, flexibleWidth: 9999, flexibleHeight: 800);
RightGroupLayout = rightGroupHolder.GetComponent<LayoutElement>();
// Evaluate vert group
EvaluateHolder = UIFactory.CreateUIObject("EvalGroup", rightGroupHolder);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(EvaluateHolder, false, false, true, true, 3);
UIFactory.SetLayoutElement(EvaluateHolder, minHeight: 25, flexibleWidth: 9999, flexibleHeight: 775);
@ -148,6 +144,8 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
UIFactory.SetLayoutElement(EvaluateButton.Button.gameObject, minWidth: 100, minHeight: 25);
EvaluateButton.OnClick += EvaluateClicked;
// Right horizontal group
var rightHoriGroup = UIFactory.CreateUIObject("RightHoriGroup", rightGroupHolder);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(rightHoriGroup, false, false, true, true, 4, childAlignment: TextAnchor.UpperLeft);
UIFactory.SetLayoutElement(rightHoriGroup, minHeight: 25, minWidth: 200, flexibleWidth: 9999, flexibleHeight: 800);
@ -159,7 +157,8 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
TypeLabel = UIFactory.CreateLabel(rightHoriGroup, "ReturnLabel", "<notset>", TextAnchor.MiddleLeft);
TypeLabel.horizontalOverflow = HorizontalWrapMode.Wrap;
UIFactory.SetLayoutElement(TypeLabel.gameObject, minHeight: 25, flexibleHeight: 150, minWidth: 70, flexibleWidth: 0);
//ReturnTypeLayout = TypeLabel.GetComponent<LayoutElement>();
// Bool and number value interaction
var toggleObj = UIFactory.CreateToggle(rightHoriGroup, "Toggle", out Toggle, out ToggleText);
UIFactory.SetLayoutElement(toggleObj, minWidth: 70, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
@ -169,6 +168,8 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
var inputObj = UIFactory.CreateInputField(rightHoriGroup, "InputField", "...", out InputField);
UIFactory.SetLayoutElement(inputObj, minWidth: 150, flexibleWidth: 0, minHeight: 25, flexibleHeight: 0);
// Inspect and apply buttons
InspectButton = UIFactory.CreateButton(rightHoriGroup, "InspectButton", "Inspect", new Color(0.15f, 0.15f, 0.15f));
UIFactory.SetLayoutElement(InspectButton.Button.gameObject, minWidth: 60, flexibleWidth: 0, minHeight: 25);
InspectButton.OnClick += InspectClicked;
@ -177,13 +178,23 @@ namespace UnityExplorer.UI.Inspectors.CacheObject.Views
UIFactory.SetLayoutElement(ApplyButton.Button.gameObject, minWidth: 70, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0);
ApplyButton.OnClick += ApplyClicked;
// Main value label
ValueLabel = UIFactory.CreateLabel(rightHoriGroup, "ValueLabel", "Value goes here", TextAnchor.MiddleLeft);
ValueLabel.horizontalOverflow = HorizontalWrapMode.Wrap;
UIFactory.SetLayoutElement(ValueLabel.gameObject, minHeight: 25, flexibleHeight: 150, flexibleWidth: 9999);
UpdateButton = UIFactory.CreateButton(rightHoriGroup, "UpdateButton", "Update", new Color(0.15f, 0.2f, 0.15f));
UIFactory.SetLayoutElement(UpdateButton.Button.gameObject, minWidth: 65, flexibleWidth: 0, minHeight: 25, flexibleHeight: 0);
UpdateButton.OnClick += UpdateClicked;
// Auto-update toggle
var updateToggle = UIFactory.CreateToggle(rightHoriGroup, "AutoUpdate", out UpdateToggle, out Text autoText);
UIFactory.SetLayoutElement(updateToggle, minHeight: 25, minWidth: 30, flexibleWidth: 0, flexibleHeight: 0);
GameObject.Destroy(autoText);
UpdateToggle.isOn = false;
UpdateToggle.onValueChanged.AddListener((bool val) => { CurrentOccupant.AutoUpdateWanted = val; });
//UpdateButton = UIFactory.CreateButton(rightHoriGroup, "UpdateButton", "Update", new Color(0.15f, 0.2f, 0.15f));
//UIFactory.SetLayoutElement(UpdateButton.Button.gameObject, minWidth: 65, flexibleWidth: 0, minHeight: 25, flexibleHeight: 0);
//UpdateButton.OnClick += UpdateClicked;
// Subcontent (todo?)

View File

@ -19,7 +19,7 @@ namespace UnityExplorer.UI.Inspectors
public class ReflectionInspector : InspectorBase, IPoolDataSource<CacheMemberCell>
{
public bool StaticOnly { get; internal set; }
public bool AutoUpdate { get; internal set; }
//public bool AutoUpdate { get; internal set; }
public object Target { get; private set; }
public Type TargetType { get; private set; }
@ -28,6 +28,7 @@ namespace UnityExplorer.UI.Inspectors
private List<CacheMember> members = new List<CacheMember>();
private readonly List<CacheMember> filteredMembers = new List<CacheMember>();
private readonly HashSet<CacheMember> displayedMembers = new HashSet<CacheMember>();
public override GameObject UIRoot => uiRoot;
private GameObject uiRoot;
@ -57,6 +58,22 @@ namespace UnityExplorer.UI.Inspectors
MemberScrollPool.Rebuild();
}
public override void OnReturnToPool()
{
foreach (var member in members)
member.OnDestroyed();
// release all cachememberviews
MemberScrollPool.ReturnCells();
MemberScrollPool.SetUninitialized();
members.Clear();
filteredMembers.Clear();
displayedMembers.Clear();
base.OnReturnToPool();
}
private void SetTarget(object target)
{
string prefix;
@ -98,21 +115,6 @@ namespace UnityExplorer.UI.Inspectors
}
}
public override void OnReturnToPool()
{
foreach (var member in members)
member.OnDestroyed();
members.Clear();
filteredMembers.Clear();
// release all cachememberviews
MemberScrollPool.ReturnCells();
MemberScrollPool.SetUninitialized();
base.OnReturnToPool();
}
public override void OnSetActive()
{
base.OnSetActive();
@ -123,6 +125,11 @@ namespace UnityExplorer.UI.Inspectors
base.OnSetInactive();
}
protected override void OnCloseClicked()
{
InspectorManager.ReleaseInspector(this);
}
private float timeOfLastUpdate;
public override void Update()
@ -136,59 +143,43 @@ namespace UnityExplorer.UI.Inspectors
return;
}
if (AutoUpdate && Time.time - timeOfLastUpdate > 1f)
if (Time.time - timeOfLastUpdate > 1f)
{
timeOfLastUpdate = Time.time;
// Update displayed values (TODO)
UpdateDisplayedMembers(true);
}
}
protected override void OnCloseClicked()
private void UpdateDisplayedMembers()
{
InspectorManager.ReleaseInspector(this);
UpdateDisplayedMembers(false);
}
private void UpdateDisplayedMembers(bool onlyAutoUpdate)
{
bool shouldRefresh = false;
foreach (var member in displayedMembers)
{
if (!onlyAutoUpdate || member.AutoUpdateWanted)
{
shouldRefresh = true;
member.Evaluate();
member.SetCell(member.CurrentView);
}
}
#region IPoolDataSource
if (shouldRefresh)
MemberScrollPool.RefreshCells(false);
}
// Member cells
public int ItemCount => filteredMembers.Count;
public void OnCellBorrowed(CacheMemberCell cell)
{
cell.CurrentOwner = this;
// todo add listeners
cell.OnInspectClicked += OnCellInspect;
cell.OnApplyClicked += OnCellApply;
cell.OnSubContentClicked += OnCellSubContentToggle;
cell.OnUpdateClicked += OnCellUpdateClicked;
cell.OnEvaluateClicked += OnCellEvaluateClicked;
}
private void OnCellInspect(CacheMember occupant)
{
InspectorManager.Inspect(occupant.Value);
}
private void OnCellApply(CacheMember occupant)
{
ExplorerCore.Log($"TODO OnApply: {occupant.NameForFiltering}");
}
private void OnCellSubContentToggle(CacheMember occupant)
{
ExplorerCore.Log($"TODO SubContentToggle: {occupant.NameForFiltering}");
}
private void OnCellUpdateClicked(CacheMember occupant)
{
ExplorerCore.Log("TODO Update: " + occupant.NameForFiltering);
}
private void OnCellEvaluateClicked(CacheMember occupant)
{
ExplorerCore.Log("TODO Evaluate or toggle: " + occupant);
}
public void OnCellReturned(CacheMemberCell cell)
@ -198,31 +189,43 @@ namespace UnityExplorer.UI.Inspectors
public void SetCell(CacheMemberCell cell, int index)
{
if (cell.CurrentOccupant != null)
{
// TODO
}
if (index < 0 || index >= filteredMembers.Count)
{
if (cell.CurrentOccupant != null)
{
if (displayedMembers.Contains(cell.CurrentOccupant))
displayedMembers.Remove(cell.CurrentOccupant);
cell.CurrentOccupant.CurrentView = null;
}
cell.Disable();
return;
}
var member = filteredMembers[index];
cell.CurrentOccupant = member;
if (member != cell.CurrentOccupant)
{
if (cell.CurrentOccupant != null)
{
// TODO
// changing occupant, put subcontent/evaluator on temp holder, etc
displayedMembers.Remove(cell.CurrentOccupant);
cell.CurrentOccupant.CurrentView = null;
}
cell.CurrentOccupant = member;
member.CurrentView = cell;
displayedMembers.Add(member);
}
member.SetCell(cell);
SetCellLayout(cell);
}
public void DisableCell(CacheMemberCell cell, int index)
{
// need to do anything?
}
#endregion
// Cell layout (fake table alignment)
private static float MemLabelWidth { get; set; }
@ -256,12 +259,18 @@ namespace UnityExplorer.UI.Inspectors
uiRoot = UIFactory.CreateVerticalGroup(parent, "ReflectionInspector", true, true, true, true, 5,
new Vector4(4, 4, 4, 4), new Color(0.12f, 0.12f, 0.12f));
// Class name, assembly. TODO more details
NameText = UIFactory.CreateLabel(uiRoot, "Title", "not set", TextAnchor.MiddleLeft, fontSize: 20);
UIFactory.SetLayoutElement(NameText.gameObject, minHeight: 25, flexibleHeight: 0);
AssemblyText = UIFactory.CreateLabel(uiRoot, "AssemblyLabel", "not set", TextAnchor.MiddleLeft);
UIFactory.SetLayoutElement(AssemblyText.gameObject, minHeight: 25, flexibleWidth: 9999);
// TODO filter row
// Member list
var listTitles = UIFactory.CreateUIObject("ListTitles", uiRoot);
UIFactory.SetLayoutElement(listTitles, minHeight: 25);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(listTitles, true, true, true, true, 5, 1, 1, 1, 1);
@ -269,21 +278,27 @@ namespace UnityExplorer.UI.Inspectors
var memberTitle = UIFactory.CreateLabel(listTitles, "MemberTitle", "Member Name", TextAnchor.LowerLeft, Color.grey, fontSize: 15);
memberTitleLayout = memberTitle.gameObject.AddComponent<LayoutElement>();
//var typeTitle = UIFactory.CreateLabel(listTitles, "TypeTitle", "Type", TextAnchor.LowerLeft, Color.grey, fontSize: 15);
//typeTitleLayout = typeTitle.gameObject.AddComponent<LayoutElement>();
var valueTitle = UIFactory.CreateLabel(listTitles, "ValueTitle", "Value", TextAnchor.LowerLeft, Color.grey, fontSize: 15);
UIFactory.SetLayoutElement(valueTitle.gameObject, minWidth: 150, flexibleWidth: 9999);
var updateButton = UIFactory.CreateButton(listTitles, "UpdateButton", "Update values", new Color(0.22f, 0.28f, 0.22f));
UIFactory.SetLayoutElement(updateButton.Button.gameObject, minHeight: 25, minWidth: 130, flexibleWidth: 0);
updateButton.OnClick += UpdateDisplayedMembers;
var updateText = UIFactory.CreateLabel(listTitles, "AutoUpdateLabel", "Auto-update", TextAnchor.MiddleRight, Color.grey);
UIFactory.SetLayoutElement(updateText.gameObject, minHeight: 25, minWidth: 80, flexibleWidth: 0);
// Member scroll pool
MemberScrollPool = UIFactory.CreateScrollPool<CacheMemberCell>(uiRoot, "MemberList", out GameObject scrollObj,
out GameObject scrollContent, new Color(0.09f, 0.09f, 0.09f));
out GameObject _, new Color(0.09f, 0.09f, 0.09f));
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
//UIFactory.SetLayoutElement(scrollContent, flexibleHeight: 9999);
MemberScrollPool.Initialize(this);
//InspectorPanel.Instance.UIRoot.GetComponent<Mask>().enabled = false;
//MemberScrollPool.Viewport.GetComponent<Mask>().enabled = false;
InspectorPanel.Instance.UIRoot.GetComponent<Mask>().enabled = false;
MemberScrollPool.Viewport.GetComponent<Mask>().enabled = false;
MemberScrollPool.Viewport.GetComponent<Image>().color = new Color(0.12f, 0.12f, 0.12f);
return uiRoot;
}

View File

@ -44,14 +44,14 @@ namespace UnityExplorer.UI.Panels
public override void LoadSaveData()
{
ApplySaveData(ConfigManager.GameObjectInspectorData.Value);
ApplySaveData(ConfigManager.InspectorData.Value);
InspectorManager.PanelWidth = this.mainPanelRect.rect.width;
}
public override void SaveToConfigManager()
public override void DoSaveToConfigElement()
{
ConfigManager.GameObjectInspectorData.Value = this.ToSaveData();
ConfigManager.InspectorData.Value = this.ToSaveData();
}
public override void SetDefaultPosAndAnchors()

View File

@ -26,7 +26,7 @@ namespace UnityExplorer.UI.Panels
public override bool ShouldSaveActiveState => true;
public int SelectedTab = -1;
public int SelectedTab = 0;
private readonly List<UIModel> tabPages = new List<UIModel>();
private readonly List<ButtonRef> tabButtons = new List<ButtonRef>();
@ -57,14 +57,14 @@ namespace UnityExplorer.UI.Panels
SceneExplorer.Update();
}
public override void SaveToConfigManager()
public override void DoSaveToConfigElement()
{
ConfigManager.SceneExplorerData.Value = this.ToSaveData();
ConfigManager.ObjectExplorerData.Value = this.ToSaveData();
}
public override void LoadSaveData()
{
ApplySaveData(ConfigManager.SceneExplorerData.Value);
ApplySaveData(ConfigManager.ObjectExplorerData.Value);
}
public override string ToSaveData()
@ -88,6 +88,9 @@ namespace UnityExplorer.UI.Panels
SelectedTab = 0;
}
SelectedTab = Math.Max(0, SelectedTab);
SelectedTab = Math.Min(1, SelectedTab);
SetTab(SelectedTab);
}

View File

@ -102,8 +102,14 @@ namespace UnityExplorer.UI.Panels
public override void SetActive(bool active)
{
if (this.Enabled.Equals(active))
return;
base.SetActive(active);
if (!ApplyingSaveData)
SaveToConfigManager();
if (NavButtonWanted)
{
if (active)
@ -186,6 +192,7 @@ namespace UnityExplorer.UI.Panels
ConstructPanelContent();
ApplyingSaveData = true;
// apply panel save data or revert to default
try
{
@ -203,18 +210,29 @@ namespace UnityExplorer.UI.Panels
{
SaveToConfigManager();
};
ApplyingSaveData = false;
}
public override void ConstructUI(GameObject parent) => ConstructUI();
// SAVE DATA
public abstract void SaveToConfigManager();
public void SaveToConfigManager()
{
if (UIManager.Initializing)
return;
DoSaveToConfigElement();
}
public abstract void DoSaveToConfigElement();
public abstract void SetDefaultPosAndAnchors();
public abstract void LoadSaveData();
public bool ApplyingSaveData { get; set; }
public virtual string ToSaveData()
{
try
@ -223,8 +241,9 @@ namespace UnityExplorer.UI.Panels
$"|{mainPanelRect.RectAnchorsToString()}" +
$"|{mainPanelRect.RectPositionToString()}";
}
catch
catch (Exception ex)
{
ExplorerCore.LogWarning($"Exception generating Panel save data: {ex}");
return "";
}
}

View File

@ -28,6 +28,8 @@ namespace UnityExplorer.UI
AutoCompleter
}
public static bool Initializing { get; private set; } = true;
public static GameObject CanvasRoot { get; private set; }
public static Canvas Canvas { get; private set; }
public static EventSystem EventSys { get; private set; }
@ -66,7 +68,7 @@ namespace UnityExplorer.UI
public static void Update()
{
if (!CanvasRoot)
if (!CanvasRoot || Initializing)
return;
//if (InspectUnderMouse.Inspecting)
@ -165,6 +167,7 @@ namespace UnityExplorer.UI
ShowMenu = !ConfigManager.Hide_On_Startup.Value;
ExplorerCore.Log("UI initialized.");
Initializing = false;
}
private static void CreateRootCanvas()
@ -238,20 +241,6 @@ namespace UnityExplorer.UI
closeBtn.OnClick += () => { ShowMenu = false; };
}
// Could be cool, need to investigate properly.
// It works but the input/eventsystem doesnt respond properly or at all.
//public static void TrySetTargetDisplay(int displayIndex)
//{
// ExplorerCore.Log("displays connected: " + Display.displays.Length);
// // Display.displays[0] is the primary, default display and is always ON, so start at index 1.
// if (Display.displays.Length > displayIndex)
// {
// Display.displays[displayIndex].Activate();
// Canvas.targetDisplay = displayIndex;
// }
//}
#region UI AssetBundle
private static void LoadBundle()

View File

@ -185,7 +185,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete
UIRoot.SetActive(false);
}
public override void SaveToConfigManager()
public override void DoSaveToConfigElement()
{
// not savable
}

View File

@ -85,6 +85,6 @@ namespace UnityExplorer.UI.Widgets
}
}
public void DisableCell(ButtonCell cell, int index) => cell.Disable();
//public void DisableCell(ButtonCell cell, int index) => cell.Disable();
}
}

View File

@ -14,6 +14,6 @@ namespace UnityExplorer.UI.Widgets
void OnCellReturned(T cell);
void SetCell(T cell, int index);
void DisableCell(T cell, int index);
//void DisableCell(T cell, int index);
}
}

View File

@ -134,7 +134,7 @@ namespace UnityExplorer.UI.Widgets
SetRecycleViewBounds(false);
SetScrollBounds();
RecreateCellPool(true, true);
ExtendCellPool();
writingLocked = false;
Content.anchoredPosition = Vector2.zero;
UpdateSliderHandle(true);
@ -244,7 +244,6 @@ namespace UnityExplorer.UI.Widgets
var cell = Pool<T>.Borrow();
DataSource.OnCellBorrowed(cell);
//var rect = cell.Rect;
CellPool.Add(cell);
cell.Rect.SetParent(ScrollRect.content, false);
@ -262,48 +261,53 @@ namespace UnityExplorer.UI.Widgets
SetCell(CellPool[enumerator.Current.cellIndex], enumerator.Current.dataIndex);
}
/// <summary>ret = cell pool was extended</summary>
private bool SetRecycleViewBounds(bool checkHeightGrow)
private void SetRecycleViewBounds(bool extendPoolIfGrown)
{
bool ret = false;
RecycleViewBounds = new Vector2(Viewport.MinY() + HalfThreshold, Viewport.MaxY() - HalfThreshold);
if (checkHeightGrow && prevViewportHeight < Viewport.rect.height && prevViewportHeight != 0.0f)
ret = RecreateCellPool(false, false);
if (extendPoolIfGrown && prevViewportHeight < Viewport.rect.height && prevViewportHeight != 0.0f)
ExtendCellPool();
prevViewportHeight = Viewport.rect.height;
return ret;
}
private bool RecreateCellPool(bool forceRecreate, bool resetDataIndex)
private bool ExtendCellPool()
{
CheckDataSourceCountChange(out _);
var requiredCoverage = Math.Abs(RecycleViewBounds.y - RecycleViewBounds.x);
var currentCoverage = CellPool.Count * PrototypeHeight;
int cellsRequired = (int)Math.Floor((decimal)(requiredCoverage - currentCoverage) / (decimal)PrototypeHeight);
if (cellsRequired > 0 || forceRecreate)
if (cellsRequired > 0)
{
WritingLocked = true;
bottomDataIndex += cellsRequired;
int maxDataIndex = Math.Max(CellPool.Count + cellsRequired - 1, DataSource.ItemCount - 1);
if (bottomDataIndex > maxDataIndex)
bottomDataIndex = maxDataIndex;
float curAnchor = Content.localPosition.y;
float curHeight = Content.rect.height;
float prevAnchor = Content.localPosition.y;
float prevHeight = Content.rect.height;
CreateCellPool(resetDataIndex);
// fix slight jumping when resizing panel and size increases
if (Content.rect.height != curHeight)
for (int i = 0; i < cellsRequired; i++)
{
var diff = Content.rect.height - curHeight;
Content.localPosition = new Vector3(Content.localPosition.x, Content.localPosition.y + (diff * 0.5f));
var cell = Pool<T>.Borrow();
DataSource.OnCellBorrowed(cell);
cell.Rect.SetParent(ScrollRect.content, false);
CellPool.Add(cell);
if (CellPool.Count > 1)
{
int index = CellPool.Count - 1 - (topPoolIndex % (CellPool.Count - 1));
cell.Rect.SetSiblingIndex(index);
}
}
RefreshCells(true);
if (Content.localPosition.y != prevAnchor)
{
var diff = Content.localPosition.y - prevAnchor;
Content.localPosition = new Vector3(Content.localPosition.x, Content.localPosition.y - diff);
}
ScrollRect.UpdatePrevData();
@ -321,7 +325,7 @@ namespace UnityExplorer.UI.Widgets
private CellInfo _cellInfo = new CellInfo();
private IEnumerator<CellInfo> GetPoolEnumerator()
public IEnumerator<CellInfo> GetPoolEnumerator()
{
int cellIdx = topPoolIndex;
int dataIndex = TopDataIndex;

View File

@ -55,7 +55,7 @@ namespace UnityExplorer.UI.Widgets
ScrollPool.Initialize(this);
}
public void DisableCell(TransformCell cell, int index) => cell.Disable();
//public void DisableCell(TransformCell cell, int index) => cell.Disable();
public bool IsCellExpanded(int instanceID)