mirror of
https://github.com/sinai-dev/UnityExplorer.git
synced 2025-01-07 18:13:35 +08:00
Cleanup and fix some small issues with scroll pool
This commit is contained in:
parent
0a9639f8a9
commit
edbb9a2882
@ -168,34 +168,54 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
public int ItemCount => Inspector.dummyContents.Count;
|
public int ItemCount => Inspector.dummyContents.Count;
|
||||||
|
|
||||||
|
public void OnDisableCell(CellViewHolder cell, int dataIndex)
|
||||||
|
{
|
||||||
|
if (cell.UIRoot.transform.Find("Content") is Transform existing)
|
||||||
|
existing.transform.SetParent(Inspector.dummyContentHolder.transform, false);
|
||||||
|
}
|
||||||
|
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
var prototype = DynamicCell.CreatePrototypeCell(Scroller.UIRoot);
|
var prototype = CellViewHolder.CreatePrototypeCell(Scroller.UIRoot);
|
||||||
|
|
||||||
Scroller.DataSource = this;
|
Scroller.DataSource = this;
|
||||||
Scroller.Initialize(this, prototype);
|
Scroller.Initialize(this, prototype);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ICell CreateCell(RectTransform cellTransform) => new DynamicCell(cellTransform.gameObject);
|
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)
|
public void SetCell(ICell icell, int index)
|
||||||
{
|
{
|
||||||
|
var root = (icell as CellViewHolder).UIRoot;
|
||||||
|
|
||||||
if (index < 0 || index >= ItemCount)
|
if (index < 0 || index >= ItemCount)
|
||||||
{
|
{
|
||||||
|
DisableContent(root);
|
||||||
icell.Disable();
|
icell.Disable();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var root = (icell as DynamicCell).uiRoot;
|
|
||||||
var content = Inspector.dummyContents[index];
|
var content = Inspector.dummyContents[index];
|
||||||
|
|
||||||
if (content.transform.parent.ReferenceEqual(root.transform))
|
if (content.transform.parent.ReferenceEqual(root.transform))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (root.transform.Find("Content") is Transform existing)
|
DisableContent(root);
|
||||||
existing.transform.SetParent(Inspector.dummyContentHolder.transform, false);
|
|
||||||
|
|
||||||
content.transform.SetParent(root.transform, false);
|
content.transform.SetParent(root.transform, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DisableContent(GameObject cellRoot)
|
||||||
|
{
|
||||||
|
if (cellRoot.transform.Find("Content") is Transform existing)
|
||||||
|
existing.transform.SetParent(Inspector.dummyContentHolder.transform, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,26 +128,26 @@ namespace UnityExplorer.UI.Panels
|
|||||||
Tree.RefreshData(true);
|
Tree.RefreshData(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private float highestRectHeight;
|
//private float highestRectHeight;
|
||||||
|
|
||||||
public override void OnFinishResize(RectTransform panel)
|
//public override void OnFinishResize(RectTransform panel)
|
||||||
{
|
//{
|
||||||
base.OnFinishResize(panel);
|
// base.OnFinishResize(panel);
|
||||||
RuntimeProvider.Instance.StartCoroutine(DelayedRefresh(panel));
|
// RuntimeProvider.Instance.StartCoroutine(DelayedRefresh(panel));
|
||||||
}
|
//}
|
||||||
|
|
||||||
private IEnumerator DelayedRefresh(RectTransform obj)
|
//private IEnumerator DelayedRefresh(RectTransform obj)
|
||||||
{
|
//{
|
||||||
yield return null;
|
// yield return null;
|
||||||
|
|
||||||
if (obj.rect.height > highestRectHeight)
|
// if (obj.rect.height > highestRectHeight)
|
||||||
{
|
// {
|
||||||
// height increased, hard refresh required.
|
// // height increased, hard refresh required.
|
||||||
highestRectHeight = obj.rect.height;
|
// highestRectHeight = obj.rect.height;
|
||||||
//Tree.Scroller.ReloadData();
|
// //Tree.Scroller.ReloadData();
|
||||||
}
|
// }
|
||||||
Tree.Scroller.RefreshCells(true);
|
// Tree.Scroller.RefreshCells(true);
|
||||||
}
|
//}
|
||||||
|
|
||||||
public override void SaveToConfigManager()
|
public override void SaveToConfigManager()
|
||||||
{
|
{
|
||||||
@ -192,10 +192,6 @@ namespace UnityExplorer.UI.Panels
|
|||||||
var filterRow = UIFactory.CreateHorizontalGroup(toolbar, "FilterGroup", true, true, true, true, 2, new Vector4(2, 2, 2, 2));
|
var filterRow = UIFactory.CreateHorizontalGroup(toolbar, "FilterGroup", true, true, true, true, 2, new Vector4(2, 2, 2, 2));
|
||||||
UIFactory.SetLayoutElement(filterRow, minHeight: 25, flexibleHeight: 0);
|
UIFactory.SetLayoutElement(filterRow, minHeight: 25, flexibleHeight: 0);
|
||||||
|
|
||||||
//// filter label
|
|
||||||
//var label = UIFactory.CreateLabel(filterRow, "FilterLabel", "Search:", TextAnchor.MiddleLeft);
|
|
||||||
//UIFactory.SetLayoutElement(label.gameObject, minWidth: 50, flexibleWidth: 0);
|
|
||||||
|
|
||||||
//Filter input field
|
//Filter input field
|
||||||
var inputFieldObj = UIFactory.CreateInputField(filterRow, "FilterInput", "Search...", out InputField inputField, 13);
|
var inputFieldObj = UIFactory.CreateInputField(filterRow, "FilterInput", "Search...", out InputField inputField, 13);
|
||||||
inputField.targetGraphic.color = new Color(0.2f, 0.2f, 0.2f);
|
inputField.targetGraphic.color = new Color(0.2f, 0.2f, 0.2f);
|
||||||
@ -224,23 +220,23 @@ namespace UnityExplorer.UI.Panels
|
|||||||
|
|
||||||
// Transform Tree
|
// Transform Tree
|
||||||
|
|
||||||
//var prototype = TransformCell.CreatePrototypeCell(scrollContent);
|
|
||||||
|
|
||||||
var infiniteScroll = UIFactory.CreateScrollPool(content, "TransformTree", out GameObject scrollObj,
|
var infiniteScroll = UIFactory.CreateScrollPool(content, "TransformTree", out GameObject scrollObj,
|
||||||
out GameObject scrollContent, new Color(0.15f, 0.15f, 0.15f));
|
out GameObject scrollContent, new Color(0.15f, 0.15f, 0.15f));
|
||||||
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
|
UIFactory.SetLayoutElement(scrollObj, flexibleHeight: 9999);
|
||||||
UIFactory.SetLayoutElement(scrollContent, flexibleHeight: 9999);
|
UIFactory.SetLayoutElement(scrollContent, flexibleHeight: 9999);
|
||||||
|
|
||||||
// Prototype tree cell
|
|
||||||
|
|
||||||
//infiniteScroll.PrototypeCell = prototype.GetComponent<RectTransform>();
|
|
||||||
|
|
||||||
Tree = new TransformTree(infiniteScroll) { GetRootEntriesMethod = GetRootEntries };
|
Tree = new TransformTree(infiniteScroll) { GetRootEntriesMethod = GetRootEntries };
|
||||||
Tree.Init();
|
Tree.Init();
|
||||||
|
|
||||||
// some references
|
// Scene Loader
|
||||||
highestRectHeight = mainPanelRect.rect.height;
|
|
||||||
|
|
||||||
|
ConstructSceneLoader();
|
||||||
|
}
|
||||||
|
|
||||||
|
private const string DEFAULT_LOAD_TEXT = "[Select a scene]";
|
||||||
|
|
||||||
|
private void ConstructSceneLoader()
|
||||||
|
{
|
||||||
// Scene Loader
|
// Scene Loader
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -256,7 +252,7 @@ namespace UnityExplorer.UI.Panels
|
|||||||
var allSceneDropObj = UIFactory.CreateDropdown(sceneLoaderObj, out Dropdown allSceneDrop, "", 14, null);
|
var allSceneDropObj = UIFactory.CreateDropdown(sceneLoaderObj, out Dropdown allSceneDrop, "", 14, null);
|
||||||
UIFactory.SetLayoutElement(allSceneDropObj, minHeight: 25, minWidth: 150, flexibleWidth: 0, flexibleHeight: 0);
|
UIFactory.SetLayoutElement(allSceneDropObj, minHeight: 25, minWidth: 150, flexibleWidth: 0, flexibleHeight: 0);
|
||||||
|
|
||||||
allSceneDrop.options.Add(new Dropdown.OptionData("[Select a scene]"));
|
allSceneDrop.options.Add(new Dropdown.OptionData(DEFAULT_LOAD_TEXT));
|
||||||
|
|
||||||
foreach (var scene in SceneHandler.AllSceneNames)
|
foreach (var scene in SceneHandler.AllSceneNames)
|
||||||
allSceneDrop.options.Add(new Dropdown.OptionData(Path.GetFileNameWithoutExtension(scene)));
|
allSceneDrop.options.Add(new Dropdown.OptionData(Path.GetFileNameWithoutExtension(scene)));
|
||||||
@ -277,20 +273,41 @@ namespace UnityExplorer.UI.Panels
|
|||||||
TryLoadScene(LoadSceneMode.Additive, allSceneDrop);
|
TryLoadScene(LoadSceneMode.Additive, allSceneDrop);
|
||||||
}, new Color(0.1f, 0.3f, 0.3f));
|
}, new Color(0.1f, 0.3f, 0.3f));
|
||||||
UIFactory.SetLayoutElement(loadAdditiveButton.gameObject, minHeight: 25, minWidth: 150);
|
UIFactory.SetLayoutElement(loadAdditiveButton.gameObject, minHeight: 25, minWidth: 150);
|
||||||
|
|
||||||
|
var disabledColor = new Color(0.24f, 0.24f, 0.24f);
|
||||||
|
RuntimeProvider.Instance.SetColorBlock(loadButton, disabled: disabledColor);
|
||||||
|
RuntimeProvider.Instance.SetColorBlock(loadAdditiveButton, disabled: disabledColor);
|
||||||
|
|
||||||
|
loadButton.interactable = false;
|
||||||
|
loadAdditiveButton.interactable = false;
|
||||||
|
|
||||||
|
allSceneDrop.onValueChanged.AddListener((int val) =>
|
||||||
|
{
|
||||||
|
var text = allSceneDrop.options[val].text;
|
||||||
|
if (text == DEFAULT_LOAD_TEXT)
|
||||||
|
{
|
||||||
|
loadButton.interactable = false;
|
||||||
|
loadAdditiveButton.interactable = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
loadButton.interactable = true;
|
||||||
|
loadAdditiveButton.interactable = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
ExplorerCore.LogWarning($"Could not create the Scene Loader helper! {ex.ReflectionExToString()}");
|
ExplorerCore.LogWarning($"Could not create the Scene Loader helper! {ex.ReflectionExToString()}");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TryLoadScene(LoadSceneMode mode, Dropdown allSceneDrop)
|
private void TryLoadScene(LoadSceneMode mode, Dropdown allSceneDrop)
|
||||||
{
|
{
|
||||||
var text = allSceneDrop.options[allSceneDrop.value].text;
|
var text = allSceneDrop.options[allSceneDrop.value].text;
|
||||||
|
|
||||||
if (text == "[Select a scene]")
|
if (text == DEFAULT_LOAD_TEXT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -17,6 +17,8 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
public ButtonListSource<T> list;
|
public ButtonListSource<T> list;
|
||||||
|
|
||||||
public GameObject uiRoot;
|
public GameObject uiRoot;
|
||||||
|
private RectTransform m_rect;
|
||||||
|
public RectTransform Rect => m_rect;
|
||||||
public Text buttonText;
|
public Text buttonText;
|
||||||
public Button button;
|
public Button button;
|
||||||
|
|
||||||
@ -24,6 +26,7 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
{
|
{
|
||||||
this.list = list;
|
this.list = list;
|
||||||
this.uiRoot = uiRoot;
|
this.uiRoot = uiRoot;
|
||||||
|
this.m_rect = uiRoot.GetComponent<RectTransform>();
|
||||||
this.buttonText = text;
|
this.buttonText = text;
|
||||||
this.button = button;
|
this.button = button;
|
||||||
|
|
||||||
|
@ -96,5 +96,7 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
SetICell.Invoke((ButtonCell<T>)cell, index);
|
SetICell.Invoke((ButtonCell<T>)cell, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DisableCell(ICell cell, int index) => cell.Disable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,30 +7,32 @@ using UnityEngine.UI;
|
|||||||
|
|
||||||
namespace UnityExplorer.UI.Widgets
|
namespace UnityExplorer.UI.Widgets
|
||||||
{
|
{
|
||||||
public class DynamicCell : ICell
|
public class CellViewHolder : ICell
|
||||||
{
|
{
|
||||||
public DynamicCell(GameObject uiRoot)
|
public CellViewHolder(GameObject uiRoot)
|
||||||
{
|
{
|
||||||
this.uiRoot = uiRoot;
|
this.UIRoot = uiRoot;
|
||||||
|
this.m_rect = uiRoot.GetComponent<RectTransform>();
|
||||||
m_enabled = uiRoot.activeSelf;
|
m_enabled = uiRoot.activeSelf;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Enabled => m_enabled;
|
public bool Enabled => m_enabled;
|
||||||
private bool m_enabled;
|
private bool m_enabled;
|
||||||
|
|
||||||
public GameObject uiRoot;
|
public GameObject UIRoot;
|
||||||
public InputField input;
|
public RectTransform Rect => m_rect;
|
||||||
|
private RectTransform m_rect;
|
||||||
|
|
||||||
public void Disable()
|
public void Disable()
|
||||||
{
|
{
|
||||||
m_enabled = false;
|
m_enabled = false;
|
||||||
uiRoot.SetActive(false);
|
UIRoot.SetActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Enable()
|
public void Enable()
|
||||||
{
|
{
|
||||||
m_enabled = true;
|
m_enabled = true;
|
||||||
uiRoot.SetActive(true);
|
UIRoot.SetActive(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RectTransform CreatePrototypeCell(GameObject parent)
|
public static RectTransform CreatePrototypeCell(GameObject parent)
|
||||||
@ -42,7 +44,6 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
rect.anchorMax = new Vector2(0, 1);
|
rect.anchorMax = new Vector2(0, 1);
|
||||||
rect.pivot = new Vector2(0.5f, 1);
|
rect.pivot = new Vector2(0.5f, 1);
|
||||||
rect.sizeDelta = new Vector2(100, 30);
|
rect.sizeDelta = new Vector2(100, 30);
|
||||||
//UIFactory.SetLayoutElement(prototype, minWidth: 100, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 9999);
|
|
||||||
|
|
||||||
prototype.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
prototype.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
|
||||||
|
|
@ -113,7 +113,7 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
|
|
||||||
if (diff != 0.0f)
|
if (diff != 0.0f)
|
||||||
{
|
{
|
||||||
//ExplorerCore.LogWarning("Height for data index " + dataIndex + " changed by " + diff);
|
ExplorerCore.LogWarning("Height for data index " + dataIndex + " changed by " + diff);
|
||||||
cache.height = value;
|
cache.height = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace UnityExplorer.UI.Widgets
|
namespace UnityExplorer.UI.Widgets
|
||||||
{
|
{
|
||||||
@ -9,6 +10,8 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
{
|
{
|
||||||
bool Enabled { get; }
|
bool Enabled { get; }
|
||||||
|
|
||||||
|
RectTransform Rect { get; }
|
||||||
|
|
||||||
void Enable();
|
void Enable();
|
||||||
void Disable();
|
void Disable();
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
int ItemCount { get; }
|
int ItemCount { get; }
|
||||||
|
|
||||||
void SetCell(ICell cell, int index);
|
void SetCell(ICell cell, int index);
|
||||||
|
void DisableCell(ICell cell, int index);
|
||||||
|
|
||||||
ICell CreateCell(RectTransform cellTransform);
|
ICell CreateCell(RectTransform cellTransform);
|
||||||
}
|
}
|
||||||
|
@ -9,28 +9,25 @@ using UnityExplorer.UI.Models;
|
|||||||
|
|
||||||
namespace UnityExplorer.UI.Widgets
|
namespace UnityExplorer.UI.Widgets
|
||||||
{
|
{
|
||||||
// TODO: there is possibly still a bug causing the content to jump around, sometimes observed when
|
|
||||||
// the pooled content height is extremely large (compared to viewport). maybe it depends on the
|
|
||||||
// top/bottom cells or something.
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An object-pooled ScrollRect, attempts to support content of any size and provide a scrollbar for it.</summary>
|
/// An object-pooled ScrollRect, attempts to support content of any size and provide a scrollbar for it.
|
||||||
|
/// </summary>
|
||||||
public class ScrollPool : UIBehaviourModel
|
public class ScrollPool : UIBehaviourModel
|
||||||
{
|
{
|
||||||
// used to track and manage cell views
|
//// used to track and manage cell views
|
||||||
public class CachedCell
|
//public class CachedCell
|
||||||
{
|
//{
|
||||||
public ScrollPool Pool { get; }
|
// public ScrollPool Pool { get; }
|
||||||
public RectTransform Rect { get; internal set; }
|
// public RectTransform Rect { get; internal set; }
|
||||||
public ICell Cell { get; }
|
// public ICell Cell { get; }
|
||||||
|
|
||||||
public CachedCell(ScrollPool pool, RectTransform rect, ICell cell)
|
// public CachedCell(ScrollPool pool, RectTransform rect, ICell cell)
|
||||||
{
|
// {
|
||||||
this.Pool = pool;
|
// this.Pool = pool;
|
||||||
this.Rect = rect;
|
// this.Rect = rect;
|
||||||
this.Cell = cell;
|
// this.Cell = cell;
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
public ScrollPool(ScrollRect scrollRect)
|
public ScrollPool(ScrollRect scrollRect)
|
||||||
{
|
{
|
||||||
@ -68,7 +65,7 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
private int bottomDataIndex;
|
private int bottomDataIndex;
|
||||||
private int TopDataIndex => bottomDataIndex - CellPool.Count + 1;
|
private int TopDataIndex => bottomDataIndex - CellPool.Count + 1;
|
||||||
|
|
||||||
private readonly List<CachedCell> CellPool = new List<CachedCell>();
|
private readonly List<ICell> CellPool = new List<ICell>();
|
||||||
|
|
||||||
private DataHeightManager HeightCache;
|
private DataHeightManager HeightCache;
|
||||||
|
|
||||||
@ -77,7 +74,7 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The first and last indices of our CellPool in the transform heirarchy
|
/// The first and last indices of our CellPool in the transform heirarchy
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private int topPoolCellIndex, bottomPoolIndex;
|
private int topPoolIndex, bottomPoolIndex;
|
||||||
|
|
||||||
private int CurrentDataCount => bottomDataIndex + 1;
|
private int CurrentDataCount => bottomDataIndex + 1;
|
||||||
|
|
||||||
@ -140,26 +137,31 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
private IEnumerator InitCoroutine()
|
private IEnumerator InitCoroutine()
|
||||||
{
|
{
|
||||||
scrollRect.content.anchoredPosition = Vector2.zero;
|
scrollRect.content.anchoredPosition = Vector2.zero;
|
||||||
|
|
||||||
yield return null;
|
yield return null;
|
||||||
|
|
||||||
|
// set intial bounds
|
||||||
_prevAnchoredPos = Content.anchoredPosition;
|
_prevAnchoredPos = Content.anchoredPosition;
|
||||||
|
|
||||||
SetRecycleViewBounds(false);
|
SetRecycleViewBounds(false);
|
||||||
|
|
||||||
float start = Time.realtimeSinceStartup;
|
// create initial cell pool and set cells
|
||||||
CreateCellPool();
|
CreateCellPool();
|
||||||
|
|
||||||
NormalizedScrollBounds = new Vector2(Viewport.rect.height * 0.5f, TotalDataHeight - (Viewport.rect.height * 0.5f));
|
// update slider
|
||||||
|
SetScrollBounds();
|
||||||
UpdateSliderHandle();
|
UpdateSliderHandle();
|
||||||
|
|
||||||
|
// add onValueChanged listener after setup
|
||||||
scrollRect.onValueChanged.AddListener(OnValueChangedListener);
|
scrollRect.onValueChanged.AddListener(OnValueChangedListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetScrollBounds()
|
||||||
|
{
|
||||||
|
NormalizedScrollBounds = new Vector2(Viewport.rect.height * 0.5f, TotalDataHeight - (Viewport.rect.height * 0.5f));
|
||||||
|
}
|
||||||
|
|
||||||
// Cell pool
|
// Cell pool
|
||||||
|
|
||||||
private void CreateCellPool()
|
private void CreateCellPool(bool andResetDataIndex = true)
|
||||||
{
|
{
|
||||||
if (CellPool.Any())
|
if (CellPool.Any())
|
||||||
{
|
{
|
||||||
@ -171,7 +173,7 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
float currentPoolCoverage = 0f;
|
float currentPoolCoverage = 0f;
|
||||||
float requiredCoverage = scrollRect.viewport.rect.height + ExtraPoolThreshold;// * ExtraPoolCoverageRatio;
|
float requiredCoverage = scrollRect.viewport.rect.height + ExtraPoolThreshold;// * ExtraPoolCoverageRatio;
|
||||||
|
|
||||||
topPoolCellIndex = 0;
|
topPoolIndex = 0;
|
||||||
bottomPoolIndex = -1;
|
bottomPoolIndex = -1;
|
||||||
|
|
||||||
// create cells until the Pool area is covered.
|
// create cells until the Pool area is covered.
|
||||||
@ -185,85 +187,65 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
rect.gameObject.SetActive(true);
|
rect.gameObject.SetActive(true);
|
||||||
rect.name = $"Cell_{CellPool.Count + 1}";
|
rect.name = $"Cell_{CellPool.Count + 1}";
|
||||||
var cell = DataSource.CreateCell(rect);
|
var cell = DataSource.CreateCell(rect);
|
||||||
CellPool.Add(new CachedCell(this, rect, cell));
|
CellPool.Add(cell);
|
||||||
rect.SetParent(scrollRect.content, false);
|
rect.SetParent(scrollRect.content, false);
|
||||||
|
|
||||||
currentPoolCoverage += rect.rect.height;
|
currentPoolCoverage += rect.rect.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
bottomDataIndex = CellPool.Count - 1;
|
if (andResetDataIndex)
|
||||||
|
bottomDataIndex = CellPool.Count - 1;
|
||||||
|
|
||||||
// after creating pool, set displayed cells.
|
// after creating pool, set displayed cells.
|
||||||
for (int i = 0; i < CellPool.Count; i++)
|
for (int i = 0; i < CellPool.Count; i++)
|
||||||
{
|
SetCell(CellPool[i], i);
|
||||||
var cell = CellPool[i];
|
|
||||||
SetCell(cell, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
LayoutRebuilder.ForceRebuildLayoutImmediate(Content);
|
LayoutRebuilder.ForceRebuildLayoutImmediate(Content);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetRecycleViewBounds(bool checkHeightGrow)
|
private void SetRecycleViewBounds(bool checkHeightGrow)
|
||||||
{
|
{
|
||||||
var extra = ExtraPoolThreshold;
|
RecycleViewBounds = new Vector2(Viewport.MinY() + HalfPoolThreshold, Viewport.MaxY() - HalfPoolThreshold);
|
||||||
extra *= 0.5f;
|
|
||||||
RecycleViewBounds = new Vector2(Viewport.MinY() + extra, Viewport.MaxY() - extra);
|
|
||||||
|
|
||||||
if (checkHeightGrow && _prevViewportHeight < Viewport.rect.height && _prevViewportHeight != 0.0f)
|
if (checkHeightGrow && _prevViewportHeight < Viewport.rect.height && _prevViewportHeight != 0.0f)
|
||||||
RefillCellPool();
|
ExtendCellPool();
|
||||||
|
|
||||||
_prevViewportHeight = Viewport.rect.height;
|
_prevViewportHeight = Viewport.rect.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RefillCellPool()
|
// TODO this is working fine except the content jumps to the top while dragging (then jumps back after).
|
||||||
{
|
// Not sure why, should be fixable though.
|
||||||
// TODO buggy for some reason, not quite right.
|
|
||||||
|
|
||||||
|
private void ExtendCellPool()
|
||||||
|
{
|
||||||
var requiredCoverage = Math.Abs(RecycleViewBounds.y - RecycleViewBounds.x);
|
var requiredCoverage = Math.Abs(RecycleViewBounds.y - RecycleViewBounds.x);
|
||||||
var currentCoverage = CellPool.Count * PrototypeHeight;
|
var currentCoverage = CellPool.Count * PrototypeHeight;
|
||||||
if (currentCoverage < requiredCoverage)
|
int cellsRequired = (int)Math.Ceiling((decimal)(requiredCoverage - currentCoverage) / (decimal)PrototypeHeight);
|
||||||
|
if (cellsRequired > 0)
|
||||||
{
|
{
|
||||||
//int cellsRequired = (int)Math.Ceiling((decimal)(requiredCoverage - currentCoverage) / (decimal)PrototypeHeight);
|
var pos = Content.anchoredPosition.y;
|
||||||
|
|
||||||
while (currentCoverage <= requiredCoverage)
|
// Disable cells so DataSource can handle its content if need be
|
||||||
|
var enumerator = GetPoolEnumerator();
|
||||||
|
while (enumerator.MoveNext())
|
||||||
{
|
{
|
||||||
//bottomPoolIndex++;
|
var curr = enumerator.Current;
|
||||||
ExplorerCore.Log("Adding to end of pool");
|
DataSource.DisableCell(CellPool[curr.cellIndex], curr.dataIndex);
|
||||||
|
|
||||||
//Instantiate and add to Pool
|
|
||||||
RectTransform rect = GameObject.Instantiate(PrototypeCell.gameObject).GetComponent<RectTransform>();
|
|
||||||
rect.gameObject.SetActive(true);
|
|
||||||
rect.name = $"Cell_{CellPool.Count + 1}";
|
|
||||||
rect.SetParent(scrollRect.content, false);
|
|
||||||
|
|
||||||
currentCoverage += rect.rect.height;
|
|
||||||
|
|
||||||
bottomDataIndex++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CellPool.Clear();
|
bottomDataIndex += cellsRequired;
|
||||||
|
|
||||||
int childCount = Content.childCount;
|
// CreateCellPool will destroy existing cells and recreate list.
|
||||||
for (int i = 0; i < childCount; i++)
|
CreateCellPool(false);
|
||||||
{
|
|
||||||
var rect = Content.GetChild(i).GetComponent<RectTransform>();
|
|
||||||
|
|
||||||
var cell = DataSource.CreateCell(rect);
|
//LayoutRebuilder.ForceRebuildLayoutImmediate(Content);
|
||||||
CellPool.Add(new CachedCell(this, rect, cell));
|
//scrollRect.UpdatePrevData();
|
||||||
|
|
||||||
ExplorerCore.Log("Assigned cell rect " + i);
|
// set content anchor position back
|
||||||
}
|
Content.anchoredPosition = new Vector2(0, pos);
|
||||||
|
|
||||||
// reassign cell references
|
LayoutRebuilder.ForceRebuildLayoutImmediate(Content);
|
||||||
topPoolCellIndex = 0;
|
scrollRect.UpdatePrevData();
|
||||||
bottomPoolIndex = CellPool.Count - 1;
|
|
||||||
|
|
||||||
// after creating pool, set displayed cells.
|
|
||||||
for (int i = 0; i < CellPool.Count; i++)
|
|
||||||
{
|
|
||||||
var cell = CellPool[i];
|
|
||||||
SetCell(cell, i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,7 +255,7 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
|
|
||||||
private IEnumerator<CellInfo> GetPoolEnumerator()
|
private IEnumerator<CellInfo> GetPoolEnumerator()
|
||||||
{
|
{
|
||||||
int cellIdx = topPoolCellIndex;
|
int cellIdx = topPoolIndex;
|
||||||
int dataIndex = TopDataIndex;
|
int dataIndex = TopDataIndex;
|
||||||
int iterated = 0;
|
int iterated = 0;
|
||||||
while (iterated < CellPool.Count)
|
while (iterated < CellPool.Count)
|
||||||
@ -353,19 +335,20 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
|
|
||||||
LayoutRebuilder.ForceRebuildLayoutImmediate(Content);
|
LayoutRebuilder.ForceRebuildLayoutImmediate(Content);
|
||||||
//SetRecycleViewBounds(false);
|
//SetRecycleViewBounds(false);
|
||||||
NormalizedScrollBounds = new Vector2(Viewport.rect.height * 0.5f, TotalDataHeight - (Viewport.rect.height * 0.5f));
|
SetScrollBounds();
|
||||||
scrollRect.UpdatePrevData();
|
scrollRect.UpdatePrevData();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetCell(CachedCell cachedCell, int dataIndex)
|
private void SetCell(ICell cachedCell, int dataIndex)
|
||||||
{
|
{
|
||||||
cachedCell.Cell.Enable();
|
cachedCell.Enable();
|
||||||
DataSource.SetCell(cachedCell.Cell, dataIndex);
|
DataSource.SetCell(cachedCell, dataIndex);
|
||||||
|
|
||||||
// DO NEED THIS! Potentially slightly expensive, but everything breaks if we dont do this.
|
// DO NEED THIS! Potentially slightly expensive, but everything breaks if we dont do this.
|
||||||
LayoutRebuilder.ForceRebuildLayoutImmediate(cachedCell.Rect);
|
LayoutRebuilder.ForceRebuildLayoutImmediate(cachedCell.Rect);
|
||||||
|
|
||||||
HeightCache.SetIndex(dataIndex, cachedCell.Cell.Enabled ? cachedCell.Rect.rect.height : 0f);
|
if (dataIndex < DataSource.ItemCount)
|
||||||
|
HeightCache.SetIndex(dataIndex, cachedCell.Rect.rect.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Value change processor
|
// Value change processor
|
||||||
@ -402,18 +385,18 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
LayoutRebuilder.ForceRebuildLayoutImmediate(Content);
|
LayoutRebuilder.ForceRebuildLayoutImmediate(Content);
|
||||||
_prevAnchoredPos = scrollRect.content.anchoredPosition;
|
_prevAnchoredPos = scrollRect.content.anchoredPosition;
|
||||||
|
|
||||||
NormalizedScrollBounds = new Vector2(Viewport.rect.height * 0.5f, TotalDataHeight - (Viewport.rect.height * 0.5f));
|
SetScrollBounds();
|
||||||
|
|
||||||
UpdateSliderHandle();
|
UpdateSliderHandle();
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ShouldRecycleTop => GetCellExtent(CellPool[topPoolCellIndex]) >= RecycleViewBounds.x;
|
private bool ShouldRecycleTop => GetCellExtent(CellPool[topPoolIndex].Rect) > RecycleViewBounds.x
|
||||||
//&& CellPool[bottomPoolIndex].Rect.position.y < Viewport.MaxY();
|
&& GetCellExtent(CellPool[bottomPoolIndex].Rect) > RecycleViewBounds.y;
|
||||||
|
|
||||||
private bool ShouldRecycleBottom => CellPool[bottomPoolIndex].Rect.position.y < RecycleViewBounds.y;
|
private bool ShouldRecycleBottom => CellPool[bottomPoolIndex].Rect.position.y < RecycleViewBounds.y
|
||||||
//&& GetCellExtent(CellPool[topPoolCellIndex]) < Viewport.MinY();
|
&& CellPool[topPoolIndex].Rect.position.y < RecycleViewBounds.x;
|
||||||
|
|
||||||
private float GetCellExtent(CachedCell cell) => cell.Rect.MaxY() - contentLayout.spacing;
|
private float GetCellExtent(RectTransform cell) => cell.MaxY() - contentLayout.spacing;
|
||||||
|
|
||||||
private float RecycleTopToBottom()
|
private float RecycleTopToBottom()
|
||||||
{
|
{
|
||||||
@ -423,7 +406,7 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
|
|
||||||
while (ShouldRecycleTop && CurrentDataCount < DataSource.ItemCount)
|
while (ShouldRecycleTop && CurrentDataCount < DataSource.ItemCount)
|
||||||
{
|
{
|
||||||
var cell = CellPool[topPoolCellIndex];
|
var cell = CellPool[topPoolIndex];
|
||||||
|
|
||||||
//Move top cell to bottom
|
//Move top cell to bottom
|
||||||
cell.Rect.SetAsLastSibling();
|
cell.Rect.SetAsLastSibling();
|
||||||
@ -439,8 +422,8 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
//set new indices
|
//set new indices
|
||||||
bottomDataIndex++;
|
bottomDataIndex++;
|
||||||
|
|
||||||
bottomPoolIndex = topPoolCellIndex;
|
bottomPoolIndex = topPoolIndex;
|
||||||
topPoolCellIndex = (topPoolCellIndex + 1) % CellPool.Count;
|
topPoolIndex = (topPoolIndex + 1) % CellPool.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -recycledheight;
|
return -recycledheight;
|
||||||
@ -480,7 +463,7 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
}
|
}
|
||||||
|
|
||||||
//set new indices
|
//set new indices
|
||||||
topPoolCellIndex = bottomPoolIndex;
|
topPoolIndex = bottomPoolIndex;
|
||||||
bottomPoolIndex = (bottomPoolIndex - 1 + CellPool.Count) % CellPool.Count;
|
bottomPoolIndex = (bottomPoolIndex - 1 + CellPool.Count) % CellPool.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -520,9 +503,10 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
val = (float)((decimal)scrollPos / (decimal)(TotalDataHeight - Viewport.rect.height));
|
val = (float)((decimal)scrollPos / (decimal)(TotalDataHeight - Viewport.rect.height));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool prev = writingLocked;
|
||||||
WritingLocked = true;
|
WritingLocked = true;
|
||||||
slider.value = val;
|
slider.value = val;
|
||||||
WritingLocked = false;
|
WritingLocked = prev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,8 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
public int _cellIndex;
|
public int _cellIndex;
|
||||||
|
|
||||||
public GameObject uiRoot;
|
public GameObject uiRoot;
|
||||||
|
public RectTransform Rect => m_rect;
|
||||||
|
private readonly RectTransform m_rect;
|
||||||
|
|
||||||
public Text nameLabel;
|
public Text nameLabel;
|
||||||
public Button nameButton;
|
public Button nameButton;
|
||||||
@ -32,6 +34,7 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
{
|
{
|
||||||
this.tree = tree;
|
this.tree = tree;
|
||||||
this.uiRoot = cellUI;
|
this.uiRoot = cellUI;
|
||||||
|
m_rect = uiRoot.GetComponent<RectTransform>();
|
||||||
this.nameButton = nameButton;
|
this.nameButton = nameButton;
|
||||||
this.nameLabel = nameButton.GetComponentInChildren<Text>();
|
this.nameLabel = nameButton.GetComponentInChildren<Text>();
|
||||||
this.expandButton = expandButton;
|
this.expandButton = expandButton;
|
||||||
|
@ -76,6 +76,8 @@ namespace UnityExplorer.UI.Widgets
|
|||||||
Scroller.Initialize(this, prototype);
|
Scroller.Initialize(this, prototype);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DisableCell(ICell cell, int index) => cell.Disable();
|
||||||
|
|
||||||
public ICell CreateCell(RectTransform cellTransform)
|
public ICell CreateCell(RectTransform cellTransform)
|
||||||
{
|
{
|
||||||
var nameButton = cellTransform.Find("NameButton").GetComponent<Button>();
|
var nameButton = cellTransform.Find("NameButton").GetComponent<Button>();
|
||||||
|
@ -273,7 +273,7 @@
|
|||||||
<Compile Include="UI\Utility\SignatureHighlighter.cs" />
|
<Compile Include="UI\Utility\SignatureHighlighter.cs" />
|
||||||
<Compile Include="UI\Utility\ToStringUtility.cs" />
|
<Compile Include="UI\Utility\ToStringUtility.cs" />
|
||||||
<Compile Include="UI\Widgets\ScrollPool\DataHeightManager.cs" />
|
<Compile Include="UI\Widgets\ScrollPool\DataHeightManager.cs" />
|
||||||
<Compile Include="UI\Widgets\ScrollPool\DynamicCell.cs" />
|
<Compile Include="UI\Widgets\ScrollPool\CellViewHolder.cs" />
|
||||||
<Compile Include="UI\Widgets\ScrollPool\ICell.cs" />
|
<Compile Include="UI\Widgets\ScrollPool\ICell.cs" />
|
||||||
<Compile Include="UI\Widgets\ScrollPool\IPoolDataSource.cs" />
|
<Compile Include="UI\Widgets\ScrollPool\IPoolDataSource.cs" />
|
||||||
<Compile Include="UI\Widgets\ScrollPool\ScrollPool.cs" />
|
<Compile Include="UI\Widgets\ScrollPool\ScrollPool.cs" />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user