feat: write some tas oper
This commit is contained in:
@@ -50,7 +50,7 @@ namespace BallanceTasEditor.Backend {
|
||||
private RawTasFrame[] m_RawFrames;
|
||||
|
||||
public IEnumerator<TasFrame> GetEnumerator() {
|
||||
return m_RawFrames.Select((f) => new TasFrame(f)).GetEnumerator();
|
||||
return m_RawFrames.Select((f) => TasFrame.FromRaw(f)).GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() {
|
||||
|
||||
@@ -23,32 +23,114 @@ namespace BallanceTasEditor.Backend {
|
||||
public uint KeyFlags;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 描述TAS文件中的可能的按键。
|
||||
/// </summary>
|
||||
public struct TasKey : IEquatable<TasKey> {
|
||||
private TasKey(int bitPos) {
|
||||
m_BitPos = bitPos;
|
||||
}
|
||||
|
||||
private int m_BitPos;
|
||||
|
||||
public static readonly TasKey KEY_UP = new TasKey(0);
|
||||
public static readonly TasKey KEY_DOWN = new TasKey(1);
|
||||
public static readonly TasKey KEY_LEFT = new TasKey(2);
|
||||
public static readonly TasKey KEY_RIGHT = new TasKey(3);
|
||||
public static readonly TasKey KEY_SHIFT = new TasKey(4);
|
||||
public static readonly TasKey KEY_SPACE = new TasKey(5);
|
||||
public static readonly TasKey KEY_Q = new TasKey(6);
|
||||
public static readonly TasKey KEY_ESC = new TasKey(7);
|
||||
public static readonly TasKey KEY_ENTER = new TasKey(8);
|
||||
|
||||
public const int MIN_KEY_INDEX = 0;
|
||||
public const int MAX_KEY_INDEX = 8;
|
||||
|
||||
public static TasKey FromIndex(int index) {
|
||||
if (index < MIN_KEY_INDEX || index > MAX_KEY_INDEX) {
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
} else {
|
||||
return new TasKey(index);
|
||||
}
|
||||
}
|
||||
|
||||
public int ToIndex() {
|
||||
return m_BitPos;
|
||||
}
|
||||
|
||||
public uint ToBitMaskKey() {
|
||||
return 1u << m_BitPos;
|
||||
}
|
||||
|
||||
public bool Equals(TasKey other) {
|
||||
return m_BitPos == other.m_BitPos;
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj) {
|
||||
if (obj is TasKey other) {
|
||||
return Equals(other);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override int GetHashCode() {
|
||||
return m_BitPos.GetHashCode();
|
||||
}
|
||||
|
||||
public static bool operator ==(TasKey left, TasKey right) {
|
||||
return left.Equals(right);
|
||||
}
|
||||
|
||||
public static bool operator !=(TasKey left, TasKey right) {
|
||||
return !left.Equals(right);
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
return m_BitPos switch {
|
||||
0 => "KeyUp",
|
||||
1 => "KeyDown",
|
||||
2 => "KeyLeft",
|
||||
3 => "KeyRight",
|
||||
4 => "KeyShift",
|
||||
5 => "KeySpace",
|
||||
6 => "KeyQ",
|
||||
7 => "KeyEsc",
|
||||
8 => "KeyEnter",
|
||||
_ => $"KeyUnknown<Pos={m_BitPos}>"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 描述TAS文件中一帧的结构。
|
||||
/// </summary>
|
||||
public class TasFrame : IEquatable<TasFrame> {
|
||||
private TasFrame(float timeDelta, uint keyFlags) {
|
||||
m_TimeDelta = timeDelta;
|
||||
m_KeyFlags = keyFlags;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 以指定的FPS,无任何按键初始化当前帧。
|
||||
/// </summary>
|
||||
public TasFrame(uint fps = 60) {
|
||||
m_TimeDelta = FpsConverter.ToDelta(fps);
|
||||
m_KeyFlags = 0;
|
||||
public static TasFrame FromFps(uint fps = 60) {
|
||||
return new TasFrame(FpsConverter.ToDelta(fps), 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从原始TAS数据初始化。
|
||||
/// </summary>
|
||||
/// <param name="raw">要用来初始化的原始数据。</param>
|
||||
public TasFrame(RawTasFrame raw) {
|
||||
m_TimeDelta = raw.TimeDelta;
|
||||
m_KeyFlags = raw.KeyFlags;
|
||||
public static TasFrame FromRaw(RawTasFrame raw) {
|
||||
return new TasFrame(raw.TimeDelta, raw.KeyFlags);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 将原始TAS数据覆写到自身
|
||||
/// </summary>
|
||||
/// <param name="raw">要写入的原始TAS数据</param>
|
||||
public void FromRaw(RawTasFrame raw) {
|
||||
public void FromRawImplace(RawTasFrame raw) {
|
||||
m_TimeDelta = raw.TimeDelta;
|
||||
m_KeyFlags = raw.KeyFlags;
|
||||
}
|
||||
@@ -65,7 +147,7 @@ namespace BallanceTasEditor.Backend {
|
||||
/// 原位转换为原始TAS数据。
|
||||
/// </summary>
|
||||
/// <param name="raw">以引用传递的原始TAS数据。</param>
|
||||
public void ToImplaceRaw(ref RawTasFrame raw) {
|
||||
public void ToRawImplace(ref RawTasFrame raw) {
|
||||
raw.TimeDelta = m_TimeDelta;
|
||||
raw.KeyFlags = m_KeyFlags;
|
||||
}
|
||||
@@ -101,7 +183,7 @@ namespace BallanceTasEditor.Backend {
|
||||
/// <param name="key">要检查的按键。</param>
|
||||
/// <returns>true表示被按下,否则为false。</returns>
|
||||
public bool IsKeyPressed(TasKey key) {
|
||||
return (m_KeyFlags & (1u << (int)key)) != 0;
|
||||
return (m_KeyFlags & key.ToBitMaskKey()) != 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -110,8 +192,8 @@ namespace BallanceTasEditor.Backend {
|
||||
/// <param name="key">要设置的按键。</param>
|
||||
/// <param name="pressed">true表示设置为按下,否则为松开。</param>
|
||||
public void SetKeyPressed(TasKey key, bool pressed = true) {
|
||||
if (pressed) m_KeyFlags |= (1u << (int)key);
|
||||
else m_KeyFlags &= ~(1u << (int)key);
|
||||
if (pressed) m_KeyFlags |= key.ToBitMaskKey();
|
||||
else m_KeyFlags &= ~key.ToBitMaskKey();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -119,45 +201,45 @@ namespace BallanceTasEditor.Backend {
|
||||
/// </summary>
|
||||
/// <param name="key">要反转的按键。</param>
|
||||
public void FlipKeyPressed(TasKey key) {
|
||||
m_KeyFlags ^= (1u << (int)key);
|
||||
m_KeyFlags ^= key.ToBitMaskKey();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置Up键的按下状态。
|
||||
/// </summary>
|
||||
public bool KeyUpPressed { get { return IsKeyPressed(TasKey.KeyUp); } set { SetKeyPressed(TasKey.KeyUp, value); } }
|
||||
public bool KeyUpPressed { get { return IsKeyPressed(TasKey.KEY_UP); } set { SetKeyPressed(TasKey.KEY_UP, value); } }
|
||||
/// <summary>
|
||||
/// 获取或设置Down键的按下状态。
|
||||
/// </summary>
|
||||
public bool KeyDownPressed { get { return IsKeyPressed(TasKey.KeyDown); } set { SetKeyPressed(TasKey.KeyDown, value); } }
|
||||
public bool KeyDownPressed { get { return IsKeyPressed(TasKey.KEY_DOWN); } set { SetKeyPressed(TasKey.KEY_DOWN, value); } }
|
||||
/// <summary>
|
||||
/// 获取或设置Left键的按下状态。
|
||||
/// </summary>
|
||||
public bool KeyLeftPressed { get { return IsKeyPressed(TasKey.KeyLeft); } set { SetKeyPressed(TasKey.KeyLeft, value); } }
|
||||
public bool KeyLeftPressed { get { return IsKeyPressed(TasKey.KEY_LEFT); } set { SetKeyPressed(TasKey.KEY_LEFT, value); } }
|
||||
/// <summary>
|
||||
/// 获取或设置Right键的按下状态。
|
||||
/// </summary>
|
||||
public bool KeyRightPressed { get { return IsKeyPressed(TasKey.KeyRight); } set { SetKeyPressed(TasKey.KeyRight, value); } }
|
||||
public bool KeyRightPressed { get { return IsKeyPressed(TasKey.KEY_RIGHT); } set { SetKeyPressed(TasKey.KEY_RIGHT, value); } }
|
||||
/// <summary>
|
||||
/// 获取或设置Shift键的按下状态。
|
||||
/// </summary>
|
||||
public bool KeyShiftPressed { get { return IsKeyPressed(TasKey.KeyShift); } set { SetKeyPressed(TasKey.KeyShift, value); } }
|
||||
public bool KeyShiftPressed { get { return IsKeyPressed(TasKey.KEY_SHIFT); } set { SetKeyPressed(TasKey.KEY_SHIFT, value); } }
|
||||
/// <summary>
|
||||
/// 获取或设置Space键的按下状态。
|
||||
/// </summary>
|
||||
public bool KeySpacePressed { get { return IsKeyPressed(TasKey.KeySpace); } set { SetKeyPressed(TasKey.KeySpace, value); } }
|
||||
public bool KeySpacePressed { get { return IsKeyPressed(TasKey.KEY_SPACE); } set { SetKeyPressed(TasKey.KEY_SPACE, value); } }
|
||||
/// <summary>
|
||||
/// 获取或设置Q键的按下状态。
|
||||
/// </summary>
|
||||
public bool KeyQPressed { get { return IsKeyPressed(TasKey.KeyQ); } set { SetKeyPressed(TasKey.KeyQ, value); } }
|
||||
public bool KeyQPressed { get { return IsKeyPressed(TasKey.KEY_Q); } set { SetKeyPressed(TasKey.KEY_Q, value); } }
|
||||
/// <summary>
|
||||
/// 获取或设置Esc键的按下状态。
|
||||
/// </summary>
|
||||
public bool KeyEscPressed { get { return IsKeyPressed(TasKey.KeyEsc); } set { SetKeyPressed(TasKey.KeyEsc, value); } }
|
||||
public bool KeyEscPressed { get { return IsKeyPressed(TasKey.KEY_ESC); } set { SetKeyPressed(TasKey.KEY_ESC, value); } }
|
||||
/// <summary>
|
||||
/// 获取或设置回车键的按下状态。
|
||||
/// </summary>
|
||||
public bool KeyEnterPressed { get { return IsKeyPressed(TasKey.KeyEnter); } set { SetKeyPressed(TasKey.KeyEnter, value); } }
|
||||
public bool KeyEnterPressed { get { return IsKeyPressed(TasKey.KEY_ENTER); } set { SetKeyPressed(TasKey.KEY_ENTER, value); } }
|
||||
|
||||
/// <summary>
|
||||
/// 清除所有按键,将所有按键设置为不按下。
|
||||
@@ -200,19 +282,4 @@ namespace BallanceTasEditor.Backend {
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 描述TAS文件中的可能的按键。
|
||||
/// </summary>
|
||||
public enum TasKey : int {
|
||||
KeyUp = 0,
|
||||
KeyDown = 1,
|
||||
KeyLeft = 2,
|
||||
KeyRight = 3,
|
||||
KeyShift = 4,
|
||||
KeySpace = 5,
|
||||
KeyQ = 6,
|
||||
KeyEsc = 7,
|
||||
KeyEnter = 8,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,8 +13,17 @@ namespace BallanceTasEditor.Backend {
|
||||
/// <summary>
|
||||
/// 执行对应的TAS操作。
|
||||
/// </summary>
|
||||
/// <param name="storage">所要操作的TAS存储容器。</param>
|
||||
void Execute(ITasSequence storage);
|
||||
/// <param name="seq">所要操作的TAS存储容器。</param>
|
||||
void Execute(ITasSequence seq);
|
||||
/// <summary>
|
||||
/// 检查该操作是否已经被执行过。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 所有Tas操作类创建后只能执行一次或者不执行,
|
||||
/// 因此有此函数用于获取是否已经执行过。
|
||||
/// </remarks>
|
||||
/// <returns>如果已经执行过,返回true,否则返回false。</returns>
|
||||
bool IsExecuted();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -24,8 +33,8 @@ namespace BallanceTasEditor.Backend {
|
||||
/// <summary>
|
||||
/// 撤销对应TAS操作。
|
||||
/// </summary>
|
||||
/// <param name="storage">所要撤销操作的TAS存储容器。</param>
|
||||
void Revoke(ITasSequence storage);
|
||||
/// <param name="seq">所要撤销操作的TAS存储容器。</param>
|
||||
void Revoke(ITasSequence seq);
|
||||
/// <summary>
|
||||
/// 返回该TAS操作占用的内存大小。
|
||||
/// </summary>
|
||||
@@ -47,42 +56,124 @@ namespace BallanceTasEditor.Backend {
|
||||
}
|
||||
|
||||
public class CellKeysOperation : ITasRevocableOperation {
|
||||
|
||||
private CellKeysOperationKind m_Kind;
|
||||
|
||||
public void Execute(ITasSequence storage) {
|
||||
throw new NotImplementedException();
|
||||
public static CellKeysOperation FromSingleCell(CellKeysOperationKind kind, int index, TasKey key) {
|
||||
return new CellKeysOperation(kind, index, index, key, key);
|
||||
}
|
||||
|
||||
public void Revoke(ITasSequence storage) {
|
||||
throw new NotImplementedException();
|
||||
public static CellKeysOperation FromCellRange(CellKeysOperationKind kind, int startIndex, int endIndex, TasKey startKey, TasKey endKey) {
|
||||
return new CellKeysOperation(kind, startIndex, endIndex, startKey, endKey);
|
||||
}
|
||||
|
||||
private CellKeysOperation(CellKeysOperationKind kind, int startIndex, int endIndex, TasKey startKey, TasKey endKey) {
|
||||
// Check arguments.
|
||||
ArgumentOutOfRangeException.ThrowIfGreaterThan(startIndex, endIndex);
|
||||
ArgumentOutOfRangeException.ThrowIfGreaterThan(startKey.ToIndex(), endKey.ToIndex());
|
||||
// Setup members.
|
||||
m_Kind = kind;
|
||||
m_StartIndex = startIndex;
|
||||
m_EndIndex = endIndex;
|
||||
m_StartKey = startKey;
|
||||
m_EndKey = endKey;
|
||||
m_FramesBackup = null;
|
||||
}
|
||||
|
||||
private CellKeysOperationKind m_Kind;
|
||||
private int m_StartIndex, m_EndIndex;
|
||||
private TasKey m_StartKey, m_EndKey;
|
||||
private RawTasFrame[]? m_FramesBackup;
|
||||
|
||||
public bool IsExecuted() {
|
||||
return m_FramesBackup is not null;
|
||||
}
|
||||
|
||||
public void Execute(ITasSequence seq) {
|
||||
if (m_FramesBackup is not null) {
|
||||
throw new InvalidOperationException("Can not execute one TAS operation multiple times.");
|
||||
}
|
||||
|
||||
// Check index range.
|
||||
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(m_EndIndex, seq.GetCount());
|
||||
ArgumentOutOfRangeException.ThrowIfLessThan(m_StartIndex, 0);
|
||||
|
||||
// Do backup and set values at the same time
|
||||
var backups = new RawTasFrame[m_EndIndex - m_StartIndex];
|
||||
// Pre-build key list for fast fetching.
|
||||
var keys = Enumerable.Range(m_StartKey.ToIndex(), m_EndKey.ToIndex() - m_StartKey.ToIndex()).Select((i) => TasKey.FromIndex(i)).ToArray();
|
||||
for (int index = m_StartIndex; index <= m_EndIndex; index++) {
|
||||
// Fetch frame
|
||||
var frame = seq.Visit(index);
|
||||
// Do backup
|
||||
frame.ToRawImplace(ref backups[index - m_StartIndex]);
|
||||
// Modify keys
|
||||
foreach (var key in keys) {
|
||||
switch (m_Kind) {
|
||||
case CellKeysOperationKind.Set:
|
||||
frame.SetKeyPressed(key, true);
|
||||
break;
|
||||
case CellKeysOperationKind.Unset:
|
||||
frame.SetKeyPressed(key, false);
|
||||
break;
|
||||
case CellKeysOperationKind.Flip:
|
||||
frame.FlipKeyPressed(key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Assign backups
|
||||
m_FramesBackup = backups;
|
||||
}
|
||||
|
||||
public void Revoke(ITasSequence seq) {
|
||||
if (m_FramesBackup is null) {
|
||||
throw new InvalidOperationException("Can not revoke an not executed TAS operation.");
|
||||
}
|
||||
|
||||
// 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]);
|
||||
}
|
||||
|
||||
// Clear backups
|
||||
m_FramesBackup = null;
|
||||
}
|
||||
|
||||
public int Occupation() {
|
||||
throw new NotImplementedException();
|
||||
return (m_EndIndex - m_StartIndex) * (m_EndKey.ToIndex() - m_StartKey.ToIndex());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class CellFpsOperation : ITasRevocableOperation {
|
||||
public void Execute(ITasSequence storage) {
|
||||
public bool IsExecuted() {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Revoke(ITasSequence storage) {
|
||||
public void Execute(ITasSequence seq) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Revoke(ITasSequence seq) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public int Occupation() {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class RemoveFrameOperation : ITasRevocableOperation {
|
||||
public void Execute(ITasSequence storage) {
|
||||
public bool IsExecuted() {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Revoke(ITasSequence storage) {
|
||||
public void Execute(ITasSequence seq) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Revoke(ITasSequence seq) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -92,25 +183,74 @@ namespace BallanceTasEditor.Backend {
|
||||
}
|
||||
|
||||
public class AddFrameOperation : ITasRevocableOperation {
|
||||
public void Execute(ITasSequence storage) {
|
||||
throw new NotImplementedException();
|
||||
public AddFrameOperation(int index, uint fps, int count) {
|
||||
// Check argument
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(count);
|
||||
ArgumentOutOfRangeException.ThrowIfZero(fps);
|
||||
// Assign argument
|
||||
m_Index = index;
|
||||
m_Fps = fps;
|
||||
m_Count = count;
|
||||
m_IsExecuted = false;
|
||||
}
|
||||
|
||||
public void Revoke(ITasSequence storage) {
|
||||
throw new NotImplementedException();
|
||||
private int m_Index;
|
||||
private uint m_Fps;
|
||||
private int m_Count;
|
||||
private bool m_IsExecuted;
|
||||
|
||||
public bool IsExecuted() {
|
||||
return m_IsExecuted;
|
||||
}
|
||||
|
||||
public void Execute(ITasSequence seq) {
|
||||
if (m_IsExecuted) {
|
||||
throw new InvalidOperationException("Can not execute one TAS operation multiple times.");
|
||||
}
|
||||
|
||||
// Check argument.
|
||||
ArgumentOutOfRangeException.ThrowIfGreaterThan(m_Index, seq.GetCount());
|
||||
|
||||
// Prepare data builder.
|
||||
var iter = Enumerable.Range(0, m_Count).Select((_) => TasFrame.FromFps(m_Fps));
|
||||
var exactSizedIter = new ExactSizeEnumerableAdapter<TasFrame>(iter, m_Count);
|
||||
// Execute inserting.
|
||||
seq.Insert(m_Index, exactSizedIter);
|
||||
|
||||
// Set status
|
||||
m_IsExecuted = true;
|
||||
}
|
||||
|
||||
public void Revoke(ITasSequence seq) {
|
||||
if (!m_IsExecuted) {
|
||||
throw new InvalidOperationException("Can not revoke an not executed TAS operation.");
|
||||
}
|
||||
|
||||
// If we inserted count is not zero, remove inserted frames
|
||||
if (m_Count != 0) {
|
||||
seq.Remove(m_Index, m_Index + m_Count - 1);
|
||||
} else {
|
||||
// Otherwise just skip it.
|
||||
}
|
||||
// Modify execution status
|
||||
m_IsExecuted = false;
|
||||
}
|
||||
|
||||
public int Occupation() {
|
||||
throw new NotImplementedException();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
public class InsertFrameOperation : ITasRevocableOperation {
|
||||
public void Execute(ITasSequence storage) {
|
||||
public bool IsExecuted() {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Revoke(ITasSequence storage) {
|
||||
public void Execute(ITasSequence seq) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Revoke(ITasSequence seq) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -120,26 +260,52 @@ namespace BallanceTasEditor.Backend {
|
||||
}
|
||||
|
||||
public class ClearKeysOperation : ITasOperation {
|
||||
public ClearKeysOperation() { }
|
||||
public ClearKeysOperation() {
|
||||
m_IsExecuted = false;
|
||||
}
|
||||
|
||||
public void Execute(ITasSequence storage) {
|
||||
foreach (var frame in storage) {
|
||||
private bool m_IsExecuted;
|
||||
|
||||
public void Execute(ITasSequence seq) {
|
||||
// Check execution status first.
|
||||
if (m_IsExecuted) {
|
||||
throw new InvalidOperationException("Can not execute one TAS operation multiple times.");
|
||||
}
|
||||
// Execute operation
|
||||
foreach (var frame in seq) {
|
||||
frame.ClearKeyPressed();
|
||||
}
|
||||
m_IsExecuted = true;
|
||||
}
|
||||
|
||||
public bool IsExecuted() {
|
||||
return m_IsExecuted;
|
||||
}
|
||||
}
|
||||
|
||||
public class UniformFpsOperation : ITasOperation {
|
||||
public UniformFpsOperation(float deltaTime) {
|
||||
m_DeltaTime = deltaTime;
|
||||
m_IsExecuted = false;
|
||||
}
|
||||
|
||||
private float m_DeltaTime;
|
||||
private bool m_IsExecuted;
|
||||
|
||||
public void Execute(ITasSequence storage) {
|
||||
foreach (var frame in storage) {
|
||||
public void Execute(ITasSequence seq) {
|
||||
// Check execution status first.
|
||||
if (m_IsExecuted) {
|
||||
throw new InvalidOperationException("Can not execute one TAS operation multiple times.");
|
||||
}
|
||||
// Execute operation
|
||||
foreach (var frame in seq) {
|
||||
frame.SetTimeDelta(m_DeltaTime);
|
||||
}
|
||||
m_IsExecuted = true;
|
||||
}
|
||||
|
||||
public bool IsExecuted() {
|
||||
return m_IsExecuted;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -74,6 +74,10 @@ namespace BallanceTasEditor.Backend {
|
||||
bool IsEmpty();
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// We may introduce ITasSequenceSlice to have iterator on a specific range.
|
||||
// We also need introduce a new function in ITasSequence to fetch this instance.
|
||||
|
||||
/// <summary>
|
||||
/// 基于Gap Buffer思想的TAS存储器。
|
||||
/// </summary>
|
||||
|
||||
@@ -123,7 +123,7 @@ namespace BallanceTasEditor.Backend {
|
||||
// Convert to raw frame type.
|
||||
var frameMemory = exactMemory.Cast<byte, RawTasFrame>();
|
||||
// Map it and return.
|
||||
return MemoryMarshal.ToEnumerable<RawTasFrame>(frameMemory).Select((rawFrame) => new TasFrame(rawFrame)).GetEnumerator();
|
||||
return MemoryMarshal.ToEnumerable<RawTasFrame>(frameMemory).Select((rawFrame) => TasFrame.FromRaw(rawFrame)).GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() {
|
||||
|
||||
Reference in New Issue
Block a user