Some UI cleanups, improving caching and reduce image allocation

This commit is contained in:
Sinai 2021-04-25 21:20:50 +10:00
parent fda5afae46
commit f3cd84804d
19 changed files with 304 additions and 500 deletions

View File

@ -106,7 +106,7 @@ namespace UnityExplorer.UI.Inspectors
var closeBtn = UIFactory.CreateButton(tabGroupObj,
"CloseButton",
"X",
parent.Destroy,
() => { InspectorManager.DestroyInspector(parent); },
new Color(0.2f, 0.2f, 0.2f, 1));
UIFactory.SetLayoutElement(closeBtn.gameObject, minWidth: 20, flexibleWidth: 0);

View File

@ -30,6 +30,14 @@ namespace UnityExplorer.UI.Inspectors
}
}
public static void DestroyInspector(InspectorBase inspector)
{
if (inspector is ReflectionInspector ri)
ri.Destroy();
else
inspector.Destroy();
}
public static void Inspect(object obj, CacheObjectBase parentMember = null)
{
var type = ReflectionProvider.Instance.GetActualType(obj);
@ -70,7 +78,7 @@ namespace UnityExplorer.UI.Inspectors
SetInspectorTab(inspector);
}
public static void InspectType(Type type)
public static void Inspect(Type type)
{
if (type == null)
{

View File

@ -29,48 +29,33 @@ namespace UnityExplorer.UI.Inspectors.Reflection
public ICell CreateCell(RectTransform cellTransform) => new CellViewHolder(cellTransform.gameObject);
public void DisableCell(ICell cell, int index)
{
var root = (cell as CellViewHolder).UIRoot;
DisableContent(root);
cell.Disable();
}
public void SetCell(ICell icell, int index)
{
var root = (icell as CellViewHolder).UIRoot;
var cell = icell as CellViewHolder;
if (index < 0 || index >= ItemCount)
{
DisableContent(root);
icell.Disable();
var existing = cell.DisableContent();
if (existing)
existing.transform.SetParent(Inspector.InactiveHolder.transform, false);
return;
}
float start = Time.realtimeSinceStartup;
index = GetRealIndexOfTempIndex(index);
var cache = Inspector.allMembers[index];
cache.Enable();
var content = cache.UIRoot;
if (content.transform.parent.ReferenceEqual(root.transform))
return;
var orig = content.transform.parent;
DisableContent(root);
content.transform.SetParent(root.transform, false);
//ExplorerCore.Log("Set cell " + index + ", took " + (Time.realtimeSinceStartup - start) + " secs");
//ExplorerCore.Log("orig parent was " + (orig?.name ?? " <null>"));
var prev = cell.SetContent(cache.UIRoot);
if (prev)
prev.transform.SetParent(Inspector.InactiveHolder.transform, false);
}
private void DisableContent(GameObject cellRoot)
public void DisableCell(ICell cell, int index)
{
if (cellRoot.transform.childCount > 0 && cellRoot.transform.GetChild(0) is Transform existing)
existing.transform.SetParent(Inspector.InactiveHolder.transform, false);
var content = (cell as CellViewHolder).DisableContent();
if (content)
content.transform.SetParent(Inspector.InactiveHolder.transform, false);
}
}
}

View File

@ -39,7 +39,7 @@ namespace UnityExplorer.UI.Inspectors.Reflection
FilterMembers(null, true);
ScrollPool.EnableTempCache();
ScrollPool.RecreateHeightCache();
ScrollPool.RefreshAndJumpToTop();
//RefreshDisplay();
//m_sliderScroller.m_slider.value = 1f;
@ -134,23 +134,21 @@ namespace UnityExplorer.UI.Inspectors.Reflection
internal void ConstructTextureHelper()
{
var rowObj = UIFactory.CreateHorizontalGroup(Content, "TextureHelper", true, false, true, true, 5, new Vector4(3, 3, 3, 3),
var rowObj = UIFactory.CreateHorizontalGroup(Content, "TextureHelper", false, false, true, true, 5, new Vector4(3, 3, 3, 3),
new Color(0.1f, 0.1f, 0.1f));
UIFactory.SetLayoutElement(rowObj, minHeight: 25, flexibleHeight: 0);
var showBtn = UIFactory.CreateButton(rowObj, "ShowButton", "Show", null, new Color(0.2f, 0.6f, 0.2f));
UIFactory.SetLayoutElement(showBtn.gameObject, minWidth: 50, flexibleWidth: 0);
var showBtn = UIFactory.CreateButton(rowObj, "ShowButton", "Show", null, new Color(0.2f, 0.3f, 0.2f));
UIFactory.SetLayoutElement(showBtn.gameObject, minWidth: 50, flexibleWidth: 0, minHeight: 20);
UIFactory.CreateLabel(rowObj, "TextureViewerLabel", "Texture Viewer", TextAnchor.MiddleLeft);
var textureViewerObj = UIFactory.CreateScrollView(Content, "TextureViewerContent", out GameObject scrollContent, out _,
m_textureViewerObj = UIFactory.CreateScrollView(Content, "TextureViewerContent", out GameObject scrollContent, out _,
new Color(0.1f, 0.1f, 0.1f));
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(textureViewerObj, false, false, true, true);
UIFactory.SetLayoutElement(textureViewerObj, minHeight: 100, flexibleHeight: 9999, flexibleWidth: 9999);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(scrollContent, false, false, true, true);
UIFactory.SetLayoutElement(m_textureViewerObj, minHeight: 100, flexibleHeight: 9999, flexibleWidth: 9999);
textureViewerObj.SetActive(false);
m_textureViewerObj = textureViewerObj;
m_textureViewerObj.SetActive(false);
var showText = showBtn.GetComponentInChildren<Text>();
showBtn.onClick.AddListener(() =>
@ -249,7 +247,7 @@ namespace UnityExplorer.UI.Inspectors.Reflection
m_textureViewerObj.SetActive(enabled);
m_filterAreaObj.SetActive(!enabled);
//m_memberListObj.SetActive(!enabled);
this.ScrollPool.UIRoot.SetActive(!enabled);
m_updateRowObj.SetActive(!enabled);
}
}

View File

@ -125,7 +125,10 @@ namespace UnityExplorer.UI.Inspectors.Reflection
base.Destroy();
if (this.Content)
{
GameObject.Destroy(this.InactiveHolder);
GameObject.Destroy(this.Content);
}
}
internal bool IsBlacklisted(string sig) => bl_typeAndMember.Any(it => sig.Contains(it));
@ -262,7 +265,7 @@ namespace UnityExplorer.UI.Inspectors.Reflection
RuntimeProvider.Instance.SetColorBlock(m_lastActiveMemButton, new Color(0.2f, 0.6f, 0.2f));
FilterMembers(null, true);
ScrollPool.EnableTempCache();
ScrollPool.RecreateHeightCache();
ScrollPool.Rebuild();
}
@ -332,7 +335,7 @@ namespace UnityExplorer.UI.Inspectors.Reflection
new Color(0.15f, 0.15f, 0.15f));
this.m_inactiveHolder = new GameObject("InactiveContentHolder");
m_inactiveHolder.transform.SetParent(parent.transform, false);
m_inactiveHolder.transform.SetParent(Content.transform, false);
m_inactiveHolder.SetActive(false);
ConstructTopArea();
@ -389,7 +392,7 @@ namespace UnityExplorer.UI.Inspectors.Reflection
nameInput.onValueChanged.AddListener((string val) =>
{
FilterMembers(val, true);
ScrollPool.EnableTempCache();
ScrollPool.RecreateHeightCache();
ScrollPool.Rebuild();
});
m_nameFilterText = nameInput.textComponent;

