Finally got the scrollpool working properly with dynamic content height

This commit is contained in:
Sinai 2021-04-19 23:47:25 +10:00
parent 7a253fa0a0
commit 300b35c2d3
8 changed files with 149 additions and 160 deletions

View File

@ -53,19 +53,19 @@ namespace UnityExplorer.UI.Panels
//scrollPool.ReloadData(); //scrollPool.ReloadData();
} }
//scrollPool.Refresh(); scrollPool.RefreshCells(true);
} }
public override void SetDefaultPosAndAnchors() public override void SetDefaultPosAndAnchors()
{ {
mainPanelRect.localPosition = Vector2.zero; mainPanelRect.localPosition = Vector2.zero;
mainPanelRect.anchorMin = new Vector2(1, 0); mainPanelRect.pivot = new Vector2(0.5f, 0.5f);
mainPanelRect.anchorMax = new Vector2(1, 1); mainPanelRect.anchorMin = new Vector2(0.5f, 0);
mainPanelRect.sizeDelta = new Vector2(-300f, mainPanelRect.sizeDelta.y); mainPanelRect.anchorMax = new Vector2(0.5f, 1);
mainPanelRect.anchoredPosition = new Vector2(-200, 0);
mainPanelRect.offsetMin = new Vector2(mainPanelRect.offsetMin.x, 100); // bottom mainPanelRect.offsetMin = new Vector2(mainPanelRect.offsetMin.x, 100); // bottom
mainPanelRect.offsetMax = new Vector2(mainPanelRect.offsetMax.x, -50); // top mainPanelRect.offsetMax = new Vector2(mainPanelRect.offsetMax.x, -50); // top
mainPanelRect.pivot = new Vector2(0.5f, 0.5f); mainPanelRect.sizeDelta = new Vector2(700f, mainPanelRect.sizeDelta.y);
mainPanelRect.anchoredPosition = new Vector2(-150, 0);
} }
private ScrollPool scrollPool; private ScrollPool scrollPool;
@ -83,14 +83,14 @@ namespace UnityExplorer.UI.Panels
var test = new DynamicListTest(scrollPool, this); var test = new DynamicListTest(scrollPool, this);
test.Init(); test.Init();
var prototype = DynamicCellTest.CreatePrototypeCell(scrollContent); var prototype = DynamicCell.CreatePrototypeCell(scrollContent);
scrollPool.PrototypeCell = prototype.GetComponent<RectTransform>(); scrollPool.PrototypeCell = prototype.GetComponent<RectTransform>();
dummyContentHolder = new GameObject("DummyHolder"); dummyContentHolder = new GameObject("DummyHolder");
dummyContentHolder.SetActive(false); dummyContentHolder.SetActive(false);
GameObject.DontDestroyOnLoad(dummyContentHolder); GameObject.DontDestroyOnLoad(dummyContentHolder);
for (int i = 0; i < 10; i++) for (int i = 0; i < 100; i++)
{ {
dummyContents.Add(CreateDummyContent()); dummyContents.Add(CreateDummyContent());
} }
@ -104,15 +104,25 @@ namespace UnityExplorer.UI.Panels
private GameObject CreateDummyContent() private GameObject CreateDummyContent()
{ {
var obj = UIFactory.CreateVerticalGroup(dummyContentHolder, "Content", true, true, true, true, 2, new Vector4(2, 2, 2, 2)); var obj = UIFactory.CreateVerticalGroup(dummyContentHolder, "Content", true, true, true, true, 2, new Vector4(2, 2, 2, 2));
UIFactory.SetLayoutElement(obj, minHeight: 25, flexibleHeight: 9999); //UIFactory.SetLayoutElement(obj, minHeight: 25, flexibleHeight: 9999);
obj.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
var label = UIFactory.CreateLabel(obj, "label", "Dummy " + dummyContents.Count, TextAnchor.MiddleCenter); var label = UIFactory.CreateLabel(obj, "label", "Dummy " + dummyContents.Count, TextAnchor.MiddleCenter);
UIFactory.SetLayoutElement(label.gameObject, minHeight: 25, flexibleHeight: 0); UIFactory.SetLayoutElement(label.gameObject, minHeight: 25, flexibleHeight: 0);
var inputObj = UIFactory.CreateInputField(obj, "input", "...", out InputField inputField); //var input = UIFactory.CreateSrollInputField(obj, "input2", "...", out InputFieldScroller inputScroller);
inputField.lineType = InputField.LineType.MultiLineNewline; //UIFactory.SetLayoutElement(input, minHeight: 50, flexibleHeight: 9999);
//input.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
var inputObj = UIFactory.CreateInputField(obj, "input", "...", out var inputField);
UIFactory.SetLayoutElement(inputObj, minHeight: 25, flexibleHeight: 9999); UIFactory.SetLayoutElement(inputObj, minHeight: 25, flexibleHeight: 9999);
//inputObj.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize; 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";
return obj; return obj;
} }
@ -138,7 +148,7 @@ namespace UnityExplorer.UI.Panels
Scroller.Initialize(this); Scroller.Initialize(this);
} }
public ICell CreateCell(RectTransform cellTransform) => new DynamicCellTest(cellTransform.gameObject); public ICell CreateCell(RectTransform cellTransform) => new DynamicCell(cellTransform.gameObject);
public void SetCell(ICell icell, int index) public void SetCell(ICell icell, int index)
{ {
@ -148,58 +158,16 @@ namespace UnityExplorer.UI.Panels
return; return;
} }
var root = (icell as DynamicCellTest).uiRoot; var root = (icell as DynamicCell).uiRoot;
var content = Inspector.dummyContents[index];
if (content.transform.parent.ReferenceEqual(root.transform))
return;
if (root.transform.Find("Content") is Transform existing) if (root.transform.Find("Content") is Transform existing)
{
ExplorerCore.Log("removing existing content");
existing.transform.SetParent(Inspector.dummyContentHolder.transform, false); existing.transform.SetParent(Inspector.dummyContentHolder.transform, false);
}
var content = Inspector.dummyContents[index];
content.transform.SetParent(root.transform, false); content.transform.SetParent(root.transform, false);
} }
} }
public class DynamicCellTest : ICell
{
public DynamicCellTest(GameObject uiRoot)
{
this.uiRoot = uiRoot;
}
public bool Enabled => m_enabled;
private bool m_enabled;
public GameObject uiRoot;
public InputField input;
public void Disable()
{
m_enabled = false;
uiRoot.SetActive(false);
}
public void Enable()
{
m_enabled = true;
uiRoot.SetActive(true);
}
public static GameObject CreatePrototypeCell(GameObject parent)
{
var prototype = UIFactory.CreateVerticalGroup(parent, "PrototypeCell", true, true, true, true, 2, default,
new Color(0.15f, 0.15f, 0.15f), TextAnchor.MiddleCenter);
var rect = prototype.GetComponent<RectTransform>();
rect.anchorMin = new Vector2(0, 1);
rect.anchorMax = new Vector2(0, 1);
rect.pivot = new Vector2(0.5f, 1);
rect.sizeDelta = new Vector2(25, 25);
UIFactory.SetLayoutElement(prototype, minWidth: 100, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 9999);
prototype.SetActive(false);
return prototype;
}
}
} }

