Fix logic in data height cache, account for spread properly

This commit is contained in:
Sinai 2021-04-24 04:02:26 +10:00
parent 59156492e7
commit 5f2f3fe1c6

View File

@ -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
{ {
@ -17,7 +18,7 @@ namespace UnityExplorer.UI.Widgets
public class DataHeightCache public class DataHeightCache
{ {
private ScrollPool ScrollPool { get; } private ScrollPool ScrollPool { get; }
private DataHeightCache sisterCache { get; } private DataHeightCache SisterCache { get; }
public DataHeightCache(ScrollPool scrollPool) public DataHeightCache(ScrollPool scrollPool)
{ {
@ -26,9 +27,10 @@ namespace UnityExplorer.UI.Widgets
public DataHeightCache(ScrollPool scrollPool, DataHeightCache sisterCache) : this(scrollPool) public DataHeightCache(ScrollPool scrollPool, DataHeightCache sisterCache) : this(scrollPool)
{ {
this.sisterCache = sisterCache; this.SisterCache = sisterCache;
TakeFromSister(scrollPool.DataSource.ItemCount); for (int i = 0; i < scrollPool.DataSource.ItemCount; i++)
Add(sisterCache[ScrollPool.DataSource.GetRealIndexOfTempIndex(i)]);
} }
private readonly List<DataViewInfo> heightCache = new List<DataViewInfo>(); private readonly List<DataViewInfo> heightCache = new List<DataViewInfo>();
@ -38,9 +40,10 @@ namespace UnityExplorer.UI.Widgets
public float TotalHeight => totalHeight; public float TotalHeight => totalHeight;
private float totalHeight; private float totalHeight;
public float DefaultHeight => ScrollPool.PrototypeCell.rect.height; public float DefaultHeight => m_defaultHeight ?? (float)(m_defaultHeight = ScrollPool.PrototypeCell.rect.height);
private float? m_defaultHeight;
private int GetNormalizedHeight(float height) => (int)Math.Floor((decimal)height / (decimal)DefaultHeight); private int GetRangeIndexOfPosition(float position) => (int)Math.Floor((decimal)position / (decimal)DefaultHeight);
// for efficient lookup of "which data index is at this position" // for efficient lookup of "which data index is at this position"
// list index: DefaultHeight * index from top of data // list index: DefaultHeight * index from top of data
@ -53,9 +56,19 @@ namespace UnityExplorer.UI.Widgets
set => SetIndex(index, value); set => SetIndex(index, value);
} }
private int GetSpread(float startPosition, float height)
{
float rem = startPosition % DefaultHeight;
if (!Mathf.Approximately(rem, 0f))
height -= (DefaultHeight - rem);
return (int)Math.Ceiling((decimal)height / (decimal)DefaultHeight);
}
public void Add(float value) public void Add(float value)
{ {
int spread = GetNormalizedHeight(value); int spread = GetSpread(totalHeight, value);
heightCache.Add(new DataViewInfo() heightCache.Add(new DataViewInfo()
{ {
@ -65,23 +78,12 @@ namespace UnityExplorer.UI.Widgets
}); });
int dataIdx = heightCache.Count - 1; int dataIdx = heightCache.Count - 1;
AppendDataSpread(dataIdx, spread); for (int i = 0; i < spread; i++)
rangeToDataIndexCache.Add(dataIdx);
totalHeight += value; totalHeight += value;
} }
public void AddRange(IEnumerable<DataViewInfo> collection)
{
foreach (var entry in collection)
Add(entry);
}
public void TakeFromSister(int count)
{
for (int i = 0; i < count; i++)
Add(sisterCache[ScrollPool.DataSource.GetRealIndexOfTempIndex(i)]);
}
public void RemoveLast() public void RemoveLast()
{ {
if (!heightCache.Any()) if (!heightCache.Any())
@ -92,16 +94,7 @@ namespace UnityExplorer.UI.Widgets
heightCache.RemoveAt(heightCache.Count - 1); heightCache.RemoveAt(heightCache.Count - 1);
} }
private void AppendDataSpread(int dataIdx, int spread) public void SetIndex(int dataIndex, float height, bool ignoreDataCount = false)
{
while (spread > 0)
{
rangeToDataIndexCache.Add(dataIdx);
spread--;
}
}
public void SetIndex(int dataIndex, float value, bool ignoreDataCount = false)
{ {
if (!ignoreDataCount) if (!ignoreDataCount)
{ {
@ -117,19 +110,19 @@ namespace UnityExplorer.UI.Widgets
{ {
while (dataIndex > heightCache.Count) while (dataIndex > heightCache.Count)
Add(DefaultHeight); Add(DefaultHeight);
Add(value); Add(height);
return; return;
} }
var cache = heightCache[dataIndex]; var cache = heightCache[dataIndex];
var prevHeight = cache.height; var prevHeight = cache.height;
var diff = value - prevHeight; var diff = height - prevHeight;
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);
totalHeight += diff; totalHeight += diff;
cache.height = value; cache.height = height;
} }
// update our start position using the previous cell (if it exists) // update our start position using the previous cell (if it exists)
@ -139,31 +132,35 @@ namespace UnityExplorer.UI.Widgets
cache.startPosition = prev.startPosition + prev.height; cache.startPosition = prev.startPosition + prev.height;
} }
int rangeIndex = GetNormalizedHeight(cache.startPosition); int rangeIndex = GetRangeIndexOfPosition(cache.startPosition);
var spread = GetNormalizedHeight(value); // var spread = GetRangeIndexOfPosition(value);
int spread = GetSpread(cache.startPosition, height);
// If we are setting an index outside of our cached range we need to naively fill the gap // setting range index beyond current count, need to append
if (rangeToDataIndexCache.Count <= rangeIndex) if (rangeToDataIndexCache.Count <= rangeIndex)
{ {
if (rangeToDataIndexCache.Any()) // if the gap is > 1, we need to fill that gap. This shouldn't really ever happen but just in case.
if (rangeToDataIndexCache.Count < rangeIndex)
{ {
int lastDataIdx = rangeToDataIndexCache[rangeToDataIndexCache.Count - 1]; int lastDataIdx = rangeToDataIndexCache[rangeToDataIndexCache.Count - 1];
while (rangeToDataIndexCache.Count <= rangeIndex) while (rangeToDataIndexCache.Count < rangeIndex)
{ {
rangeToDataIndexCache.Add(lastDataIdx);
heightCache[lastDataIdx].normalizedSpread++;
if (lastDataIdx < dataIndex - 1) if (lastDataIdx < dataIndex - 1)
lastDataIdx++; lastDataIdx++;
rangeToDataIndexCache.Add(lastDataIdx);
heightCache[lastDataIdx].normalizedSpread++;
} }
} }
AppendDataSpread(dataIndex, spread); // apend spread for this data
for (int i = 0; i < spread; i++)
rangeToDataIndexCache.Add(dataIndex);
cache.normalizedSpread = spread; cache.normalizedSpread = spread;
} }
else if (spread != cache.normalizedSpread) else if (spread != cache.normalizedSpread)
{ {
// The cell's height has changed by +/- DefaultCellHeight since we last set the range spread cache for it. // The cell's spread has changed, need to update.
// Need to add or remove accordingly.
int spreadDiff = spread - cache.normalizedSpread; int spreadDiff = spread - cache.normalizedSpread;
cache.normalizedSpread = spread; cache.normalizedSpread = spread;
@ -205,11 +202,11 @@ namespace UnityExplorer.UI.Widgets
} }
// if sister cache is set, then update it too. // if sister cache is set, then update it too.
if (sisterCache != null) if (SisterCache != null)
{ {
var realIdx = ScrollPool.DataSource.GetRealIndexOfTempIndex(dataIndex); var realIdx = ScrollPool.DataSource.GetRealIndexOfTempIndex(dataIndex);
if (realIdx >= 0) if (realIdx >= 0)
sisterCache.SetIndex(realIdx, value, true); SisterCache.SetIndex(realIdx, height, true);
} }
} }
@ -221,7 +218,7 @@ namespace UnityExplorer.UI.Widgets
public int GetDataIndexAtPosition(float desiredHeight, out DataViewInfo cache) public int GetDataIndexAtPosition(float desiredHeight, out DataViewInfo cache)
{ {
cache = null; cache = null;
int rangeIndex = GetNormalizedHeight(desiredHeight); int rangeIndex = GetRangeIndexOfPosition(desiredHeight);
if (rangeToDataIndexCache.Count <= rangeIndex || rangeIndex < 0) if (rangeToDataIndexCache.Count <= rangeIndex || rangeIndex < 0)
return -1; return -1;