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.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -108,14 +109,13 @@ namespace BallanceTasEditor.Backend {
|
||||
ArgumentOutOfRangeException.ThrowIfLessThan(m_StartIndex, 0);
|
||||
|
||||
// Do backup and set values at the same time
|
||||
int backupIndex = 0;
|
||||
var backups = new RawTasFrame[m_EndIndex - m_StartIndex + 1];
|
||||
// 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();
|
||||
for (int index = m_StartIndex; index <= m_EndIndex; index++) {
|
||||
// Fetch frame
|
||||
var frame = seq.Visit(index);
|
||||
foreach (var frame in seq.BatchlyVisit(m_StartIndex, m_EndIndex)) {
|
||||
// Do backup
|
||||
frame.ToRawImplace(ref backups[index - m_StartIndex]);
|
||||
frame.ToRawImplace(ref backups[backupIndex++]);
|
||||
// Modify keys
|
||||
foreach (var key in keys) {
|
||||
switch (m_Kind) {
|
||||
@@ -143,8 +143,9 @@ namespace BallanceTasEditor.Backend {
|
||||
|
||||
// Index range is checked,
|
||||
// so we directly restore backup.
|
||||
for (int index = m_StartIndex; index <= m_EndIndex; index++) {
|
||||
seq.Visit(index).FromRawImplace(m_FramesBackup[index - m_StartIndex]);
|
||||
int backupIndex = 0;
|
||||
foreach (var frame in seq.BatchlyVisit(m_StartIndex, m_EndIndex)) {
|
||||
frame.FromRawImplace(m_FramesBackup[backupIndex++]);
|
||||
}
|
||||
|
||||
// Clear backups
|
||||
@@ -197,12 +198,11 @@ namespace BallanceTasEditor.Backend {
|
||||
ArgumentOutOfRangeException.ThrowIfLessThan(m_StartIndex, 0);
|
||||
|
||||
// Do backup and set values at the same time
|
||||
int backupIndex = 0;
|
||||
var backups = new float[m_EndIndex - m_StartIndex + 1];
|
||||
for (int index = m_StartIndex; index <= m_EndIndex; index++) {
|
||||
// Fetch frame
|
||||
var frame = seq.Visit(index);
|
||||
foreach (var frame in seq.BatchlyVisit(m_StartIndex, m_EndIndex)) {
|
||||
// Do backup
|
||||
backups[index - m_StartIndex] = frame.GetTimeDelta();
|
||||
backups[backupIndex++] = frame.GetTimeDelta();
|
||||
// Modify delta time
|
||||
frame.SetTimeDelta(m_DeltaTime);
|
||||
}
|
||||
@@ -218,8 +218,9 @@ namespace BallanceTasEditor.Backend {
|
||||
|
||||
// Index range is checked,
|
||||
// so we directly restore backup.
|
||||
for (int index = m_StartIndex; index <= m_EndIndex; index++) {
|
||||
seq.Visit(index).SetTimeDelta(m_DeltaTimesBackup[index - m_StartIndex]);
|
||||
int backupIndex = 0;
|
||||
foreach (var frame in seq.BatchlyVisit(m_StartIndex, m_EndIndex)) {
|
||||
frame.SetTimeDelta(m_DeltaTimesBackup[backupIndex++]);
|
||||
}
|
||||
|
||||
// Clear backups
|
||||
@@ -259,9 +260,10 @@ namespace BallanceTasEditor.Backend {
|
||||
ArgumentOutOfRangeException.ThrowIfLessThan(m_StartIndex, 0);
|
||||
|
||||
// Do backups
|
||||
int backupIndex = 0;
|
||||
var backups = new RawTasFrame[m_EndIndex - m_StartIndex + 1];
|
||||
for (int index = m_StartIndex; index <= m_EndIndex; index++) {
|
||||
seq.Visit(index).ToRawImplace(ref backups[index - m_StartIndex]);
|
||||
foreach (var frame in seq.BatchlyVisit(m_StartIndex, m_EndIndex)) {
|
||||
frame.ToRawImplace(ref backups[backupIndex++]);
|
||||
}
|
||||
// Do remove
|
||||
seq.Remove(m_StartIndex, m_EndIndex);
|
||||
|
||||
@@ -30,6 +30,21 @@ namespace BallanceTasEditor.Backend {
|
||||
/// <exception cref="IndexOutOfRangeException">给定的索引无效。</exception>
|
||||
TasFrame Visit(int index);
|
||||
/// <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>插入给定的项目。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
@@ -93,6 +108,10 @@ namespace BallanceTasEditor.Backend {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IExactSizeEnumerable<TasFrame> BatchlyVisit(int startIndex, int endIndex) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Insert(int index, IExactSizeEnumerable<TasFrame> items) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
@@ -120,6 +139,7 @@ namespace BallanceTasEditor.Backend {
|
||||
IEnumerator IEnumerable.GetEnumerator() {
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <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) {
|
||||
if (index == m_Container.Count) {
|
||||
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) {
|
||||
// YYC MARK:
|
||||
// We must test the equal first, to handle back appending properly.
|
||||
|
||||
Reference in New Issue
Block a user