View File

@ -461,7 +461,7 @@ namespace UnityExplorer.UI
var mainObj = CreateScrollView(parent, "InputFieldScrollView", out GameObject scrollContent, out SliderScrollbar scroller, color); var mainObj = CreateScrollView(parent, "InputFieldScrollView", out GameObject scrollContent, out SliderScrollbar scroller, color);
var inputObj = CreateInputField(scrollContent, name, placeHolderText ?? "...", out InputField inputField, fontSize, 0); CreateInputField(scrollContent, name, placeHolderText ?? "...", out InputField inputField, fontSize, 0);
inputField.lineType = InputField.LineType.MultiLineNewline; inputField.lineType = InputField.LineType.MultiLineNewline;
inputField.targetGraphic.color = color; inputField.targetGraphic.color = color;
@ -471,6 +471,31 @@ namespace UnityExplorer.UI
return mainObj; return mainObj;
} }
// Little helper class to force rebuild of an input field's layout on value change.
// This is limited to once per frame per input field, so its not too expensive.
private class InputFieldRefresher
{
private float timeOfLastRebuild;
private readonly RectTransform rectTransform;
public InputFieldRefresher(InputField inputField)
{
if (!inputField)
return;
rectTransform = inputField.GetComponent<RectTransform>();
inputField.onValueChanged.AddListener((string val) =>
{
if (Time.time > timeOfLastRebuild)
{
timeOfLastRebuild = Time.time;
LayoutRebuilder.ForceRebuildLayoutImmediate(rectTransform);
}
});
}
}
/// <summary> /// <summary>
/// Create a standard InputField control. /// Create a standard InputField control.
/// </summary> /// </summary>
@ -546,6 +571,8 @@ namespace UnityExplorer.UI
inputField.textComponent = inputText; inputField.textComponent = inputText;
new InputFieldRefresher(inputField);
return mainObj; return mainObj;
} }
@ -715,14 +742,17 @@ namespace UnityExplorer.UI
var contentRect = content.GetComponent<RectTransform>(); var contentRect = content.GetComponent<RectTransform>();
contentRect.anchorMin = Vector2.zero; contentRect.anchorMin = Vector2.zero;
contentRect.anchorMax = Vector2.one; contentRect.anchorMax = Vector2.one;
contentRect.pivot = new Vector2(0.0f, 1.0f); contentRect.pivot = new Vector2(0.5f, 1f);
contentRect.sizeDelta = new Vector2(0f, 0f); contentRect.sizeDelta = new Vector2(0f, 0f);
contentRect.offsetMax = new Vector2(0f, 0f); contentRect.offsetMax = new Vector2(0f, 0f);
SetLayoutGroup<VerticalLayoutGroup>(content, true, false, true, true, 0, 2, 2, 2, 2, TextAnchor.UpperCenter);
content.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
var scrollRect = mainObj.AddComponent<ScrollRect>(); var scrollRect = mainObj.AddComponent<ScrollRect>();
scrollRect.movementType = ScrollRect.MovementType.Clamped; scrollRect.movementType = ScrollRect.MovementType.Clamped;
scrollRect.inertia = false; scrollRect.inertia = false;
//scrollRect.decelerationRate = 0.135f;
scrollRect.scrollSensitivity = 15; scrollRect.scrollSensitivity = 15;
scrollRect.horizontal = false; scrollRect.horizontal = false;
scrollRect.vertical = true; scrollRect.vertical = true;
@ -730,6 +760,8 @@ namespace UnityExplorer.UI
scrollRect.viewport = viewportRect; scrollRect.viewport = viewportRect;
scrollRect.content = contentRect; scrollRect.content = contentRect;
// Slider
var sliderContainer = CreateVerticalGroup(mainObj, "SliderContainer", var sliderContainer = CreateVerticalGroup(mainObj, "SliderContainer",
false, false, true, true, 0, default, new Color(0.05f, 0.05f, 0.05f)); false, false, true, true, 0, default, new Color(0.05f, 0.05f, 0.05f));
SetLayoutElement(sliderContainer, minWidth: 25, flexibleWidth:0, flexibleHeight: 9999); SetLayoutElement(sliderContainer, minWidth: 25, flexibleWidth:0, flexibleHeight: 9999);
@ -753,6 +785,8 @@ namespace UnityExplorer.UI
container.pivot = new Vector3(0.5f, 0.5f); container.pivot = new Vector3(0.5f, 0.5f);
} }
// finalize and create ScrollPool
uiRoot = mainObj; uiRoot = mainObj;
var scrollPool = new ScrollPool(scrollRect) var scrollPool = new ScrollPool(scrollRect)
@ -760,14 +794,8 @@ namespace UnityExplorer.UI
AutoResizeHandleRect = autoResizeSliderHandle AutoResizeHandleRect = autoResizeSliderHandle
}; };
SetLayoutGroup<VerticalLayoutGroup>(content, true, false, true, false, 0, 2, 2, 2, 2,
TextAnchor.UpperCenter);
//viewportObj.GetComponent<Mask>().enabled = false; //viewportObj.GetComponent<Mask>().enabled = false;
var rect = content.GetComponent<RectTransform>();
rect.pivot = new Vector2(0.5f, 1f);
return scrollPool; return scrollPool;
} }