View File

@ -22,7 +22,6 @@ namespace UnityExplorer.UI.Models
var instance = Instances[i];
if (instance == null || !instance.UIRoot)
{
ExplorerCore.Log($"Instance {instance?.GetType().Name ?? "<null>"} has no UIRoot or it was destroyed!");
Instances.RemoveAt(i);
continue;
}

View File

@ -70,7 +70,7 @@ namespace UnityExplorer.UI.Panels
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(this.content, forceHeight: true, spacing: 10, padLeft: 5, padRight: 5);
this.NavbarHolder = UIFactory.CreateGridGroup(this.content, "Navbar", new Vector2(200, 22), new Vector2(4, 2),
new Color(0.18f, 0.18f, 0.18f));
new Color(0.12f, 0.12f, 0.12f));
//UIFactory.SetLayoutElement(NavbarHolder, flexibleWidth: 9999, minHeight: 0, preferredHeight: 0, flexibleHeight: 9999);
NavbarHolder.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
@ -81,267 +81,4 @@ namespace UnityExplorer.UI.Panels
UIManager.SetPanelActive(PanelType, false);
}
}
}
//using System;
//using System.Collections;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using UnityEngine;
//using UnityEngine.UI;
//using UnityExplorer.Core.Config;
//using UnityExplorer.Core.Runtime;
//using UnityExplorer.UI.Models;
//using UnityExplorer.UI.Utility;
//using UnityExplorer.UI.Widgets;
//namespace UnityExplorer.UI.Panels
//{
// public class InspectorPanel : UIPanel
// {
// public static InspectorPanel Instance { get; private set; }
// public GameObject NavbarHolder;
// public GameObject ContentHolder;
// public override string Name => "Inspector";
// public override UIManager.Panels PanelType => UIManager.Panels.Inspector;
// public override bool ShouldSaveActiveState => false;
// public InspectorPanel() { Instance = this; }
// public override void Update()
// {
// }
// public override void LoadSaveData()
// {
// ApplySaveData(ConfigManager.GameObjectInspectorData.Value);
// }
// public override void SaveToConfigManager()
// {
// ConfigManager.GameObjectInspectorData.Value = this.ToSaveData();
// }
// public override void SetDefaultPosAndAnchors()
// {
// mainPanelRect.localPosition = Vector2.zero;
// mainPanelRect.pivot = new Vector2(0.5f, 0.5f);
// mainPanelRect.anchorMin = new Vector2(0.5f, 0);
// mainPanelRect.anchorMax = new Vector2(0.5f, 1);
// mainPanelRect.offsetMin = new Vector2(mainPanelRect.offsetMin.x, 100); // bottom
// mainPanelRect.offsetMax = new Vector2(mainPanelRect.offsetMax.x, -50); // top
// mainPanelRect.sizeDelta = new Vector2(700f, mainPanelRect.sizeDelta.y);
// mainPanelRect.anchoredPosition = new Vector2(-150, 0);
// }
// internal static DynamicListTest listInstance;
// private ScrollPool scrollPool;
// public override void ConstructPanelContent()
// {
// // temp test
// scrollPool = UIFactory.CreateScrollPool(content, "Test", out GameObject scrollObj,
// out GameObject scrollContent, new Color(0.15f, 0.15f, 0.15f));
// UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
// UIFactory.SetLayoutElement(scrollContent, flexibleHeight: 9999);
// // disable masks for debug
// UIRoot.GetComponent<Mask>().enabled = false;
// scrollPool.Viewport.GetComponent<Mask>().enabled = false;
// scrollPool.Content.gameObject.AddComponent<Image>().color = new Color(1f, 0f, 1f, 0.3f);
// listInstance = new DynamicListTest(scrollPool, this);
// listInstance.Init();
// //var prototype = DynamicCell.CreatePrototypeCell(scrollContent);
// //scrollPool.PrototypeCell = prototype.GetComponent<RectTransform>();
// contentHolder = new GameObject("DummyHolder");
// contentHolder.SetActive(false);
// contentHolder.transform.SetParent(this.content.transform, false);
// ExplorerCore.Log("Creating dummy objects");
// for (int i = 0; i < 150; i++)
// {
// dummyContents.Add(CreateDummyContent());
// }
// ExplorerCore.Log("Done");
// //previousRectHeight = mainPanelRect.rect.height;
// UIManager.SetPanelActive(PanelType, false);
// }
// internal GameObject contentHolder;
// internal readonly List<GameObject> dummyContents = new List<GameObject>();
// private GameObject CreateDummyContent()
// {
// var obj = UIFactory.CreateVerticalGroup(contentHolder, "Content", true, true, true, true, 2, new Vector4(2, 2, 2, 2));
// obj.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
// var horiGroup = UIFactory.CreateHorizontalGroup(obj, "topGroup", true, true, true, true);
// UIFactory.SetLayoutElement(horiGroup, minHeight: 25, flexibleHeight: 0);
// var mainLabel = UIFactory.CreateLabel(horiGroup, "label", "Dummy " + dummyContents.Count, TextAnchor.MiddleCenter);
// UIFactory.SetLayoutElement(mainLabel.gameObject, minHeight: 25, flexibleHeight: 0);
// var expandButton = UIFactory.CreateButton(horiGroup, "Expand", "V");
// UIFactory.SetLayoutElement(expandButton.gameObject, minWidth: 25, flexibleWidth: 0);
// var subContent = UIFactory.CreateVerticalGroup(obj, "SubContent", true, true, true, true);
// var inputObj = UIFactory.CreateInputField(subContent, "input", "...", out var inputField);
// UIFactory.SetLayoutElement(inputObj, minHeight: 25, flexibleHeight: 9999);
// inputObj.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
// inputField.lineType = InputField.LineType.MultiLineNewline;
// int numLines = UnityEngine.Random.Range(0, 10);
// inputField.text = "This field has " + numLines + " lines";
// for (int i = 0; i < numLines; i++)
// inputField.text += "\r\n";
// //subContent.SetActive(false);
// var btnLabel = expandButton.GetComponentInChildren<Text>();
// expandButton.onClick.AddListener(OnExpand);
// void OnExpand()
// {
// bool active = !subContent.activeSelf;
// if (active)
// {
// subContent.SetActive(true);
// btnLabel.text = "^";
// }
// else
// {
// subContent.SetActive(false);
// btnLabel.text = "V";
// }
// }
// return obj;
// }
// }
// public class DynamicListTest : IPoolDataSource
// {
// internal ScrollPool ScrollPool;
// internal InspectorPanel Inspector;
// public DynamicListTest(ScrollPool scroller, InspectorPanel inspector)
// {
// ScrollPool = scroller;
// Inspector = inspector;
// }
// public int ItemCount => filtering ? filteredIndices.Count : Inspector.dummyContents.Count;
// private bool filtering;
// private readonly List<int> filteredIndices = new List<int>();
// public int GetRealIndexOfTempIndex(int index)
// {
// if (index < 0 || index >= filteredIndices.Count)
// return -1;
// return filteredIndices[index];
// }
// public void ToggleFilter()
// {
// if (filtering)
// {
// DisableFilter();
// ScrollPool.DisableTempCache();
// }
// else
// {
// EnableRandomFilter();
// ScrollPool.EnableTempCache();
// }
// ExplorerCore.Log("Filter toggled, new count: " + ItemCount);
// ScrollPool.Rebuild();
// }
// public void EnableRandomFilter()
// {
// filteredIndices.Clear();
// filtering = true;
// int counter = UnityEngine.Random.Range(0, Inspector.dummyContents.Count);
// while (filteredIndices.Count < counter)
// {
// var i = UnityEngine.Random.Range(0, Inspector.dummyContents.Count);
// if (!filteredIndices.Contains(i))
// filteredIndices.Add(i);
// }
// filteredIndices.Sort();
// }
// public void DisableFilter()
// {
// filtering = false;
// }
// public void OnDisableCell(CellViewHolder cell, int dataIndex)
// {
// if (cell.UIRoot.transform.Find("Content") is Transform existing)
// existing.transform.SetParent(Inspector.contentHolder.transform, false);
// }
// public void Init()
// {
// var prototype = CellViewHolder.CreatePrototypeCell(ScrollPool.UIRoot);
// ScrollPool.DataSource = this;
// ScrollPool.Initialize(this, prototype);
// }
// public ICell CreateCell(RectTransform cellTransform) => new CellViewHolder(cellTransform.gameObject);
// public void DisableCell(ICell icell, int index)
// {
// var root = (icell as CellViewHolder).UIRoot;
// DisableContent(root);
// icell.Disable();
// }
// public void SetCell(ICell icell, int index)
// {
// var root = (icell as CellViewHolder).UIRoot;
// if (index < 0 || index >= ItemCount)
// {
// DisableContent(root);
// icell.Disable();
// return;
// }
// if (filtering)
// index = GetRealIndexOfTempIndex(index);
// var content = Inspector.dummyContents[index];
// if (content.transform.parent.ReferenceEqual(root.transform))
// return;
// ExplorerCore.Log("Setting index " + index + " to cell " + root.transform.name);
// DisableContent(root);
// content.transform.SetParent(root.transform, false);
// }
// private void DisableContent(GameObject cellRoot)
// {
// if (cellRoot.transform.Find("Content") is Transform existing)
// existing.transform.SetParent(Inspector.contentHolder.transform, false);
// }
// }
//}
}

