feat: update some interface
This commit is contained in:
@@ -1,64 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BallanceTasEditor.Backend {
|
||||
/// <summary>
|
||||
/// 一种提前给定元素个数的的IEnumerable。
|
||||
/// </summary>
|
||||
public sealed class CountableEnumerable<T> {
|
||||
/// <summary>
|
||||
/// 以直接方式构建。
|
||||
/// </summary>
|
||||
/// <param name="enumerable">一个迭代器,其最多只能迭代给定次数。</param>
|
||||
/// <param name="count">迭代器会迭代的次数。</param>
|
||||
public CountableEnumerable(IEnumerable<T> enumerable, int count) {
|
||||
m_Inner = enumerable;
|
||||
m_Count = count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从数组便捷构建。
|
||||
/// </summary>
|
||||
/// <param name="array">要使用的数组。</param>
|
||||
public CountableEnumerable(T[] array) {
|
||||
m_Inner = array;
|
||||
m_Count = array.Length;
|
||||
}
|
||||
|
||||
private readonly IEnumerable<T> m_Inner;
|
||||
private readonly int m_Count;
|
||||
|
||||
/// <summary>
|
||||
/// 获取迭代器对象。
|
||||
/// </summary>
|
||||
/// <returns>用于迭代的迭代器。</returns>
|
||||
/// <exception cref="ArgumentException">当迭代器迭代次数与给定次数不匹配时。</exception>
|
||||
public IEnumerable<T> GetInner() {
|
||||
int counter = 0;
|
||||
foreach (var item in m_Inner) {
|
||||
if (counter >= m_Count) {
|
||||
throw new ArgumentException("Given IEnumerable<T> is not stopped at given count.");
|
||||
} else {
|
||||
yield return item;
|
||||
++counter;
|
||||
}
|
||||
}
|
||||
|
||||
if (counter != m_Count) {
|
||||
throw new ArgumentException("Given IEnumerable<T> is not stopped at given count.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取该迭代器会迭代的次数。
|
||||
/// </summary>
|
||||
/// <returns>迭代器会迭代的次数,用于给使用该结构的方法提前分配必要的空间。</returns>
|
||||
public int GetCount() {
|
||||
return m_Count;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
/// <summary>
|
||||
/// 一种提前给定元素个数的的IEnumerable。
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public interface IExactSizeEnumerable<out T> : IEnumerable<T> {
|
||||
/// <summary>
|
||||
/// 该迭代器会返回的元素的个数。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 如果迭代器返回的元素个数与该方法给定的个数不同,
|
||||
/// 则是未定义行为。
|
||||
/// </remarks>
|
||||
/// <returns>迭代器会返回的元素的准确个数。大于等于0。</returns>
|
||||
public int GetCount();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将普通IEnumerable转变为IExactSizeEnumerable的适配器。
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public sealed class ExactSizeEnumerableAdapter<T> : IExactSizeEnumerable<T> {
|
||||
/// <summary>
|
||||
/// 以迭代器和指定长度构建适配器。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 如果迭代器返回的元素个数与该方法给定的个数不同,
|
||||
/// 则是未定义行为。
|
||||
/// </remarks>
|
||||
/// <param name="enumerable">一个迭代器,其最多只能迭代给定次数。</param>
|
||||
/// <param name="count">迭代器会迭代的次数。</param>
|
||||
public ExactSizeEnumerableAdapter(IEnumerable<T> enumerable, int count) {
|
||||
m_Inner = enumerable;
|
||||
m_Count = count;
|
||||
}
|
||||
|
||||
private readonly IEnumerable<T> m_Inner;
|
||||
private readonly int m_Count;
|
||||
|
||||
public IEnumerator<T> GetEnumerator() {
|
||||
return m_Inner.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() {
|
||||
return m_Inner.GetEnumerator();
|
||||
}
|
||||
|
||||
public int GetCount() {
|
||||
return m_Count;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
66
BallanceTasEditor/BallanceTasEditor/Backend/TasClipboard.cs
Normal file
66
BallanceTasEditor/BallanceTasEditor/Backend/TasClipboard.cs
Normal file
@@ -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<TasFrame> 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<TasFrame> {
|
||||
public EnumerableArray(RawTasFrame[] rawFrames) {
|
||||
m_RawFrames = rawFrames;
|
||||
}
|
||||
|
||||
private RawTasFrame[] m_RawFrames;
|
||||
|
||||
public IEnumerator<TasFrame> GetEnumerator() {
|
||||
return m_RawFrames.Select((f) => new TasFrame(f)).GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() {
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public int GetCount() {
|
||||
return m_RawFrames.Length;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ namespace BallanceTasEditor.Backend {
|
||||
/// 原始的TAS帧结构,与二进制结构保持一致。
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
[Serializable]
|
||||
public struct RawTasFrame {
|
||||
/// <summary>
|
||||
/// 该帧的持续时间(以秒为单位)。
|
||||
|
||||
@@ -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 {
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,7 @@ namespace BallanceTasEditor.Backend {
|
||||
/// <param name="index">要在前方插入数据的元素的索引。</param>
|
||||
/// <param name="items">要插入的元素的迭代器。</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">给定的索引无效。</exception>
|
||||
void Insert(int index, CountableEnumerable<TasFrame> items);
|
||||
void Insert(int index, IExactSizeEnumerable<TasFrame> items);
|
||||
/// <summary>
|
||||
/// 从序列中移出给定帧区间的元素。
|
||||
/// </summary>
|
||||
@@ -89,7 +89,7 @@ namespace BallanceTasEditor.Backend {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Insert(int index, CountableEnumerable<TasFrame> items) {
|
||||
public void Insert(int index, IExactSizeEnumerable<TasFrame> items) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -139,14 +139,14 @@ namespace BallanceTasEditor.Backend {
|
||||
}
|
||||
}
|
||||
|
||||
public void Insert(int index, CountableEnumerable<TasFrame> items) {
|
||||
public void Insert(int index, IExactSizeEnumerable<TasFrame> 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<TasFrame> items) {
|
||||
public void Insert(int index, IExactSizeEnumerable<TasFrame> 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();
|
||||
|
||||
@@ -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<TasFrame>(memWrapper, expectedCount));
|
||||
seq.Insert(0, memWrapper);
|
||||
|
||||
mem.Close();
|
||||
}
|
||||
@@ -105,7 +105,7 @@ namespace BallanceTasEditor.Backend {
|
||||
//target.Flush();
|
||||
}
|
||||
|
||||
private class EnumerableMemoryStream : IEnumerable<TasFrame> {
|
||||
private sealed class EnumerableMemoryStream : IExactSizeEnumerable<TasFrame> {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user