View File

@ -14,13 +14,13 @@ namespace UnityExplorer.UI.Widgets
public Action<ButtonCell<T>> OnClick; public Action<ButtonCell<T>> OnClick;
public ButtonListCell<T> list; public ButtonListSource<T> list;
public GameObject uiRoot; public GameObject uiRoot;
public Text buttonText; public Text buttonText;
public Button button; public Button button;
public ButtonCell(ButtonListCell<T> list, GameObject uiRoot, Button button, Text text) public ButtonCell(ButtonListSource<T> list, GameObject uiRoot, Button button, Text text)
{ {
this.list = list; this.list = list;
this.uiRoot = uiRoot; this.uiRoot = uiRoot;

View File

@ -9,7 +9,7 @@ using UnityExplorer.UI.Widgets;
namespace UnityExplorer.UI.Widgets namespace UnityExplorer.UI.Widgets
{ {
public class ButtonListCell<T> : IPoolDataSource public class ButtonListSource<T> : IPoolDataSource
{ {
internal ScrollPool Scroller; internal ScrollPool Scroller;
@ -28,7 +28,7 @@ namespace UnityExplorer.UI.Widgets
} }
private string currentFilter; private string currentFilter;
public ButtonListCell(ScrollPool infiniteScroller, Func<List<T>> getEntriesMethod, public ButtonListSource(ScrollPool infiniteScroller, Func<List<T>> getEntriesMethod,
Action<ButtonCell<T>, int> setICellMethod, Func<T, string, bool> shouldDisplayMethod, Action<ButtonCell<T>, int> setICellMethod, Func<T, string, bool> shouldDisplayMethod,
Action<ButtonCell<T>> onCellClickedMethod) Action<ButtonCell<T>> onCellClickedMethod)
{ {

View File

@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
namespace UnityExplorer.UI.Widgets
{
public class DynamicCell : ICell
{
public DynamicCell(GameObject uiRoot)
{
this.uiRoot = uiRoot;
}
public bool Enabled => m_enabled;
private bool m_enabled;
public GameObject uiRoot;
public InputField input;
public void Disable()
{
m_enabled = false;
uiRoot.SetActive(false);
}
public void Enable()
{
m_enabled = true;
uiRoot.SetActive(true);
}
public static GameObject CreatePrototypeCell(GameObject parent)
{
var prototype = UIFactory.CreateVerticalGroup(parent, "PrototypeCell", true, true, true, true, 0, new Vector4(1,1,1,1),
new Color(0.15f, 0.15f, 0.15f), TextAnchor.MiddleCenter);
var rect = prototype.GetComponent<RectTransform>();
rect.anchorMin = new Vector2(0, 1);
rect.anchorMax = new Vector2(0, 1);
rect.pivot = new Vector2(0.5f, 1);
rect.sizeDelta = new Vector2(25, 25);
//UIFactory.SetLayoutElement(prototype, minWidth: 100, flexibleWidth: 9999, minHeight: 25, flexibleHeight: 9999);
prototype.AddComponent<ContentSizeFitter>().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
prototype.SetActive(false);
return prototype;
}
}
}

View File

@ -47,7 +47,7 @@ namespace UnityExplorer.UI.Widgets
if (index >= heightCache.Count) if (index >= heightCache.Count)
{ {
while (index > heightCache.Count) while (index > heightCache.Count)
heightCache.Add(defaultCellHeight); Add(defaultCellHeight);
Add(value); Add(value);
return; return;
} }
@ -138,7 +138,7 @@ namespace UnityExplorer.UI.Widgets
if (TotalCellHeight.Equals(value)) if (TotalCellHeight.Equals(value))
return; return;
m_totalCellHeight = value; m_totalCellHeight = value;
SetContentHeight(); //SetContentHeight();
} }
} }
private float m_totalCellHeight; private float m_totalCellHeight;
@ -153,28 +153,27 @@ namespace UnityExplorer.UI.Widgets
private Vector2 _prevAnchoredPos; private Vector2 _prevAnchoredPos;
private Vector2 _prevViewportSize; // TODO track viewport height and rebuild on change private Vector2 _prevViewportSize; // TODO track viewport height and rebuild on change
#region internal set tracking and update #region Internal set tracking and update
//private bool _recycling; // A sanity check so only one thing is setting the value per frame.
public bool WritingLocked
public bool ExternallySetting
{ {
get => externallySetting; get => writingLocked;
internal set internal set
{ {
if (externallySetting == value) if (writingLocked == value)
return; return;
timeOfLastExternalSet = Time.time; timeofLastWriteLock = Time.time;
externallySetting = value; writingLocked = value;
} }
} }
private bool externallySetting; private bool writingLocked;
private float timeOfLastExternalSet; private float timeofLastWriteLock;
public override void Update() public override void Update()
{ {
if (externallySetting && timeOfLastExternalSet < Time.time) if (writingLocked && timeofLastWriteLock < Time.time)
externallySetting = false; writingLocked = false;
} }
#endregion #endregion
@ -214,7 +213,7 @@ namespace UnityExplorer.UI.Widgets
BuildInitialHeightCache(); BuildInitialHeightCache();
CreateCellPool(); CreateCellPool();
SetContentHeight(); //SetContentHeight();
UpdateSliderPositionAndSize(); UpdateSliderPositionAndSize();
@ -241,14 +240,6 @@ namespace UnityExplorer.UI.Widgets
RecycleViewBounds = new Vector2(Viewport.MinY() + extra, Viewport.MaxY() - extra); RecycleViewBounds = new Vector2(Viewport.MinY() + extra, Viewport.MaxY() - extra);
} }
private void SetContentHeight()
{
var viewRect = scrollRect.viewport;
scrollRect.content.sizeDelta = new Vector2(
scrollRect.content.sizeDelta.x,
AdjustedTotalCellHeight - viewRect.rect.height);
}
// Refresh methods // Refresh methods
private struct CellInfo { public int cellIndex, dataIndex; } private struct CellInfo { public int cellIndex, dataIndex; }
@ -275,8 +266,6 @@ namespace UnityExplorer.UI.Widgets
} }
} }
// TODO this is not quite right, it can move the content, it shouldnt move it
public void RefreshCells(bool andReloadFromDataSource = false) public void RefreshCells(bool andReloadFromDataSource = false)
{ {
if (!CellPool.Any()) return; if (!CellPool.Any()) return;
@ -310,7 +299,6 @@ namespace UnityExplorer.UI.Widgets
} }
SetRecycleViewBounds(); SetRecycleViewBounds();
SetContentHeight();
if (andReloadFromDataSource) if (andReloadFromDataSource)
{ {
@ -318,7 +306,6 @@ namespace UnityExplorer.UI.Widgets
RecycleTopToBottom(); RecycleTopToBottom();
} }
SetContentHeight();
UpdateSliderPositionAndSize(); UpdateSliderPositionAndSize();
if (jumpToBottom) if (jumpToBottom)
@ -335,49 +322,14 @@ namespace UnityExplorer.UI.Widgets
LayoutRebuilder.ForceRebuildLayoutImmediate(Content); LayoutRebuilder.ForceRebuildLayoutImmediate(Content);
// ExplorerCore.Log("Set cell, real height is " + cachedCell.Rect.rect.height + ", pref height is " + cachedCell.Rect.GetComponent<LayoutElement>().preferredHeight);
cachedCell.Height = cachedCell.Cell.Enabled ? cachedCell.Rect.rect.height : 0f; cachedCell.Height = cachedCell.Cell.Enabled ? cachedCell.Rect.rect.height : 0f;
DataHeightCache[dataIndex] = cachedCell.Height; DataHeightCache[dataIndex] = cachedCell.Height;
//ExplorerCore.Log("set to cache as " + cachedCell.Height);
} }
//private void UpdateDisplayedHeightCache()
//{
// if (!CellPool.Any()) return;
// var enumerator = GetPoolEnumerator();
// while (enumerator.MoveNext())
// {
// var curr = enumerator.Current;
// var cell = CellPool[curr.cellIndex];
// cell.Height = cell.Rect.rect.height;
// DataHeightCache[curr.dataIndex] = cell.Height;
// }
// //int cellIdx = topPoolCellIndex;
// //int dataIndex = topDataIndex;
// //int iterated = 0;
// //while (iterated < CellPool.Count)
// //{
// // var cell = CellPool[cellIdx];
// // cellIdx++;
// // if (cellIdx >= CellPool.Count)
// // cellIdx = 0;
// //
// // cell.Height = cell.Rect.rect.height;
// // DataHeightCache[dataIndex] = cell.Height;
// //
// // dataIndex++;
// // iterated++;
// //}
//}
// Cell pool // Cell pool
private void CreateCellPool() private void CreateCellPool()
{ {
//Reseting Pool
if (CellPool.Any()) if (CellPool.Any())
{ {
foreach (var cell in CellPool) foreach (var cell in CellPool)
@ -386,10 +338,7 @@ namespace UnityExplorer.UI.Widgets
} }
if (!PrototypeCell) if (!PrototypeCell)
{ throw new Exception("No prototype cell set, cannot initialize");
ExplorerCore.Log("no prototype cell, cannot initialize");
return;
}
//Set the prototype cell active and set cell anchor as top //Set the prototype cell active and set cell anchor as top
PrototypeCell.gameObject.SetActive(true); PrototypeCell.gameObject.SetActive(true);
@ -398,7 +347,6 @@ namespace UnityExplorer.UI.Widgets
float requiredCoverage = scrollRect.viewport.rect.height * ExtraPoolCoverageRatio; float requiredCoverage = scrollRect.viewport.rect.height * ExtraPoolCoverageRatio;
topPoolCellIndex = 0; topPoolCellIndex = 0;
//topDataIndex = 0;
bottomPoolIndex = -1; bottomPoolIndex = -1;
// create cells until the Pool area is covered. // create cells until the Pool area is covered.
@ -414,13 +362,14 @@ namespace UnityExplorer.UI.Widgets
CellPool.Add(new CachedCell(this, rect, cell)); CellPool.Add(new CachedCell(this, rect, cell));
rect.SetParent(scrollRect.content, false); rect.SetParent(scrollRect.content, false);
cell.Disable();
currentPoolCoverage += rect.rect.height + this.contentLayout.spacing; currentPoolCoverage += rect.rect.height + this.contentLayout.spacing;
} }
bottomDataIndex = bottomPoolIndex; bottomDataIndex = bottomPoolIndex;
// after creating pool, set displayed cells. // after creating pool, set displayed cells.
//posY = 0f;
for (int i = 0; i < CellPool.Count; i++) for (int i = 0; i < CellPool.Count; i++)
{ {
var cell = CellPool[i]; var cell = CellPool[i];
@ -436,7 +385,7 @@ namespace UnityExplorer.UI.Widgets
private void OnValueChangedListener(Vector2 val) private void OnValueChangedListener(Vector2 val)
{ {
if (ExternallySetting) if (WritingLocked)
return; return;
SetRecycleViewBounds(); SetRecycleViewBounds();
@ -468,23 +417,20 @@ namespace UnityExplorer.UI.Widgets
} }
private bool ShouldRecycleTop => GetCellExtent(CellPool[topPoolCellIndex]) >= RecycleViewBounds.x private bool ShouldRecycleTop => GetCellExtent(CellPool[topPoolCellIndex]) >= RecycleViewBounds.x
//&& CellPool[topMostCellIndex].Rect.position.y >= Viewport.MinY()
&& CellPool[bottomPoolIndex].Rect.position.y > RecycleViewBounds.y; && CellPool[bottomPoolIndex].Rect.position.y > RecycleViewBounds.y;
private bool ShouldRecycleBottom => GetCellExtent(CellPool[bottomPoolIndex]) < RecycleViewBounds.y private bool ShouldRecycleBottom => GetCellExtent(CellPool[bottomPoolIndex]) < RecycleViewBounds.y
//&& CellPool[bottomMostCellIndex].Rect.position.y < Viewport.MaxY()
&& CellPool[topPoolCellIndex].Rect.position.y < RecycleViewBounds.x; && CellPool[topPoolCellIndex].Rect.position.y < RecycleViewBounds.x;
private float GetCellExtent(CachedCell cell) => cell.Rect.MaxY() - contentLayout.spacing; private float GetCellExtent(CachedCell cell) => cell.Rect.MaxY() - contentLayout.spacing;
private float RecycleTopToBottom() private float RecycleTopToBottom()
{ {
ExternallySetting = true; WritingLocked = true;
float recycledheight = 0f; float recycledheight = 0f;
while (ShouldRecycleTop && CurrentDataCount < DataSource.ItemCount) while (ShouldRecycleTop && CurrentDataCount < DataSource.ItemCount)
//while (GetCellExtent(CellPool[topMostCellIndex]) > Viewport.MinY() && CurrentDataCount < DataSource.ItemCount)
{ {
var cell = CellPool[topPoolCellIndex]; var cell = CellPool[topPoolCellIndex];
@ -500,7 +446,6 @@ namespace UnityExplorer.UI.Widgets
SetCell(cell, CurrentDataCount); SetCell(cell, CurrentDataCount);
//set new indices //set new indices
//topDataIndex++;
bottomDataIndex++; bottomDataIndex++;
bottomPoolIndex = topPoolCellIndex; bottomPoolIndex = topPoolCellIndex;
@ -512,12 +457,10 @@ namespace UnityExplorer.UI.Widgets
private float RecycleBottomToTop() private float RecycleBottomToTop()
{ {
ExternallySetting = true; WritingLocked = true;
float recycledheight = 0f; float recycledheight = 0f;
// works, except when moving+resizing a cell at the top, that seems to cause issues, need to fix that.
while (ShouldRecycleBottom && CurrentDataCount > CellPool.Count) while (ShouldRecycleBottom && CurrentDataCount > CellPool.Count)
{ {
var cell = CellPool[bottomPoolIndex]; var cell = CellPool[bottomPoolIndex];
@ -531,7 +474,6 @@ namespace UnityExplorer.UI.Widgets
recycledheight += prevHeight + contentLayout.spacing; recycledheight += prevHeight + contentLayout.spacing;
//set new index //set new index
//topDataIndex--;
bottomDataIndex--; bottomDataIndex--;
//set Cell //set Cell
@ -542,7 +484,6 @@ namespace UnityExplorer.UI.Widgets
var diff = newHeight - prevHeight; var diff = newHeight - prevHeight;
if (diff != 0.0f) if (diff != 0.0f)
{ {
SetContentHeight();
Content.anchoredPosition += Vector2.up * diff; Content.anchoredPosition += Vector2.up * diff;
recycledheight += diff; recycledheight += diff;
} }
@ -601,9 +542,9 @@ namespace UnityExplorer.UI.Widgets
private void OnSliderValueChanged(float val) private void OnSliderValueChanged(float val)
{ {
if (this.ExternallySetting) if (this.WritingLocked)
return; return;
this.ExternallySetting = true; this.WritingLocked = true;
// TODO this cant work until we have a cache of all data heights. // TODO this cant work until we have a cache of all data heights.
// will need to maintain that as we go and assume default height for indeterminate cells. // will need to maintain that as we go and assume default height for indeterminate cells.

View File

@ -272,14 +272,15 @@
<Compile Include="UI\Utility\PanelDragger.cs" /> <Compile Include="UI\Utility\PanelDragger.cs" />
<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\DynamicCell.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\ScrollPoolBak.cs" /> <Compile Include="UI\Widgets\ScrollPool\ScrollPool_bak.cs" />
<Compile Include="UI\Widgets\ScrollPool\ScrollPool.cs" /> <Compile Include="UI\Widgets\ScrollPool\ScrollPool.cs" />
<Compile Include="UI\Widgets\ScrollPool\UIExtensions.cs" /> <Compile Include="UI\Widgets\ScrollPool\UIExtensions.cs" />
<Compile Include="UI\Widgets\InputFieldScroller.cs" /> <Compile Include="UI\Widgets\InputFieldScroller.cs" />
<Compile Include="UI\Widgets\ButtonList\ButtonCell.cs" /> <Compile Include="UI\Widgets\ButtonList\ButtonCell.cs" />
<Compile Include="UI\Widgets\ButtonList\ButtonListCell.cs" /> <Compile Include="UI\Widgets\ButtonList\ButtonListSource.cs" />
<Compile Include="UI\Widgets\SliderScrollbar.cs" /> <Compile Include="UI\Widgets\SliderScrollbar.cs" />
<Compile Include="UI\Widgets\TransformTree\CachedTransform.cs" /> <Compile Include="UI\Widgets\TransformTree\CachedTransform.cs" />
<Compile Include="UI\Widgets\TransformTree\TransformCell.cs" /> <Compile Include="UI\Widgets\TransformTree\TransformCell.cs" />
@ -290,9 +291,7 @@
<None Include="ILRepack.targets" /> <None Include="ILRepack.targets" />
<None Include="packages.config" /> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup />
<Folder Include="UI\Widgets\ScrollPool\Dynamic\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="packages\ILRepack.Lib.MSBuild.Task.2.0.18.1\build\ILRepack.Lib.MSBuild.Task.targets" Condition="Exists('packages\ILRepack.Lib.MSBuild.Task.2.0.18.1\build\ILRepack.Lib.MSBuild.Task.targets')" /> <Import Project="packages\ILRepack.Lib.MSBuild.Task.2.0.18.1\build\ILRepack.Lib.MSBuild.Task.targets" Condition="Exists('packages\ILRepack.Lib.MSBuild.Task.2.0.18.1\build\ILRepack.Lib.MSBuild.Task.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">