diff --git a/BallanceTasEditor/BallanceTasEditor/Backend/TasOperation.cs b/BallanceTasEditor/BallanceTasEditor/Backend/TasOperation.cs
index 535400e..ced2fdb 100644
--- a/BallanceTasEditor/BallanceTasEditor/Backend/TasOperation.cs
+++ b/BallanceTasEditor/BallanceTasEditor/Backend/TasOperation.cs
@@ -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);
diff --git a/BallanceTasEditor/BallanceTasEditor/Backend/TasSequence.cs b/BallanceTasEditor/BallanceTasEditor/Backend/TasSequence.cs
index 6ed4971..101bcb3 100644
--- a/BallanceTasEditor/BallanceTasEditor/Backend/TasSequence.cs
+++ b/BallanceTasEditor/BallanceTasEditor/Backend/TasSequence.cs
@@ -30,6 +30,21 @@ namespace BallanceTasEditor.Backend {
/// 给定的索引无效。
TasFrame Visit(int index);
///
+ /// 按顺序访问给定索引区间内的帧的值。
+ ///
+ ///
+ /// 实现此函数时需要格外注意以下事项:
+ ///
+ /// 该函数如果可以进行顺序访问优化,则应当优化。
+ /// 即使用此函数可以获得等于或大于单独一次使用函数。
+ ///
+ /// 该函数理论上的复杂度应为O(1)。
+ ///
+ /// 要访问的帧区间的起始索引(包含)。
+ /// 要访问的帧区间的终止索引(包含)
+ /// 给定的索引无效。
+ IExactSizeEnumerable BatchlyVisit(int startIndex, int endIndex);
+ ///
/// 在给定的帧索引之前插入给定的项目。
///
///
@@ -93,6 +108,10 @@ namespace BallanceTasEditor.Backend {
throw new NotImplementedException();
}
+ public IExactSizeEnumerable BatchlyVisit(int startIndex, int endIndex) {
+ throw new NotImplementedException();
+ }
+
public void Insert(int index, IExactSizeEnumerable items) {
throw new NotImplementedException();
}
@@ -120,6 +139,7 @@ namespace BallanceTasEditor.Backend {
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
+
}
///
@@ -143,6 +163,21 @@ namespace BallanceTasEditor.Backend {
}
}
+ private IEnumerable 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 BatchlyVisit(int startIndex, int endIndex) {
+ return new ExactSizeEnumerableAdapter(BatchlyVisitEx(startIndex, endIndex), endIndex - startIndex + 1);
+ }
+
public void Insert(int index, IExactSizeEnumerable items) {
if (index == m_Container.Count) {
m_Container.AddRange(items);
@@ -276,6 +311,29 @@ namespace BallanceTasEditor.Backend {
}
}
+ private IEnumerable 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? 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 BatchlyVisit(int startIndex, int endIndex) {
+ return new ExactSizeEnumerableAdapter(BatchlyVisitEx(startIndex, endIndex), endIndex - startIndex + 1);
+ }
+
public void Insert(int index, IExactSizeEnumerable items) {
// YYC MARK:
// We must test the equal first, to handle back appending properly.