Files
BallanceTasEditor/Core/TASFile.cs

182 lines
6.7 KiB
C#
Raw Normal View History

2021-05-13 15:49:26 +08:00
using BallanceTASEditor.Core.TASStruct;
2021-05-16 14:15:35 +08:00
using BallanceTASEditor.UI;
2021-05-13 15:49:26 +08:00
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
namespace BallanceTASEditor.Core {
public class TASFile {
public TASFile(string filename) {
mFilename = filename;
mMem = new LinkedList<FrameData>();
var fs = new FileStream(mFilename, FileMode.Open, FileAccess.Read, FileShare.Read);
ZlibUtil.DecompressTAS(mMem, fs);
fs.Close();
fs.Dispose();
mPointer = mMem.First;
2021-05-21 22:37:25 +08:00
mPointerIndex = 0;
2021-05-13 15:49:26 +08:00
}
public string mFilename { get; private set; }
public long mFrameCount { get { return mMem.Count; } }
LinkedList<FrameData> mMem;
LinkedListNode<FrameData> mPointer;
2021-05-21 22:37:25 +08:00
long mPointerIndex;
2021-05-13 15:49:26 +08:00
2021-05-21 22:37:25 +08:00
public bool IsEmpty() {
return (mPointer == null);
}
public long GetPointerIndex() {
if (mPointer == null) throw new Exception("Data is not ready");
return mPointerIndex;
}
public void Shift(long absoluteIndex) {
2021-05-13 15:49:26 +08:00
if (mPointer == null) return;
2021-05-21 22:37:25 +08:00
mPointer = mMem.FastGetNode(mPointer, mPointerIndex, absoluteIndex);
mPointerIndex = absoluteIndex;
2021-05-13 15:49:26 +08:00
}
2021-05-21 22:37:25 +08:00
public void Get(List<FrameDataDisplay> container, int count) {
2021-05-13 22:18:51 +08:00
// no item. clean container
if (mPointer == null) {
for(int j = 0; j < count; j++) {
container[j].isEnable = false;
}
return;
}
// fill container
2021-05-13 15:49:26 +08:00
var cachePointer = mPointer;
2021-05-21 22:37:25 +08:00
var startIndex = mPointerIndex;
2021-05-13 15:49:26 +08:00
int i;
for(i = 0; i < count && cachePointer != null; i++, startIndex++) {
container[i].Reload(startIndex, cachePointer.Value);
2021-05-13 22:18:51 +08:00
container[i].isEnable = true;
2021-05-13 15:49:26 +08:00
cachePointer = cachePointer.Next;
}
2021-05-13 22:18:51 +08:00
for(; i < count; i++) {
container[i].isEnable = false;
}
2021-05-13 15:49:26 +08:00
}
2021-05-16 14:15:35 +08:00
// if isSet is null, mean flip state
2021-05-21 22:37:25 +08:00
public void Set(SelectionRange field, SelectionRange absoluteRange, bool? isSet) {
2021-05-13 15:49:26 +08:00
if (mPointer == null) return;
2021-05-16 14:15:35 +08:00
uint offset = 0;
for(int i = (int)field.start; i <= (int)field.end; i++) {
offset |= ConstValue.Mapping[(FrameDataField)i];
}
2021-05-21 22:37:25 +08:00
foreach(var item in mMem.IterateWithSelectionRange(absoluteRange, mPointer, mPointerIndex)) {
2021-05-16 14:15:35 +08:00
if (isSet == null) item.Value.ReverseKeyStates(offset);
else if (isSet == true) item.Value.SetKeyStates(offset);
else if (isSet == false) item.Value.UnsetKeyStates(offset);
2021-05-13 15:49:26 +08:00
}
2021-05-16 14:15:35 +08:00
}
2021-05-21 22:37:25 +08:00
public void Remove(SelectionRange absoluteRange) {
2021-05-16 14:15:35 +08:00
if (mPointer == null) return;
2021-05-21 22:37:25 +08:00
// 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
2021-05-22 13:25:37 +08:00
if (mPointerIndex >= absoluteRange.start) {
2021-05-21 22:37:25 +08:00
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;
}
}
2021-05-16 14:15:35 +08:00
}
2021-05-21 22:37:25 +08:00
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));
}
}
}
2021-05-16 14:15:35 +08:00
}
2021-05-21 22:37:25 +08:00
public void Insert(long absolutePos, LinkedList<FrameData> data, bool isInsertBefore) {
if (data.Count == 0) return;
2021-05-16 14:15:35 +08:00
2021-05-21 22:37:25 +08:00
// 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);
}
}
}
2021-05-16 14:15:35 +08:00
}
2021-05-21 22:37:25 +08:00
public void Copy(SelectionRange absoluteRange, LinkedList<FrameData> data) {
2021-05-16 14:15:35 +08:00
if (mPointer == null) return;
2021-05-21 22:37:25 +08:00
foreach (var item in mMem.IterateWithSelectionRange(absoluteRange, mPointer, mPointerIndex)) {
2021-05-16 14:15:35 +08:00
data.AddLast(item.Value);
2021-05-13 15:49:26 +08:00
}
}
public void Save() {
var fs = new FileStream(mFilename, FileMode.Create, FileAccess.Write, FileShare.None);
ZlibUtil.CompressTAS(mMem, fs);
fs.Close();
fs.Dispose();
}
public void SaveAs(string newfile) {
mFilename = newfile;
Save();
}
}
}