feat: introduce batchly visit in tas sequence
This commit is contained in:
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@@ -108,14 +109,13 @@ namespace BallanceTasEditor.Backend {
|
|||||||
ArgumentOutOfRangeException.ThrowIfLessThan(m_StartIndex, 0);
|
ArgumentOutOfRangeException.ThrowIfLessThan(m_StartIndex, 0);
|
||||||
|
|
||||||
// Do backup and set values at the same time
|
// Do backup and set values at the same time
|
||||||
|
int backupIndex = 0;
|
||||||
var backups = new RawTasFrame[m_EndIndex - m_StartIndex + 1];
|
var backups = new RawTasFrame[m_EndIndex - m_StartIndex + 1];
|
||||||
// Pre-build key list for fast fetching.
|
// Pre-build key list for fast fetching.
|
||||||
var keys = Enumerable.Range(m_StartKey.ToIndex(), m_EndKey.ToIndex() - m_StartKey.ToIndex() + 1).Select((i) => TasKey.FromIndex(i)).ToArray();
|
var keys = Enumerable.Range(m_StartKey.ToIndex(), m_EndKey.ToIndex() - m_StartKey.ToIndex() + 1).Select((i) => TasKey.FromIndex(i)).ToArray();
|
||||||
for (int index = m_StartIndex; index <= m_EndIndex; index++) {
|
foreach (var frame in seq.BatchlyVisit(m_StartIndex, m_EndIndex)) {
|
||||||
// Fetch frame
|
|
||||||
var frame = seq.Visit(index);
|
|
||||||
// Do backup
|
// Do backup
|
||||||
frame.ToRawImplace(ref backups[index - m_StartIndex]);
|
frame.ToRawImplace(ref backups[backupIndex++]);
|
||||||
// Modify keys
|
// Modify keys
|
||||||
foreach (var key in keys) {
|
foreach (var key in keys) {
|
||||||
switch (m_Kind) {
|
switch (m_Kind) {
|
||||||
@@ -143,8 +143,9 @@ namespace BallanceTasEditor.Backend {
|
|||||||
|
|
||||||
// Index range is checked,
|
// Index range is checked,
|
||||||
// so we directly restore backup.
|
// so we directly restore backup.
|
||||||
for (int index = m_StartIndex; index <= m_EndIndex; index++) {
|
int backupIndex = 0;
|
||||||
seq.Visit(index).FromRawImplace(m_FramesBackup[index - m_StartIndex]);
|
foreach (var frame in seq.BatchlyVisit(m_StartIndex, m_EndIndex)) {
|
||||||
|
frame.FromRawImplace(m_FramesBackup[backupIndex++]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear backups
|
// Clear backups
|
||||||
@@ -197,12 +198,11 @@ namespace BallanceTasEditor.Backend {
|
|||||||
ArgumentOutOfRangeException.ThrowIfLessThan(m_StartIndex, 0);
|
ArgumentOutOfRangeException.ThrowIfLessThan(m_StartIndex, 0);
|
||||||
|
|
||||||
// Do backup and set values at the same time
|
// Do backup and set values at the same time
|
||||||
|
int backupIndex = 0;
|
||||||
var backups = new float[m_EndIndex - m_StartIndex + 1];
|
var backups = new float[m_EndIndex - m_StartIndex + 1];
|
||||||
for (int index = m_StartIndex; index <= m_EndIndex; index++) {
|
foreach (var frame in seq.BatchlyVisit(m_StartIndex, m_EndIndex)) {
|
||||||
// Fetch frame
|
|
||||||
var frame = seq.Visit(index);
|
|
||||||
// Do backup
|
// Do backup
|
||||||
backups[index - m_StartIndex] = frame.GetTimeDelta();
|
backups[backupIndex++] = frame.GetTimeDelta();
|
||||||
// Modify delta time
|
// Modify delta time
|
||||||
frame.SetTimeDelta(m_DeltaTime);
|
frame.SetTimeDelta(m_DeltaTime);
|
||||||
}
|
}
|
||||||
@@ -218,8 +218,9 @@ namespace BallanceTasEditor.Backend {
|
|||||||
|
|
||||||
// Index range is checked,
|
// Index range is checked,
|
||||||
// so we directly restore backup.
|
// so we directly restore backup.
|
||||||
for (int index = m_StartIndex; index <= m_EndIndex; index++) {
|
int backupIndex = 0;
|
||||||
seq.Visit(index).SetTimeDelta(m_DeltaTimesBackup[index - m_StartIndex]);
|
foreach (var frame in seq.BatchlyVisit(m_StartIndex, m_EndIndex)) {
|
||||||
|
frame.SetTimeDelta(m_DeltaTimesBackup[backupIndex++]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear backups
|
// Clear backups
|
||||||
@@ -259,9 +260,10 @@ namespace BallanceTasEditor.Backend {
|
|||||||
ArgumentOutOfRangeException.ThrowIfLessThan(m_StartIndex, 0);
|
ArgumentOutOfRangeException.ThrowIfLessThan(m_StartIndex, 0);
|
||||||
|
|
||||||
// Do backups
|
// Do backups
|
||||||
|
int backupIndex = 0;
|
||||||
var backups = new RawTasFrame[m_EndIndex - m_StartIndex + 1];
|
var backups = new RawTasFrame[m_EndIndex - m_StartIndex + 1];
|
||||||
for (int index = m_StartIndex; index <= m_EndIndex; index++) {
|
foreach (var frame in seq.BatchlyVisit(m_StartIndex, m_EndIndex)) {
|
||||||
seq.Visit(index).ToRawImplace(ref backups[index - m_StartIndex]);
|
frame.ToRawImplace(ref backups[backupIndex++]);
|
||||||
}
|
}
|
||||||
// Do remove
|
// Do remove
|
||||||
seq.Remove(m_StartIndex, m_EndIndex);
|
seq.Remove(m_StartIndex, m_EndIndex);
|
||||||
|
|||||||
@@ -30,6 +30,21 @@ namespace BallanceTasEditor.Backend {
|
|||||||
/// <exception cref="IndexOutOfRangeException">给定的索引无效。</exception>
|
/// <exception cref="IndexOutOfRangeException">给定的索引无效。</exception>
|
||||||
TasFrame Visit(int index);
|
TasFrame Visit(int index);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// 按顺序访问给定索引区间内的帧的值。
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// 实现此函数时需要格外注意以下事项:
|
||||||
|
/// <para/>
|
||||||
|
/// 该函数如果可以进行顺序访问优化,则应当优化。
|
||||||
|
/// 即使用此函数可以获得等于或大于单独一次使用<see cref="Visit(int)"/>函数。
|
||||||
|
/// <para/>
|
||||||
|
/// 该函数理论上的复杂度应为O(1)。
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="startIndex">要访问的帧区间的起始索引(包含)。</param>
|
||||||
|
/// <param name="endIndex">要访问的帧区间的终止索引(包含)</param>
|
||||||
|
/// <exception cref="IndexOutOfRangeException">给定的索引无效。</exception>
|
||||||
|
IExactSizeEnumerable<TasFrame> BatchlyVisit(int startIndex, int endIndex);
|
||||||
|
/// <summary>
|
||||||
/// 在给定的帧索引<b>之前</b>插入给定的项目。
|
/// 在给定的帧索引<b>之前</b>插入给定的项目。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
@@ -93,6 +108,10 @@ namespace BallanceTasEditor.Backend {
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IExactSizeEnumerable<TasFrame> BatchlyVisit(int startIndex, int endIndex) {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
public void Insert(int index, IExactSizeEnumerable<TasFrame> items) {
|
public void Insert(int index, IExactSizeEnumerable<TasFrame> items) {
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
@@ -120,6 +139,7 @@ namespace BallanceTasEditor.Backend {
|
|||||||
IEnumerator IEnumerable.GetEnumerator() {
|
IEnumerator IEnumerable.GetEnumerator() {
|
||||||
return GetEnumerator();
|
return GetEnumerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -143,6 +163,21 @@ namespace BallanceTasEditor.Backend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IEnumerable<TasFrame> BatchlyVisitEx(int startIndex, int endIndex) {
|
||||||
|
if (endIndex < startIndex || startIndex < 0 || endIndex >= m_Container.Count) {
|
||||||
|
throw new IndexOutOfRangeException("Invalid index for frame.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate items one by one.
|
||||||
|
for (int i = startIndex; i <= endIndex; ++i) {
|
||||||
|
yield return m_Container[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IExactSizeEnumerable<TasFrame> BatchlyVisit(int startIndex, int endIndex) {
|
||||||
|
return new ExactSizeEnumerableAdapter<TasFrame>(BatchlyVisitEx(startIndex, endIndex), endIndex - startIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
public void Insert(int index, IExactSizeEnumerable<TasFrame> items) {
|
public void Insert(int index, IExactSizeEnumerable<TasFrame> items) {
|
||||||
if (index == m_Container.Count) {
|
if (index == m_Container.Count) {
|
||||||
m_Container.AddRange(items);
|
m_Container.AddRange(items);
|
||||||
@@ -276,6 +311,29 @@ namespace BallanceTasEditor.Backend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IEnumerable<TasFrame> BatchlyVisitEx(int startIndex, int endIndex) {
|
||||||
|
if (endIndex < startIndex || startIndex < 0 || endIndex >= m_Container.Count) {
|
||||||
|
throw new IndexOutOfRangeException("Invalid index for frame.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// We move to start index first.
|
||||||
|
MoveToIndex(startIndex);
|
||||||
|
// Then we copy its reference
|
||||||
|
LinkedListNode<TasFrame>? node = m_Cursor.Node;
|
||||||
|
// Then compute count
|
||||||
|
var count = endIndex - startIndex + 1;
|
||||||
|
// Now we can iterate items one by one.
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
node = node.Unwrap();
|
||||||
|
yield return node.Unwrap().Value;
|
||||||
|
node = node.Next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IExactSizeEnumerable<TasFrame> BatchlyVisit(int startIndex, int endIndex) {
|
||||||
|
return new ExactSizeEnumerableAdapter<TasFrame>(BatchlyVisitEx(startIndex, endIndex), endIndex - startIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
public void Insert(int index, IExactSizeEnumerable<TasFrame> items) {
|
public void Insert(int index, IExactSizeEnumerable<TasFrame> items) {
|
||||||
// YYC MARK:
|
// YYC MARK:
|
||||||
// We must test the equal first, to handle back appending properly.
|
// We must test the equal first, to handle back appending properly.
|
||||||
|
|||||||
Reference in New Issue
Block a user