diff --git a/BallanceTasEditor/BallanceTasEditor/Backend/CountableEnumerable.cs b/BallanceTasEditor/BallanceTasEditor/Backend/CountableEnumerable.cs deleted file mode 100644 index 96d283c..0000000 --- a/BallanceTasEditor/BallanceTasEditor/Backend/CountableEnumerable.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace BallanceTasEditor.Backend { - /// - /// 一种提前给定元素个数的的IEnumerable。 - /// - public sealed class CountableEnumerable { - /// - /// 以直接方式构建。 - /// - /// 一个迭代器,其最多只能迭代给定次数。 - /// 迭代器会迭代的次数。 - public CountableEnumerable(IEnumerable enumerable, int count) { - m_Inner = enumerable; - m_Count = count; - } - - /// - /// 从数组便捷构建。 - /// - /// 要使用的数组。 - public CountableEnumerable(T[] array) { - m_Inner = array; - m_Count = array.Length; - } - - private readonly IEnumerable m_Inner; - private readonly int m_Count; - - /// - /// 获取迭代器对象。 - /// - /// 用于迭代的迭代器。 - /// 当迭代器迭代次数与给定次数不匹配时。 - public IEnumerable GetInner() { - int counter = 0; - foreach (var item in m_Inner) { - if (counter >= m_Count) { - throw new ArgumentException("Given IEnumerable is not stopped at given count."); - } else { - yield return item; - ++counter; - } - } - - if (counter != m_Count) { - throw new ArgumentException("Given IEnumerable is not stopped at given count."); - } - } - - /// - /// 获取该迭代器会迭代的次数。 - /// - /// 迭代器会迭代的次数,用于给使用该结构的方法提前分配必要的空间。 - public int GetCount() { - return m_Count; - } - - } -} diff --git a/BallanceTasEditor/BallanceTasEditor/Backend/ExactSizeEnumerable.cs b/BallanceTasEditor/BallanceTasEditor/Backend/ExactSizeEnumerable.cs new file mode 100644 index 0000000..c2dd6b7 --- /dev/null +++ b/BallanceTasEditor/BallanceTasEditor/Backend/ExactSizeEnumerable.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BallanceTasEditor.Backend { + + /// + /// 一种提前给定元素个数的的IEnumerable。 + /// + /// + public interface IExactSizeEnumerable : IEnumerable { + /// + /// 该迭代器会返回的元素的个数。 + /// + /// + /// 如果迭代器返回的元素个数与该方法给定的个数不同, + /// 则是未定义行为。 + /// + /// 迭代器会返回的元素的准确个数。大于等于0。 + public int GetCount(); + } + + /// + /// 将普通IEnumerable转变为IExactSizeEnumerable的适配器。 + /// + /// + public sealed class ExactSizeEnumerableAdapter : IExactSizeEnumerable { + /// + /// 以迭代器和指定长度构建适配器。 + /// + /// + /// 如果迭代器返回的元素个数与该方法给定的个数不同, + /// 则是未定义行为。 + /// + /// 一个迭代器,其最多只能迭代给定次数。 + /// 迭代器会迭代的次数。 + public ExactSizeEnumerableAdapter(IEnumerable enumerable, int count) { + m_Inner = enumerable; + m_Count = count; + } + + private readonly IEnumerable m_Inner; + private readonly int m_Count; + + public IEnumerator GetEnumerator() { + return m_Inner.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() { + return m_Inner.GetEnumerator(); + } + + public int GetCount() { + return m_Count; + } + + } + +} diff --git a/BallanceTasEditor/BallanceTasEditor/Backend/TasClipboard.cs b/BallanceTasEditor/BallanceTasEditor/Backend/TasClipboard.cs new file mode 100644 index 0000000..a0495fd --- /dev/null +++ b/BallanceTasEditor/BallanceTasEditor/Backend/TasClipboard.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; + +namespace BallanceTasEditor.Backend { + public class TasClipboard { + // Reference: https://stackoverflow.com/questions/22272822/copy-binary-data-to-clipboard + + private static readonly string CLIPBOARD_DATA_FORMAT = "BallanceTasEditor.TasFrames"; + + public static void SetClipboard(IExactSizeEnumerable frames) { + DataObject data = new DataObject(); + var rawFrames = frames.Select((f) => f.ToRaw()).ToArray(); + data.SetData(CLIPBOARD_DATA_FORMAT, rawFrames, false); + Clipboard.SetDataObject(data, true); + } + + private static RawTasFrame[]? GetClipboardObject() { + DataObject? retrievedData = Clipboard.GetDataObject() as DataObject; + if (retrievedData is null) return null; + if (!retrievedData.GetDataPresent(CLIPBOARD_DATA_FORMAT)) return null; + + RawTasFrame[]? rawFrames = retrievedData.GetData(CLIPBOARD_DATA_FORMAT) as RawTasFrame[]; + if (rawFrames is null) return null; + + return rawFrames; + } + + public static bool HasClipboard() { + return GetClipboardObject() is not null; + } + + public static EnumerableArray? GetClipboard() { + var rawFrames = GetClipboardObject(); + if (rawFrames is null) return null; + + return new EnumerableArray(rawFrames); + } + + public sealed class EnumerableArray : IExactSizeEnumerable { + public EnumerableArray(RawTasFrame[] rawFrames) { + m_RawFrames = rawFrames; + } + + private RawTasFrame[] m_RawFrames; + + public IEnumerator GetEnumerator() { + return m_RawFrames.Select((f) => new TasFrame(f)).GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() { + return GetEnumerator(); + } + + public int GetCount() { + return m_RawFrames.Length; + } + + } + } +} diff --git a/BallanceTasEditor/BallanceTasEditor/Backend/TasFrame.cs b/BallanceTasEditor/BallanceTasEditor/Backend/TasFrame.cs index f8a6853..ed8675d 100644 --- a/BallanceTasEditor/BallanceTasEditor/Backend/TasFrame.cs +++ b/BallanceTasEditor/BallanceTasEditor/Backend/TasFrame.cs @@ -11,6 +11,7 @@ namespace BallanceTasEditor.Backend { /// 原始的TAS帧结构,与二进制结构保持一致。 /// [StructLayout(LayoutKind.Sequential)] + [Serializable] public struct RawTasFrame { /// /// 该帧的持续时间(以秒为单位)。 diff --git a/BallanceTasEditor/BallanceTasEditor/Backend/TasOperationStack.cs b/BallanceTasEditor/BallanceTasEditor/Backend/TasOperationStack.cs deleted file mode 100644 index 5bec10a..0000000 --- a/BallanceTasEditor/BallanceTasEditor/Backend/TasOperationStack.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace BallanceTasEditor.Backend { - internal class TasOperationStack { - } -} diff --git a/BallanceTasEditor/BallanceTasEditor/Backend/TasSequence.cs b/BallanceTasEditor/BallanceTasEditor/Backend/TasSequence.cs index 5f65ace..2875f67 100644 --- a/BallanceTasEditor/BallanceTasEditor/Backend/TasSequence.cs +++ b/BallanceTasEditor/BallanceTasEditor/Backend/TasSequence.cs @@ -44,7 +44,7 @@ namespace BallanceTasEditor.Backend { /// 要在前方插入数据的元素的索引。 /// 要插入的元素的迭代器。 /// 给定的索引无效。 - void Insert(int index, CountableEnumerable items); + void Insert(int index, IExactSizeEnumerable items); /// /// 从序列中移出给定帧区间的元素。 /// @@ -89,7 +89,7 @@ namespace BallanceTasEditor.Backend { throw new NotImplementedException(); } - public void Insert(int index, CountableEnumerable items) { + public void Insert(int index, IExactSizeEnumerable items) { throw new NotImplementedException(); } @@ -139,14 +139,14 @@ namespace BallanceTasEditor.Backend { } } - public void Insert(int index, CountableEnumerable items) { + public void Insert(int index, IExactSizeEnumerable items) { if (index == m_Container.Count) { - m_Container.AddRange(items.GetInner()); + m_Container.AddRange(items); } else { if (index > m_Container.Count || index < 0) { throw new IndexOutOfRangeException("Invalid index for frame."); } else { - m_Container.InsertRange(index, items.GetInner()); + m_Container.InsertRange(index, items); } } } @@ -272,12 +272,12 @@ namespace BallanceTasEditor.Backend { } } - public void Insert(int index, CountableEnumerable items) { + public void Insert(int index, IExactSizeEnumerable items) { if (index >= m_Container.Count || index < 0) { throw new IndexOutOfRangeException("Invalid index for frame."); } else { if (index == m_Container.Count) { - foreach (TasFrame item in items.GetInner()) { + foreach (TasFrame item in items) { m_Container.AddLast(item); } @@ -290,7 +290,7 @@ namespace BallanceTasEditor.Backend { } else { MoveToIndex(index); - foreach (TasFrame item in items.GetInner()) { + foreach (TasFrame item in items) { m_Container.AddBefore(m_Cursor.Node, item); } m_Cursor.Index += items.GetCount(); diff --git a/BallanceTasEditor/BallanceTasEditor/Backend/TasStorage.cs b/BallanceTasEditor/BallanceTasEditor/Backend/TasStorage.cs index f940190..3f820dd 100644 --- a/BallanceTasEditor/BallanceTasEditor/Backend/TasStorage.cs +++ b/BallanceTasEditor/BallanceTasEditor/Backend/TasStorage.cs @@ -10,8 +10,8 @@ using System.Threading.Tasks; namespace BallanceTasEditor.Backend { public static class TasStorage { - internal const int SIZEOF_F32 = sizeof(float); internal const int SIZEOF_I32 = sizeof(int); + internal const int SIZEOF_F32 = sizeof(float); internal const int SIZEOF_U32 = sizeof(uint); internal const int SIZEOF_RAW_TAS_FRAME = SIZEOF_F32 + SIZEOF_U32; @@ -70,7 +70,7 @@ namespace BallanceTasEditor.Backend { var memWrapper = new EnumerableMemoryStream(mem, expectedCount); seq.Clear(); - seq.Insert(0, new CountableEnumerable(memWrapper, expectedCount)); + seq.Insert(0, memWrapper); mem.Close(); } @@ -105,7 +105,7 @@ namespace BallanceTasEditor.Backend { //target.Flush(); } - private class EnumerableMemoryStream : IEnumerable { + private sealed class EnumerableMemoryStream : IExactSizeEnumerable { public EnumerableMemoryStream(MemoryStream mem, int frameCnt) { m_MemoryStream = mem; m_FrameCount = frameCnt; @@ -130,6 +130,9 @@ namespace BallanceTasEditor.Backend { return GetEnumerator(); } + public int GetCount() { + return m_FrameCount; + } } }