View File

@ -33,7 +33,7 @@ namespace UnityExplorer.UI
var obj = new GameObject(name)
{
layer = 5,
hideFlags = HideFlags.HideAndDontSave
hideFlags = HideFlags.HideAndDontSave,
};
obj.transform.SetParent(parent.transform, false);
@ -752,6 +752,7 @@ namespace UnityExplorer.UI
var scrollRect = mainObj.AddComponent<ScrollRect>();
scrollRect.movementType = ScrollRect.MovementType.Clamped;
//scrollRect.inertia = false;
scrollRect.inertia = true;
scrollRect.elasticity = 0.125f;
scrollRect.scrollSensitivity = 25;

View File

@ -16,7 +16,7 @@ namespace UnityExplorer.UI.Widgets
internal ScrollPool Scroller;
public int ItemCount => currentEntries.Count;
public List<T> currentEntries;
public readonly List<T> currentEntries = new List<T>();
public Func<List<T>> GetEntries;
public Action<ButtonCell<T>, int> SetICell;
@ -54,7 +54,7 @@ namespace UnityExplorer.UI.Widgets
public void RefreshData()
{
var allEntries = GetEntries.Invoke();
var list = new List<T>();
currentEntries.Clear();
foreach (var entry in allEntries)
{
@ -63,13 +63,11 @@ namespace UnityExplorer.UI.Widgets
if (!ShouldDisplay.Invoke(entry, currentFilter))
continue;
list.Add(entry);
currentEntries.Add(entry);
}
else
list.Add(entry);
currentEntries.Add(entry);
}
currentEntries = list;
}
public ICell CreateCell(RectTransform rect)

View File

