write shit
This commit is contained in:
123
Core/TASFile.cs
123
Core/TASFile.cs
@ -17,29 +17,32 @@ namespace BallanceTASEditor.Core {
|
||||
fs.Close();
|
||||
fs.Dispose();
|
||||
mPointer = mMem.First;
|
||||
mPointerIndex = 0;
|
||||
}
|
||||
|
||||
public string mFilename { get; private set; }
|
||||
public long mFrameCount { get { return mMem.Count; } }
|
||||
LinkedList<FrameData> mMem;
|
||||
LinkedListNode<FrameData> mPointer;
|
||||
long mPointerIndex;
|
||||
|
||||
public void Shift(long shiftNum) {
|
||||
if (mPointer == null) return;
|
||||
if (shiftNum == 0) return;
|
||||
var absNum = Math.Abs(shiftNum);
|
||||
if (shiftNum > 0) {
|
||||
for(long num = 0; num < absNum && mPointer.Next != null; num++) {
|
||||
mPointer = mPointer.Next;
|
||||
}
|
||||
} else {
|
||||
for (long num = 0; num < absNum && mPointer.Previous != null; num++) {
|
||||
mPointer = mPointer.Previous;
|
||||
}
|
||||
}
|
||||
public bool IsEmpty() {
|
||||
return (mPointer == null);
|
||||
}
|
||||
|
||||
public void Get(List<FrameDataDisplay> container, long startIndex, int count) {
|
||||
public long GetPointerIndex() {
|
||||
if (mPointer == null) throw new Exception("Data is not ready");
|
||||
return mPointerIndex;
|
||||
}
|
||||
|
||||
public void Shift(long absoluteIndex) {
|
||||
if (mPointer == null) return;
|
||||
|
||||
mPointer = mMem.FastGetNode(mPointer, mPointerIndex, absoluteIndex);
|
||||
mPointerIndex = absoluteIndex;
|
||||
}
|
||||
|
||||
public void Get(List<FrameDataDisplay> container, int count) {
|
||||
// no item. clean container
|
||||
if (mPointer == null) {
|
||||
for(int j = 0; j < count; j++) {
|
||||
@ -50,6 +53,7 @@ namespace BallanceTASEditor.Core {
|
||||
|
||||
// fill container
|
||||
var cachePointer = mPointer;
|
||||
var startIndex = mPointerIndex;
|
||||
int i;
|
||||
for(i = 0; i < count && cachePointer != null; i++, startIndex++) {
|
||||
container[i].Reload(startIndex, cachePointer.Value);
|
||||
@ -62,41 +66,102 @@ namespace BallanceTASEditor.Core {
|
||||
}
|
||||
|
||||
// if isSet is null, mean flip state
|
||||
public void Set(SelectionRange field, SelectionRange relativeRange, bool? isSet) {
|
||||
public void Set(SelectionRange field, SelectionRange absoluteRange, bool? isSet) {
|
||||
if (mPointer == null) return;
|
||||
|
||||
var cachePointer = mPointer;
|
||||
uint offset = 0;
|
||||
for(int i = (int)field.start; i <= (int)field.end; i++) {
|
||||
offset |= ConstValue.Mapping[(FrameDataField)i];
|
||||
}
|
||||
foreach(var item in mMem.IterateWithSelectionRange(relativeRange, mPointer)) {
|
||||
foreach(var item in mMem.IterateWithSelectionRange(absoluteRange, mPointer, mPointerIndex)) {
|
||||
if (isSet == null) item.Value.ReverseKeyStates(offset);
|
||||
else if (isSet == true) item.Value.SetKeyStates(offset);
|
||||
else if (isSet == false) item.Value.UnsetKeyStates(offset);
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove(SelectionRange relativeRange) {
|
||||
public void Remove(SelectionRange absoluteRange) {
|
||||
if (mPointer == null) return;
|
||||
|
||||
mMem.RemoveWithSelectionRange(relativeRange, mPointer);
|
||||
// todo: fix pointer point to invalid item
|
||||
// remove
|
||||
foreach(var item in mMem.IterateWithSelectionRange(absoluteRange, mPointer, mPointerIndex)) {
|
||||
mMem.Remove(item);
|
||||
}
|
||||
|
||||
// correct index data
|
||||
// if state is true, it mean the deleted content is placed before pointer previously.
|
||||
// so we need shift the pointer to the head of selection range.
|
||||
// and we should consider 2 situations, the full delete of LinkedList and delete from head
|
||||
if (mPointerIndex <= absoluteRange.end) {
|
||||
var newIndex = absoluteRange.start - 1;
|
||||
if (newIndex < 0) {
|
||||
// this contains 2 situation
|
||||
// if full delete, mPointer is null and mPointerIndex is invalid(with wrong data: 0)
|
||||
// if delete from head, mPointer and mPointerIndex all are valid.
|
||||
mPointer = mMem.First;
|
||||
mPointerIndex = 0;
|
||||
} else {
|
||||
mPointer = mMem.FastGetNode(mPointer, mPointerIndex, newIndex);
|
||||
mPointerIndex = newIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(long relativePos, bool isAddBefore) {
|
||||
|
||||
public void Add(long absolutePos, long count, float deltaTime, bool isAddBefore) {
|
||||
if (count <= 0) return;
|
||||
|
||||
if (mPointer == null) {
|
||||
// add into blank list, absolutePos and isAddBefore parameters are invalid
|
||||
// specially process
|
||||
for(long i = 0; i < count; i++) {
|
||||
mMem.AddFirst(new FrameData(deltaTime, 0));
|
||||
}
|
||||
mPointer = mMem.First;
|
||||
mPointerIndex = 0;
|
||||
} else {
|
||||
// normal add
|
||||
// normal add doesn't affect pointer
|
||||
LinkedListNode<FrameData> node = mMem.FastGetNode(mPointer, mPointerIndex, absolutePos);
|
||||
if (isAddBefore) {
|
||||
for (long i = 0; i < count; i++) {
|
||||
mMem.AddBefore(node, new FrameData(deltaTime, 0));
|
||||
}
|
||||
} else {
|
||||
for (long i = 0; i < count; i++) {
|
||||
mMem.AddAfter(node, new FrameData(deltaTime, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Insert(long relativePos, LinkedList<FrameData> data, bool isInsertBefore) {
|
||||
public void Insert(long absolutePos, LinkedList<FrameData> data, bool isInsertBefore) {
|
||||
if (data.Count == 0) return;
|
||||
|
||||
// the same process route with add function
|
||||
if (mPointer == null) {
|
||||
foreach (var item in data.IterateFull()) {
|
||||
mMem.AddFirst(item.Value);
|
||||
}
|
||||
mPointer = mMem.First;
|
||||
mPointerIndex = 0;
|
||||
} else {
|
||||
LinkedListNode<FrameData> node = mMem.FastGetNode(mPointer, mPointerIndex, absolutePos);
|
||||
if (isInsertBefore) {
|
||||
foreach (var item in data.IterateFull()) {
|
||||
mMem.AddBefore(node, item.Value);
|
||||
}
|
||||
} else {
|
||||
foreach (var item in data.IterateFull()) {
|
||||
mMem.AddAfter(node, item.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Copy(SelectionRange absoluteRange, LinkedList<FrameData> data) {
|
||||
if (mPointer == null) return;
|
||||
|
||||
}
|
||||
|
||||
public void Copy(SelectionRange relativeRange, LinkedList<FrameData> data) {
|
||||
if (mPointer == null) return;
|
||||
|
||||
foreach (var item in mMem.IterateWithSelectionRange(relativeRange, mPointer)) {
|
||||
foreach (var item in mMem.IterateWithSelectionRange(absoluteRange, mPointer, mPointerIndex)) {
|
||||
data.AddLast(item.Value);
|
||||
}
|
||||
}
|
||||
|
||||
99
Core/Util.cs
99
Core/Util.cs
@ -28,52 +28,66 @@ namespace BallanceTASEditor.Core {
|
||||
}
|
||||
}
|
||||
|
||||
public static LinkedListNode<FrameData> FastGetNode(this LinkedList<FrameData> ls, LinkedListNode<FrameData> refNode, long refIndex, long targetIndex) {
|
||||
long count = ls.Count;
|
||||
if (targetIndex >= count || refIndex >= count) throw new Exception("Index is invalid!");
|
||||
var span = new StupidSortStruct[3] {
|
||||
new StupidSortStruct() { type = 1, data = targetIndex },
|
||||
new StupidSortStruct() { type = 2, data = count - targetIndex },
|
||||
new StupidSortStruct() { type = 3, data = targetIndex - refIndex }
|
||||
};
|
||||
|
||||
public static IEnumerable<LinkedListNode<FrameData>> IterateWithSelectionRange(this LinkedList<FrameData> ls, SelectionRange relativeRange, LinkedListNode<FrameData> current) {
|
||||
if (current == null) goto end;
|
||||
|
||||
// goto header first
|
||||
long counter;
|
||||
var cache = current.TryShiftTo(relativeRange.start, out counter);
|
||||
|
||||
while (counter <= relativeRange.end && cache != null) {
|
||||
yield return cache;
|
||||
cache = cache.Next;
|
||||
counter++;
|
||||
// sort to get the min value
|
||||
StupidSortStruct tmp;
|
||||
if (Math.Abs(span[0].data) < Math.Abs(span[1].data)) {
|
||||
tmp = span[0];
|
||||
span[0] = span[1];
|
||||
span[1] = tmp;
|
||||
}
|
||||
|
||||
end:;
|
||||
if (Math.Abs(span[1].data) < Math.Abs(span[2].data)) {
|
||||
tmp = span[1];
|
||||
span[2] = span[1];
|
||||
span[2] = tmp;
|
||||
}
|
||||
|
||||
LinkedListNode<FrameData> iterateNode;
|
||||
if (span[2].type == 1) iterateNode = ls.First;
|
||||
else if (span[2].type == 2) iterateNode = ls.Last;
|
||||
else if (span[2].type == 3) iterateNode = refNode;
|
||||
else throw new Exception("Unknow node type");
|
||||
|
||||
return iterateNode.ShiftTo(span[2].data);
|
||||
}
|
||||
|
||||
public static void RemoveWithSelectionRange(this LinkedList<FrameData> ls, SelectionRange relativeRange, LinkedListNode<FrameData> current) {
|
||||
if (current == null) goto end;
|
||||
|
||||
// remove safety. because it store the next node.
|
||||
public static IEnumerable<LinkedListNode<FrameData>> IterateWithSelectionRange(this LinkedList<FrameData> ls, SelectionRange absoluteRange, LinkedListNode<FrameData> refNode, long refIndex) {
|
||||
// goto header first
|
||||
long counter;
|
||||
var cache = current.TryShiftTo(relativeRange.start, out counter);
|
||||
var cache = ls.FastGetNode(refNode, refIndex, absoluteRange.start);
|
||||
|
||||
var counter = absoluteRange.start;
|
||||
LinkedListNode<FrameData> cacheNextNode;
|
||||
while (counter <= relativeRange.end && cache != null) {
|
||||
while (counter <= absoluteRange.end) {
|
||||
if (cache == null) throw new Exception("Unexpected head or tail of linked list!");
|
||||
cacheNextNode = cache.Next;
|
||||
ls.Remove(cache);
|
||||
yield return cache;
|
||||
cache = cacheNextNode;
|
||||
counter++;
|
||||
}
|
||||
|
||||
end:;
|
||||
}
|
||||
|
||||
public static LinkedListNode<FrameData> TryShiftTo(this LinkedListNode<FrameData> node, long offset, out long realShifted) {
|
||||
public static LinkedListNode<FrameData> ShiftTo(this LinkedListNode<FrameData> node, long offset) {
|
||||
var cache = node;
|
||||
|
||||
realShifted = 0;
|
||||
long realShifted = 0;
|
||||
if (offset < 0) {
|
||||
while (realShifted != offset && cache.Previous != null) {
|
||||
while (realShifted != offset) {
|
||||
if (cache.Previous == null) throw new Exception("Unexpected head or tail of linked list!");
|
||||
cache = cache.Previous;
|
||||
realShifted--;
|
||||
}
|
||||
} else if (offset > 0) {
|
||||
while (realShifted != offset && cache.Next != null) {
|
||||
while (realShifted != offset) {
|
||||
if (cache.Next == null) throw new Exception("Unexpected head or tail of linked list!");
|
||||
cache = cache.Next;
|
||||
realShifted++;
|
||||
}
|
||||
@ -82,4 +96,37 @@ namespace BallanceTASEditor.Core {
|
||||
return cache;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public struct SelectionRange {
|
||||
public SelectionRange(long value1, long value2) {
|
||||
if (value1 > value2) {
|
||||
start = value2;
|
||||
end = value1;
|
||||
} else {
|
||||
start = value1;
|
||||
end = value2;
|
||||
}
|
||||
}
|
||||
public long start;
|
||||
public long end;
|
||||
public SelectionRange GetRelative(long refer) {
|
||||
var res = new SelectionRange();
|
||||
res.start = start - refer;
|
||||
res.end = end - refer;
|
||||
return res;
|
||||
}
|
||||
public bool Within(long num) {
|
||||
return (num >= start && num <= end);
|
||||
}
|
||||
public long GetCount() {
|
||||
return end - start;
|
||||
}
|
||||
}
|
||||
|
||||
public struct StupidSortStruct {
|
||||
public int type;
|
||||
public long data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user