From 7b477a8b0ee4286feab7f92d3bbc3c1b7569bd23 Mon Sep 17 00:00:00 2001 From: Sinai <49360850+sinai-dev@users.noreply.github.com> Date: Sun, 2 Jan 2022 19:43:55 +1100 Subject: [PATCH] Rewrite EvaluateWidget, add BaseArgumentHandler, use autocomplete for InteractiveEnum --- src/CacheObject/CacheMember.cs | 1 + src/CacheObject/IValues/InteractiveEnum.cs | 203 +++++----- src/CacheObject/Views/EvaluateWidget.cs | 374 ------------------ src/Core/Tests/TestClass.cs | 6 +- .../Widgets/AutoComplete/AutoCompleteModal.cs | 13 +- src/UI/Widgets/AutoComplete/EnumCompleter.cs | 160 ++++++++ src/UI/Widgets/AutoComplete/Suggestion.cs | 2 - src/UI/Widgets/AutoComplete/TypeCompleter.cs | 19 +- .../EvaluateWidget/BaseArgumentHandler.cs | 51 +++ .../Widgets/EvaluateWidget/EvaluateWidget.cs | 176 +++++++++ .../EvaluateWidget/GenericArgumentHandler.cs | 61 +++ .../EvaluateWidget/ParameterHandler.cs | 186 +++++++++ src/UnityExplorer.csproj | 6 +- 13 files changed, 768 insertions(+), 490 deletions(-) delete mode 100644 src/CacheObject/Views/EvaluateWidget.cs create mode 100644 src/UI/Widgets/AutoComplete/EnumCompleter.cs create mode 100644 src/UI/Widgets/EvaluateWidget/BaseArgumentHandler.cs create mode 100644 src/UI/Widgets/EvaluateWidget/EvaluateWidget.cs create mode 100644 src/UI/Widgets/EvaluateWidget/GenericArgumentHandler.cs create mode 100644 src/UI/Widgets/EvaluateWidget/ParameterHandler.cs diff --git a/src/CacheObject/CacheMember.cs b/src/CacheObject/CacheMember.cs index 846f950..e2bffb0 100644 --- a/src/CacheObject/CacheMember.cs +++ b/src/CacheObject/CacheMember.cs @@ -11,6 +11,7 @@ using UniverseLib.UI.Models; using UnityExplorer.UI; using UniverseLib; using UniverseLib.UI; +using UnityExplorer.UI.Widgets; namespace UnityExplorer.CacheObject { diff --git a/src/CacheObject/IValues/InteractiveEnum.cs b/src/CacheObject/IValues/InteractiveEnum.cs index 9a67c5e..c825195 100644 --- a/src/CacheObject/IValues/InteractiveEnum.cs +++ b/src/CacheObject/IValues/InteractiveEnum.cs @@ -7,6 +7,8 @@ using UnityEngine; using UnityEngine.UI; using UnityExplorer.CacheObject; using UnityExplorer.UI; +using UnityExplorer.UI.Widgets.AutoComplete; +using UniverseLib; using UniverseLib.UI; namespace UnityExplorer.CacheObject.IValues @@ -20,10 +22,10 @@ namespace UnityExplorer.CacheObject.IValues public OrderedDictionary CurrentValues; - public CachedEnumValue ValueAtIdx(int idx) => (CachedEnumValue)CurrentValues[idx]; - public CachedEnumValue ValueAtKey(object key) => (CachedEnumValue)CurrentValues[key]; + private InputFieldRef inputField; + private ButtonRef enumHelperButton; + private EnumCompleter enumCompleter; - private Dropdown enumDropdown; private GameObject toggleHolder; private readonly List flagToggles = new List(); private readonly List flagTexts = new List(); @@ -35,38 +37,68 @@ namespace UnityExplorer.CacheObject.IValues if (lastType != EnumType) { - CurrentValues = GetEnumValues(EnumType, out IsFlags); + CurrentValues = GetEnumValues(EnumType); + IsFlags = EnumType.GetCustomAttributes(typeof(FlagsAttribute), true) is object[] fa && fa.Any(); if (IsFlags) SetupTogglesForEnumType(); else - SetupDropdownForEnumType(); + { + inputField.Component.gameObject.SetActive(true); + enumHelperButton.Component.gameObject.SetActive(true); + toggleHolder.SetActive(false); + } + + enumCompleter.EnumType = EnumType; + enumCompleter.CacheEnumValues(); lastType = EnumType; } - // setup ui for changes - if (IsFlags) - SetTogglesForValue(value); + if (!IsFlags) + inputField.Text = value.ToString(); else - SetDropdownForValue(value); + SetTogglesForValue(value); + + this.enumCompleter.chosenSuggestion = value.ToString(); + AutoCompleteModal.Instance.ReleaseOwnership(this.enumCompleter); + } + + private void SetTogglesForValue(object value) + { + try + { + var split = value.ToString().Split(','); + var set = new HashSet(); + foreach (var s in split) + set.Add(s.Trim()); + + for (int i = 0; i < CurrentValues.Count; i++) + flagToggles[i].isOn = set.Contains(ValueAtIdx(i).Name); + } + catch (Exception ex) + { + ExplorerCore.LogWarning("Exception setting flag toggles: " + ex); + } } // Setting value to owner private void OnApplyClicked() - { - if (IsFlags) - SetValueFromFlags(); - else - SetValueFromDropdown(); - } - - private void SetValueFromDropdown() { try { - CurrentOwner.SetUserValue(ValueAtIdx(enumDropdown.value).ActualValue); + if (!IsFlags) + { + if (ParseUtility.TryParse(this.inputField.Text, EnumType, out object value, out Exception ex)) + CurrentOwner.SetUserValue(value); + else + throw ex; + } + else + { + SetValueFromFlags(); + } } catch (Exception ex) { @@ -93,59 +125,53 @@ namespace UnityExplorer.CacheObject.IValues } } - // setting UI state for value + // UI Construction - private void SetDropdownForValue(object value) + private void EnumHelper_OnClick() { - if (CurrentValues.Contains(value)) - { - var cached = ValueAtKey(value); - enumDropdown.value = cached.EnumIndex; - enumDropdown.RefreshShownValue(); - } - else - ExplorerCore.LogWarning("CurrentValues does not contain key '" + value?.ToString() ?? "" + "'"); + enumCompleter.HelperButtonClicked(); } - private void SetTogglesForValue(object value) + public override GameObject CreateContent(GameObject parent) { - try - { - var split = value.ToString().Split(','); - var set = new HashSet(); - foreach (var s in split) - set.Add(s.Trim()); + UIRoot = UIFactory.CreateVerticalGroup(parent, "InteractiveEnum", false, false, true, true, 3, new Vector4(4, 4, 4, 4), + new Color(0.06f, 0.06f, 0.06f)); + UIFactory.SetLayoutElement(UIRoot, minHeight: 25, flexibleHeight: 9999, flexibleWidth: 9999); - for (int i = 0; i < CurrentValues.Count; i++) - flagToggles[i].isOn = set.Contains(ValueAtIdx(i).Name); - } - catch (Exception ex) - { - ExplorerCore.LogWarning("Exception setting flag toggles: " + ex); - } + var hori = UIFactory.CreateUIObject("Hori", UIRoot); + UIFactory.SetLayoutElement(hori, minHeight: 25, flexibleWidth: 9999); + UIFactory.SetLayoutGroup(hori, false, false, true, true, 2); + + var applyButton = UIFactory.CreateButton(hori, "ApplyButton", "Apply", new Color(0.2f, 0.27f, 0.2f)); + UIFactory.SetLayoutElement(applyButton.Component.gameObject, minHeight: 25, minWidth: 100); + applyButton.OnClick += OnApplyClicked; + + inputField = UIFactory.CreateInputField(hori, "InputField", "Enter name or underlying value..."); + UIFactory.SetLayoutElement(inputField.UIRoot, minHeight: 25, flexibleHeight: 50, minWidth: 100, flexibleWidth: 1000); + inputField.Component.lineType = InputField.LineType.MultiLineNewline; + inputField.UIRoot.AddComponent().verticalFit = ContentSizeFitter.FitMode.PreferredSize; + + enumHelperButton = UIFactory.CreateButton(hori, "EnumHelper", "▼"); + UIFactory.SetLayoutElement(enumHelperButton.Component.gameObject, minWidth: 25, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0); + enumHelperButton.OnClick += EnumHelper_OnClick; + + enumCompleter = new EnumCompleter(this.EnumType, this.inputField); + + toggleHolder = UIFactory.CreateUIObject("ToggleHolder", UIRoot); + UIFactory.SetLayoutGroup(toggleHolder, false, false, true, true, 4); + UIFactory.SetLayoutElement(toggleHolder, minHeight: 25, flexibleWidth: 9999, flexibleHeight: 9999); + + return UIRoot; } - // Setting up the UI for the enum type when it changes or is first set - - private void SetupDropdownForEnumType() - { - toggleHolder.SetActive(false); - enumDropdown.gameObject.SetActive(true); - - // create dropdown entries - enumDropdown.options.Clear(); - - foreach (CachedEnumValue entry in CurrentValues.Values) - enumDropdown.options.Add(new Dropdown.OptionData(entry.Name)); - - enumDropdown.value = 0; - enumDropdown.RefreshShownValue(); - } + public CachedEnumValue ValueAtIdx(int idx) => (CachedEnumValue)CurrentValues[idx]; + public CachedEnumValue ValueAtKey(object key) => (CachedEnumValue)CurrentValues[key]; private void SetupTogglesForEnumType() { toggleHolder.SetActive(true); - enumDropdown.gameObject.SetActive(false); + inputField.Component.gameObject.SetActive(false); + enumHelperButton.Component.gameObject.SetActive(false); // create / set / hide toggles for (int i = 0; i < CurrentValues.Count || i < flagToggles.Count; i++) @@ -180,54 +206,13 @@ namespace UnityExplorer.CacheObject.IValues flagTexts.Add(toggleText); } - // UI Construction - - public override GameObject CreateContent(GameObject parent) - { - UIRoot = UIFactory.CreateVerticalGroup(parent, "InteractiveEnum", false, false, true, true, 3, new Vector4(4, 4, 4, 4), - new Color(0.06f, 0.06f, 0.06f)); - UIFactory.SetLayoutElement(UIRoot, minHeight: 25, flexibleHeight: 9999, flexibleWidth: 9999); - - var hori = UIFactory.CreateUIObject("Hori", UIRoot); - UIFactory.SetLayoutElement(hori, minHeight: 25, flexibleWidth: 9999); - UIFactory.SetLayoutGroup(hori, false, false, true, true, 2); - - var applyButton = UIFactory.CreateButton(hori, "ApplyButton", "Apply", new Color(0.2f, 0.27f, 0.2f)); - UIFactory.SetLayoutElement(applyButton.Component.gameObject, minHeight: 25, minWidth: 100); - applyButton.OnClick += OnApplyClicked; - - var dropdownObj = UIFactory.CreateDropdown(hori, out enumDropdown, "not set", 14, null); - UIFactory.SetLayoutElement(dropdownObj, minHeight: 25, flexibleWidth: 600); - - toggleHolder = UIFactory.CreateUIObject("ToggleHolder", UIRoot); - UIFactory.SetLayoutGroup(toggleHolder, false, false, true, true, 4); - UIFactory.SetLayoutElement(toggleHolder, minHeight: 25, flexibleWidth: 9999, flexibleHeight: 9999); - - return UIRoot; - } - - #region Enum cache - public struct CachedEnumValue - { - public CachedEnumValue(object value, int index, string name) - { - EnumIndex = index; - Name = name; - ActualValue = value; - } - - public readonly object ActualValue; - public int EnumIndex; - public readonly string Name; - } - internal static readonly Dictionary enumCache = new Dictionary(); - internal static OrderedDictionary GetEnumValues(Type enumType, out bool isFlags) + internal static OrderedDictionary GetEnumValues(Type enumType) { - isFlags = enumType.GetCustomAttributes(typeof(FlagsAttribute), true) is object[] fa && fa.Any(); + //isFlags = enumType.GetCustomAttributes(typeof(FlagsAttribute), true) is object[] fa && fa.Any(); if (!enumCache.ContainsKey(enumType.AssemblyQualifiedName)) { @@ -254,4 +239,18 @@ namespace UnityExplorer.CacheObject.IValues #endregion } + + public struct CachedEnumValue + { + public CachedEnumValue(object value, int index, string name) + { + EnumIndex = index; + Name = name; + ActualValue = value; + } + + public readonly object ActualValue; + public int EnumIndex; + public readonly string Name; + } } diff --git a/src/CacheObject/Views/EvaluateWidget.cs b/src/CacheObject/Views/EvaluateWidget.cs deleted file mode 100644 index 2dd235d..0000000 --- a/src/CacheObject/Views/EvaluateWidget.cs +++ /dev/null @@ -1,374 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using UnityEngine; -using UnityEngine.UI; -using UnityExplorer.UI; -using UniverseLib.UI.Models; -using UnityExplorer.UI.Widgets.AutoComplete; -using UniverseLib.UI; -using UniverseLib; - -namespace UnityExplorer.CacheObject.Views -{ - public class EvaluateWidget : IPooledObject - { - public CacheMember Owner { get; set; } - - public GameObject UIRoot { get; set; } - public float DefaultHeight => -1f; - - private ParameterInfo[] arguments; - private string[] argumentInput; - - private GameObject argHolder; - private readonly List argRows = new List(); - private readonly List argLabels = new List(); - private readonly List argInputFields = new List(); - private readonly List argDropdowns = new List(); - - private Type[] genericArguments; - private string[] genericInput; - - private GameObject genericArgHolder; - private readonly List genericArgRows = new List(); - private readonly List genericArgLabels = new List(); - private readonly List genericAutocompleters = new List(); - private readonly List genericInputFields = new List(); - - public void OnBorrowedFromPool(CacheMember owner) - { - this.Owner = owner; - - arguments = owner.Arguments; - argumentInput = new string[arguments.Length]; - - genericArguments = owner.GenericArguments; - genericInput = new string[genericArguments.Length]; - - SetArgRows(); - - this.UIRoot.SetActive(true); - - InspectorManager.OnInspectedTabsChanged += InspectorManager_OnInspectedTabsChanged; - } - - public void OnReturnToPool() - { - foreach (var input in argInputFields) - input.Text = ""; - foreach (var input in genericInputFields) - input.Text = ""; - - this.Owner = null; - - InspectorManager.OnInspectedTabsChanged -= InspectorManager_OnInspectedTabsChanged; - } - - private void InspectorManager_OnInspectedTabsChanged() - { - for (int i = 0; i < argDropdowns.Count; i++) - { - var drop = argDropdowns[i]; - PopulateNonPrimitiveArgumentDropdown(drop, i); - } - } - - public Type[] TryParseGenericArguments() - { - Type[] outArgs = new Type[genericArguments.Length]; - - for (int i = 0; i < genericArguments.Length; i++) - { - outArgs[i] = ReflectionUtility.GetTypeByName(genericInput[i]) - ?? throw new Exception($"Could not find any type by name '{genericInput[i]}'!"); - } - - return outArgs; - } - - public object[] TryParseArguments() - { - object[] outArgs = new object[arguments.Length]; - - for (int i = 0; i < arguments.Length; i++) - { - var paramInfo = arguments[i]; - - var argType = paramInfo.ParameterType; - if (argType.IsByRef) - argType = argType.GetElementType(); - - if (ParseUtility.CanParse(argType)) - { - var input = argumentInput[i]; - - if (argType == typeof(string)) - { - outArgs[i] = input; - continue; - } - - if (string.IsNullOrEmpty(input)) - { - if (paramInfo.IsOptional) - outArgs[i] = paramInfo.DefaultValue; - else - outArgs[i] = null; - continue; - } - - if (!ParseUtility.TryParse(input, argType, out outArgs[i], out Exception ex)) - { - outArgs[i] = null; - ExplorerCore.LogWarning($"Cannot parse argument '{paramInfo.Name}' ({paramInfo.ParameterType.Name})" + - $"{(ex == null ? "" : $", {ex.GetType().Name}: {ex.Message}")}"); - } - } - else - { - var dropdown = argDropdowns[i]; - if (dropdown.value == 0) - { - outArgs[i] = null; - } - else - { - // Probably should do this in a better way... - // Parse the text of the dropdown option to get the inspector tab index. - string tabIndexString = ""; - for (int j = 4; ; j++) - { - char c = dropdown.options[dropdown.value].text[j]; - if (c == ':') - break; - tabIndexString += c; - } - int tabIndex = int.Parse(tabIndexString); - var tab = InspectorManager.Inspectors[tabIndex - 1]; - - outArgs[i] = tab.Target; - } - } - } - - return outArgs; - } - - private void SetArgRows() - { - if (genericArguments.Any()) - { - genericArgHolder.SetActive(true); - SetGenericRows(); - } - else - genericArgHolder.SetActive(false); - - if (arguments.Any()) - { - argHolder.SetActive(true); - SetNormalArgRows(); - } - else - argHolder.SetActive(false); - } - - private void SetGenericRows() - { - for (int i = 0; i < genericArguments.Length || i < genericArgRows.Count; i++) - { - if (i >= genericArguments.Length) - { - if (i >= genericArgRows.Count) - break; - else - // exceeded actual args, but still iterating so there must be views left, disable them - genericArgRows[i].SetActive(false); - continue; - } - - var arg = genericArguments[i]; - - if (i >= genericArgRows.Count) - AddArgRow(i, true); - - genericArgRows[i].SetActive(true); - - var autoCompleter = genericAutocompleters[i]; - autoCompleter.BaseType = arg; - autoCompleter.CacheTypes(); - - var constraints = arg.GetGenericParameterConstraints(); - autoCompleter.GenericConstraints = constraints; - - var sb = new StringBuilder($"{arg.Name}"); - - for (int j = 0; j < constraints.Length; j++) - { - if (j == 0) sb.Append(' ').Append('('); - else sb.Append(',').Append(' '); - - sb.Append(SignatureHighlighter.Parse(constraints[j], false)); - - if (j + 1 == constraints.Length) - sb.Append(')'); - } - - genericArgLabels[i].text = sb.ToString(); - } - } - - private void SetNormalArgRows() - { - for (int i = 0; i < arguments.Length || i < argRows.Count; i++) - { - if (i >= arguments.Length) - { - if (i >= argRows.Count) - break; - else - // exceeded actual args, but still iterating so there must be views left, disable them - argRows[i].SetActive(false); - continue; - } - - var arg = arguments[i]; - var argType = arg.ParameterType; - if (argType.IsByRef) - argType = argType.GetElementType(); - - if (i >= argRows.Count) - AddArgRow(i, false); - - argRows[i].SetActive(true); - argLabels[i].text = - $"{SignatureHighlighter.Parse(argType, false)} {arg.Name}"; - - if (ParseUtility.CanParse(argType)) - { - argInputFields[i].Component.gameObject.SetActive(true); - argDropdowns[i].gameObject.SetActive(false); - - if (arg.ParameterType == typeof(string)) - argInputFields[i].PlaceholderText.text = ""; - else - argInputFields[i].PlaceholderText.text = $"eg. {ParseUtility.GetExampleInput(argType)}"; - } - else - { - argInputFields[i].Component.gameObject.SetActive(false); - argDropdowns[i].gameObject.SetActive(true); - - PopulateNonPrimitiveArgumentDropdown(argDropdowns[i], i); - } - } - } - - private void PopulateNonPrimitiveArgumentDropdown(Dropdown dropdown, int argIndex) - { - dropdown.options.Clear(); - dropdown.options.Add(new Dropdown.OptionData("null")); - - var argType = arguments[argIndex].ParameterType; - - int tabIndex = 0; - foreach (var tab in InspectorManager.Inspectors) - { - tabIndex++; - - if (argType.IsAssignableFrom(tab.Target.GetActualType())) - dropdown.options.Add(new Dropdown.OptionData($"Tab {tabIndex}: {tab.Tab.TabText.text}")); - } - } - - private void AddArgRow(int index, bool generic) - { - if (!generic) - AddArgRow(index, argHolder, argRows, argLabels, argumentInput, false); - else - AddArgRow(index, genericArgHolder, genericArgRows, genericArgLabels, genericInput, true); - } - - private void AddArgRow(int index, GameObject parent, List objectList, List labelList, string[] inputArray, bool generic) - { - var horiGroup = UIFactory.CreateUIObject("ArgRow_" + index, parent); - UIFactory.SetLayoutElement(horiGroup, minHeight: 25, flexibleHeight: 50, minWidth: 50, flexibleWidth: 9999); - UIFactory.SetLayoutGroup(horiGroup, false, false, true, true, 5); - horiGroup.AddComponent().verticalFit = ContentSizeFitter.FitMode.PreferredSize; - objectList.Add(horiGroup); - - var label = UIFactory.CreateLabel(horiGroup, "ArgLabel", "not set", TextAnchor.MiddleLeft); - UIFactory.SetLayoutElement(label.gameObject, minWidth: 40, flexibleWidth: 90, minHeight: 25, flexibleHeight: 50); - labelList.Add(label); - label.horizontalOverflow = HorizontalWrapMode.Wrap; - - var inputField = UIFactory.CreateInputField(horiGroup, "InputField", "..."); - UIFactory.SetLayoutElement(inputField.UIRoot, minHeight: 25, flexibleHeight: 50, minWidth: 100, flexibleWidth: 1000); - inputField.Component.lineType = InputField.LineType.MultiLineNewline; - inputField.UIRoot.AddComponent().verticalFit = ContentSizeFitter.FitMode.PreferredSize; - inputField.OnValueChanged += (string val) => { inputArray[index] = val; }; - - if (!generic) - { - var dropdownObj = UIFactory.CreateDropdown(horiGroup, out Dropdown dropdown, "Select argument...", 14, (int val) => - { - ArgDropdownChanged(index, val); - }); - UIFactory.SetLayoutElement(dropdownObj, minHeight: 25, flexibleHeight: 50, minWidth: 100, flexibleWidth: 1000); - dropdownObj.AddComponent().verticalFit = ContentSizeFitter.FitMode.PreferredSize; - - argInputFields.Add(inputField); - argDropdowns.Add(dropdown); - } - else - genericInputFields.Add(inputField); - - if (generic) - genericAutocompleters.Add(new TypeCompleter(null, inputField)); - } - - private void ArgDropdownChanged(int argIndex, int value) - { - // not sure if necessary - } - - public GameObject CreateContent(GameObject parent) - { - UIRoot = UIFactory.CreateVerticalGroup(parent, "EvaluateWidget", false, false, true, true, 3, new Vector4(2, 2, 2, 2), - new Color(0.15f, 0.15f, 0.15f)); - UIFactory.SetLayoutElement(UIRoot, minWidth: 50, flexibleWidth: 9999, minHeight: 50, flexibleHeight: 800); - //UIRoot.AddComponent().verticalFit = ContentSizeFitter.FitMode.PreferredSize; - - // generic args - this.genericArgHolder = UIFactory.CreateUIObject("GenericHolder", UIRoot); - UIFactory.SetLayoutElement(genericArgHolder, flexibleWidth: 1000); - var genericsTitle = UIFactory.CreateLabel(genericArgHolder, "GenericsTitle", "Generic Arguments", TextAnchor.MiddleLeft); - UIFactory.SetLayoutElement(genericsTitle.gameObject, minHeight: 25, flexibleWidth: 1000); - UIFactory.SetLayoutGroup(genericArgHolder, false, false, true, true, 3); - UIFactory.SetLayoutElement(genericArgHolder, minHeight: 25, flexibleHeight: 750, minWidth: 50, flexibleWidth: 9999); - //genericArgHolder.AddComponent().verticalFit = ContentSizeFitter.FitMode.PreferredSize; - - // args - this.argHolder = UIFactory.CreateUIObject("ArgHolder", UIRoot); - UIFactory.SetLayoutElement(argHolder, flexibleWidth: 1000); - var argsTitle = UIFactory.CreateLabel(argHolder, "ArgsTitle", "Arguments", TextAnchor.MiddleLeft); - UIFactory.SetLayoutElement(argsTitle.gameObject, minHeight: 25, flexibleWidth: 1000); - UIFactory.SetLayoutGroup(argHolder, false, false, true, true, 3); - UIFactory.SetLayoutElement(argHolder, minHeight: 25, flexibleHeight: 750, minWidth: 50, flexibleWidth: 9999); - //argHolder.AddComponent().verticalFit = ContentSizeFitter.FitMode.PreferredSize; - - // evaluate button - var evalButton = UIFactory.CreateButton(UIRoot, "EvaluateButton", "Evaluate", new Color(0.2f, 0.2f, 0.2f)); - UIFactory.SetLayoutElement(evalButton.Component.gameObject, minHeight: 25, minWidth: 150, flexibleWidth: 0); - evalButton.OnClick += () => - { - Owner.EvaluateAndSetCell(); - }; - - return UIRoot; - } - } -} diff --git a/src/Core/Tests/TestClass.cs b/src/Core/Tests/TestClass.cs index b94b9c7..56f3abd 100644 --- a/src/Core/Tests/TestClass.cs +++ b/src/Core/Tests/TestClass.cs @@ -36,6 +36,8 @@ namespace UnityExplorer.Tests public const int ConstantInt5 = 5; // Testing other InteractiveValues + public static BindingFlags EnumTest; + public static CameraClearFlags EnumTest2; public static Color Color = Color.magenta; public static Color32 Color32 = Color.red; public static string ALongString = new string('#', 10000); @@ -78,9 +80,9 @@ namespace UnityExplorer.Tests ExplorerCore.Log($"Test3 {typeof(T).FullName}"); } - public static void TestArgumentParse(string s, int i, Color color, CameraClearFlags flags, Vector3 vector, Quaternion quaternion) + public static void TestArgumentParse(string s, int i, Color color, CameraClearFlags flags, Vector3 vector, Quaternion quaternion, object obj) { - ExplorerCore.Log($"{s}, {i}, {color.ToString()}, {flags}, {vector.ToString()}, {quaternion.ToString()}"); + ExplorerCore.Log($"{s}, {i}, {color.ToString()}, {flags}, {vector.ToString()}, {quaternion.ToString()}, {obj?.ToString() ?? "null"}"); } private static void Init_Mono() diff --git a/src/UI/Widgets/AutoComplete/AutoCompleteModal.cs b/src/UI/Widgets/AutoComplete/AutoCompleteModal.cs index 3e96dea..9a1b0de 100644 --- a/src/UI/Widgets/AutoComplete/AutoCompleteModal.cs +++ b/src/UI/Widgets/AutoComplete/AutoCompleteModal.cs @@ -164,9 +164,7 @@ namespace UnityExplorer.UI.Widgets.AutoComplete if (!CurrentHandler.InputField.UIRoot.activeInHierarchy) ReleaseOwnership(CurrentHandler); else - { UpdatePosition(); - } } } @@ -228,9 +226,9 @@ namespace UnityExplorer.UI.Widgets.AutoComplete private int lastCaretPosition; private Vector3 lastInputPosition; - private void UpdatePosition() + internal void UpdatePosition() { - if (CurrentHandler == null || !CurrentHandler.InputField.Component.isFocused) + if (CurrentHandler == null) return; var input = CurrentHandler.InputField; @@ -255,9 +253,10 @@ namespace UnityExplorer.UI.Widgets.AutoComplete } else { - var textGen = input.Component.textComponent.cachedTextGenerator; - var pos = input.UIRoot.transform.TransformPoint(textGen.characters[0].cursorPos); - uiRoot.transform.position = new Vector3(pos.x + 10, pos.y - 20, 0); + uiRoot.transform.position = input.Rect.position + new Vector3(-(input.Rect.rect.width / 2) + 10, -20, 0); + //var textGen = input.Component.textComponent.cachedTextGenerator; + //var pos = input.UIRoot.transform.TransformPoint(textGen.characters[0].cursorPos); + //uiRoot.transform.position = new Vector3(pos.x + 10, pos.y - 20, 0); } this.Dragger.OnEndResize(); diff --git a/src/UI/Widgets/AutoComplete/EnumCompleter.cs b/src/UI/Widgets/AutoComplete/EnumCompleter.cs new file mode 100644 index 0000000..01ff1f8 --- /dev/null +++ b/src/UI/Widgets/AutoComplete/EnumCompleter.cs @@ -0,0 +1,160 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using UnityExplorer.CacheObject.IValues; +using UniverseLib; +using UniverseLib.UI; + +namespace UnityExplorer.UI.Widgets.AutoComplete +{ + public class EnumCompleter : ISuggestionProvider + { + public bool Enabled + { + get => _enabled; + set + { + _enabled = value; + if (!_enabled) + AutoCompleteModal.Instance.ReleaseOwnership(this); + } + } + private bool _enabled = true; + + public event Action SuggestionClicked; + + public Type EnumType { get; set; } + + public InputFieldRef InputField { get; } + public bool AnchorToCaretPosition => false; + + private readonly List suggestions = new List(); + private readonly HashSet suggestedValues = new HashSet(); + + private OrderedDictionary enumValues; + + internal string chosenSuggestion; + + bool ISuggestionProvider.AllowNavigation => false; + + public EnumCompleter(Type enumType, InputFieldRef inputField) + { + EnumType = enumType; + InputField = inputField; + + inputField.OnValueChanged += OnInputFieldChanged; + + if (EnumType != null) + CacheEnumValues(); + } + + public void CacheEnumValues() + { + enumValues = InteractiveEnum.GetEnumValues(EnumType); + } + + private string GetLastSplitInput(string fullInput) + { + string ret = fullInput; + + int lastSplit = fullInput.LastIndexOf(','); + if (lastSplit >= 0) + { + lastSplit++; + if (lastSplit == fullInput.Length) + ret = ""; + else + ret = fullInput.Substring(lastSplit); + } + + return ret; + } + + public void OnSuggestionClicked(Suggestion suggestion) + { + chosenSuggestion = suggestion.UnderlyingValue; + + string lastInput = GetLastSplitInput(InputField.Text); + + if (lastInput != suggestion.UnderlyingValue) + { + string valueToSet = InputField.Text; + + if (valueToSet.Length > 0) + valueToSet = valueToSet.Substring(0, InputField.Text.Length - lastInput.Length); + + valueToSet += suggestion.UnderlyingValue; + + InputField.Text = valueToSet; + + //InputField.Text += suggestion.UnderlyingValue.Substring(lastInput.Length); + } + + SuggestionClicked?.Invoke(suggestion); + + suggestions.Clear(); + AutoCompleteModal.Instance.SetSuggestions(suggestions); + } + + public void HelperButtonClicked() + { + GetSuggestions(""); + AutoCompleteModal.Instance.TakeOwnership(this); + AutoCompleteModal.Instance.SetSuggestions(suggestions); + } + + private void OnInputFieldChanged(string value) + { + if (!Enabled) + return; + + if (string.IsNullOrEmpty(value) || GetLastSplitInput(value) == chosenSuggestion) + { + chosenSuggestion = null; + AutoCompleteModal.Instance.ReleaseOwnership(this); + } + else + { + GetSuggestions(value); + + AutoCompleteModal.Instance.TakeOwnership(this); + AutoCompleteModal.Instance.SetSuggestions(suggestions); + } + } + + private void GetSuggestions(string value) + { + suggestions.Clear(); + suggestedValues.Clear(); + + if (EnumType == null) + { + ExplorerCore.LogWarning("Autocompleter Base enum type is null!"); + return; + } + + value = GetLastSplitInput(value); + + for (int i = 0; i < this.enumValues.Count; i++) + { + var enumValue = (CachedEnumValue)enumValues[i]; + if (enumValue.Name.ContainsIgnoreCase(value)) + AddSuggestion(enumValue.Name); + } + } + + internal static readonly Dictionary sharedValueToLabel = new Dictionary(4096); + + void AddSuggestion(string value) + { + if (suggestedValues.Contains(value)) + return; + suggestedValues.Add(value); + + if (!sharedValueToLabel.ContainsKey(value)) + sharedValueToLabel.Add(value, $"{value}"); + + suggestions.Add(new Suggestion(sharedValueToLabel[value], value)); + } + } +} diff --git a/src/UI/Widgets/AutoComplete/Suggestion.cs b/src/UI/Widgets/AutoComplete/Suggestion.cs index 7b67c5f..a25dbb8 100644 --- a/src/UI/Widgets/AutoComplete/Suggestion.cs +++ b/src/UI/Widgets/AutoComplete/Suggestion.cs @@ -12,8 +12,6 @@ namespace UnityExplorer.UI.Widgets.AutoComplete public readonly string DisplayText; public readonly string UnderlyingValue; - public string Combined => DisplayText + UnderlyingValue; - public Suggestion(string displayText, string underlyingValue) { DisplayText = displayText; diff --git a/src/UI/Widgets/AutoComplete/TypeCompleter.cs b/src/UI/Widgets/AutoComplete/TypeCompleter.cs index dc5b20f..5e3d936 100644 --- a/src/UI/Widgets/AutoComplete/TypeCompleter.cs +++ b/src/UI/Widgets/AutoComplete/TypeCompleter.cs @@ -9,12 +9,24 @@ namespace UnityExplorer.UI.Widgets.AutoComplete { internal static readonly Dictionary sharedTypeToLabel = new Dictionary(4096); + public bool Enabled + { + get => _enabled; + set + { + _enabled = value; + if (!_enabled) + AutoCompleteModal.Instance.ReleaseOwnership(this); + } + } + private bool _enabled = true; + public event Action SuggestionClicked; public Type BaseType { get; set; } public Type[] GenericConstraints { get; set; } - private bool allowAbstract; - private bool allowEnum; + private readonly bool allowAbstract; + private readonly bool allowEnum; public InputFieldRef InputField { get; } public bool AnchorToCaretPosition => false; @@ -61,6 +73,9 @@ namespace UnityExplorer.UI.Widgets.AutoComplete private void OnInputFieldChanged(string value) { + if (!Enabled) + return; + if (string.IsNullOrEmpty(value) || value == chosenSuggestion) { chosenSuggestion = null; diff --git a/src/UI/Widgets/EvaluateWidget/BaseArgumentHandler.cs b/src/UI/Widgets/EvaluateWidget/BaseArgumentHandler.cs new file mode 100644 index 0000000..a02c419 --- /dev/null +++ b/src/UI/Widgets/EvaluateWidget/BaseArgumentHandler.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using UnityEngine; +using UnityEngine.UI; +using UnityExplorer.UI.Widgets.AutoComplete; +using UniverseLib.UI; +using UniverseLib.UI.Models; + +namespace UnityExplorer.UI.Widgets +{ + public abstract class BaseArgumentHandler : IPooledObject + { + protected EvaluateWidget evaluator; + + internal Text argNameLabel; + internal InputFieldRef inputField; + internal TypeCompleter typeCompleter; + + // IPooledObject + public float DefaultHeight => 25f; + public GameObject UIRoot { get; set; } + + public abstract void CreateSpecialContent(); + + public GameObject CreateContent(GameObject parent) + { + UIRoot = UIFactory.CreateUIObject("ArgRow", parent); + UIFactory.SetLayoutElement(UIRoot, minHeight: 25, flexibleHeight: 50, minWidth: 50, flexibleWidth: 9999); + UIFactory.SetLayoutGroup(UIRoot, false, false, true, true, 5); + UIRoot.AddComponent().verticalFit = ContentSizeFitter.FitMode.PreferredSize; + + argNameLabel = UIFactory.CreateLabel(UIRoot, "ArgLabel", "not set", TextAnchor.MiddleLeft); + UIFactory.SetLayoutElement(argNameLabel.gameObject, minWidth: 40, flexibleWidth: 90, minHeight: 25, flexibleHeight: 50); + argNameLabel.horizontalOverflow = HorizontalWrapMode.Wrap; + + inputField = UIFactory.CreateInputField(UIRoot, "InputField", "..."); + UIFactory.SetLayoutElement(inputField.UIRoot, minHeight: 25, flexibleHeight: 50, minWidth: 100, flexibleWidth: 1000); + inputField.Component.lineType = InputField.LineType.MultiLineNewline; + inputField.UIRoot.AddComponent().verticalFit = ContentSizeFitter.FitMode.PreferredSize; + + typeCompleter = new TypeCompleter(typeof(object), this.inputField); + typeCompleter.Enabled = false; + + CreateSpecialContent(); + + return UIRoot; + } + } +} diff --git a/src/UI/Widgets/EvaluateWidget/EvaluateWidget.cs b/src/UI/Widgets/EvaluateWidget/EvaluateWidget.cs new file mode 100644 index 0000000..a72393f --- /dev/null +++ b/src/UI/Widgets/EvaluateWidget/EvaluateWidget.cs @@ -0,0 +1,176 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using UnityEngine; +using UnityEngine.UI; +using UnityExplorer.UI; +using UniverseLib.UI.Models; +using UnityExplorer.UI.Widgets.AutoComplete; +using UniverseLib.UI; +using UniverseLib; +using UnityExplorer.CacheObject; + +namespace UnityExplorer.UI.Widgets +{ + public class EvaluateWidget : IPooledObject + { + public CacheMember Owner { get; set; } + + public GameObject UIRoot { get; set; } + public float DefaultHeight => -1f; + + private ParameterInfo[] parameters; + internal GameObject parametersHolder; + private ParameterHandler[] paramHandlers; + + private Type[] genericArguments; + internal GameObject genericArgumentsHolder; + private GenericArgumentHandler[] genericHandlers; + + public void OnBorrowedFromPool(CacheMember owner) + { + this.Owner = owner; + + parameters = owner.Arguments; + paramHandlers = new ParameterHandler[parameters.Length]; + + genericArguments = owner.GenericArguments; + genericHandlers = new GenericArgumentHandler[genericArguments.Length]; + + SetArgRows(); + + this.UIRoot.SetActive(true); + + InspectorManager.OnInspectedTabsChanged += InspectorManager_OnInspectedTabsChanged; + } + + public void OnReturnToPool() + { + foreach (var widget in paramHandlers) + { + widget.OnReturned(); + Pool.Return(widget); + } + paramHandlers = null; + + foreach (var widget in genericHandlers) + { + widget.OnReturned(); + Pool.Return(widget); + } + genericHandlers = null; + + this.Owner = null; + + InspectorManager.OnInspectedTabsChanged -= InspectorManager_OnInspectedTabsChanged; + } + + private void InspectorManager_OnInspectedTabsChanged() + { + foreach (var handler in this.paramHandlers) + handler.PopulateDropdown(); + } + + public Type[] TryParseGenericArguments() + { + Type[] outArgs = new Type[genericArguments.Length]; + + for (int i = 0; i < genericArguments.Length; i++) + outArgs[i] = genericHandlers[i].Evaluate(); + + return outArgs; + } + + public object[] TryParseArguments() + { + object[] outArgs = new object[parameters.Length]; + + for (int i = 0; i < parameters.Length; i++) + outArgs[i] = paramHandlers[i].Evaluate(); + + return outArgs; + } + + private void SetArgRows() + { + if (genericArguments.Any()) + { + genericArgumentsHolder.SetActive(true); + SetGenericRows(); + } + else + genericArgumentsHolder.SetActive(false); + + if (parameters.Any()) + { + parametersHolder.SetActive(true); + SetNormalArgRows(); + } + else + parametersHolder.SetActive(false); + } + + private void SetGenericRows() + { + for (int i = 0; i < genericArguments.Length; i++) + { + var type = genericArguments[i]; + + var holder = genericHandlers[i] = Pool.Borrow(); + holder.UIRoot.transform.SetParent(this.genericArgumentsHolder.transform, false); + holder.OnBorrowed(this, type); + } + } + + private void SetNormalArgRows() + { + for (int i = 0; i < parameters.Length; i++) + { + var param = parameters[i]; + + var holder = paramHandlers[i] = Pool.Borrow(); + holder.UIRoot.transform.SetParent(this.parametersHolder.transform, false); + holder.OnBorrowed(this, param); + } + } + + + public GameObject CreateContent(GameObject parent) + { + UIRoot = UIFactory.CreateVerticalGroup(parent, "EvaluateWidget", false, false, true, true, 3, new Vector4(2, 2, 2, 2), + new Color(0.15f, 0.15f, 0.15f)); + UIFactory.SetLayoutElement(UIRoot, minWidth: 50, flexibleWidth: 9999, minHeight: 50, flexibleHeight: 800); + //UIRoot.AddComponent().verticalFit = ContentSizeFitter.FitMode.PreferredSize; + + // generic args + this.genericArgumentsHolder = UIFactory.CreateUIObject("GenericHolder", UIRoot); + UIFactory.SetLayoutElement(genericArgumentsHolder, flexibleWidth: 1000); + var genericsTitle = UIFactory.CreateLabel(genericArgumentsHolder, "GenericsTitle", "Generic Arguments", TextAnchor.MiddleLeft); + UIFactory.SetLayoutElement(genericsTitle.gameObject, minHeight: 25, flexibleWidth: 1000); + UIFactory.SetLayoutGroup(genericArgumentsHolder, false, false, true, true, 3); + UIFactory.SetLayoutElement(genericArgumentsHolder, minHeight: 25, flexibleHeight: 750, minWidth: 50, flexibleWidth: 9999); + //genericArgHolder.AddComponent().verticalFit = ContentSizeFitter.FitMode.PreferredSize; + + // args + this.parametersHolder = UIFactory.CreateUIObject("ArgHolder", UIRoot); + UIFactory.SetLayoutElement(parametersHolder, flexibleWidth: 1000); + var argsTitle = UIFactory.CreateLabel(parametersHolder, "ArgsTitle", "Arguments", TextAnchor.MiddleLeft); + UIFactory.SetLayoutElement(argsTitle.gameObject, minHeight: 25, flexibleWidth: 1000); + UIFactory.SetLayoutGroup(parametersHolder, false, false, true, true, 3); + UIFactory.SetLayoutElement(parametersHolder, minHeight: 25, flexibleHeight: 750, minWidth: 50, flexibleWidth: 9999); + //argHolder.AddComponent().verticalFit = ContentSizeFitter.FitMode.PreferredSize; + + // evaluate button + var evalButton = UIFactory.CreateButton(UIRoot, "EvaluateButton", "Evaluate", new Color(0.2f, 0.2f, 0.2f)); + UIFactory.SetLayoutElement(evalButton.Component.gameObject, minHeight: 25, minWidth: 150, flexibleWidth: 0); + evalButton.OnClick += () => + { + Owner.EvaluateAndSetCell(); + }; + + return UIRoot; + } + } +} diff --git a/src/UI/Widgets/EvaluateWidget/GenericArgumentHandler.cs b/src/UI/Widgets/EvaluateWidget/GenericArgumentHandler.cs new file mode 100644 index 0000000..03b292f --- /dev/null +++ b/src/UI/Widgets/EvaluateWidget/GenericArgumentHandler.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using UniverseLib; + +namespace UnityExplorer.UI.Widgets +{ + public class GenericArgumentHandler : BaseArgumentHandler + { + private Type genericType; + + public void OnBorrowed(EvaluateWidget evaluator, Type genericConstraint) + { + this.evaluator = evaluator; + this.genericType = genericConstraint; + + typeCompleter.Enabled = true; + typeCompleter.BaseType = genericType; + typeCompleter.CacheTypes(); + + var constraints = genericType.GetGenericParameterConstraints(); + typeCompleter.GenericConstraints = constraints; + + var sb = new StringBuilder($"{genericType.Name}"); + + for (int j = 0; j < constraints.Length; j++) + { + if (j == 0) sb.Append(' ').Append('('); + else sb.Append(',').Append(' '); + + sb.Append(SignatureHighlighter.Parse(constraints[j], false)); + + if (j + 1 == constraints.Length) + sb.Append(')'); + } + + argNameLabel.text = sb.ToString(); + } + + public void OnReturned() + { + this.evaluator = null; + this.genericType = null; + + this.typeCompleter.Enabled = false; + + this.inputField.Text = ""; + } + + public Type Evaluate() + { + return ReflectionUtility.GetTypeByName(this.inputField.Text) + ?? throw new Exception($"Could not find any type by name '{this.inputField.Text}'!"); + } + + public override void CreateSpecialContent() + { + } + } +} diff --git a/src/UI/Widgets/EvaluateWidget/ParameterHandler.cs b/src/UI/Widgets/EvaluateWidget/ParameterHandler.cs new file mode 100644 index 0000000..e632784 --- /dev/null +++ b/src/UI/Widgets/EvaluateWidget/ParameterHandler.cs @@ -0,0 +1,186 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Reflection; +using UnityEngine.UI; +using UnityExplorer.CacheObject.IValues; +using UnityExplorer.UI.Widgets.AutoComplete; +using UniverseLib; +using UniverseLib.UI; + +namespace UnityExplorer.UI.Widgets +{ + public class ParameterHandler : BaseArgumentHandler + { + private ParameterInfo paramInfo; + private Type paramType; + + internal Dropdown dropdown; + private bool usingDropdown; + internal EnumCompleter enumCompleter; + private ButtonRef enumHelperButton; + + public void OnBorrowed(EvaluateWidget evaluator, ParameterInfo paramInfo) + { + this.evaluator = evaluator; + this.paramInfo = paramInfo; + + this.paramType = paramInfo.ParameterType; + if (paramType.IsByRef) + paramType = paramType.GetElementType(); + + this.argNameLabel.text = + $"{SignatureHighlighter.Parse(paramType, false)} {paramInfo.Name}"; + + if (ParseUtility.CanParse(paramType) || typeof(Type).IsAssignableFrom(paramType)) + { + this.inputField.Component.gameObject.SetActive(true); + this.dropdown.gameObject.SetActive(false); + this.typeCompleter.Enabled = typeof(Type).IsAssignableFrom(paramType); + this.enumCompleter.Enabled = paramType.IsEnum; + this.enumHelperButton.Component.gameObject.SetActive(paramType.IsEnum); + + if (!typeCompleter.Enabled) + { + if (paramType == typeof(string)) + inputField.PlaceholderText.text = "..."; + else + inputField.PlaceholderText.text = $"eg. {ParseUtility.GetExampleInput(paramType)}"; + } + else + { + inputField.PlaceholderText.text = "Enter a Type name..."; + this.typeCompleter.BaseType = typeof(object); + this.typeCompleter.CacheTypes(); + } + + if (enumCompleter.Enabled) + { + enumCompleter.EnumType = paramType; + enumCompleter.CacheEnumValues(); + } + } + else + { + // non-parsable, and not a Type + this.inputField.Component.gameObject.SetActive(false); + this.dropdown.gameObject.SetActive(true); + this.typeCompleter.Enabled = false; + this.enumCompleter.Enabled = false; + this.enumHelperButton.Component.gameObject.SetActive(false); + + usingDropdown = true; + PopulateDropdown(); + + InspectorManager.OnInspectedTabsChanged += PopulateDropdown; + } + } + + public void OnReturned() + { + this.evaluator = null; + this.paramInfo = null; + + usingDropdown = false; + + this.enumCompleter.Enabled = false; + this.typeCompleter.Enabled = false; + + this.inputField.Text = ""; + + InspectorManager.OnInspectedTabsChanged -= PopulateDropdown; + } + + public object Evaluate() + { + if (!usingDropdown) + { + var input = this.inputField.Text; + + if (paramType == typeof(string)) + return input; + + if (string.IsNullOrEmpty(input)) + { + if (paramInfo.IsOptional) + return paramInfo.DefaultValue; + else + return null; + } + + if (!ParseUtility.TryParse(input, paramType, out object parsed, out Exception ex)) + { + ExplorerCore.LogWarning($"Cannot parse argument '{paramInfo.Name}' ({paramInfo.ParameterType.Name})" + + $"{(ex == null ? "" : $", {ex.GetType().Name}: {ex.Message}")}"); + return null; + } + else + return parsed; + } + else + { + if (dropdown.value == 0) + return null; + else + return dropdownUnderlyingValues[dropdown.value]; + } + } + + private object[] dropdownUnderlyingValues; + + internal void PopulateDropdown() + { + if (!usingDropdown) + return; + + dropdown.options.Clear(); + var underlyingValues = new List(); + + dropdown.options.Add(new Dropdown.OptionData("null")); + underlyingValues.Add(null); + + var argType = paramType; + + int tabIndex = 0; + foreach (var tab in InspectorManager.Inspectors) + { + tabIndex++; + + if (argType.IsAssignableFrom(tab.Target.GetActualType())) + { + dropdown.options.Add(new Dropdown.OptionData($"Tab {tabIndex}: {tab.Tab.TabText.text}")); + underlyingValues.Add(tab.Target); + } + } + + dropdownUnderlyingValues = underlyingValues.ToArray(); + } + + private void EnumHelper_OnClick() + { + enumCompleter.HelperButtonClicked(); + } + + public override void CreateSpecialContent() + { + enumHelperButton = UIFactory.CreateButton(UIRoot, "EnumHelper", "▼"); + UIFactory.SetLayoutElement(enumHelperButton.Component.gameObject, minWidth: 25, minHeight: 25, flexibleWidth: 0, flexibleHeight: 0); + enumHelperButton.OnClick += EnumHelper_OnClick; + + var dropdownObj = UIFactory.CreateDropdown(UIRoot, out dropdown, "Select argument...", 14, (int val) => + { + //ArgDropdownChanged(val); + }); + UIFactory.SetLayoutElement(dropdownObj, minHeight: 25, flexibleHeight: 50, minWidth: 100, flexibleWidth: 1000); + dropdownObj.AddComponent().verticalFit = ContentSizeFitter.FitMode.PreferredSize; + + enumCompleter = new EnumCompleter(paramType, this.inputField); + enumCompleter.Enabled = false; + } + + //private void ArgDropdownChanged(int value) + //{ + // // not needed + //} + } +} diff --git a/src/UnityExplorer.csproj b/src/UnityExplorer.csproj index aefc3fd..e1eb456 100644 --- a/src/UnityExplorer.csproj +++ b/src/UnityExplorer.csproj @@ -255,7 +255,8 @@ - + + @@ -307,6 +308,9 @@ + + +