@ -31,9 +31,6 @@ namespace UnityExplorer.UI.CacheObject
ConstructUI();
UpdateValue();
}
//if (!m_mainContent.activeSelf)
// m_mainContent.SetActive(true);
}
public virtual void Disable()
@ -79,33 +76,44 @@ namespace UnityExplorer.UI.CacheObject
internal GameObject m_parentContent;
internal RectTransform m_mainRect;
internal GameObject UIRoot;
internal GameObject SubContentGroup;
internal bool constructedSubcontent;
// Make base UI holder for CacheObject, this doesnt actually display anything.
internal virtual void ConstructUI()
{
m_constructedUI = true;
UIRoot = UIFactory.CreateVerticalGroup(m_parentContent, $"{this.GetType().Name}.MainContent", true, true, true, true, 2,
new Vector4(0, 5, 0, 0), new Color(0.1f, 0.1f, 0.1f), TextAnchor.UpperLeft);
//UIRoot = UIFactory.CreateVerticalGroup(m_parentContent, $"{this.GetType().Name}.MainContent", true, true, true, true, 2,
// new Vector4(0, 5, 0, 0), new Color(0.1f, 0.1f, 0.1f), TextAnchor.UpperLeft);
UIRoot = UIFactory.CreateUIObject($"{this.GetType().Name}.MainContent", m_parentContent);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(UIRoot, true, true, true, true, 2, 0, 5, 0, 0, TextAnchor.UpperLeft);
m_mainRect = UIRoot.GetComponent<RectTransform>();
m_mainRect.pivot = new Vector2(0, 1);
m_mainRect.anchorMin = Vector2.zero;
m_mainRect.anchorMax = Vector2.one;
UIFactory.SetLayoutElement(UIRoot, minHeight: 30, flexibleHeight: 9999, minWidth: 200, flexibleWidth: 5000);
//UIRoot.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
// subcontent
SubContentGroup = UIFactory.CreateVerticalGroup(UIRoot, $"{this.GetType().Name}.SubContent", true, false, true, true, 0, default,
new Color(0.085f, 0.085f, 0.085f));
SubContentGroup = new GameObject("SubContent");
SubContentGroup.transform.parent = UIRoot.transform;
UIFactory.SetLayoutElement(SubContentGroup, minHeight: 30, flexibleHeight: 9999, minWidth: 125, flexibleWidth: 9000);
UIFactory.SetLayoutGroup<VerticalLayoutGroup>(SubContentGroup, true, false, true, true);
SubContentGroup.SetActive(false);
IValue.m_subContentParent = SubContentGroup;
}
public virtual void CheckSubcontentCreation()
{
if (!constructedSubcontent)
{
SubContentGroup.AddComponent<Image>().color = new Color(0.08f, 0.08f, 0.08f);
constructedSubcontent = true;
}
}
#endregion
}

View File

@ -42,7 +42,7 @@ namespace UnityExplorer.UI.InteractiveValues
{
get
{
if (m_recacheWanted)
if (m_recacheWanted && Value != null)
return true;
else return m_entries.Count > 0;
}

View File

@ -11,11 +11,90 @@ using UnityExplorer.Core.Config;
using UnityExplorer.UI;
using UnityExplorer.UI.CacheObject;
using UnityExplorer.UI.Utility;
using UnityExplorer.UI.Widgets;
namespace UnityExplorer.UI.InteractiveValues
{
public class InteractiveEnumerable : InteractiveValue
public class InteractiveEnumerable : InteractiveValue, IPoolDataSource
{
// IPoolDataSource
public ScrollPool ScrollPool;
public GameObject InactiveHolder;
internal LayoutElement listLayout;
public int ItemCount => m_entries?.Count ?? 0;
public void SetCell(ICell icell, int index)
{
var cell = icell as CellViewHolder;
if (index < 0 || index >= ItemCount)
{
var existing = cell.DisableContent();
if (existing)
existing.transform.SetParent(InactiveHolder.transform, false);
return;
}
var cache = m_entries[index];
cache.Enable();
var prev = cell.SetContent(cache.UIRoot);
if (prev)
prev.transform.SetParent(InactiveHolder.transform, false);
}
public void DisableCell(ICell cell, int index)
{
var content = (cell as CellViewHolder).DisableContent();
if (content)
content.transform.SetParent(InactiveHolder.transform, false);
}
//public void SetCell(ICell cell, int index)
//{
// var root = (cell as CellViewHolder).UIRoot;
// if (index < 0 || index >= ItemCount)
// {
// DisableContent(root);
// cell.Disable();
// return;
// }
// var cache = m_entries[index];
// cache.Enable();
// var content = cache.UIRoot;
// if (content.transform.parent.ReferenceEqual(root.transform))
// return;
// DisableContent(root);
// content.transform.SetParent(root.transform, false);
//}
//public void DisableCell(ICell cell, int index)
//{
// var root = (cell as CellViewHolder).UIRoot;
// DisableContent(root);
// cell.Disable();
//}
//private void DisableContent(GameObject cellRoot)
//{
// if (cellRoot.transform.childCount > 0 && cellRoot.transform.GetChild(0) is Transform existing)
// existing.transform.SetParent(InactiveHolder.transform, false);
//}
public ICell CreateCell(RectTransform cellTransform) => new CellViewHolder(cellTransform.gameObject);
public int GetRealIndexOfTempIndex(int tempIndex) => throw new NotImplementedException("Filtering not supported");
// InteractiveEnumerable
public InteractiveEnumerable(object value, Type valueType) : base(value, valueType)
{
if (valueType.IsGenericType)
@ -30,12 +109,13 @@ namespace UnityExplorer.UI.InteractiveValues
{
get
{
if (m_recacheWanted)
if (m_recacheWanted && Value != null)
return true;
else return m_entries.Count > 0;
}
}
internal IEnumerable RefIEnumerable;
internal IList RefIList;
@ -50,13 +130,14 @@ namespace UnityExplorer.UI.InteractiveValues
RefIEnumerable = Value as IEnumerable;
RefIList = Value as IList;
if (m_subContentParent.activeSelf)
if (m_subContentParent && m_subContentParent.activeSelf)
{
GetCacheEntries();
RefreshDisplay();
ToggleSubcontent();
//GetCacheEntries();
//RefreshDisplay();
}
else
m_recacheWanted = true;
m_recacheWanted = true;
base.OnValueUpdated();
}
@ -66,11 +147,6 @@ namespace UnityExplorer.UI.InteractiveValues
base.OnException(member);
}
private void OnPageTurned()
{
RefreshDisplay();
}
public override void RefreshUIForValue()
{
GetDefaultLabel();
@ -95,8 +171,6 @@ namespace UnityExplorer.UI.InteractiveValues
{
if (m_entries.Any())
{
// maybe improve this, probably could be more efficient i guess
foreach (var entry in m_entries)
entry.Destroy();
@ -111,7 +185,7 @@ namespace UnityExplorer.UI.InteractiveValues
int index = 0;
foreach (var entry in RefIEnumerable)
{
var cache = new CacheEnumerated(index, this, RefIList, this.m_listContent);
var cache = new CacheEnumerated(index, this, RefIList, this.InactiveHolder);
cache.CreateIValue(entry, m_baseEntryType);
m_entries.Add(cache);
@ -126,32 +200,9 @@ namespace UnityExplorer.UI.InteractiveValues
public void RefreshDisplay()
{
//var entries = m_entries;
//m_pageHandler.ListCount = entries.Count;
//
//for (int i = 0; i < m_displayedEntries.Length; i++)
//{
// var entry = m_displayedEntries[i];
// if (entry != null)
// entry.Disable();
// else
// break;
//}
//
//if (entries.Count < 1)
// return;
//
//foreach (var itemIndex in m_pageHandler)
//{
// if (itemIndex >= entries.Count)
// break;
//
// CacheEnumerated entry = entries[itemIndex];
// m_displayedEntries[itemIndex - m_pageHandler.StartIndex] = entry;
// entry.Enable();
//}
//
////UpdateSubcontentHeight();
ScrollPool.RefreshCells(true);
listLayout.minHeight = Math.Min(500f, m_entries.Count * 32f);
}
internal override void OnToggleSubcontent(bool active)
@ -168,39 +219,27 @@ namespace UnityExplorer.UI.InteractiveValues
RefreshDisplay();
}
internal GameObject m_listContent;
internal LayoutElement m_listLayout;
//internal PageHandler m_pageHandler;
public override void ConstructUI(GameObject parent, GameObject subGroup)
{
base.ConstructUI(parent, subGroup);
InactiveHolder = new GameObject("InactiveHolder");
InactiveHolder.transform.SetParent(parent.transform, false);
InactiveHolder.SetActive(false);
}
public override void ConstructSubcontent()
{
base.ConstructSubcontent();
//m_pageHandler = new PageHandler(null);
//m_pageHandler.ConstructUI(m_subContentParent);
//m_pageHandler.OnPageChanged += OnPageTurned;
ScrollPool = UIFactory.CreateScrollPool(m_subContentParent, "ListEntries", out GameObject scrollRoot, out GameObject scrollContent,
new Color(0.05f, 0.05f, 0.05f));
m_listContent = UIFactory.CreateVerticalGroup(this.m_subContentParent, "EnumerableContent", true, true, true, true, 2, new Vector4(5,5,5,5),
new Color(0.08f, 0.08f, 0.08f));
listLayout = scrollRoot.AddComponent<LayoutElement>();
var scrollRect = m_listContent.GetComponent<RectTransform>();
scrollRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 0);
m_listLayout = Owner.UIRoot.GetComponent<LayoutElement>();
m_listLayout.minHeight = 25;
m_listLayout.flexibleHeight = 0;
Owner.m_mainRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 25);
var contentFitter = m_listContent.AddComponent<ContentSizeFitter>();
contentFitter.horizontalFit = ContentSizeFitter.FitMode.Unconstrained;
contentFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
var proto = CellViewHolder.CreatePrototypeCell(scrollRoot);
proto.sizeDelta = new Vector2(100, 30);
ScrollPool.Initialize(this, proto);
}
}
}

View File

@ -67,6 +67,9 @@ namespace UnityExplorer.UI.InteractiveValues
if (_typeSupportCache.TryGetValue(type.AssemblyQualifiedName, out bool ret))
return ret;
if (type.FullName == "System.Void")
return false;
ret = true;
var fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
foreach (var field in fields)

View File

@ -172,6 +172,8 @@ namespace UnityExplorer.UI.InteractiveValues
public virtual void ConstructSubcontent()
{
Owner.CheckSubcontentCreation();
m_subContentConstructed = true;
}
@ -305,8 +307,11 @@ namespace UnityExplorer.UI.InteractiveValues
{
m_UIConstructed = true;
m_mainContent = UIFactory.CreateHorizontalGroup(parent, $"InteractiveValue_{this.GetType().Name}", false, false, true, true, 4, default,
new Color(1, 1, 1, 0), TextAnchor.UpperLeft);
//m_mainContent = UIFactory.CreateHorizontalGroup(parent, $"InteractiveValue_{this.GetType().Name}", false, false, true, true, 4, default,
// new Color(1, 1, 1, 0), TextAnchor.UpperLeft);
m_mainContent = UIFactory.CreateUIObject($"InteractiveValue_{this.GetType().Name}", parent);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(m_mainContent, false, false, true, true, 4, 0, 0, 0, 0, TextAnchor.UpperLeft);
var mainRect = m_mainContent.GetComponent<RectTransform>();
mainRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 25);
@ -316,7 +321,7 @@ namespace UnityExplorer.UI.InteractiveValues
// subcontent expand button
if (HasSubContent)
{
m_subExpandBtn = UIFactory.CreateButton(m_mainContent, "ExpandSubcontentButton", "▲", ToggleSubcontent, new Color(0.3f, 0.3f, 0.3f));
m_subExpandBtn = UIFactory.CreateButton(m_mainContent, "ExpandSubcontentButton", "▲", ToggleSubcontent, new Color(1,1,1,0));
UIFactory.SetLayoutElement(m_subExpandBtn.gameObject, minHeight: 25, minWidth: 25, flexibleWidth: 0, flexibleHeight: 0);
}

View File

@ -66,6 +66,8 @@ namespace UnityExplorer.UI.Widgets
public void DoSearch()
{
cachedCellTexts.Clear();
if (m_context == SearchContext.Singleton)
currentResults = SearchProvider.SingletonSearch(nameInputField.text);
else if (m_context == SearchContext.StaticClass)
@ -85,20 +87,29 @@ namespace UnityExplorer.UI.Widgets
resultsLabel.text = $"{currentResults.Count} results";
}
// Cache the syntax-highlighted text for each search result to reduce allocs.
private static readonly Dictionary<int, string> cachedCellTexts = new Dictionary<int, string>();
public void SetCell(ButtonCell<object> cell, int index)
{
if (m_context == SearchContext.StaticClass)
if (!cachedCellTexts.ContainsKey(index))
{
cell.buttonText.text = SignatureHighlighter.HighlightTypeName(currentResults[index].GetActualType());
string text;
if (m_context == SearchContext.StaticClass)
text = SignatureHighlighter.HighlightTypeName(currentResults[index].GetActualType());
else
text = ToStringUtility.ToString(currentResults[index], currentResults[index].GetActualType());
cachedCellTexts.Add(index, text);
}
else
cell.buttonText.text = ToStringUtility.ToString(currentResults[index], currentResults[index].GetActualType());
cell.buttonText.text = cachedCellTexts[index];
}
private void OnCellClicked(int dataIndex)
{
if (m_context == SearchContext.StaticClass)
InspectorManager.InspectType(currentResults[dataIndex] as Type);
InspectorManager.Inspect(currentResults[dataIndex] as Type);
else
InspectorManager.Inspect(currentResults[dataIndex]);
}

View File

@ -12,33 +12,57 @@ namespace UnityExplorer.UI.Widgets
public CellViewHolder(GameObject uiRoot)
{
this.UIRoot = uiRoot;
this.m_rect = uiRoot.GetComponent<RectTransform>();
this.Rect = uiRoot.GetComponent<RectTransform>();
m_enabled = uiRoot.activeSelf;
}
public bool Enabled => m_enabled;
private bool m_enabled;
public GameObject UIRoot;
public RectTransform Rect => m_rect;
private RectTransform m_rect;
public GameObject UIRoot { get; }
public RectTransform Rect { get; }
public void Disable()
private GameObject m_content;
public GameObject SetContent(GameObject newContent)
{
m_enabled = false;
UIRoot.SetActive(false);
var ret = m_content;
if (ret && newContent && ret.ReferenceEqual(newContent))
return null;
newContent.transform.SetParent(this.UIRoot.transform, false);
(this as ICell).Enable();
m_content = newContent;
return ret;
}
public void Enable()
public GameObject DisableContent()
{
var ret = m_content;
(this as ICell).Disable();
return ret;
}
void ICell.Enable()
{
m_enabled = true;
UIRoot.SetActive(true);
}
void ICell.Disable()
{
m_enabled = false;
UIRoot.SetActive(false);
}
public static RectTransform CreatePrototypeCell(GameObject parent)
{
var prototype = UIFactory.CreateVerticalGroup(parent, "PrototypeCell", true, true, true, true, 0, new Vector4(1, 0, 0, 0),
new Color(0.15f, 0.15f, 0.15f), TextAnchor.MiddleCenter);
// using an image on the cell view holder is fine, we only need to make about 20-50 of these per pool.
var prototype = UIFactory.CreateVerticalGroup(parent, "PrototypeCell", true, true, true, true, 0, new Vector4(0, 0, 0, 0),
new Color(0.11f, 0.11f, 0.11f), TextAnchor.MiddleCenter);
var rect = prototype.GetComponent<RectTransform>();
rect.anchorMin = new Vector2(0, 1);
rect.anchorMax = new Vector2(0, 1);
@ -47,6 +71,10 @@ namespace UnityExplorer.UI.Widgets
prototype.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
var sepObj = UIFactory.CreateUIObject("separator", prototype);
sepObj.AddComponent<Image>().color = Color.black;
UIFactory.SetLayoutElement(sepObj, minHeight: 1, preferredHeight: 1, flexibleHeight: 0);
prototype.SetActive(false);
return rect;

View File

@ -18,22 +18,14 @@ namespace UnityExplorer.UI.Widgets
public class DataHeightCache
{
private ScrollPool ScrollPool { get; }
//private DataHeightCache SisterCache { get; }
public DataHeightCache(ScrollPool scrollPool)
{
ScrollPool = scrollPool;
}
public DataHeightCache(ScrollPool scrollPool, DataHeightCache sisterCache) : this(scrollPool)
{
//this.SisterCache = sisterCache;
//for (int i = 0; i < scrollPool.DataSource.ItemCount; i++)
// Add(sisterCache[ScrollPool.DataSource.GetRealIndexOfTempIndex(i)]);
}
private readonly List<DataViewInfo> heightCache = new List<DataViewInfo>();
// initialize with a reasonably sized pool, most caches will allocate a fair bit.
private readonly List<DataViewInfo> heightCache = new List<DataViewInfo>(16384);
public DataViewInfo this[int index]
{
@ -118,14 +110,23 @@ namespace UnityExplorer.UI.Widgets
/// <summary>Get the data index at the specific position of the total height cache.</summary>
public int GetDataIndexAtPosition(float desiredHeight, out DataViewInfo cache)
{
cache = null;
cache = default;
int rangeIndex = GetRangeIndexOfPosition(desiredHeight);
if (rangeIndex < 0)
throw new Exception("Range index (" + rangeIndex + ") is below 0");
{
ExplorerCore.LogWarning("RangeIndex < 0? " + rangeIndex);
return -1;
}
if (rangeCache.Count <= rangeIndex)
throw new Exception("Range index (" + rangeIndex + ") exceeded rangeCache count (" + rangeCache.Count + ")");
{
ExplorerCore.LogWarning("Want range index " + rangeIndex + " but count is " + rangeCache.Count);
RebuildCache();
rangeIndex = GetRangeIndexOfPosition(desiredHeight);
if (rangeCache.Count <= rangeIndex)
throw new Exception("Range index (" + rangeIndex + ") exceeded rangeCache count (" + rangeCache.Count + ")");
}
int dataIndex = rangeCache[rangeIndex];
cache = heightCache[dataIndex];
@ -134,16 +135,13 @@ namespace UnityExplorer.UI.Widgets
}
/// <summary>Set a given data index with the specified value.</summary>
public void SetIndex(int dataIndex, float height, bool ignoreDataCount = false)
public void SetIndex(int dataIndex, float height)
{
if (!ignoreDataCount)
if (dataIndex >= ScrollPool.DataSource.ItemCount)
{
if (dataIndex >= ScrollPool.DataSource.ItemCount)
{
while (heightCache.Count > dataIndex)
RemoveLast();
return;
}
while (heightCache.Count > dataIndex)
RemoveLast();
return;
}
if (dataIndex >= heightCache.Count)
@ -175,14 +173,10 @@ namespace UnityExplorer.UI.Widgets
int rangeIndex = GetRangeCeilingOfPosition(cache.startPosition);
int spread = GetRangeSpread(cache.startPosition, height);
// check if our range cache is "corrupt" or not. If so we need to do a quick rebuild,
// so that each cell's start position is correct again.
if (rangeCache.Count <= rangeIndex || rangeCache[rangeIndex] != dataIndex)
if (rangeCache.Count <= rangeIndex)
{
RebuildStartPositions(ignoreDataCount);
// get these values again after rebuilding
rangeIndex = GetRangeCeilingOfPosition(cache.startPosition);
spread = GetRangeSpread(cache.startPosition, height);
RebuildCache();
return;
}
if (spread != cache.normalizedSpread)
@ -196,7 +190,7 @@ namespace UnityExplorer.UI.Widgets
{
// In some rare cases we may not find our data index at the expected range index.
// We can make some educated guesses and find the real index pretty quickly.
int minStart = rangeCache[dataIndex];
int minStart = GetRangeIndexOfPosition(dataIndex * DefaultHeight);
for (int i = minStart; i < rangeCache.Count; i++)
{
if (rangeCache[i] == dataIndex)
@ -211,16 +205,16 @@ namespace UnityExplorer.UI.Widgets
// This should never happen. We might be in a rebuild right now so don't
// rebuild again, we could overflow the stack. Just log it.
ExplorerCore.LogWarning($"DataHeightCache: Looking for range index of data {dataIndex} but reached the end and didn't find it.");
ExplorerCore.Log($"startPos: {cache.startPosition}, rangeIndex: {rangeIndex}, total height: {TotalHeight}");
return;
}
// our data index is further down. add the min difference and try again.
// the iterator will add 1 on the next loop so account for that.
// also, add the (spread - 1) of the cell we found at this index to skip it.
var spreadCurr = heightCache[rangeCache[i]].normalizedSpread;
int jmp = dataIndex - rangeCache[i] - 1;
jmp += heightCache[rangeCache[i]].normalizedSpread - 1;
i += jmp < 1 ? 0 : jmp;
jmp += spreadCurr - 2;
i = (jmp < 1 ? i : i + jmp);
}
}
@ -232,19 +226,19 @@ namespace UnityExplorer.UI.Widgets
if (rangeCache[rangeIndex] == dataIndex)
rangeCache.Insert(rangeIndex, dataIndex);
else
ExplorerCore.LogWarning($"DataHeightCache error increasing spread of data {dataIndex}, " +
$"the value at range {rangeIndex} is {rangeCache[rangeIndex]}!");
break;
}
}
else
{
// need to remove
for (int i = 0; i < -spreadDiff; i++)
{
if (rangeCache[rangeIndex] == dataIndex)
rangeCache.RemoveAt(rangeIndex);
else
ExplorerCore.LogWarning($"DataHeightCache error decreasing spread of data {dataIndex}, " +
$"the value at range {rangeIndex} is {rangeCache[rangeIndex]}!");
break;
}
}
}
@ -257,11 +251,11 @@ namespace UnityExplorer.UI.Widgets
//}
}
private void RebuildStartPositions(bool ignoreDataCount)
private void RebuildCache()
{
//start at 1 because 0's start pos is always 0
for (int i = 1; i < heightCache.Count; i++)
SetIndex(i, heightCache[i].height, ignoreDataCount);
SetIndex(i, heightCache[i].height);
}
}
}

View File

@ -10,6 +10,11 @@ using UnityExplorer.UI.Models;
namespace UnityExplorer.UI.Widgets
{
public struct CellInfo
{
public int cellIndex, dataIndex;
}
/// <summary>
/// An object-pooled ScrollRect, attempts to support content of any size and provide a scrollbar for it.
/// </summary>
@ -62,7 +67,6 @@ namespace UnityExplorer.UI.Widgets
private readonly List<ICell> CellPool = new List<ICell>();
internal DataHeightCache HeightCache;
internal DataHeightCache tempHeightCache;
private float TotalDataHeight => HeightCache.TotalHeight + contentLayout.padding.top + contentLayout.padding.bottom;
@ -114,7 +118,10 @@ namespace UnityExplorer.UI.Widgets
public void Rebuild()
{
RecreateCellPool(true, true, null);
SetRecycleViewBounds(false);
SetScrollBounds();
RecreateCellPool(true, true);
writingLocked = false;
Content.anchoredPosition = Vector2.zero;
UpdateSliderHandle(true);
@ -128,22 +135,23 @@ namespace UnityExplorer.UI.Widgets
UpdateSliderHandle(true);
}
public void EnableTempCache()
public void RecreateHeightCache()
{
if (tempHeightCache == null)
tempHeightCache = HeightCache;
//if (tempHeightCache == null)
// tempHeightCache = HeightCache;
HeightCache = new DataHeightCache(this, tempHeightCache);
HeightCache = new DataHeightCache(this);
CheckDataSourceCountChange(out _);
}
public void DisableTempCache()
{
if (tempHeightCache == null)
return;
//public void DisableTempCache()
//{
// if (tempHeightCache == null)
// return;
HeightCache = tempHeightCache;
tempHeightCache = null;
}
// HeightCache = tempHeightCache;
// tempHeightCache = null;
//}
public void RefreshCells(bool reloadData)
{
@ -252,23 +260,15 @@ namespace UnityExplorer.UI.Widgets
RecycleViewBounds = new Vector2(Viewport.MinY() + HalfThreshold, Viewport.MaxY() - HalfThreshold);
if (checkHeightGrow && prevViewportHeight < Viewport.rect.height && prevViewportHeight != 0.0f)
ret = RecreateCellPool(false, false, null);
ret = RecreateCellPool(false, false);
prevViewportHeight = Viewport.rect.height;
return ret;
}
private bool RecreateCellPool(bool forceRecreate, bool resetDataIndex, bool? setTempCacheEnabledTo)
private bool RecreateCellPool(bool forceRecreate, bool resetDataIndex)
{
if (setTempCacheEnabledTo != null)
{
if (setTempCacheEnabledTo == true)
EnableTempCache();
else if (setTempCacheEnabledTo == false)
DisableTempCache();
}
CheckDataSourceCountChange(out _);
var requiredCoverage = Math.Abs(RecycleViewBounds.y - RecycleViewBounds.x);
@ -310,7 +310,7 @@ namespace UnityExplorer.UI.Widgets
// Refresh methods
private struct CellInfo { public int cellIndex, dataIndex; }
private CellInfo _cellInfo = new CellInfo();
private IEnumerator<CellInfo> GetPoolEnumerator()
{
@ -319,11 +319,9 @@ namespace UnityExplorer.UI.Widgets
int iterated = 0;
while (iterated < CellPool.Count)
{
yield return new CellInfo()
{
cellIndex = cellIdx,
dataIndex = dataIndex
};
_cellInfo.cellIndex = cellIdx;
_cellInfo.dataIndex = dataIndex;
yield return _cellInfo;
cellIdx++;
if (cellIdx >= CellPool.Count)
@ -407,7 +405,7 @@ namespace UnityExplorer.UI.Widgets
cachedCell.Enable();
DataSource.SetCell(cachedCell, dataIndex);
//LayoutRebuilder.ForceRebuildLayoutImmediate(cachedCell.Rect);
LayoutRebuilder.ForceRebuildLayoutImmediate(cachedCell.Rect);
HeightCache.SetIndex(dataIndex, cachedCell.Rect.rect.height);
}
@ -443,11 +441,11 @@ namespace UnityExplorer.UI.Widgets
ScrollRect.m_ContentStartPosition += vector;
ScrollRect.m_PrevPosition += vector;
// LayoutRebuilder.ForceRebuildLayoutImmediate(Content);
prevAnchoredPos = ScrollRect.content.anchoredPosition;
SetScrollBounds();
//WritingLocked = true;
UpdateSliderHandle();
}
@ -487,6 +485,8 @@ namespace UnityExplorer.UI.Widgets
topPoolIndex = (topPoolIndex + 1) % CellPool.Count;
}
//LayoutRebuilder.ForceRebuildLayoutImmediate(Content);
return -recycledheight;
}
@ -528,6 +528,8 @@ namespace UnityExplorer.UI.Widgets
bottomPoolIndex = (bottomPoolIndex - 1 + CellPool.Count) % CellPool.Count;
}
//LayoutRebuilder.ForceRebuildLayoutImmediate(Content);
return recycledheight;
}

View File

@ -37,8 +37,6 @@ namespace UnityExplorer.UI.Utility
public SliderScrollbar(Scrollbar scrollbar, Slider slider)
{
//Instances.Add(this);
this.m_scrollbar = scrollbar;
this.m_slider = slider;
this.m_scrollRect = scrollbar.transform.parent.GetComponent<RectTransform>();
@ -50,17 +48,6 @@ namespace UnityExplorer.UI.Utility
this.m_slider.Set(1f, false);
}
//internal bool CheckDestroyed()
//{
// if (!m_slider || !m_scrollbar)
// {
// Instances.Remove(this);
// return true;
// }
// return false;
//}
public override void Update()
{
this.RefreshVisibility();
@ -75,12 +62,12 @@ namespace UnityExplorer.UI.Utility
}
bool shouldShow = !Mathf.Approximately(this.m_scrollbar.size, 1);
var obj = this.m_slider.handleRect.gameObject;
//var obj = this.m_slider.handleRect.gameObject;
if (IsActive != shouldShow)
{
IsActive = shouldShow;
obj.SetActive(IsActive);
m_slider.interactable = shouldShow;
if (IsActive)
this.m_slider.Set(this.m_scrollbar.value, false);
@ -109,14 +96,12 @@ namespace UnityExplorer.UI.Utility
GameObject sliderObj = UIFactory.CreateUIObject("SliderScrollbar", parent, UIFactory._smallElementSize);
GameObject bgObj = UIFactory.CreateUIObject("Background", sliderObj);
//GameObject fillAreaObj = UIFactory.CreateUIObject("Fill Area", sliderObj);
//GameObject fillObj = UIFactory.CreateUIObject("Fill", fillAreaObj);
GameObject handleSlideAreaObj = UIFactory.CreateUIObject("Handle Slide Area", sliderObj);
GameObject handleObj = UIFactory.CreateUIObject("Handle", handleSlideAreaObj);
Image bgImage = bgObj.AddComponent<Image>();
bgImage.type = Image.Type.Sliced;
bgImage.color = new Color(0.05f, 0.05f, 0.05f, 1.0f);
bgImage.color = new Color(0.1f, 0.1f, 0.1f, 1.0f);
RectTransform bgRect = bgObj.GetComponent<RectTransform>();
bgRect.anchorMin = Vector2.zero;
@ -128,7 +113,7 @@ namespace UnityExplorer.UI.Utility
handleSlideRect.anchorMin = new Vector2(0f, 0f);
handleSlideRect.anchorMax = new Vector2(1f, 1f);
handleSlideRect.pivot = new Vector2(0.5f, 0.5f);
handleSlideRect.offsetMin = new Vector2(27f, 30f);
handleSlideRect.offsetMin = new Vector2(25f, 30f);
handleSlideRect.offsetMax = new Vector2(-15f, 0f);
handleSlideRect.sizeDelta = new Vector2(-20f, -30f);
@ -147,14 +132,14 @@ namespace UnityExplorer.UI.Utility
sliderBarLayout.flexibleHeight = 5000;
slider = sliderObj.AddComponent<Slider>();
//slider.fillRect = fillObj.GetComponent<RectTransform>();
slider.handleRect = handleObj.GetComponent<RectTransform>();
slider.targetGraphic = handleImage;
slider.direction = Slider.Direction.BottomToTop;
RuntimeProvider.Instance.SetColorBlock(slider,
new Color(0.25f, 0.25f, 0.25f),
new Color(0.3f, 0.3f, 0.3f),
RuntimeProvider.Instance.SetColorBlock(slider,
new Color(0.4f, 0.4f, 0.4f),
new Color(0.5f, 0.5f, 0.5f),
new Color(0.3f, 0.3f, 0.3f),
new Color(0.2f, 0.2f, 0.2f));
return sliderObj;