refactor: migrate project and start refactor
This commit is contained in:
31
Legacy/BallanceTASEditor.sln
Normal file
31
Legacy/BallanceTASEditor.sln
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29418.71
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BallanceTASEditor", "BallanceTASEditor\BallanceTASEditor.csproj", "{3127A635-B9E5-4C78-8414-0B9B196EC25E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BallanceTASEditorTests", "BallanceTASEditorTests\BallanceTASEditorTests.csproj", "{EC35111D-6259-4C69-B7E4-F4E727AC0E1A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{3127A635-B9E5-4C78-8414-0B9B196EC25E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3127A635-B9E5-4C78-8414-0B9B196EC25E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3127A635-B9E5-4C78-8414-0B9B196EC25E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3127A635-B9E5-4C78-8414-0B9B196EC25E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EC35111D-6259-4C69-B7E4-F4E727AC0E1A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EC35111D-6259-4C69-B7E4-F4E727AC0E1A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EC35111D-6259-4C69-B7E4-F4E727AC0E1A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EC35111D-6259-4C69-B7E4-F4E727AC0E1A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {ABECA811-4FBB-4394-805E-EEBC799ECC89}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
14
Legacy/BallanceTASEditor/App.xaml
Normal file
14
Legacy/BallanceTASEditor/App.xaml
Normal file
@ -0,0 +1,14 @@
|
||||
<Application x:Class="BallanceTASEditor.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:BallanceTASEditor"
|
||||
StartupUri="MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="Language/DefaultLanguage.xaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
81
Legacy/BallanceTASEditor/App.xaml.cs
Normal file
81
Legacy/BallanceTASEditor/App.xaml.cs
Normal file
@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
|
||||
namespace BallanceTASEditor {
|
||||
/// <summary>
|
||||
/// App.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class App : Application {
|
||||
|
||||
protected override void OnStartup(StartupEventArgs e) {
|
||||
base.OnStartup(e);
|
||||
|
||||
#if DEBUG
|
||||
#else
|
||||
AppDomain.CurrentDomain.UnhandledException += (sender, ex) => {
|
||||
if (ex.ExceptionObject is System.Exception) {
|
||||
var exx = (System.Exception)ex.ExceptionObject;
|
||||
UncatchedErrorHandle(exx.Message, exx.StackTrace);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
// init configure manager
|
||||
GlobalVariable.configManager = new Core.ConfigManager("ballance-tas-editor.cfg", new Dictionary<string, string>() {
|
||||
{Core.ConfigManager.CfgNode_Language, CultureInfo.CurrentCulture.ThreeLetterWindowsLanguageName},
|
||||
{Core.ConfigManager.CfgNode_ItemCount, "15"},
|
||||
{Core.ConfigManager.CfgNode_IsHorizonLayout, "True"},
|
||||
{Core.ConfigManager.CfgNode_IsOverwrittenPaste, "False"}
|
||||
});
|
||||
|
||||
// init i18n
|
||||
Core.I18NProcessor.ChangeLanguage(GlobalVariable.configManager.Configuration[Core.ConfigManager.CfgNode_Language]);
|
||||
|
||||
}
|
||||
|
||||
protected override void OnExit(ExitEventArgs e) {
|
||||
base.OnExit(e);
|
||||
|
||||
GlobalVariable.configManager.Save();
|
||||
}
|
||||
|
||||
private void UncatchedErrorHandle(string message, string stackTrace) {
|
||||
try {
|
||||
if (!Directory.Exists("./logs"))
|
||||
Directory.CreateDirectory("./logs");
|
||||
|
||||
int counter = 1;
|
||||
var filename = "";
|
||||
var datetime = DateTime.Now;
|
||||
while (true) {
|
||||
filename = $"./logs/crash-{datetime.ToString("yyyyMMddHHmmss")}-{counter.ToString().PadLeft(2, '0')}.log";
|
||||
if (!File.Exists(filename)) break;
|
||||
}
|
||||
|
||||
var fs = new StreamWriter(filename, false, Encoding.UTF8);
|
||||
fs.WriteLine("[SYS][ERROR] FATAL ERROR !");
|
||||
fs.WriteLine(message);
|
||||
fs.WriteLine(stackTrace);
|
||||
fs.Close();
|
||||
fs.Dispose();
|
||||
} catch {
|
||||
;//skip
|
||||
}
|
||||
|
||||
MessageBox.Show("A fatal error occurs. The application should exit. Please send the error log, reproduce step and corresponding TAS file(if possible) to developer to help fixing this problem.",
|
||||
"Ballance TAS Editor",
|
||||
MessageBoxButton.OK, MessageBoxImage.Error
|
||||
);
|
||||
App.Current.Shutdown();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
145
Legacy/BallanceTASEditor/BallanceTASEditor.csproj
Normal file
145
Legacy/BallanceTASEditor/BallanceTASEditor.csproj
Normal file
@ -0,0 +1,145 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{3127A635-B9E5-4C78-8414-0B9B196EC25E}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>BallanceTASEditor</RootNamespace>
|
||||
<AssemblyName>BallanceTASEditor</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Deterministic>true</Deterministic>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>icon.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Ionic.Zip, Version=1.9.1.8, Culture=neutral, PublicKeyToken=edbe51ad942a3f5c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DotNetZip.1.9.1.8\lib\net20\Ionic.Zip.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualBasic" />
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Xaml">
|
||||
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="WindowsBase" />
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="App.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Compile Include="Core\ClipboardUtil.cs" />
|
||||
<Compile Include="Core\ConfigManager.cs" />
|
||||
<Compile Include="Core\FileOperation.cs" />
|
||||
<Compile Include="Core\I18NProcessor.cs" />
|
||||
<Compile Include="Core\KeyboardState.cs" />
|
||||
<Compile Include="Core\LimitedStack.cs" />
|
||||
<Compile Include="GlobalVariable.cs" />
|
||||
<Compile Include="UI\AddItem.xaml.cs">
|
||||
<DependentUpon>AddItem.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="UI\OperationEnum.cs" />
|
||||
<Compile Include="UI\SelectionHelp.cs" />
|
||||
<Compile Include="UI\StyleConverter.cs" />
|
||||
<Compile Include="UI\TASFlow.cs" />
|
||||
<Compile Include="UI\TASSlider.cs" />
|
||||
<Compile Include="UI\TASViewer.cs" />
|
||||
<Compile Include="UI\Util.cs" />
|
||||
<Page Include="Language\CHS.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Language\DefaultLanguage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="MainWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Core\TASFile.cs" />
|
||||
<Compile Include="Core\TASStruct.cs" />
|
||||
<Compile Include="Core\Util.cs" />
|
||||
<Compile Include="Core\ZlibUtil.cs" />
|
||||
<Compile Include="UI\DialogUtil.cs" />
|
||||
<Compile Include="MainWindow.xaml.cs">
|
||||
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Page Include="UI\AddItem.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<None Include="app.config" />
|
||||
<None Include="packages.config" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="icon.ico" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
71
Legacy/BallanceTASEditor/Core/ClipboardUtil.cs
Normal file
71
Legacy/BallanceTASEditor/Core/ClipboardUtil.cs
Normal file
@ -0,0 +1,71 @@
|
||||
using BallanceTASEditor.Core.TASStruct;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
|
||||
namespace BallanceTASEditor.Core {
|
||||
public class ClipboardUtil {
|
||||
|
||||
// comes from https://stackoverflow.com/questions/22272822/copy-binary-data-to-clipboard
|
||||
|
||||
private static readonly string CLIPBOARD_DATA_FORMAT = "BallanceTASFrameData";
|
||||
public static bool SetFrameData(LinkedList<FrameData> ls) {
|
||||
try {
|
||||
DataObject data = new DataObject();
|
||||
using (var mem = new MemoryStream()) {
|
||||
mem.Write(BitConverter.GetBytes(ls.Count), 0, 4);
|
||||
|
||||
var node = ls.First;
|
||||
while (node != null) {
|
||||
mem.Write(BitConverter.GetBytes(node.Value.deltaTime), 0, 4);
|
||||
mem.Write(BitConverter.GetBytes(node.Value.keystates), 0, 4);
|
||||
node = node.Next;
|
||||
}
|
||||
|
||||
data.SetData(CLIPBOARD_DATA_FORMAT, mem, false);
|
||||
Clipboard.SetDataObject(data, true);
|
||||
}
|
||||
return true;
|
||||
#if DEBUG
|
||||
} catch (Exception e) {
|
||||
#else
|
||||
} catch {
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool GetFrameData(LinkedList<FrameData> ls) {
|
||||
try {
|
||||
// detect
|
||||
DataObject retrievedData = Clipboard.GetDataObject() as DataObject;
|
||||
if (retrievedData == null || !retrievedData.GetDataPresent(CLIPBOARD_DATA_FORMAT))
|
||||
return false;
|
||||
MemoryStream byteStream = retrievedData.GetData(CLIPBOARD_DATA_FORMAT) as MemoryStream;
|
||||
if (byteStream == null)
|
||||
return false;
|
||||
|
||||
// read
|
||||
byteStream.Seek(0, SeekOrigin.Begin);
|
||||
byte[] temp = new byte[8];
|
||||
byteStream.Read(temp, 0, 4);
|
||||
int count = BitConverter.ToInt32(temp, 0);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
ls.AddLast(new FrameData(byteStream));
|
||||
}
|
||||
|
||||
return true;
|
||||
#if DEBUG
|
||||
} catch (Exception e) {
|
||||
#else
|
||||
} catch {
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
65
Legacy/BallanceTASEditor/Core/ConfigManager.cs
Normal file
65
Legacy/BallanceTASEditor/Core/ConfigManager.cs
Normal file
@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BallanceTASEditor.Core {
|
||||
public class ConfigManager {
|
||||
|
||||
public ConfigManager(string fileName, Dictionary<string, string> defaultValue) {
|
||||
_fileName = fileName;
|
||||
_defaultValue = defaultValue;
|
||||
|
||||
Configuration = Read();
|
||||
}
|
||||
|
||||
string _fileName;
|
||||
Dictionary<string, string> _defaultValue;
|
||||
public Dictionary<string, string> Configuration;
|
||||
|
||||
public static readonly string CfgNode_Language = "Language";
|
||||
public static readonly string CfgNode_ItemCount = "ItemCount";
|
||||
public static readonly string CfgNode_IsHorizonLayout = "IsHorizonLayout";
|
||||
public static readonly string CfgNode_IsOverwrittenPaste = "IsOverwrittenPaste";
|
||||
|
||||
Dictionary<string, string> Read() {
|
||||
if (!File.Exists(Path.Combine(Environment.CurrentDirectory, _fileName)))
|
||||
Init();
|
||||
|
||||
Dictionary<string, string> data;
|
||||
using (StreamReader fs = new StreamReader(Path.Combine(Environment.CurrentDirectory, _fileName), Encoding.UTF8)) {
|
||||
data = JsonConvert.DeserializeObject<Dictionary<string, string>>(fs.ReadToEnd());
|
||||
fs.Close();
|
||||
}
|
||||
|
||||
// check field to make sure each field is existed
|
||||
// because version update it might be changed
|
||||
foreach(var pair in _defaultValue) {
|
||||
if (!data.ContainsKey(pair.Key)) {
|
||||
data.Add(pair.Key, pair.Value);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void Init() {
|
||||
using (StreamWriter fs = new StreamWriter(Path.Combine(Environment.CurrentDirectory, _fileName), false, Encoding.UTF8)) {
|
||||
fs.Write(JsonConvert.SerializeObject(_defaultValue));
|
||||
fs.Close();
|
||||
}
|
||||
}
|
||||
|
||||
public void Save() {
|
||||
using (StreamWriter fs = new StreamWriter(Path.Combine(Environment.CurrentDirectory, _fileName), false, Encoding.UTF8)) {
|
||||
fs.Write(JsonConvert.SerializeObject(this.Configuration));
|
||||
fs.Close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
437
Legacy/BallanceTASEditor/Core/FileOperation.cs
Normal file
437
Legacy/BallanceTASEditor/Core/FileOperation.cs
Normal file
@ -0,0 +1,437 @@
|
||||
using BallanceTASEditor.Core.TASStruct;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace BallanceTASEditor.Core.FileOperation {
|
||||
public abstract class RevocableOperation {
|
||||
public RevocableOperation() {
|
||||
hasBeenDone = false;
|
||||
}
|
||||
|
||||
private bool hasBeenDone;
|
||||
public virtual void Do(ref LinkedList<FrameData> mMem, ref LinkedListNode<FrameData> mPointer, ref long mPointerIndex) {
|
||||
if (hasBeenDone) throw new Exception("Try to call operation.do when the operation has been done.");
|
||||
hasBeenDone = true;
|
||||
}
|
||||
|
||||
public virtual void Undo(ref LinkedList<FrameData> mMem, ref LinkedListNode<FrameData> mPointer, ref long mPointerIndex) {
|
||||
if (!hasBeenDone) throw new Exception("Try to call operation.undo when the operation has not been done.");
|
||||
hasBeenDone = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class SetOperation : RevocableOperation {
|
||||
private SelectionRange field;
|
||||
private SelectionRange absoluteRange;
|
||||
private bool? isSet;
|
||||
|
||||
private uint internalOffset;
|
||||
private List<uint> changedItems;
|
||||
|
||||
public SetOperation(SelectionRange _field, SelectionRange _absoluteRange, bool? _isSet) : base() {
|
||||
field = _field;
|
||||
absoluteRange = _absoluteRange;
|
||||
isSet = _isSet;
|
||||
|
||||
// calc offset first for following operation
|
||||
internalOffset = 0;
|
||||
for (int i = (int)field.start; i <= (int)field.end; i++) {
|
||||
internalOffset |= ConstValue.Mapping[(FrameDataField)i];
|
||||
}
|
||||
|
||||
changedItems = new List<uint>();
|
||||
}
|
||||
|
||||
public override void Do(ref LinkedList<FrameData> mMem, ref LinkedListNode<FrameData> mPointer, ref long mPointerIndex) {
|
||||
base.Do(ref mMem, ref mPointer, ref mPointerIndex);
|
||||
if (mPointer == null) return;
|
||||
|
||||
changedItems.Clear();
|
||||
foreach (var item in mMem.IterateWithSelectionRange(absoluteRange, mPointer, mPointerIndex)) {
|
||||
// backup item first
|
||||
changedItems.Add(item.Value.keystates);
|
||||
|
||||
if (isSet == null) item.Value.ReverseKeyStates(internalOffset);
|
||||
else if (isSet == true) item.Value.SetKeyStates(internalOffset);
|
||||
else if (isSet == false) item.Value.UnsetKeyStates(internalOffset);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Undo(ref LinkedList<FrameData> mMem, ref LinkedListNode<FrameData> mPointer, ref long mPointerIndex) {
|
||||
base.Undo(ref mMem, ref mPointer, ref mPointerIndex);
|
||||
if (mPointer == null) return;
|
||||
|
||||
int counter = 0;
|
||||
foreach (var item in mMem.IterateWithSelectionRange(absoluteRange, mPointer, mPointerIndex)) {
|
||||
// restore data
|
||||
item.Value.keystates = changedItems[counter];
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class RemoveOperation : RevocableOperation {
|
||||
private SelectionRange absoluteRange;
|
||||
|
||||
private LinkedList<FrameData> removedItems;
|
||||
private LinkedListNode<FrameData> oldPointer;
|
||||
private long oldPointerIndex;
|
||||
private LinkedListNode<FrameData> removeStartNode;
|
||||
|
||||
public RemoveOperation(SelectionRange _absoluteRange) : base() {
|
||||
absoluteRange = _absoluteRange;
|
||||
|
||||
removedItems = new LinkedList<FrameData>();
|
||||
}
|
||||
|
||||
public override void Do(ref LinkedList<FrameData> mMem, ref LinkedListNode<FrameData> mPointer, ref long mPointerIndex) {
|
||||
base.Do(ref mMem, ref mPointer, ref mPointerIndex);
|
||||
if (mPointer == null) return;
|
||||
|
||||
// init backups list and backups 2 data
|
||||
// and backups remove start node(ps: if it is null, mean removed from head)
|
||||
removedItems.Clear();
|
||||
oldPointer = mPointer;
|
||||
oldPointerIndex = mPointerIndex;
|
||||
removeStartNode = absoluteRange.start == 0 ? null : mMem.FastGetNode(mPointer, mPointerIndex, absoluteRange.start - 1);
|
||||
|
||||
// find proper pointer after remove first. but we do not apply it in there.
|
||||
// if state is true, it mean the deleted content is placed before pointer previously. we should consider pointer data and we should correct them.
|
||||
LinkedListNode<FrameData> newPointer;
|
||||
long newPointerIndex;
|
||||
if (mPointerIndex >= absoluteRange.start) {
|
||||
// if point within removed content, we need to shift it to the head of removed content,
|
||||
// otherwise we only need to minus index with the length of removed content.
|
||||
if (absoluteRange.Within(mPointerIndex)) {
|
||||
// this contains 3 situation
|
||||
// if full delete, mPointer is null and mPointerIndex is invalid(with wrong data: -1)
|
||||
// if delete from head, mPointer and mPointerIndex all are valid. but it is the tail of removed content
|
||||
// otherwise, just find the head of removed content and shift to it.
|
||||
if (absoluteRange.start == 0 && absoluteRange.end == mMem.Count - 1) {
|
||||
// fully remove
|
||||
newPointer = null;
|
||||
newPointerIndex = -1;
|
||||
} else if (absoluteRange.start == 0) {
|
||||
// remove from head
|
||||
newPointerIndex = 0;
|
||||
newPointer = mMem.FastGetNode(mPointer, mPointerIndex, absoluteRange.end + 1);
|
||||
} else {
|
||||
// simple remove
|
||||
newPointerIndex = absoluteRange.start - 1;
|
||||
newPointer = mMem.FastGetNode(mPointer, mPointerIndex, absoluteRange.start - 1);
|
||||
}
|
||||
} else {
|
||||
newPointer = mPointer;
|
||||
newPointerIndex = mPointerIndex - absoluteRange.GetCount();
|
||||
}
|
||||
} else {
|
||||
// not affected situation
|
||||
newPointer = mPointer;
|
||||
newPointerIndex = mPointerIndex;
|
||||
}
|
||||
|
||||
// the real remove operation
|
||||
foreach (var item in mMem.IterateWithSelectionRange(absoluteRange, mPointer, mPointerIndex)) {
|
||||
mMem.Remove(item);
|
||||
removedItems.AddLast(item); // backups node;
|
||||
}
|
||||
|
||||
// apply gotten new pointer
|
||||
mPointer = newPointer;
|
||||
mPointerIndex = newPointerIndex;
|
||||
|
||||
}
|
||||
|
||||
public override void Undo(ref LinkedList<FrameData> mMem, ref LinkedListNode<FrameData> mPointer, ref long mPointerIndex) {
|
||||
base.Undo(ref mMem, ref mPointer, ref mPointerIndex);
|
||||
// may recovered from empty list
|
||||
//if (mPointer == null) return;
|
||||
|
||||
// re-insert data
|
||||
foreach (var item in removedItems.IterateFullReversed()) {
|
||||
removedItems.Remove(item);
|
||||
if (removeStartNode == null) {
|
||||
// insert at first
|
||||
mMem.AddFirst(item);
|
||||
} else {
|
||||
// insert after this node
|
||||
mMem.AddAfter(removeStartNode, item);
|
||||
}
|
||||
}
|
||||
|
||||
// reset pointer
|
||||
mPointer = oldPointer;
|
||||
mPointerIndex = oldPointerIndex;
|
||||
}
|
||||
}
|
||||
|
||||
public class AddOperation : RevocableOperation {
|
||||
private long absolutePos;
|
||||
private long count;
|
||||
private float deltaTime;
|
||||
private bool isAddBefore;
|
||||
|
||||
private LinkedListNode<FrameData> addStartNode;
|
||||
private LinkedListNode<FrameData> oldPointer;
|
||||
private long oldPointerIndex;
|
||||
|
||||
public AddOperation(long _absolutePos, long _count, float _deltaTime, bool _isAddBefore) : base() {
|
||||
absolutePos = _absolutePos;
|
||||
count = _count;
|
||||
deltaTime = _deltaTime;
|
||||
isAddBefore = _isAddBefore;
|
||||
}
|
||||
|
||||
public override void Do(ref LinkedList<FrameData> mMem, ref LinkedListNode<FrameData> mPointer, ref long mPointerIndex) {
|
||||
base.Do(ref mMem, ref mPointer, ref mPointerIndex);
|
||||
if (count <= 0) return;
|
||||
|
||||
// backups 2 data
|
||||
oldPointer = mPointer;
|
||||
oldPointerIndex = mPointerIndex;
|
||||
|
||||
// real add operation
|
||||
if (mPointer == null) {
|
||||
// backups start pointer
|
||||
addStartNode = 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
|
||||
LinkedListNode<FrameData> node = mMem.FastGetNode(mPointer, mPointerIndex, absolutePos);
|
||||
// backups start pointer
|
||||
addStartNode = node;
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
// if the items are added before pointer, the index should add with the count of added items
|
||||
// but pointer don't need to be shifted.
|
||||
if ((isAddBefore && mPointerIndex >= absolutePos) ||
|
||||
(!isAddBefore && mPointerIndex > absolutePos))
|
||||
mPointerIndex += count;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Undo(ref LinkedList<FrameData> mMem, ref LinkedListNode<FrameData> mPointer, ref long mPointerIndex) {
|
||||
base.Undo(ref mMem, ref mPointer, ref mPointerIndex);
|
||||
if (count <= 0) return;
|
||||
|
||||
if (addStartNode == null) {
|
||||
// original state is blank
|
||||
// just clear mmem is ok
|
||||
mMem.Clear();
|
||||
} else {
|
||||
if (isAddBefore) {
|
||||
for (long i = 0; i < count; i++) {
|
||||
mMem.Remove(addStartNode.Previous);
|
||||
}
|
||||
} else {
|
||||
for (long i = 0; i < count; i++) {
|
||||
mMem.Remove(addStartNode.Next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// re-set pointer
|
||||
mPointer = oldPointer;
|
||||
mPointerIndex = oldPointerIndex;
|
||||
}
|
||||
}
|
||||
|
||||
public class InsertOperation : RevocableOperation {
|
||||
private long absolutePos;
|
||||
private LinkedList<FrameData> data;
|
||||
private bool isInsertBefore;
|
||||
private bool isOverwritten;
|
||||
|
||||
private LinkedListNode<FrameData> addStartNode;
|
||||
private bool isBlankList;
|
||||
private LinkedListNode<FrameData> oldPointer;
|
||||
private long oldPointerIndex;
|
||||
|
||||
// because insert including remove oeration(overwritten mode)
|
||||
// so we need include this for code re-use
|
||||
private RemoveOperation internalRemoveOper;
|
||||
|
||||
private const long LINKEDLIST_HEAD = -1;
|
||||
private const long LINKEDLIST_TAIL = -2;
|
||||
|
||||
public InsertOperation(long _absolutePos, LinkedList<FrameData> _data, bool _isInsertBefore, bool _isOverwritten) : base() {
|
||||
absolutePos = _absolutePos;
|
||||
data = _data;
|
||||
isInsertBefore = _isInsertBefore;
|
||||
isOverwritten = _isOverwritten;
|
||||
|
||||
}
|
||||
|
||||
public override void Do(ref LinkedList<FrameData> mMem, ref LinkedListNode<FrameData> mPointer, ref long mPointerIndex) {
|
||||
base.Do(ref mMem, ref mPointer, ref mPointerIndex);
|
||||
if (data.Count == 0) return;
|
||||
|
||||
// because this oper have internal oper, so we need backup data after potential remove oper
|
||||
// so in there, no object need to be backuped
|
||||
|
||||
// if the list is blank, overwritten is invalid, just normal add them.
|
||||
if (mPointer == null) {
|
||||
// backups
|
||||
oldPointer = mPointer;
|
||||
oldPointerIndex = mPointerIndex;
|
||||
addStartNode = null;
|
||||
isBlankList = true;
|
||||
|
||||
foreach (var item in data.IterateFull()) {
|
||||
mMem.AddFirst(item.Value);
|
||||
}
|
||||
mPointer = mMem.First;
|
||||
mPointerIndex = 0;
|
||||
} else {
|
||||
LinkedListNode<FrameData> node = mMem.FastGetNode(mPointer, mPointerIndex, absolutePos);
|
||||
|
||||
// absolutePos is class member and shouldn't be changed.
|
||||
// but in overwritten mode, this value need to be changed so we create a temp value in there
|
||||
// to instead the fucntion of original variable
|
||||
var modifiedAbsolutePos = absolutePos;
|
||||
|
||||
// if list is not a blank list, we should consider overwritten
|
||||
// if in overwritten mode, we need to overwrite data from selected item.
|
||||
// otherwise, not in overwritten mode, just normally add them just like add operation.
|
||||
if (isOverwritten) {
|
||||
// in overwritten mode, if follwoing item is not enough to fufill the count of overwritten data
|
||||
// normally add them
|
||||
// we use delete and add method to do this
|
||||
|
||||
// now, try init internal remove oper if in overwritten mode
|
||||
// first, we need compare the length of remained item located in mMem and the length of added item
|
||||
// then construct remove oper
|
||||
long remainLength;
|
||||
if (isInsertBefore) remainLength = absolutePos + 1;
|
||||
else remainLength = mMem.Count - absolutePos;
|
||||
|
||||
long dataLength = data.Count;
|
||||
long expectedLength = dataLength > remainLength ? remainLength : dataLength;
|
||||
long expectedPos;
|
||||
if (isInsertBefore) expectedPos = absolutePos - expectedLength + 1;
|
||||
else expectedPos = absolutePos + expectedLength - 1;
|
||||
|
||||
if (isInsertBefore)
|
||||
internalRemoveOper = new RemoveOperation(new SelectionRange(expectedPos, absolutePos));
|
||||
else
|
||||
internalRemoveOper = new RemoveOperation(new SelectionRange(absolutePos, expectedPos));
|
||||
|
||||
node = isInsertBefore ? node.Next : node.Previous;
|
||||
internalRemoveOper.Do(ref mMem, ref mPointer, ref mPointerIndex);
|
||||
// now, we can treat it as normal insert(without overwritten)
|
||||
// but with one exception: absolutePos
|
||||
// we need re calc absolutePos bucause we have called remove oper
|
||||
|
||||
if (isInsertBefore) {
|
||||
if (node == null)
|
||||
modifiedAbsolutePos = LINKEDLIST_TAIL;
|
||||
else
|
||||
modifiedAbsolutePos = absolutePos + 1 - expectedLength;
|
||||
} else {
|
||||
if (node == null)
|
||||
modifiedAbsolutePos = LINKEDLIST_HEAD;
|
||||
else
|
||||
modifiedAbsolutePos -= 1;
|
||||
}
|
||||
|
||||
}
|
||||
// backups
|
||||
oldPointer = mPointer;
|
||||
oldPointerIndex = mPointerIndex;
|
||||
addStartNode = node;
|
||||
isBlankList = false;
|
||||
|
||||
if (isInsertBefore) {
|
||||
foreach (var item in data.IterateFull()) {
|
||||
if (node == null)
|
||||
mMem.AddLast(item.Value);
|
||||
else
|
||||
mMem.AddBefore(node, item.Value);
|
||||
}
|
||||
} else {
|
||||
foreach (var item in data.IterateFullReversed()) {
|
||||
if (node == null)
|
||||
mMem.AddFirst(item.Value);
|
||||
else
|
||||
mMem.AddAfter(node, item.Value);
|
||||
}
|
||||
}
|
||||
|
||||
if (modifiedAbsolutePos != LINKEDLIST_TAIL && modifiedAbsolutePos != LINKEDLIST_HEAD) {
|
||||
if ((isInsertBefore && mPointerIndex >= modifiedAbsolutePos) ||
|
||||
(!isInsertBefore && mPointerIndex > modifiedAbsolutePos))
|
||||
mPointerIndex += data.Count;
|
||||
}
|
||||
else if (modifiedAbsolutePos == LINKEDLIST_HEAD)
|
||||
mPointerIndex += data.Count;
|
||||
|
||||
// remove have chance to remove entire list
|
||||
// so we need restore pointer in that situation
|
||||
if (mPointer == null) {
|
||||
mPointer = mMem.First;
|
||||
mPointerIndex = mPointer == null ? -1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Undo(ref LinkedList<FrameData> mMem, ref LinkedListNode<FrameData> mPointer, ref long mPointerIndex) {
|
||||
base.Undo(ref mMem, ref mPointer, ref mPointerIndex);
|
||||
if (data.Count == 0) return;
|
||||
|
||||
if (isBlankList) {
|
||||
// original state is blank
|
||||
// just clear mmem is ok
|
||||
mMem.Clear();
|
||||
|
||||
// re-set pointer
|
||||
mPointer = oldPointer;
|
||||
mPointerIndex = oldPointerIndex;
|
||||
} else {
|
||||
// in overwrite or not in overwrite mode, we all need to remove inserted data first
|
||||
if (isInsertBefore) {
|
||||
for (long i = 0; i < data.Count; i++) {
|
||||
if (addStartNode == null)
|
||||
mMem.RemoveLast();
|
||||
else
|
||||
mMem.Remove(addStartNode.Previous);
|
||||
}
|
||||
} else {
|
||||
for (long i = 0; i < data.Count; i++) {
|
||||
if (addStartNode == null)
|
||||
mMem.RemoveFirst();
|
||||
else
|
||||
mMem.Remove(addStartNode.Next);
|
||||
}
|
||||
}
|
||||
|
||||
// re-set pointer
|
||||
mPointer = oldPointer;
|
||||
mPointerIndex = oldPointerIndex;
|
||||
|
||||
// if we use overwrite mode, we need re-add lost data
|
||||
if (isOverwritten) {
|
||||
internalRemoveOper.Undo(ref mMem, ref mPointer, ref mPointerIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
40
Legacy/BallanceTASEditor/Core/I18NProcessor.cs
Normal file
40
Legacy/BallanceTASEditor/Core/I18NProcessor.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
|
||||
namespace BallanceTASEditor.Core {
|
||||
public static class I18NProcessor {
|
||||
|
||||
public static string GetI18N(string key, params string[] parameters) {
|
||||
try {
|
||||
var cache = (string)(App.Current.Resources[key]);
|
||||
return string.Format(cache, parameters);
|
||||
} catch (Exception) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public static void ChangeLanguage(string target) {
|
||||
ResourceDictionary langRd = null;
|
||||
try {
|
||||
langRd =
|
||||
Application.LoadComponent(
|
||||
new Uri(@"Language/" + target + ".xaml", UriKind.Relative))
|
||||
as ResourceDictionary;
|
||||
} catch {
|
||||
;
|
||||
}
|
||||
|
||||
if (langRd != null) {
|
||||
if (App.Current.Resources.MergedDictionaries.Count > 0) {
|
||||
App.Current.Resources.MergedDictionaries.Clear();
|
||||
}
|
||||
App.Current.Resources.MergedDictionaries.Add(langRd);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
223
Legacy/BallanceTASEditor/Core/KeyboardState.cs
Normal file
223
Legacy/BallanceTASEditor/Core/KeyboardState.cs
Normal file
@ -0,0 +1,223 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace BallanceTASEditor.Core {
|
||||
public class KeyboardState {
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
static extern short GetKeyState(VirtualKeyStates nVirtKey);
|
||||
|
||||
public static bool IsKeyPressed(VirtualKeyStates testKey) {
|
||||
bool keyPressed = false;
|
||||
short result = GetKeyState(testKey);
|
||||
switch (result) {
|
||||
case 0:
|
||||
// Not pressed and not toggled on.
|
||||
keyPressed = false;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Not pressed, but toggled on
|
||||
keyPressed = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Pressed (and may be toggled on)
|
||||
keyPressed = true;
|
||||
break;
|
||||
}
|
||||
return keyPressed;
|
||||
}
|
||||
|
||||
public enum VirtualKeyStates : int {
|
||||
VK_LBUTTON = 0x01,
|
||||
VK_RBUTTON = 0x02,
|
||||
VK_CANCEL = 0x03,
|
||||
VK_MBUTTON = 0x04,
|
||||
//
|
||||
VK_XBUTTON1 = 0x05,
|
||||
VK_XBUTTON2 = 0x06,
|
||||
//
|
||||
VK_BACK = 0x08,
|
||||
VK_TAB = 0x09,
|
||||
//
|
||||
VK_CLEAR = 0x0C,
|
||||
VK_RETURN = 0x0D,
|
||||
//
|
||||
VK_SHIFT = 0x10,
|
||||
VK_CONTROL = 0x11,
|
||||
VK_MENU = 0x12,
|
||||
VK_PAUSE = 0x13,
|
||||
VK_CAPITAL = 0x14,
|
||||
//
|
||||
VK_KANA = 0x15,
|
||||
VK_HANGEUL = 0x15, /* old name - should be here for compatibility */
|
||||
VK_HANGUL = 0x15,
|
||||
VK_JUNJA = 0x17,
|
||||
VK_FINAL = 0x18,
|
||||
VK_HANJA = 0x19,
|
||||
VK_KANJI = 0x19,
|
||||
//
|
||||
VK_ESCAPE = 0x1B,
|
||||
//
|
||||
VK_CONVERT = 0x1C,
|
||||
VK_NONCONVERT = 0x1D,
|
||||
VK_ACCEPT = 0x1E,
|
||||
VK_MODECHANGE = 0x1F,
|
||||
//
|
||||
VK_SPACE = 0x20,
|
||||
VK_PRIOR = 0x21,
|
||||
VK_NEXT = 0x22,
|
||||
VK_END = 0x23,
|
||||
VK_HOME = 0x24,
|
||||
VK_LEFT = 0x25,
|
||||
VK_UP = 0x26,
|
||||
VK_RIGHT = 0x27,
|
||||
VK_DOWN = 0x28,
|
||||
VK_SELECT = 0x29,
|
||||
VK_PRINT = 0x2A,
|
||||
VK_EXECUTE = 0x2B,
|
||||
VK_SNAPSHOT = 0x2C,
|
||||
VK_INSERT = 0x2D,
|
||||
VK_DELETE = 0x2E,
|
||||
VK_HELP = 0x2F,
|
||||
//
|
||||
VK_LWIN = 0x5B,
|
||||
VK_RWIN = 0x5C,
|
||||
VK_APPS = 0x5D,
|
||||
//
|
||||
VK_SLEEP = 0x5F,
|
||||
//
|
||||
VK_NUMPAD0 = 0x60,
|
||||
VK_NUMPAD1 = 0x61,
|
||||
VK_NUMPAD2 = 0x62,
|
||||
VK_NUMPAD3 = 0x63,
|
||||
VK_NUMPAD4 = 0x64,
|
||||
VK_NUMPAD5 = 0x65,
|
||||
VK_NUMPAD6 = 0x66,
|
||||
VK_NUMPAD7 = 0x67,
|
||||
VK_NUMPAD8 = 0x68,
|
||||
VK_NUMPAD9 = 0x69,
|
||||
VK_MULTIPLY = 0x6A,
|
||||
VK_ADD = 0x6B,
|
||||
VK_SEPARATOR = 0x6C,
|
||||
VK_SUBTRACT = 0x6D,
|
||||
VK_DECIMAL = 0x6E,
|
||||
VK_DIVIDE = 0x6F,
|
||||
VK_F1 = 0x70,
|
||||
VK_F2 = 0x71,
|
||||
VK_F3 = 0x72,
|
||||
VK_F4 = 0x73,
|
||||
VK_F5 = 0x74,
|
||||
VK_F6 = 0x75,
|
||||
VK_F7 = 0x76,
|
||||
VK_F8 = 0x77,
|
||||
VK_F9 = 0x78,
|
||||
VK_F10 = 0x79,
|
||||
VK_F11 = 0x7A,
|
||||
VK_F12 = 0x7B,
|
||||
VK_F13 = 0x7C,
|
||||
VK_F14 = 0x7D,
|
||||
VK_F15 = 0x7E,
|
||||
VK_F16 = 0x7F,
|
||||
VK_F17 = 0x80,
|
||||
VK_F18 = 0x81,
|
||||
VK_F19 = 0x82,
|
||||
VK_F20 = 0x83,
|
||||
VK_F21 = 0x84,
|
||||
VK_F22 = 0x85,
|
||||
VK_F23 = 0x86,
|
||||
VK_F24 = 0x87,
|
||||
//
|
||||
VK_NUMLOCK = 0x90,
|
||||
VK_SCROLL = 0x91,
|
||||
//
|
||||
VK_OEM_NEC_EQUAL = 0x92, // '=' key on numpad
|
||||
//
|
||||
VK_OEM_FJ_JISHO = 0x92, // 'Dictionary' key
|
||||
VK_OEM_FJ_MASSHOU = 0x93, // 'Unregister word' key
|
||||
VK_OEM_FJ_TOUROKU = 0x94, // 'Register word' key
|
||||
VK_OEM_FJ_LOYA = 0x95, // 'Left OYAYUBI' key
|
||||
VK_OEM_FJ_ROYA = 0x96, // 'Right OYAYUBI' key
|
||||
//
|
||||
VK_LSHIFT = 0xA0,
|
||||
VK_RSHIFT = 0xA1,
|
||||
VK_LCONTROL = 0xA2,
|
||||
VK_RCONTROL = 0xA3,
|
||||
VK_LMENU = 0xA4,
|
||||
VK_RMENU = 0xA5,
|
||||
//
|
||||
VK_BROWSER_BACK = 0xA6,
|
||||
VK_BROWSER_FORWARD = 0xA7,
|
||||
VK_BROWSER_REFRESH = 0xA8,
|
||||
VK_BROWSER_STOP = 0xA9,
|
||||
VK_BROWSER_SEARCH = 0xAA,
|
||||
VK_BROWSER_FAVORITES = 0xAB,
|
||||
VK_BROWSER_HOME = 0xAC,
|
||||
//
|
||||
VK_VOLUME_MUTE = 0xAD,
|
||||
VK_VOLUME_DOWN = 0xAE,
|
||||
VK_VOLUME_UP = 0xAF,
|
||||
VK_MEDIA_NEXT_TRACK = 0xB0,
|
||||
VK_MEDIA_PREV_TRACK = 0xB1,
|
||||
VK_MEDIA_STOP = 0xB2,
|
||||
VK_MEDIA_PLAY_PAUSE = 0xB3,
|
||||
VK_LAUNCH_MAIL = 0xB4,
|
||||
VK_LAUNCH_MEDIA_SELECT = 0xB5,
|
||||
VK_LAUNCH_APP1 = 0xB6,
|
||||
VK_LAUNCH_APP2 = 0xB7,
|
||||
//
|
||||
VK_OEM_1 = 0xBA, // ';:' for US
|
||||
VK_OEM_PLUS = 0xBB, // '+' any country
|
||||
VK_OEM_COMMA = 0xBC, // ',' any country
|
||||
VK_OEM_MINUS = 0xBD, // '-' any country
|
||||
VK_OEM_PERIOD = 0xBE, // '.' any country
|
||||
VK_OEM_2 = 0xBF, // '/?' for US
|
||||
VK_OEM_3 = 0xC0, // '`~' for US
|
||||
//
|
||||
VK_OEM_4 = 0xDB, // '[{' for US
|
||||
VK_OEM_5 = 0xDC, // '\|' for US
|
||||
VK_OEM_6 = 0xDD, // ']}' for US
|
||||
VK_OEM_7 = 0xDE, // ''"' for US
|
||||
VK_OEM_8 = 0xDF,
|
||||
//
|
||||
VK_OEM_AX = 0xE1, // 'AX' key on Japanese AX kbd
|
||||
VK_OEM_102 = 0xE2, // "<>" or "\|" on RT 102-key kbd.
|
||||
VK_ICO_HELP = 0xE3, // Help key on ICO
|
||||
VK_ICO_00 = 0xE4, // 00 key on ICO
|
||||
//
|
||||
VK_PROCESSKEY = 0xE5,
|
||||
//
|
||||
VK_ICO_CLEAR = 0xE6,
|
||||
//
|
||||
VK_PACKET = 0xE7,
|
||||
//
|
||||
VK_OEM_RESET = 0xE9,
|
||||
VK_OEM_JUMP = 0xEA,
|
||||
VK_OEM_PA1 = 0xEB,
|
||||
VK_OEM_PA2 = 0xEC,
|
||||
VK_OEM_PA3 = 0xED,
|
||||
VK_OEM_WSCTRL = 0xEE,
|
||||
VK_OEM_CUSEL = 0xEF,
|
||||
VK_OEM_ATTN = 0xF0,
|
||||
VK_OEM_FINISH = 0xF1,
|
||||
VK_OEM_COPY = 0xF2,
|
||||
VK_OEM_AUTO = 0xF3,
|
||||
VK_OEM_ENLW = 0xF4,
|
||||
VK_OEM_BACKTAB = 0xF5,
|
||||
//
|
||||
VK_ATTN = 0xF6,
|
||||
VK_CRSEL = 0xF7,
|
||||
VK_EXSEL = 0xF8,
|
||||
VK_EREOF = 0xF9,
|
||||
VK_PLAY = 0xFA,
|
||||
VK_ZOOM = 0xFB,
|
||||
VK_NONAME = 0xFC,
|
||||
VK_PA1 = 0xFD,
|
||||
VK_OEM_CLEAR = 0xFE
|
||||
}
|
||||
}
|
||||
}
|
||||
39
Legacy/BallanceTASEditor/Core/LimitedStack.cs
Normal file
39
Legacy/BallanceTASEditor/Core/LimitedStack.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace BallanceTASEditor.Core {
|
||||
public class LimitedStack<T> {
|
||||
private static readonly int STACK_LENGTH = 20;
|
||||
|
||||
public LimitedStack() {
|
||||
_stack = new LinkedList<T>();
|
||||
}
|
||||
|
||||
private LinkedList<T> _stack;
|
||||
|
||||
public void Push(T data) {
|
||||
_stack.AddLast(data);
|
||||
if (_stack.Count > STACK_LENGTH) {
|
||||
_stack.RemoveFirst();
|
||||
}
|
||||
}
|
||||
|
||||
public T Pop() {
|
||||
if (_stack.Last == null) return default(T);
|
||||
var data = _stack.Last.Value;
|
||||
_stack.RemoveLast();
|
||||
return data;
|
||||
}
|
||||
|
||||
public void Clear() {
|
||||
_stack.Clear();
|
||||
}
|
||||
|
||||
public bool IsEmpty() {
|
||||
return _stack.Count == 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
256
Legacy/BallanceTASEditor/Core/TASFile.cs
Normal file
256
Legacy/BallanceTASEditor/Core/TASFile.cs
Normal file
@ -0,0 +1,256 @@
|
||||
using BallanceTASEditor.Core.FileOperation;
|
||||
using BallanceTASEditor.Core.TASStruct;
|
||||
using BallanceTASEditor.UI;
|
||||
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;
|
||||
mPointerIndex = mPointer == null ? -1 : 0;
|
||||
|
||||
mRedoStack = new LimitedStack<RevocableOperation>();
|
||||
mUndoStack = new LimitedStack<RevocableOperation>();
|
||||
}
|
||||
|
||||
public string mFilename { get; private set; }
|
||||
public long mFrameCount { get { return mMem.Count; } }
|
||||
LinkedList<FrameData> mMem;
|
||||
LinkedListNode<FrameData> mPointer;
|
||||
long mPointerIndex;
|
||||
|
||||
LimitedStack<RevocableOperation> mRedoStack;
|
||||
LimitedStack<RevocableOperation> mUndoStack;
|
||||
|
||||
public bool IsEmpty() {
|
||||
return (mPointer == null);
|
||||
}
|
||||
|
||||
public long GetPointerIndex() {
|
||||
// return invalid data to prevent error
|
||||
if (mPointer == null) return -1;//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++) {
|
||||
container[j].isEnable = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 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);
|
||||
container[i].isEnable = true;
|
||||
cachePointer = cachePointer.Next;
|
||||
}
|
||||
for (; i < count; i++) {
|
||||
container[i].isEnable = false;
|
||||
}
|
||||
}
|
||||
|
||||
// if isSet is null, mean flip state
|
||||
public void Set(SelectionRange field, SelectionRange absoluteRange, bool? isSet) {
|
||||
var oper = new SetOperation(field, absoluteRange, isSet);
|
||||
oper.Do(ref mMem, ref mPointer, ref mPointerIndex);
|
||||
mUndoStack.Push(oper);
|
||||
mRedoStack.Clear();
|
||||
/*
|
||||
if (mPointer == null) return;
|
||||
|
||||
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(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 absoluteRange) {
|
||||
var oper = new RemoveOperation(absoluteRange);
|
||||
oper.Do(ref mMem, ref mPointer, ref mPointerIndex);
|
||||
mUndoStack.Push(oper);
|
||||
mRedoStack.Clear();
|
||||
/*
|
||||
if (mPointer == null) return;
|
||||
|
||||
// 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.start) {
|
||||
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 absolutePos, long count, float deltaTime, bool isAddBefore) {
|
||||
var oper = new AddOperation(absolutePos, count, deltaTime, isAddBefore);
|
||||
oper.Do(ref mMem, ref mPointer, ref mPointerIndex);
|
||||
mUndoStack.Push(oper);
|
||||
mRedoStack.Clear();
|
||||
/*
|
||||
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 absolutePos, LinkedList<FrameData> data, bool isInsertBefore, bool isOverwritten) {
|
||||
var oper = new InsertOperation(absolutePos, data, isInsertBefore, isOverwritten);
|
||||
oper.Do(ref mMem, ref mPointer, ref mPointerIndex);
|
||||
mUndoStack.Push(oper);
|
||||
mRedoStack.Clear();
|
||||
/*
|
||||
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.IterateFullReversed()) {
|
||||
mMem.AddAfter(node, item.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
public void Redo() {
|
||||
if (mRedoStack.IsEmpty()) return;
|
||||
var oper = mRedoStack.Pop();
|
||||
oper.Do(ref mMem, ref mPointer, ref mPointerIndex);
|
||||
mUndoStack.Push(oper);
|
||||
}
|
||||
|
||||
public void Undo() {
|
||||
if (mUndoStack.IsEmpty()) return;
|
||||
var oper = mUndoStack.Pop();
|
||||
oper.Undo(ref mMem, ref mPointer, ref mPointerIndex);
|
||||
mRedoStack.Push(oper);
|
||||
}
|
||||
|
||||
public void Copy(SelectionRange absoluteRange, LinkedList<FrameData> data) {
|
||||
if (mPointer == null) return;
|
||||
|
||||
foreach (var item in mMem.IterateWithSelectionRange(absoluteRange, mPointer, mPointerIndex)) {
|
||||
data.AddLast(item.Value);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
#if DEBUG
|
||||
// following code only should be used in debug mode and served for testbench
|
||||
public TASFile(LinkedList<FrameData> items) {
|
||||
mFilename = "";
|
||||
mMem = items;
|
||||
mPointer = mMem.First;
|
||||
mPointerIndex = mPointer == null ? -1 : 0;
|
||||
|
||||
mRedoStack = new LimitedStack<RevocableOperation>();
|
||||
mUndoStack = new LimitedStack<RevocableOperation>();
|
||||
}
|
||||
|
||||
public string Output2TestString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if (mPointer == null) sb.Append("null;");
|
||||
else sb.Append($"{mPointer.Value.keystates.ToString()};");
|
||||
sb.Append($"{mPointerIndex};");
|
||||
|
||||
foreach (var item in mMem.IterateFull()) {
|
||||
sb.Append(item.Value.keystates.ToString());
|
||||
sb.Append(",");
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
131
Legacy/BallanceTASEditor/Core/TASStruct.cs
Normal file
131
Legacy/BallanceTASEditor/Core/TASStruct.cs
Normal file
@ -0,0 +1,131 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace BallanceTASEditor.Core.TASStruct {
|
||||
public class FrameDataDisplay {
|
||||
public FrameDataDisplay(long index, FrameData fd) {
|
||||
isEnable = true;
|
||||
Reload(index, fd);
|
||||
}
|
||||
|
||||
public void Reload(long index, FrameData fd) {
|
||||
this.index = index;
|
||||
this.deltaTime = fd.deltaTime;
|
||||
this.keystates = fd.keystates;
|
||||
}
|
||||
|
||||
public bool isEnable { get; set; }
|
||||
public long index { get; set; }
|
||||
public float deltaTime { get; set; }
|
||||
public UInt32 keystates {
|
||||
get {
|
||||
UInt32 result = 0;
|
||||
if (key_enter) result |= 1; result <<= 1;
|
||||
if (key_esc) result |= 1; result <<= 1;
|
||||
if (key_q) result |= 1; result <<= 1;
|
||||
if (key_space) result |= 1; result <<= 1;
|
||||
if (key_shift) result |= 1; result <<= 1;
|
||||
if (key_right) result |= 1; result <<= 1;
|
||||
if (key_left) result |= 1; result <<= 1;
|
||||
if (key_down) result |= 1; result <<= 1;
|
||||
if (key_up) result |= 1; result <<= 1;
|
||||
|
||||
return result;
|
||||
}
|
||||
set {
|
||||
key_up = (value & (1 << 0)).ToBool();
|
||||
key_down = (value & (1 << 1)).ToBool();
|
||||
key_left = (value & (1 << 2)).ToBool();
|
||||
key_right = (value & (1 << 3)).ToBool();
|
||||
key_shift = (value & (1 << 4)).ToBool();
|
||||
key_space = (value & (1 << 5)).ToBool();
|
||||
key_q = (value & (1 << 6)).ToBool();
|
||||
key_esc = (value & (1 << 7)).ToBool();
|
||||
key_enter = (value & (1 << 8)).ToBool();
|
||||
}
|
||||
}
|
||||
public bool key_up { get; set; }
|
||||
public bool key_down { get; set; }
|
||||
public bool key_left { get; set; }
|
||||
public bool key_right { get; set; }
|
||||
public bool key_shift { get; set; }
|
||||
public bool key_space { get; set; }
|
||||
public bool key_q { get; set; }
|
||||
public bool key_esc { get; set; }
|
||||
public bool key_enter { get; set; }
|
||||
}
|
||||
|
||||
public class FrameData {
|
||||
|
||||
public FrameData(Stream st) {
|
||||
var temp = new byte[ConstValue.FRAMEDATA_SIZE];
|
||||
st.Read(temp, 0, ConstValue.FRAMEDATA_SIZE);
|
||||
|
||||
deltaTime = BitConverter.ToSingle(temp, ConstValue.FRAMEDATA_OFFSET_DELTATIME);
|
||||
keystates = BitConverter.ToUInt32(temp, ConstValue.FRAMEDATA_OFFSET_KEY_STATES);
|
||||
}
|
||||
public FrameData(FrameDataDisplay fdd) {
|
||||
this.deltaTime = fdd.deltaTime;
|
||||
this.keystates = fdd.keystates;
|
||||
}
|
||||
|
||||
public FrameData() {
|
||||
this.deltaTime = 0f;
|
||||
this.keystates = 0;
|
||||
}
|
||||
|
||||
public FrameData(float d, UInt32 k) {
|
||||
this.deltaTime = d;
|
||||
this.keystates = k;
|
||||
}
|
||||
|
||||
public void SetKeyStates(UInt32 offset) {
|
||||
keystates |= offset;
|
||||
}
|
||||
|
||||
public void UnsetKeyStates(UInt32 offset) {
|
||||
keystates &= ~offset;
|
||||
}
|
||||
|
||||
public void ReverseKeyStates(UInt32 offset) {
|
||||
keystates ^= offset;
|
||||
}
|
||||
|
||||
public float deltaTime;
|
||||
public UInt32 keystates;
|
||||
}
|
||||
|
||||
public class ConstValue {
|
||||
public static readonly Dictionary<FrameDataField, UInt32> Mapping = new Dictionary<FrameDataField, UInt32>() {
|
||||
{FrameDataField.Key_Up, (1 << 0)},
|
||||
{FrameDataField.Key_Down, (1 << 1)},
|
||||
{FrameDataField.Key_Left, (1 << 2)},
|
||||
{FrameDataField.Key_Right, (1 << 3)},
|
||||
{FrameDataField.Key_Shift, (1 << 4)},
|
||||
{FrameDataField.Key_Space, (1 << 5)},
|
||||
{FrameDataField.Key_Q, (1 << 6)},
|
||||
{FrameDataField.Key_Esc, (1 << 7)},
|
||||
{FrameDataField.Key_Enter, (1 << 8)}
|
||||
};
|
||||
public const int FRAMEDATA_SIZE = 8;
|
||||
public const int FRAMEDATA_OFFSET_DELTATIME = 0;
|
||||
public const int FRAMEDATA_OFFSET_KEY_STATES = 4;
|
||||
}
|
||||
|
||||
public enum FrameDataField : int {
|
||||
Key_Up = 0,
|
||||
Key_Down = 1,
|
||||
Key_Left = 2,
|
||||
Key_Right = 3,
|
||||
Key_Shift = 4,
|
||||
Key_Space = 5,
|
||||
Key_Q = 6,
|
||||
Key_Esc = 7,
|
||||
Key_Enter = 8
|
||||
}
|
||||
|
||||
}
|
||||
161
Legacy/BallanceTASEditor/Core/Util.cs
Normal file
161
Legacy/BallanceTASEditor/Core/Util.cs
Normal file
@ -0,0 +1,161 @@
|
||||
using BallanceTASEditor.Core.TASStruct;
|
||||
using BallanceTASEditor.UI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace BallanceTASEditor.Core {
|
||||
public static class Util {
|
||||
public static Int32 ToInt32(this double value) {
|
||||
return (Int32)Math.Floor(value);
|
||||
}
|
||||
public static Int64 ToInt64(this double value) {
|
||||
return (Int64)Math.Floor(value);
|
||||
}
|
||||
|
||||
public static int Clamp(int value, int min, int max) {
|
||||
if (value < min) return min;
|
||||
if (value > max) return max;
|
||||
return value;
|
||||
}
|
||||
|
||||
public static bool ToBool(this UInt32 num) {
|
||||
return (num != 0);
|
||||
}
|
||||
public static UInt32 ToUInt32(this bool b) {
|
||||
return (UInt32)(b ? 1 : 0);
|
||||
}
|
||||
//public static void RemoveRange(this ModifiedObservableCollection<FrameData> list, int index, int count) {
|
||||
// if (index >= list.Count) return;
|
||||
// if (index + count > list.Count) count = list.Count - index;
|
||||
// for (int i = 0; i < count; i++) list.RemoveAt(index);
|
||||
//}
|
||||
|
||||
// remove safety. because it store the next node.
|
||||
public static IEnumerable<LinkedListNode<FrameData>> IterateFullReversed(this LinkedList<FrameData> ls) {
|
||||
var pos = ls.Last;
|
||||
LinkedListNode<FrameData> cacheNextNode;
|
||||
|
||||
while (pos != null) {
|
||||
cacheNextNode = pos.Previous;
|
||||
yield return pos;
|
||||
pos = cacheNextNode;
|
||||
}
|
||||
}
|
||||
|
||||
// remove safety. because it store the next node.
|
||||
public static IEnumerable<LinkedListNode<FrameData>> IterateFull(this LinkedList<FrameData> ls) {
|
||||
var pos = ls.First;
|
||||
LinkedListNode<FrameData> cacheNextNode;
|
||||
|
||||
while(pos != null) {
|
||||
cacheNextNode = pos.Next;
|
||||
yield return pos;
|
||||
pos = cacheNextNode;
|
||||
}
|
||||
}
|
||||
|
||||
public static LinkedListNode<FrameData> FastGetNode(this LinkedList<FrameData> ls, LinkedListNode<FrameData> refNode, long refIndex, long targetIndex) {
|
||||
long count = ls.Count - 1;
|
||||
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 = targetIndex - count },
|
||||
new StupidSortStruct() { type = 3, data = targetIndex - refIndex }
|
||||
};
|
||||
|
||||
// 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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
// 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
|
||||
var cache = ls.FastGetNode(refNode, refIndex, absoluteRange.start);
|
||||
|
||||
var counter = absoluteRange.start;
|
||||
LinkedListNode<FrameData> cacheNextNode;
|
||||
while (counter <= absoluteRange.end) {
|
||||
if (cache == null) throw new Exception("Unexpected head or tail of linked list!");
|
||||
cacheNextNode = cache.Next;
|
||||
yield return cache;
|
||||
cache = cacheNextNode;
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
public static LinkedListNode<FrameData> ShiftTo(this LinkedListNode<FrameData> node, long offset) {
|
||||
var cache = node;
|
||||
|
||||
long realShifted = 0;
|
||||
if (offset < 0) {
|
||||
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) {
|
||||
if (cache.Next == null) throw new Exception("Unexpected head or tail of linked list!");
|
||||
cache = cache.Next;
|
||||
realShifted++;
|
||||
}
|
||||
}
|
||||
|
||||
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 + 1;
|
||||
}
|
||||
}
|
||||
|
||||
public struct StupidSortStruct {
|
||||
public int type;
|
||||
public long data;
|
||||
}
|
||||
|
||||
}
|
||||
84
Legacy/BallanceTASEditor/Core/ZlibUtil.cs
Normal file
84
Legacy/BallanceTASEditor/Core/ZlibUtil.cs
Normal file
@ -0,0 +1,84 @@
|
||||
using BallanceTASEditor.Core.TASStruct;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace BallanceTASEditor.Core {
|
||||
public class ZlibUtil {
|
||||
private const int COPY_STREAM_UNIT = 1024;
|
||||
|
||||
public static void CompressTAS(LinkedList<FrameData> mem, FileStream file) {
|
||||
file.Write(BitConverter.GetBytes(mem.Count * ConstValue.FRAMEDATA_SIZE), 0, 4);
|
||||
|
||||
using (var zo = new Ionic.Zlib.ZlibStream(file, Ionic.Zlib.CompressionMode.Compress, Ionic.Zlib.CompressionLevel.Level9, true)) {
|
||||
var node = mem.First;
|
||||
while (node != null) {
|
||||
zo.Write(BitConverter.GetBytes(node.Value.deltaTime), 0, 4);
|
||||
zo.Write(BitConverter.GetBytes(node.Value.keystates), 0, 4);
|
||||
node = node.Next;
|
||||
}
|
||||
zo.Close();
|
||||
}
|
||||
|
||||
//var zo = new zlib.ZOutputStream(file, 9);
|
||||
//var node = mem.First;
|
||||
//while (node != null) {
|
||||
// zo.Write(BitConverter.GetBytes(node.Value.deltaTime), 0, 4);
|
||||
// zo.Write(BitConverter.GetBytes(node.Value.keystates), 0, 4);
|
||||
// node = node.Next;
|
||||
//}
|
||||
//zo.finish();
|
||||
//zo.Close();
|
||||
}
|
||||
|
||||
public static void DecompressTAS(LinkedList<FrameData> ls, FileStream file) {
|
||||
var lengthTemp = new byte[4];
|
||||
file.Read(lengthTemp, 0, 4);
|
||||
Int32 expectedLength = BitConverter.ToInt32(lengthTemp, 0);
|
||||
long expectedCount = expectedLength / ConstValue.FRAMEDATA_SIZE;
|
||||
|
||||
using (var mem = new MemoryStream()) {
|
||||
using (var zo = new Ionic.Zlib.ZlibStream(mem, Ionic.Zlib.CompressionMode.Decompress, true)) {
|
||||
CopyStream(file, zo);
|
||||
zo.Close();
|
||||
}
|
||||
|
||||
mem.Seek(0, SeekOrigin.Begin);
|
||||
for (long i = 0; i < expectedCount; i++) {
|
||||
ls.AddLast(new FrameData(mem));
|
||||
}
|
||||
mem.Close();
|
||||
}
|
||||
|
||||
//mem.Seek(0, SeekOrigin.Begin);
|
||||
//for (long i = 0; i < expectedCount; i++) {
|
||||
// ls.AddLast(new FrameData(mem));
|
||||
//}
|
||||
//mem.Close();
|
||||
//zo.Close();
|
||||
|
||||
//var zo = new zlib.ZOutputStream(mem);
|
||||
//CopyStream(file, zo);
|
||||
//zo.finish();
|
||||
|
||||
//mem.Seek(0, SeekOrigin.Begin);
|
||||
//for (long i = 0; i < expectedCount; i++) {
|
||||
// ls.AddLast(new FrameData(mem));
|
||||
//}
|
||||
//mem.Close();
|
||||
//zo.Close();
|
||||
}
|
||||
|
||||
public static void CopyStream(Stream origin, Stream target) {
|
||||
var buffer = new byte[COPY_STREAM_UNIT];
|
||||
int len;
|
||||
while ((len = origin.Read(buffer, 0, COPY_STREAM_UNIT)) > 0) {
|
||||
target.Write(buffer, 0, len);
|
||||
}
|
||||
//target.Flush();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
13
Legacy/BallanceTASEditor/GlobalVariable.cs
Normal file
13
Legacy/BallanceTASEditor/GlobalVariable.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BallanceTASEditor {
|
||||
public class GlobalVariable {
|
||||
|
||||
public static Core.ConfigManager configManager;
|
||||
|
||||
}
|
||||
}
|
||||
77
Legacy/BallanceTASEditor/Language/CHS.xaml
Normal file
77
Legacy/BallanceTASEditor/Language/CHS.xaml
Normal file
@ -0,0 +1,77 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:BallanceTASEditor.Language"
|
||||
xmlns:sys="clr-namespace:System;assembly=mscorlib">
|
||||
<!-- ui data-->
|
||||
<sys:String x:Key="ui_MainWindow_Title">Ballance TAS 编辑器</sys:String>
|
||||
|
||||
<sys:String x:Key="ui_MainWindow_Menu_File">文件</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_Menu_File_Open">打开</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_Menu_File_Save">保存</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_Menu_File_SaveAs">另存为...</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_Menu_File_Close">关闭</sys:String>
|
||||
|
||||
<sys:String x:Key="ui_MainWindow_Menu_Display">编辑</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_Menu_Display_Undo">撤销</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_Menu_Display_Redo">重做</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_Menu_Display_ItemCount">项个数</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_Menu_Display_OverwrittenPaste">覆盖式粘贴</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_Menu_Display_HorizontalLayout">横向布局</sys:String>
|
||||
|
||||
<sys:String x:Key="ui_MainWindow_Menu_Help">帮助</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_Menu_Help_ReportBugs">汇报漏洞</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_Menu_Help_About">关于</sys:String>
|
||||
|
||||
<sys:String x:Key="ui_MainWindow_EditorNote">打开或拖入一个 TAS 文件以编辑</sys:String>
|
||||
|
||||
<sys:String x:Key="ui_MainWindow_Tools_Cursor">选择模式</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_Tools_Fill">填充模式</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_Tools_Overwritten">画笔模式</sys:String>
|
||||
|
||||
<sys:String x:Key="ui_MainWindow_StatusBar_Mode_Cursor">选择模式</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_StatusBar_Mode_Fill">填充模式</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_StatusBar_Mode_Overwritten">画笔模式</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_StatusBar_OverwrittenPaste">覆盖式粘贴</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_StatusBar_Selected">已选择:</sys:String>
|
||||
|
||||
|
||||
<sys:String x:Key="ui_TASFlow_Sheet_Frame">帧</sys:String>
|
||||
<sys:String x:Key="ui_TASFlow_Sheet_DeltaTime">间隔时间</sys:String>
|
||||
|
||||
<sys:String x:Key="ui_TASFlow_Menu_Set">设置</sys:String>
|
||||
<sys:String x:Key="ui_TASFlow_Menu_Unset">不设置</sys:String>
|
||||
<sys:String x:Key="ui_TASFlow_Menu_Cut">剪切</sys:String>
|
||||
<sys:String x:Key="ui_TASFlow_Menu_Copy">复制</sys:String>
|
||||
<sys:String x:Key="ui_TASFlow_Menu_PasteAfter">粘贴于后方</sys:String>
|
||||
<sys:String x:Key="ui_TASFlow_Menu_PasteBefore">粘贴于前方</sys:String>
|
||||
<sys:String x:Key="ui_TASFlow_Menu_Delete">删除</sys:String>
|
||||
<sys:String x:Key="ui_TASFlow_Menu_DeleteAfter">向后删除</sys:String>
|
||||
<sys:String x:Key="ui_TASFlow_Menu_DeleteBefore">向前删除</sys:String>
|
||||
<sys:String x:Key="ui_TASFlow_Menu_AddAfter">在后方添加新项</sys:String>
|
||||
<sys:String x:Key="ui_TASFlow_Menu_AddBefore">在前方添加新项</sys:String>
|
||||
|
||||
<sys:String x:Key="ui_AddItem_Title">添加项</sys:String>
|
||||
<sys:String x:Key="ui_AddItem_Count">个数</sys:String>
|
||||
<sys:String x:Key="ui_AddItem_FPS">帧率</sys:String>
|
||||
<sys:String x:Key="ui_AddItem_DeltaTime">间隔时间</sys:String>
|
||||
<sys:String x:Key="ui_AddItem_OK">好</sys:String>
|
||||
<sys:String x:Key="ui_AddItem_Cancel">取消</sys:String>
|
||||
|
||||
<!-- code data-->
|
||||
|
||||
<sys:String x:Key="code_Shared_ProgramName">Ballance TAS 编辑器</sys:String>
|
||||
|
||||
<sys:String x:Key="code_MainWindow_Menu_Help_About" xml:space="preserve">基于 MIT 开源许可证发布
|
||||
版本:1.2 stable
|
||||
程序:yyc12345.
|
||||
图标设计:plAer_2</sys:String>
|
||||
<sys:String x:Key="code_MainWindow_Closing">文件未关闭。您想直接退出吗?所有修改不会被保存。</sys:String>
|
||||
<sys:String x:Key="code_MainWindow_Menu_File_Close">您想要关闭这个TAS文件吗?</sys:String>
|
||||
<sys:String x:Key="code_MainWindow_Menu_File_Open_Fail">无法打开文件,文件可能不是合法的TAS文件。</sys:String>
|
||||
<sys:String x:Key="code_MainWindow_Menu_Display_ItemCount">输入新的数量(<=5 && >=30)</sys:String>
|
||||
<sys:String x:Key="code_DialogUtil_Warning">警告</sys:String>
|
||||
<sys:String x:Key="code_DialogUtil_FileFilter">TAS 文件(*.tas)|*.tas|所有文件(*.*)|*.*</sys:String>
|
||||
<sys:String x:Key="code_DialogUtil_InputNumber_Title">输入数字</sys:String>
|
||||
<sys:String x:Key="code_DialogUtil_InputNumber_Wrong">无效的数字,请再试一次。</sys:String>
|
||||
|
||||
</ResourceDictionary>
|
||||
77
Legacy/BallanceTASEditor/Language/DefaultLanguage.xaml
Normal file
77
Legacy/BallanceTASEditor/Language/DefaultLanguage.xaml
Normal file
@ -0,0 +1,77 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:BallanceTASEditor.Language"
|
||||
xmlns:sys="clr-namespace:System;assembly=mscorlib">
|
||||
<!-- ui data-->
|
||||
<sys:String x:Key="ui_MainWindow_Title">Ballance TAS Editor</sys:String>
|
||||
|
||||
<sys:String x:Key="ui_MainWindow_Menu_File">File</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_Menu_File_Open">Open</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_Menu_File_Save">Save</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_Menu_File_SaveAs">Save As ...</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_Menu_File_Close">Close</sys:String>
|
||||
|
||||
<sys:String x:Key="ui_MainWindow_Menu_Display">Edit</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_Menu_Display_Undo">Undo</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_Menu_Display_Redo">Redo</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_Menu_Display_ItemCount">Item Count</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_Menu_Display_OverwrittenPaste">Overwritten Paste</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_Menu_Display_HorizontalLayout">Horizontal Layout</sys:String>
|
||||
|
||||
<sys:String x:Key="ui_MainWindow_Menu_Help">Help</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_Menu_Help_ReportBugs">Report Bugs</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_Menu_Help_About">About</sys:String>
|
||||
|
||||
<sys:String x:Key="ui_MainWindow_EditorNote">Open or drop a TAS file for editing</sys:String>
|
||||
|
||||
<sys:String x:Key="ui_MainWindow_Tools_Cursor">Select mode</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_Tools_Fill">Fill mode</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_Tools_Overwritten">Draw mode</sys:String>
|
||||
|
||||
<sys:String x:Key="ui_MainWindow_StatusBar_Mode_Cursor">Select mode</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_StatusBar_Mode_Fill">Fill mode</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_StatusBar_Mode_Overwritten">Draw mode</sys:String>
|
||||
<sys:String x:Key="ui_MainWindow_StatusBar_OverwrittenPaste">Overwritten paste</sys:String>
|
||||
<sys:String xml:space="preserve" x:Key="ui_MainWindow_StatusBar_Selected">Selected: </sys:String>
|
||||
|
||||
|
||||
<sys:String x:Key="ui_TASFlow_Sheet_Frame">Frame</sys:String>
|
||||
<sys:String x:Key="ui_TASFlow_Sheet_DeltaTime">Delta Time</sys:String>
|
||||
|
||||
<sys:String x:Key="ui_TASFlow_Menu_Set">Set</sys:String>
|
||||
<sys:String x:Key="ui_TASFlow_Menu_Unset">Unset</sys:String>
|
||||
<sys:String x:Key="ui_TASFlow_Menu_Cut">Cut</sys:String>
|
||||
<sys:String x:Key="ui_TASFlow_Menu_Copy">Copy</sys:String>
|
||||
<sys:String x:Key="ui_TASFlow_Menu_PasteAfter">Paste after this</sys:String>
|
||||
<sys:String x:Key="ui_TASFlow_Menu_PasteBefore">Paste before this</sys:String>
|
||||
<sys:String x:Key="ui_TASFlow_Menu_Delete">Delete</sys:String>
|
||||
<sys:String x:Key="ui_TASFlow_Menu_DeleteAfter">Delete this frame</sys:String>
|
||||
<sys:String x:Key="ui_TASFlow_Menu_DeleteBefore">Delete last frame</sys:String>
|
||||
<sys:String x:Key="ui_TASFlow_Menu_AddAfter">Add blank item after this</sys:String>
|
||||
<sys:String x:Key="ui_TASFlow_Menu_AddBefore">Add blank item before this</sys:String>
|
||||
|
||||
<sys:String x:Key="ui_AddItem_Title">Add Item</sys:String>
|
||||
<sys:String x:Key="ui_AddItem_Count">Count</sys:String>
|
||||
<sys:String x:Key="ui_AddItem_FPS">FPS</sys:String>
|
||||
<sys:String x:Key="ui_AddItem_DeltaTime">Delta Time</sys:String>
|
||||
<sys:String x:Key="ui_AddItem_OK">OK</sys:String>
|
||||
<sys:String x:Key="ui_AddItem_Cancel">Cancel</sys:String>
|
||||
|
||||
<!-- code data-->
|
||||
|
||||
<sys:String x:Key="code_Shared_ProgramName">Ballance TAS Editor</sys:String>
|
||||
|
||||
<sys:String x:Key="code_MainWindow_Menu_Help_About" xml:space="preserve">Under MIT License
|
||||
Version: 1.2 stable
|
||||
Program: yyc12345.
|
||||
Icon design: plAer_2</sys:String>
|
||||
<sys:String x:Key="code_MainWindow_Closing">File is not closed. Do you want to just quit? All changes will not be saved.</sys:String>
|
||||
<sys:String x:Key="code_MainWindow_Menu_File_Close">Do you want to close this TAS file?</sys:String>
|
||||
<sys:String x:Key="code_MainWindow_Menu_File_Open_Fail">Fail to open file. This file might not a legal TAS file.</sys:String>
|
||||
<sys:String x:Key="code_MainWindow_Menu_Display_ItemCount">Input new count (<=5 && >=30)</sys:String>
|
||||
<sys:String x:Key="code_DialogUtil_Warning">Warning</sys:String>
|
||||
<sys:String x:Key="code_DialogUtil_FileFilter">TAS file(*.tas)|*.tas|All file(*.*)|*.*</sys:String>
|
||||
<sys:String x:Key="code_DialogUtil_InputNumber_Title">Input number</sys:String>
|
||||
<sys:String x:Key="code_DialogUtil_InputNumber_Wrong">Invalid number. Please input again.</sys:String>
|
||||
|
||||
</ResourceDictionary>
|
||||
270
Legacy/BallanceTASEditor/MainWindow.xaml
Normal file
270
Legacy/BallanceTASEditor/MainWindow.xaml
Normal file
@ -0,0 +1,270 @@
|
||||
<Window x:Class="BallanceTASEditor.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:BallanceTASEditor"
|
||||
xmlns:controls="clr-namespace:BallanceTASEditor.UI"
|
||||
xmlns:input="clr-namespace:System.Windows.Input;assembly=PresentationCore"
|
||||
mc:Ignorable="d"
|
||||
Title="{DynamicResource ui_MainWindow_Title}" Height="500" Width="800" KeyUp="funcWindow_KeyUp"
|
||||
input:InputMethod.IsInputMethodEnabled="False" MouseWheel="funcWindow_MouseWheel" Icon="icon.ico" Closing="funcWindow_Closing">
|
||||
|
||||
<!-- shortcut defination-->
|
||||
<Window.Resources>
|
||||
<RoutedUICommand x:Key="commandMenu_File_Open"/>
|
||||
<RoutedUICommand x:Key="commandMenu_File_Save"/>
|
||||
<RoutedUICommand x:Key="commandMenu_Display_Undo"/>
|
||||
<RoutedUICommand x:Key="commandMenu_Display_Redo"/>
|
||||
<RoutedUICommand x:Key="commandDataMenu_Cut"/>
|
||||
<RoutedUICommand x:Key="commandDataMenu_Copy"/>
|
||||
<RoutedUICommand x:Key="commandDataMenu_PasteAfter"/>
|
||||
<RoutedUICommand x:Key="commandDataMenu_DeleteAfter"/>
|
||||
<RoutedUICommand x:Key="commandDataMenu_DeleteBefore"/>
|
||||
</Window.Resources>
|
||||
|
||||
<Window.InputBindings>
|
||||
<KeyBinding Gesture="Ctrl+O" Command="{StaticResource commandMenu_File_Open}"/>
|
||||
<KeyBinding Gesture="Ctrl+S" Command="{StaticResource commandMenu_File_Save}"/>
|
||||
<KeyBinding Gesture="Ctrl+Z" Command="{StaticResource commandMenu_Display_Undo}"/>
|
||||
<KeyBinding Gesture="Ctrl+Y" Command="{StaticResource commandMenu_Display_Redo}"/>
|
||||
<KeyBinding Gesture="Ctrl+X" Command="{StaticResource commandDataMenu_Cut}"/>
|
||||
<KeyBinding Gesture="Ctrl+C" Command="{StaticResource commandDataMenu_Copy}"/>
|
||||
<KeyBinding Gesture="Ctrl+V" Command="{StaticResource commandDataMenu_PasteAfter}"/>
|
||||
<KeyBinding Gesture="Delete" Command="{StaticResource commandDataMenu_DeleteAfter}"/>
|
||||
<KeyBinding Gesture="Back" Command="{StaticResource commandDataMenu_DeleteBefore}"/>
|
||||
</Window.InputBindings>
|
||||
|
||||
<Window.CommandBindings>
|
||||
<CommandBinding Command="{StaticResource commandMenu_File_Open}" Executed="funcCommand_Menu_File_Open" CanExecute="funcCanExeCmd_Menu_File_Open"/>
|
||||
<CommandBinding Command="{StaticResource commandMenu_File_Save}" Executed="funcCommand_Menu_File_Save" CanExecute="funcCanExeCmd_Menu_File_Save"/>
|
||||
<CommandBinding Command="{StaticResource commandMenu_Display_Undo}" Executed="funcCommand_Menu_Display_Undo" CanExecute="funcCanExeCmd_Menu_Display_Undo"/>
|
||||
<CommandBinding Command="{StaticResource commandMenu_Display_Redo}" Executed="funcCommand_Menu_Display_Redo" CanExecute="funcCanExeCmd_Menu_Display_Redo"/>
|
||||
<CommandBinding Command="{StaticResource commandDataMenu_Cut}" Executed="funcCommand_DataMenu_Cut" CanExecute="funcCanExeCmd_DataMenu_Cut"/>
|
||||
<CommandBinding Command="{StaticResource commandDataMenu_Copy}" Executed="funcCommand_DataMenu_Copy" CanExecute="funcCanExeCmd_DataMenu_Copy"/>
|
||||
<CommandBinding Command="{StaticResource commandDataMenu_PasteAfter}" Executed="funcCommand_DataMenu_PasteAfter" CanExecute="funcCanExeCmd_DataMenu_PasteAfter"/>
|
||||
<CommandBinding Command="{StaticResource commandDataMenu_DeleteAfter}" Executed="funcCommand_DataMenu_DeleteAfter" CanExecute="funcCanExeCmd_DataMenu_DeleteAfter"/>
|
||||
<CommandBinding Command="{StaticResource commandDataMenu_DeleteBefore}" Executed="funcCommand_DataMenu_DeleteBefore" CanExecute="funcCanExeCmd_DataMenu_DeleteBefore"/>
|
||||
</Window.CommandBindings>
|
||||
|
||||
<!-- real ui elements-->
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Menu Grid.Row="0">
|
||||
<MenuItem Header="{DynamicResource ui_MainWindow_Menu_File}">
|
||||
<MenuItem x:Name="uiMenu_File_Open" Header="{DynamicResource ui_MainWindow_Menu_File_Open}" Click="funcMenu_File_Open" InputGestureText="Ctrl + O"/>
|
||||
<MenuItem x:Name="uiMenu_File_Save" Header="{DynamicResource ui_MainWindow_Menu_File_Save}" Click="funcMenu_File_Save" InputGestureText="Ctrl + S"/>
|
||||
<MenuItem x:Name="uiMenu_File_SaveAs" Header="{DynamicResource ui_MainWindow_Menu_File_SaveAs}" Click="funcMenu_File_SaveAs"/>
|
||||
<MenuItem x:Name="uiMenu_File_Close" Header="{DynamicResource ui_MainWindow_Menu_File_Close}" Click="funcMenu_File_Close"/>
|
||||
</MenuItem>
|
||||
<MenuItem Header="{DynamicResource ui_MainWindow_Menu_Display}">
|
||||
<MenuItem x:Name="uiMenu_Display_Undo" Header="{DynamicResource ui_MainWindow_Menu_Display_Undo}" Click="funcMenu_Display_Undo" InputGestureText="Ctrl + Z"/>
|
||||
<MenuItem x:Name="uiMenu_Display_Redo" Header="{DynamicResource ui_MainWindow_Menu_Display_Redo}" Click="funcMenu_Display_Redo" InputGestureText="Ctrl + Y"/>
|
||||
<Separator/>
|
||||
<MenuItem x:Name="uiMenu_Display_ItemCount" Header="{DynamicResource ui_MainWindow_Menu_Display_ItemCount}" Click="funcMenu_Display_ItemCount"/>
|
||||
<Separator/>
|
||||
<MenuItem x:Name="uiMenu_Display_OverwrittenPaste" Header="{DynamicResource ui_MainWindow_Menu_Display_OverwrittenPaste}" Click="funcMenu_Display_OverwrittenPaste"/>
|
||||
<MenuItem x:Name="uiMenu_Display_HorizontalLayout" Header="{DynamicResource ui_MainWindow_Menu_Display_HorizontalLayout}" Click="funcMenu_Display_HorizontalLayout"/>
|
||||
</MenuItem>
|
||||
<MenuItem Header="{DynamicResource ui_MainWindow_Menu_Help}">
|
||||
<MenuItem x:Name="uiMenu_Help_ReportBugs" Header="{DynamicResource ui_MainWindow_Menu_Help_ReportBugs}" Click="funcMenu_Help_ReportBugs"/>
|
||||
<MenuItem x:Name="uiMenu_Help_About" Header="{DynamicResource ui_MainWindow_Menu_Help_About}" Click="funcMenu_Help_About"/>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
|
||||
<Grid x:Name="uiEditorNote" Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Center" AllowDrop="True" Drop="funcDrop_Drop" DragEnter="funcDrop_DragEnter" Visibility="Collapsed">
|
||||
<Rectangle StrokeThickness="4" Stroke="Gray" StrokeDashArray="4 4" Fill="#ffffff"/>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Viewbox Width="24" Height="24" Margin="20, 20, 0, 20" VerticalAlignment="Center">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="Gray" Data="M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
<TextBlock Margin="20" Text="{DynamicResource ui_MainWindow_EditorNote}" Foreground="Gray" FontSize="16" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
|
||||
</Grid>
|
||||
|
||||
<Grid x:Name="uiEditorPanel" Grid.Row="1">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Grid.Row="0" Grid.ColumnSpan="2">
|
||||
<Button x:Name="uiBtn_Cursor" Margin="5" Padding="5" Click="funcBtn_Cursor">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Viewbox Width="24" Height="24">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="Black" Data="M10.07,14.27C10.57,14.03 11.16,14.25 11.4,14.75L13.7,19.74L15.5,18.89L13.19,13.91C12.95,13.41 13.17,12.81 13.67,12.58L13.95,12.5L16.25,12.05L8,5.12V15.9L9.82,14.43L10.07,14.27M13.64,21.97C13.14,22.21 12.54,22 12.31,21.5L10.13,16.76L7.62,18.78C7.45,18.92 7.24,19 7,19A1,1 0 0,1 6,18V3A1,1 0 0,1 7,2C7.24,2 7.47,2.09 7.64,2.23L7.65,2.22L19.14,11.86C19.57,12.22 19.62,12.85 19.27,13.27C19.12,13.45 18.91,13.57 18.7,13.61L15.54,14.23L17.74,18.96C18,19.46 17.76,20.05 17.26,20.28L13.64,21.97Z" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
<TextBlock Text="{DynamicResource ui_MainWindow_Tools_Cursor}" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button x:Name="uiBtn_Fill" Margin="5" Padding="5" Click="funcBtn_Fill">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Viewbox Width="24" Height="24">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="Black" Data="M19,11.5C19,11.5 17,13.67 17,15A2,2 0 0,0 19,17A2,2 0 0,0 21,15C21,13.67 19,11.5 19,11.5M5.21,10L10,5.21L14.79,10M16.56,8.94L7.62,0L6.21,1.41L8.59,3.79L3.44,8.94C2.85,9.5 2.85,10.47 3.44,11.06L8.94,16.56C9.23,16.85 9.62,17 10,17C10.38,17 10.77,16.85 11.06,16.56L16.56,11.06C17.15,10.47 17.15,9.5 16.56,8.94Z" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
<TextBlock Text="{DynamicResource ui_MainWindow_Tools_Fill}" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button x:Name="uiBtn_Overwrite" Margin="5" Padding="5" Click="funcBtn_Overwrite">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Viewbox Width="24" Height="24">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="Black" Data="M18.62,1.5C18.11,1.5 17.6,1.69 17.21,2.09L10.75,8.55L14.95,12.74L21.41,6.29C22.2,5.5 22.2,4.24 21.41,3.46L20.04,2.09C19.65,1.69 19.14,1.5 18.62,1.5M9.8,9.5L3.23,16.07L3.93,16.77C3.4,17.24 2.89,17.78 2.38,18.29C1.6,19.08 1.6,20.34 2.38,21.12C3.16,21.9 4.42,21.9 5.21,21.12C5.72,20.63 6.25,20.08 6.73,19.58L7.43,20.27L14,13.7" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
<TextBlock Text="{DynamicResource ui_MainWindow_Tools_Overwritten}" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
|
||||
<Grid x:Name="uiLayoutContainer" Grid.Row="1">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Border x:Name="uiTASFlowContainer" BorderThickness="1" BorderBrush="Gray" Grid.Row="0" Margin="5" Background="#ffffff">
|
||||
<Grid x:Name="uiTASData">
|
||||
<Grid.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem x:Name="uiDataMenu_Set" Header="{DynamicResource ui_TASFlow_Menu_Set}" Click="funcDataMenu_Set"/>
|
||||
<MenuItem x:Name="uiDataMenu_Unset" Header="{DynamicResource ui_TASFlow_Menu_Unset}" Click="funcDataMenu_Unset"/>
|
||||
<Separator/>
|
||||
<MenuItem x:Name="uiDataMenu_Cut" Header="{DynamicResource ui_TASFlow_Menu_Cut}" Click="funcDataMenu_Cut" InputGestureText="Ctrl + X"/>
|
||||
<MenuItem x:Name="uiDataMenu_Copy" Header="{DynamicResource ui_TASFlow_Menu_Copy}" Click="funcDataMenu_Copy" InputGestureText="Ctrl + C"/>
|
||||
<MenuItem x:Name="uiDataMenu_PasteAfter" Header="{DynamicResource ui_TASFlow_Menu_PasteAfter}" Click="funcDataMenu_PasteAfter" InputGestureText="Ctrl + V"/>
|
||||
<MenuItem x:Name="uiDataMenu_PasteBefore" Header="{DynamicResource ui_TASFlow_Menu_PasteBefore}" Click="funcDataMenu_PasteBefore"/>
|
||||
<Separator/>
|
||||
<MenuItem x:Name="uiDataMenu_Delete" Header="{DynamicResource ui_TASFlow_Menu_Delete}" Click="funcDataMenu_Delete"/>
|
||||
<MenuItem x:Name="uiDataMenu_DeleteAfter" Header="{DynamicResource ui_TASFlow_Menu_DeleteAfter}" Click="funcDataMenu_DeleteAfter" InputGestureText="Del"/>
|
||||
<MenuItem x:Name="uiDataMenu_DeleteBefore" Header="{DynamicResource ui_TASFlow_Menu_DeleteBefore}" Click="funcDataMenu_DeleteBefore" InputGestureText="Backspace"/>
|
||||
<Separator/>
|
||||
<MenuItem x:Name="uiDataMenu_AddAfter" Header="{DynamicResource ui_TASFlow_Menu_AddAfter}" Click="funcDataMenu_AddAfter"/>
|
||||
<MenuItem x:Name="uiDataMenu_AddBefore" Header="{DynamicResource ui_TASFlow_Menu_AddBefore}" Click="funcDataMenu_AddBefore"/>
|
||||
</ContextMenu>
|
||||
</Grid.ContextMenu>
|
||||
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock x:Name="uiFlowHeader_Frame" Padding="2" Background="#afafaf" Grid.Column="0" Grid.Row="1" Text="{DynamicResource ui_TASFlow_Sheet_Frame}"/>
|
||||
<TextBlock x:Name="uiFlowHeader_DeltaTime" Padding="2" Background="#afafaf" Grid.Column="0" Grid.Row="2" Text="{DynamicResource ui_TASFlow_Sheet_DeltaTime}"/>
|
||||
<TextBlock x:Name="uiFlowHeader_Up" Padding="2" Background="#afafaf" Grid.Column="0" Grid.Row="3" Text="^"/>
|
||||
<TextBlock x:Name="uiFlowHeader_Down" Padding="2" Background="#afafaf" Grid.Column="0" Grid.Row="4" Text="v"/>
|
||||
<TextBlock x:Name="uiFlowHeader_Left" Padding="2" Background="#afafaf" Grid.Column="0" Grid.Row="5" Text="<"/>
|
||||
<TextBlock x:Name="uiFlowHeader_Right" Padding="2" Background="#afafaf" Grid.Column="0" Grid.Row="6" Text=">"/>
|
||||
<TextBlock x:Name="uiFlowHeader_Shift" Padding="2" Background="#afafaf" Grid.Column="0" Grid.Row="7" Text="shift"/>
|
||||
<TextBlock x:Name="uiFlowHeader_Space" Padding="2" Background="#afafaf" Grid.Column="0" Grid.Row="8" Text="space"/>
|
||||
<TextBlock x:Name="uiFlowHeader_Q" Padding="2" Background="#afafaf" Grid.Column="0" Grid.Row="9" Text="q"/>
|
||||
<TextBlock x:Name="uiFlowHeader_Esc" Padding="2" Background="#afafaf" Grid.Column="0" Grid.Row="10" Text="esc"/>
|
||||
<TextBlock x:Name="uiFlowHeader_Enter" Padding="2" Background="#afafaf" Grid.Column="0" Grid.Row="11" Text="enter"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<Grid x:Name="uiTASSliderContainer" Grid.Row="1" Margin="5">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Button x:Name="uiBtn_FastMovePrev" Grid.Column="0" Margin="2" HorizontalAlignment="Center" Click="funcBtn_FastMovePrev" RenderTransformOrigin="0.5, 0.5">
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="Black" Data="M11.5,12L20,18V6M11,18V6L2.5,12L11,18Z" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</Button>
|
||||
<Button x:Name="uiBtn_MovePrev" Grid.Column="1" Margin="2" HorizontalAlignment="Center" Click="funcBtn_MovePrev" RenderTransformOrigin="0.5, 0.5">
|
||||
<Viewbox Width="16" Height="16" RenderTransformOrigin="0.5,0.5">
|
||||
<Viewbox.RenderTransform>
|
||||
<RotateTransform Angle="-90"/>
|
||||
</Viewbox.RenderTransform>
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="Black" Data="M7,15L12,10L17,15H7Z" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</Button>
|
||||
<Button x:Name="uiBtn_MoveNext" Grid.Column="2" Margin="2" HorizontalAlignment="Center" Click="funcBtn_MoveNext" RenderTransformOrigin="0.5, 0.5">
|
||||
<Viewbox Width="16" Height="16" RenderTransformOrigin="0.5,0.5">
|
||||
<Viewbox.RenderTransform>
|
||||
<RotateTransform Angle="-90"/>
|
||||
</Viewbox.RenderTransform>
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="Black" Data="M7,10L12,15L17,10H7Z" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</Button>
|
||||
<Button x:Name="uiBtn_FastMoveNext" Grid.Column="3" Margin="2" HorizontalAlignment="Center" Click="funcBtn_FastMoveNext" RenderTransformOrigin="0.5, 0.5">
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="Black" Data="M13,6V18L21.5,12M4,18L12.5,12L4,6V18Z" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</Button>
|
||||
<Slider x:Name="uiTASSlider" Margin="2" Grid.Column="4" SmallChange="1" LargeChange="10" Maximum="1" VerticalAlignment="Center" RenderTransformOrigin="0.5, 0.5">
|
||||
</Slider>
|
||||
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
|
||||
<StatusBar x:Name="uiStatusbar" Grid.Row="2">
|
||||
<StatusBarItem x:Name="uiStatusbar_Runtime_Mode">
|
||||
<Grid>
|
||||
<TextBlock x:Name="uiStatusbar_Mode_Cursor" Text="{DynamicResource ui_MainWindow_StatusBar_Mode_Cursor}"/>
|
||||
<TextBlock x:Name="uiStatusbar_Mode_Fill" Text="{DynamicResource ui_MainWindow_StatusBar_Mode_Fill}"/>
|
||||
<TextBlock x:Name="uiStatusbar_Mode_Overwrite" Text="{DynamicResource ui_MainWindow_StatusBar_Mode_Overwritten}"/>
|
||||
</Grid>
|
||||
</StatusBarItem>
|
||||
<Separator x:Name="uiStatusbar_Runtime_Separator1"/>
|
||||
<StatusBarItem x:Name="uiStatusbar_Runtime_PasteMode">
|
||||
<TextBlock x:Name="uiStatusbar_OverwrittenPaste" Text="{DynamicResource ui_MainWindow_StatusBar_OverwrittenPaste}"/>
|
||||
</StatusBarItem>
|
||||
<Separator x:Name="uiStatusbar_Runtime_Separator2"/>
|
||||
<StatusBarItem x:Name="uiStatusbar_Runtime_Selected">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{DynamicResource ui_MainWindow_StatusBar_Selected}"/>
|
||||
<TextBlock x:Name="uiStatusbar_Selected" Text="-"/>
|
||||
</StackPanel>
|
||||
</StatusBarItem>
|
||||
|
||||
<StatusBarItem DockPanel.Dock="Right" HorizontalAlignment="Right">
|
||||
<TextBlock Text="v1.2 stable" Foreground="Gray" FontStyle="Italic"/>
|
||||
</StatusBarItem>
|
||||
</StatusBar>
|
||||
|
||||
</Grid>
|
||||
</Window>
|
||||
511
Legacy/BallanceTASEditor/MainWindow.xaml.cs
Normal file
511
Legacy/BallanceTASEditor/MainWindow.xaml.cs
Normal file
@ -0,0 +1,511 @@
|
||||
using BallanceTASEditor.Core;
|
||||
using BallanceTASEditor.Core.TASStruct;
|
||||
using BallanceTASEditor.UI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace BallanceTASEditor {
|
||||
/// <summary>
|
||||
/// MainWindow.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class MainWindow : Window {
|
||||
public MainWindow() {
|
||||
InitializeComponent();
|
||||
mIsHorizontalLayout = true;
|
||||
|
||||
// init layout controller
|
||||
var headers = new List<TextBlock>();
|
||||
headers.Add(uiFlowHeader_Frame);
|
||||
headers.Add(uiFlowHeader_DeltaTime);
|
||||
headers.Add(uiFlowHeader_Up);
|
||||
headers.Add(uiFlowHeader_Down);
|
||||
headers.Add(uiFlowHeader_Left);
|
||||
headers.Add(uiFlowHeader_Right);
|
||||
headers.Add(uiFlowHeader_Shift);
|
||||
headers.Add(uiFlowHeader_Space);
|
||||
headers.Add(uiFlowHeader_Q);
|
||||
headers.Add(uiFlowHeader_Esc);
|
||||
headers.Add(uiFlowHeader_Enter);
|
||||
mFlow = new TASFlow(uiTASData, headers.ToArray());
|
||||
|
||||
var components = new TASSliderComponents();
|
||||
components.container = uiTASSliderContainer;
|
||||
components.btnFastPrev = uiBtn_FastMovePrev;
|
||||
components.btnPrev = uiBtn_MovePrev;
|
||||
components.btnNext = uiBtn_MoveNext;
|
||||
components.btnFastNext = uiBtn_FastMoveNext;
|
||||
components.mSlider = uiTASSlider;
|
||||
mSlider = new TASSlider(components); ;
|
||||
|
||||
// refresh ui and load cfg
|
||||
RefreshUI(false);
|
||||
ApplyConfigureManager();
|
||||
}
|
||||
|
||||
TASFile mFile;
|
||||
TASViewer mViewer;
|
||||
TASFlow mFlow;
|
||||
TASSlider mSlider;
|
||||
bool mIsHorizontalLayout;
|
||||
|
||||
#region ui func
|
||||
|
||||
// shortcut
|
||||
|
||||
private void funcCommand_Menu_File_Open(object sender, ExecutedRoutedEventArgs e) => funcMenu_File_Open(sender, e);
|
||||
private void funcCommand_Menu_File_Save(object sender, ExecutedRoutedEventArgs e) => funcMenu_File_Save(sender, e);
|
||||
private void funcCommand_Menu_Display_Undo(object sender, ExecutedRoutedEventArgs e) => funcMenu_Display_Undo(sender, e);
|
||||
private void funcCommand_Menu_Display_Redo(object sender, ExecutedRoutedEventArgs e) => funcMenu_Display_Redo(sender, e);
|
||||
private void funcCommand_DataMenu_Cut(object sender, ExecutedRoutedEventArgs e) => funcDataMenu_Cut(sender, e);
|
||||
private void funcCommand_DataMenu_Copy(object sender, ExecutedRoutedEventArgs e) => funcDataMenu_Copy(sender, e);
|
||||
private void funcCommand_DataMenu_PasteAfter(object sender, ExecutedRoutedEventArgs e) => funcDataMenu_PasteAfter(sender, e);
|
||||
private void funcCommand_DataMenu_DeleteAfter(object sender, ExecutedRoutedEventArgs e) => funcDataMenu_DeleteAfter(sender, e);
|
||||
private void funcCommand_DataMenu_DeleteBefore(object sender, ExecutedRoutedEventArgs e) => funcDataMenu_DeleteBefore(sender, e);
|
||||
private void funcCanExeCmd_Menu_File_Open(object sender, CanExecuteRoutedEventArgs e) => e.CanExecute = uiMenu_File_Open.IsEnabled;
|
||||
private void funcCanExeCmd_Menu_File_Save(object sender, CanExecuteRoutedEventArgs e) => e.CanExecute = uiMenu_File_Save.IsEnabled;
|
||||
private void funcCanExeCmd_Menu_Display_Undo(object sender, CanExecuteRoutedEventArgs e) => e.CanExecute = uiMenu_Display_Undo.IsEnabled;
|
||||
private void funcCanExeCmd_Menu_Display_Redo(object sender, CanExecuteRoutedEventArgs e) => e.CanExecute = uiMenu_Display_Redo.IsEnabled;
|
||||
private void funcCanExeCmd_DataMenu_Cut(object sender, CanExecuteRoutedEventArgs e) => e.CanExecute = mViewer != null && uiDataMenu_Cut.IsEnabled;
|
||||
private void funcCanExeCmd_DataMenu_Copy(object sender, CanExecuteRoutedEventArgs e) => e.CanExecute = mViewer != null && uiDataMenu_Copy.IsEnabled;
|
||||
private void funcCanExeCmd_DataMenu_PasteAfter(object sender, CanExecuteRoutedEventArgs e) => e.CanExecute = mViewer != null && uiDataMenu_PasteAfter.IsEnabled;
|
||||
private void funcCanExeCmd_DataMenu_DeleteAfter(object sender, CanExecuteRoutedEventArgs e) => e.CanExecute = mViewer != null && uiDataMenu_DeleteAfter.IsEnabled;
|
||||
private void funcCanExeCmd_DataMenu_DeleteBefore(object sender, CanExecuteRoutedEventArgs e) => e.CanExecute = mViewer != null && uiDataMenu_DeleteBefore.IsEnabled;
|
||||
|
||||
// =========================== menu
|
||||
#region window menu
|
||||
|
||||
private void funcMenu_Help_ReportBugs(object sender, RoutedEventArgs e) {
|
||||
System.Diagnostics.Process.Start("https://github.com/yyc12345/BallanceTASEditor/issues");
|
||||
}
|
||||
|
||||
private void funcMenu_Help_About(object sender, RoutedEventArgs e) {
|
||||
MessageBox.Show(I18NProcessor.GetI18N("code_MainWindow_Menu_Help_About"),
|
||||
I18NProcessor.GetI18N("code_Shared_ProgramName"),
|
||||
MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
|
||||
private void funcMenu_File_Open(object sender, RoutedEventArgs e) {
|
||||
var file = DialogUtil.OpenFileDialog();
|
||||
if (file == "") return;
|
||||
OpenFile(file);
|
||||
}
|
||||
|
||||
private void funcMenu_File_Save(object sender, RoutedEventArgs e) {
|
||||
mFile.Save();
|
||||
}
|
||||
|
||||
private void funcMenu_File_SaveAs(object sender, RoutedEventArgs e) {
|
||||
var file = DialogUtil.SaveFileDialog();
|
||||
if (file == "") return;
|
||||
mFile.SaveAs(file);
|
||||
}
|
||||
|
||||
private void funcMenu_File_Close(object sender, RoutedEventArgs e) {
|
||||
if (!DialogUtil.ConfirmDialog(I18NProcessor.GetI18N("code_MainWindow_Menu_File_Close"))) return;
|
||||
|
||||
mViewer.UpdateDataUI -= RefreshDataUI;
|
||||
mViewer.UpdateSelection -= RefreshSelection;
|
||||
mViewer.UpdateToolMode -= RefreshToolMode;
|
||||
|
||||
mViewer.Dispose();
|
||||
mFile = null;
|
||||
mViewer = null;
|
||||
RefreshUI(false);
|
||||
}
|
||||
|
||||
private void funcWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
|
||||
if (!(mFile is null)) {
|
||||
if (!DialogUtil.ConfirmDialog(I18NProcessor.GetI18N("code_MainWindow_Closing"))) {
|
||||
e.Cancel = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void funcMenu_Display_ItemCount(object sender, RoutedEventArgs e) {
|
||||
int newvalue = 0;
|
||||
if (DialogUtil.InputNumber(I18NProcessor.GetI18N("code_MainWindow_Menu_Display_ItemCount"), 5, 30, ref newvalue)) {
|
||||
ChangeItemCount(newvalue);
|
||||
}
|
||||
}
|
||||
|
||||
private void funcMenu_Display_OverwrittenPaste(object sender, RoutedEventArgs e) {
|
||||
uiMenu_Display_OverwrittenPaste.IsChecked = !uiMenu_Display_OverwrittenPaste.IsChecked;
|
||||
uiStatusbar_OverwrittenPaste.Visibility = uiMenu_Display_OverwrittenPaste.IsChecked ? Visibility.Visible : Visibility.Hidden;
|
||||
|
||||
GlobalVariable.configManager.Configuration[ConfigManager.CfgNode_IsOverwrittenPaste] = uiMenu_Display_OverwrittenPaste.IsChecked.ToString();
|
||||
if (mViewer != null)
|
||||
mViewer.ChangeOverwrittenMode(uiMenu_Display_OverwrittenPaste.IsChecked);
|
||||
}
|
||||
|
||||
private void funcMenu_Display_HorizontalLayout(object sender, RoutedEventArgs e) {
|
||||
uiMenu_Display_HorizontalLayout.IsChecked = !uiMenu_Display_HorizontalLayout.IsChecked;
|
||||
GlobalVariable.configManager.Configuration[ConfigManager.CfgNode_IsHorizonLayout] = uiMenu_Display_HorizontalLayout.IsChecked.ToString();
|
||||
ChangeLayout(uiMenu_Display_HorizontalLayout.IsChecked);
|
||||
}
|
||||
|
||||
private void funcMenu_Display_Redo(object sender, RoutedEventArgs e) {
|
||||
mViewer.ProcessOperation(OperationEnum.Redo);
|
||||
}
|
||||
|
||||
private void funcMenu_Display_Undo(object sender, RoutedEventArgs e) {
|
||||
mViewer.ProcessOperation(OperationEnum.Undo);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region datamenu operation
|
||||
|
||||
private void funcDataMenu_Set(object sender, RoutedEventArgs e) {
|
||||
mViewer.ProcessOperation(OperationEnum.Set);
|
||||
}
|
||||
|
||||
private void funcDataMenu_Unset(object sender, RoutedEventArgs e) {
|
||||
mViewer.ProcessOperation(OperationEnum.Unset);
|
||||
}
|
||||
|
||||
private void funcDataMenu_Cut(object sender, RoutedEventArgs e) {
|
||||
mViewer.ProcessOperation(OperationEnum.Cut);
|
||||
}
|
||||
|
||||
private void funcDataMenu_Copy(object sender, RoutedEventArgs e) {
|
||||
mViewer.ProcessOperation(OperationEnum.Copy);
|
||||
}
|
||||
|
||||
private void funcDataMenu_PasteAfter(object sender, RoutedEventArgs e) {
|
||||
mViewer.ProcessOperation(OperationEnum.PasteAfter);
|
||||
}
|
||||
|
||||
private void funcDataMenu_PasteBefore(object sender, RoutedEventArgs e) {
|
||||
mViewer.ProcessOperation(OperationEnum.PasteBefore);
|
||||
}
|
||||
|
||||
private void funcDataMenu_Delete(object sender, RoutedEventArgs e) {
|
||||
mViewer.ProcessOperation(OperationEnum.Delete);
|
||||
}
|
||||
|
||||
private void funcDataMenu_DeleteAfter(object sender, RoutedEventArgs e) {
|
||||
mViewer.ProcessOperation(OperationEnum.DeleteAfter);
|
||||
}
|
||||
|
||||
private void funcDataMenu_DeleteBefore(object sender, RoutedEventArgs e) {
|
||||
mViewer.ProcessOperation(OperationEnum.DeleteBefore);
|
||||
}
|
||||
|
||||
private void funcDataMenu_AddAfter(object sender, RoutedEventArgs e) {
|
||||
mViewer.ProcessOperation(OperationEnum.AddAfter);
|
||||
}
|
||||
|
||||
private void funcDataMenu_AddBefore(object sender, RoutedEventArgs e) {
|
||||
mViewer.ProcessOperation(OperationEnum.AddBefore);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// =========================== btn
|
||||
private void funcBtn_Cursor(object sender, RoutedEventArgs e) {
|
||||
mViewer.ChangeToolMode(ToolMode.Cursor);
|
||||
}
|
||||
|
||||
private void funcBtn_Fill(object sender, RoutedEventArgs e) {
|
||||
mViewer.ChangeToolMode(ToolMode.Fill);
|
||||
}
|
||||
|
||||
private void funcBtn_Overwrite(object sender, RoutedEventArgs e) {
|
||||
mViewer.ChangeToolMode(ToolMode.Overwrite);
|
||||
}
|
||||
|
||||
// move btn
|
||||
|
||||
private void funcBtn_FastMovePrev(object sender, RoutedEventArgs e) {
|
||||
mSlider.MoveSliderManually(true, true, mViewer.GetItemCountInPage());
|
||||
}
|
||||
|
||||
private void funcBtn_MovePrev(object sender, RoutedEventArgs e) {
|
||||
mSlider.MoveSliderManually(true, false, mViewer.GetItemCountInPage());
|
||||
}
|
||||
|
||||
private void funcBtn_MoveNext(object sender, RoutedEventArgs e) {
|
||||
mSlider.MoveSliderManually(false, false, mViewer.GetItemCountInPage());
|
||||
}
|
||||
|
||||
private void funcBtn_FastMoveNext(object sender, RoutedEventArgs e) {
|
||||
mSlider.MoveSliderManually(false, true, mViewer.GetItemCountInPage());
|
||||
}
|
||||
|
||||
// move keyboard
|
||||
|
||||
private void funcWindow_KeyUp(object sender, KeyEventArgs e) {
|
||||
if (mFile == null || mViewer == null) return;
|
||||
|
||||
switch (e.Key) {
|
||||
case Key.A:
|
||||
mSlider.MoveSliderManually(true, true, mViewer.GetItemCountInPage());
|
||||
break;
|
||||
case Key.S:
|
||||
mSlider.MoveSliderManually(true, false, mViewer.GetItemCountInPage());
|
||||
break;
|
||||
case Key.D:
|
||||
mSlider.MoveSliderManually(false, false, mViewer.GetItemCountInPage());
|
||||
break;
|
||||
case Key.F:
|
||||
mSlider.MoveSliderManually(false, true, mViewer.GetItemCountInPage());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// move mouse
|
||||
|
||||
private void funcWindow_MouseWheel(object sender, MouseWheelEventArgs e) {
|
||||
if (e.Delta > 0) {
|
||||
// wheel up
|
||||
if (KeyboardState.IsKeyPressed(KeyboardState.VirtualKeyStates.VK_SHIFT)) {
|
||||
// move quickly
|
||||
mSlider.MoveSliderManually(true, true, mViewer.GetItemCountInPage());
|
||||
} else if (KeyboardState.IsKeyPressed(KeyboardState.VirtualKeyStates.VK_CONTROL)) {
|
||||
// decrease item count
|
||||
var newvalue = mViewer.GetItemCountInPage();
|
||||
ChangeItemCount(newvalue - 1);
|
||||
} else {
|
||||
// normally move
|
||||
mSlider.MoveSliderManually(true, false, mViewer.GetItemCountInPage());
|
||||
}
|
||||
|
||||
} else if (e.Delta < 0) {
|
||||
// wheel down
|
||||
if (KeyboardState.IsKeyPressed(KeyboardState.VirtualKeyStates.VK_SHIFT)) {
|
||||
// move quickly
|
||||
mSlider.MoveSliderManually(false, true, mViewer.GetItemCountInPage());
|
||||
} else if (KeyboardState.IsKeyPressed(KeyboardState.VirtualKeyStates.VK_CONTROL)) {
|
||||
// increase item count
|
||||
var newvalue = mViewer.GetItemCountInPage();
|
||||
ChangeItemCount(newvalue + 1);
|
||||
} else {
|
||||
// normally move
|
||||
mSlider.MoveSliderManually(false, false, mViewer.GetItemCountInPage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// drop file to open
|
||||
private void funcDrop_Drop(object sender, DragEventArgs e) {
|
||||
string fileName = ((System.Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString();
|
||||
OpenFile(fileName);
|
||||
}
|
||||
|
||||
private void funcDrop_DragEnter(object sender, DragEventArgs e) {
|
||||
// only accept one file
|
||||
if (e.Data.GetDataPresent(DataFormats.FileDrop)) {
|
||||
var arr = (System.Array)e.Data.GetData(DataFormats.FileDrop);
|
||||
if (arr.Length != 1) e.Effects = DragDropEffects.None;
|
||||
else e.Effects = DragDropEffects.Link;
|
||||
} else e.Effects = DragDropEffects.None;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void ApplyConfigureManager() {
|
||||
var isOverwrittenPaste = bool.Parse(GlobalVariable.configManager.Configuration[ConfigManager.CfgNode_IsOverwrittenPaste]);
|
||||
var isHorizontalLayout = bool.Parse(GlobalVariable.configManager.Configuration[ConfigManager.CfgNode_IsHorizonLayout]);
|
||||
var itemCount = int.Parse(GlobalVariable.configManager.Configuration[ConfigManager.CfgNode_ItemCount]);
|
||||
|
||||
uiMenu_Display_OverwrittenPaste.IsChecked = isOverwrittenPaste;
|
||||
uiMenu_Display_HorizontalLayout.IsChecked = isHorizontalLayout;
|
||||
uiStatusbar_OverwrittenPaste.Visibility = isOverwrittenPaste ? Visibility.Visible : Visibility.Hidden;
|
||||
if (mViewer != null) {
|
||||
mViewer.ChangeOverwrittenMode(isOverwrittenPaste);
|
||||
mViewer.ChangeListLength(itemCount);
|
||||
ChangeLayout(isHorizontalLayout);
|
||||
}
|
||||
}
|
||||
|
||||
private void OpenFile(string file) {
|
||||
#if DEBUG
|
||||
#else
|
||||
try {
|
||||
#endif
|
||||
mFile = new TASFile(file);
|
||||
|
||||
#if DEBUG
|
||||
#else
|
||||
} catch {
|
||||
MessageBox.Show(I18NProcessor.GetI18N("code_MainWindow_Menu_File_Open_Fail"),
|
||||
I18NProcessor.GetI18N("code_Shared_ProgramName"),
|
||||
MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
mFile = null;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
mViewer = new TASViewer(mFile, mSlider, mFlow);
|
||||
|
||||
mViewer.UpdateDataUI += RefreshDataUI;
|
||||
mViewer.UpdateSelection += RefreshSelection;
|
||||
mViewer.UpdateToolMode += RefreshToolMode;
|
||||
|
||||
RefreshUI(true);
|
||||
ApplyConfigureManager(); // apply item count and overwritten item
|
||||
mViewer.ChangeToolMode(ToolMode.Cursor);
|
||||
}
|
||||
|
||||
private void RefreshToolMode(ToolMode mode) {
|
||||
switch (mode) {
|
||||
case ToolMode.Cursor:
|
||||
uiBtn_Cursor.IsEnabled = false;
|
||||
uiBtn_Fill.IsEnabled = true;
|
||||
uiBtn_Overwrite.IsEnabled = true;
|
||||
|
||||
uiStatusbar_Mode_Cursor.Visibility = Visibility.Visible;
|
||||
uiStatusbar_Mode_Fill.Visibility = Visibility.Collapsed;
|
||||
uiStatusbar_Mode_Overwrite.Visibility = Visibility.Collapsed;
|
||||
break;
|
||||
case ToolMode.Fill:
|
||||
uiBtn_Cursor.IsEnabled = true;
|
||||
uiBtn_Fill.IsEnabled = false;
|
||||
uiBtn_Overwrite.IsEnabled = true;
|
||||
|
||||
uiStatusbar_Mode_Cursor.Visibility = Visibility.Collapsed;
|
||||
uiStatusbar_Mode_Fill.Visibility = Visibility.Visible;
|
||||
uiStatusbar_Mode_Overwrite.Visibility = Visibility.Collapsed;
|
||||
break;
|
||||
case ToolMode.Overwrite:
|
||||
uiBtn_Cursor.IsEnabled = true;
|
||||
uiBtn_Fill.IsEnabled = true;
|
||||
uiBtn_Overwrite.IsEnabled = false;
|
||||
|
||||
uiStatusbar_Mode_Cursor.Visibility = Visibility.Collapsed;
|
||||
uiStatusbar_Mode_Fill.Visibility = Visibility.Collapsed;
|
||||
uiStatusbar_Mode_Overwrite.Visibility = Visibility.Visible;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshUI(bool isFileOpened) {
|
||||
if (isFileOpened) {
|
||||
uiEditorPanel.Visibility = Visibility.Visible;
|
||||
uiEditorNote.Visibility = Visibility.Collapsed;
|
||||
|
||||
uiMenu_File_Open.IsEnabled = false;
|
||||
uiMenu_File_Save.IsEnabled = true;
|
||||
uiMenu_File_SaveAs.IsEnabled = true;
|
||||
uiMenu_File_Close.IsEnabled = true;
|
||||
|
||||
uiMenu_Display_ItemCount.IsEnabled = true;
|
||||
uiMenu_Display_OverwrittenPaste.IsEnabled = true;
|
||||
uiMenu_Display_HorizontalLayout.IsEnabled = true;
|
||||
uiMenu_Display_Undo.IsEnabled = true;
|
||||
uiMenu_Display_Redo.IsEnabled = true;
|
||||
|
||||
uiStatusbar_Runtime_Mode.Visibility = Visibility.Visible;
|
||||
uiStatusbar_Runtime_PasteMode.Visibility = Visibility.Visible;
|
||||
uiStatusbar_Runtime_Selected.Visibility = Visibility.Visible;
|
||||
uiStatusbar_Runtime_Separator1.Visibility = Visibility.Visible;
|
||||
uiStatusbar_Runtime_Separator2.Visibility = Visibility.Visible;
|
||||
} else {
|
||||
uiEditorPanel.Visibility = Visibility.Collapsed;
|
||||
uiEditorNote.Visibility = Visibility.Visible;
|
||||
|
||||
uiMenu_File_Open.IsEnabled = true;
|
||||
uiMenu_File_Save.IsEnabled = false;
|
||||
uiMenu_File_SaveAs.IsEnabled = false;
|
||||
uiMenu_File_Close.IsEnabled = false;
|
||||
|
||||
uiMenu_Display_ItemCount.IsEnabled = false;
|
||||
uiMenu_Display_OverwrittenPaste.IsEnabled = false;
|
||||
uiMenu_Display_HorizontalLayout.IsEnabled = false;
|
||||
uiMenu_Display_Undo.IsEnabled = false;
|
||||
uiMenu_Display_Redo.IsEnabled = false;
|
||||
|
||||
uiStatusbar_Runtime_Mode.Visibility = Visibility.Collapsed;
|
||||
uiStatusbar_Runtime_PasteMode.Visibility = Visibility.Collapsed;
|
||||
uiStatusbar_Runtime_Selected.Visibility = Visibility.Collapsed;
|
||||
uiStatusbar_Runtime_Separator1.Visibility = Visibility.Collapsed;
|
||||
uiStatusbar_Runtime_Separator2.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshDataUI(bool showCursorPasteAddDeleteOne, bool showFill, bool showCursorCopyDelete) {
|
||||
uiDataMenu_Set.IsEnabled = showFill;
|
||||
uiDataMenu_Unset.IsEnabled = showFill;
|
||||
uiDataMenu_Cut.IsEnabled = showCursorCopyDelete;
|
||||
uiDataMenu_Copy.IsEnabled = showCursorCopyDelete;
|
||||
uiDataMenu_Delete.IsEnabled = showCursorCopyDelete;
|
||||
uiDataMenu_DeleteAfter.IsEnabled = showCursorPasteAddDeleteOne;
|
||||
uiDataMenu_DeleteBefore.IsEnabled = showCursorPasteAddDeleteOne;
|
||||
uiDataMenu_PasteAfter.IsEnabled = showCursorPasteAddDeleteOne;
|
||||
uiDataMenu_PasteBefore.IsEnabled = showCursorPasteAddDeleteOne;
|
||||
uiDataMenu_AddAfter.IsEnabled = showCursorPasteAddDeleteOne;
|
||||
uiDataMenu_AddBefore.IsEnabled = showCursorPasteAddDeleteOne;
|
||||
}
|
||||
|
||||
private void RefreshSelection(SelectionHelp mSelectionHelp) {
|
||||
var mode = mSelectionHelp.GetToolMode();
|
||||
|
||||
switch (mode) {
|
||||
case ToolMode.Cursor:
|
||||
if (mSelectionHelp.IsDataReady()) {
|
||||
var data = mSelectionHelp.GetRange();
|
||||
uiStatusbar_Selected.Text = $"{data.start} - {data.end}";
|
||||
} else if (mSelectionHelp.IsDataPartialReady()) {
|
||||
var data2 = mSelectionHelp.GetPoint();
|
||||
uiStatusbar_Selected.Text = data2.ToString();
|
||||
} else uiStatusbar_Selected.Text = "-";
|
||||
break;
|
||||
case ToolMode.Fill:
|
||||
if (mSelectionHelp.IsDataReady()) {
|
||||
var data3 = mSelectionHelp.GetRange();
|
||||
uiStatusbar_Selected.Text = $"{data3.start} - {data3.end}";
|
||||
} else uiStatusbar_Selected.Text = "-";
|
||||
break;
|
||||
case ToolMode.Overwrite:
|
||||
if (mSelectionHelp.IsDataReady()) {
|
||||
var data4 = mSelectionHelp.GetPoint();
|
||||
uiStatusbar_Selected.Text = data4.ToString();
|
||||
} else uiStatusbar_Selected.Text = "-";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void ChangeItemCount(int count) {
|
||||
GlobalVariable.configManager.Configuration[ConfigManager.CfgNode_ItemCount] = count.ToString();
|
||||
mViewer.ChangeListLength(count);
|
||||
}
|
||||
|
||||
private void ChangeLayout(bool isHorizontal) {
|
||||
if (isHorizontal == mIsHorizontalLayout) return;
|
||||
mIsHorizontalLayout = isHorizontal;
|
||||
|
||||
// swap window size
|
||||
var swap = this.Width;
|
||||
this.Width = this.Height;
|
||||
this.Height = swap;
|
||||
// change self layout first
|
||||
uiLayoutContainer.RowDefinitions.Clear();
|
||||
uiLayoutContainer.ColumnDefinitions.Clear();
|
||||
if (isHorizontal) {
|
||||
UI.Util.GridRowAdder(uiLayoutContainer, new GridLength(1, GridUnitType.Star));
|
||||
UI.Util.GridRowAdder(uiLayoutContainer, GridLength.Auto);
|
||||
} else {
|
||||
UI.Util.GridColumnAdder(uiLayoutContainer, new GridLength(1, GridUnitType.Star));
|
||||
UI.Util.GridColumnAdder(uiLayoutContainer, GridLength.Auto);
|
||||
}
|
||||
UI.Util.SwapGridItemRC(uiTASFlowContainer);
|
||||
UI.Util.SwapGridItemRC(uiTASSliderContainer);
|
||||
|
||||
// change sub layout
|
||||
mFlow.ChangeLayout(isHorizontal);
|
||||
mSlider.ChangeLayout(isHorizontal);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
55
Legacy/BallanceTASEditor/Properties/AssemblyInfo.cs
Normal file
55
Legacy/BallanceTASEditor/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,55 @@
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
|
||||
// 有关程序集的一般信息由以下
|
||||
// 控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle("Ballance TAS Editor")]
|
||||
[assembly: AssemblyDescription("Ballance TAS Editor")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Ballance Community")]
|
||||
[assembly: AssemblyProduct("Ballance TAS Editor")]
|
||||
[assembly: AssemblyCopyright("Copyright © Ballance Community 2022")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// 将 ComVisible 设置为 false 会使此程序集中的类型
|
||||
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
|
||||
//请将此类型的 ComVisible 特性设置为 true。
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
//若要开始生成可本地化的应用程序,请设置
|
||||
//.csproj 文件中的 <UICulture>CultureYouAreCodingWith</UICulture>
|
||||
//例如,如果您在源文件中使用的是美国英语,
|
||||
//使用的是美国英语,请将 <UICulture> 设置为 en-US。 然后取消
|
||||
//对以下 NeutralResourceLanguage 特性的注释。 更新
|
||||
//以下行中的“en-US”以匹配项目文件中的 UICulture 设置。
|
||||
|
||||
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
|
||||
|
||||
|
||||
[assembly: ThemeInfo(
|
||||
ResourceDictionaryLocation.None, //主题特定资源词典所处位置
|
||||
//(未在页面中找到资源时使用,
|
||||
//或应用程序资源字典中找到时使用)
|
||||
ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
|
||||
//(未在页面中找到资源时使用,
|
||||
//、应用程序或任何主题专用资源字典中找到时使用)
|
||||
)]
|
||||
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 生成号
|
||||
// 修订号
|
||||
//
|
||||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
|
||||
//通过使用 "*",如下所示:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.1.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.1.0.0")]
|
||||
63
Legacy/BallanceTASEditor/Properties/Resources.Designer.cs
generated
Normal file
63
Legacy/BallanceTASEditor/Properties/Resources.Designer.cs
generated
Normal file
@ -0,0 +1,63 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 此代码由工具生成。
|
||||
// 运行时版本:4.0.30319.42000
|
||||
//
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果
|
||||
// 重新生成代码,这些更改将会丢失。
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace BallanceTASEditor.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 一个强类型的资源类,用于查找本地化的字符串等。
|
||||
/// </summary>
|
||||
// 此类是由 StronglyTypedResourceBuilder
|
||||
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
|
||||
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
|
||||
// (以 /str 作为命令选项),或重新生成 VS 项目。
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回此类使用的缓存的 ResourceManager 实例。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("BallanceTASEditor.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写当前线程的 CurrentUICulture 属性
|
||||
/// 重写当前线程的 CurrentUICulture 属性。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
117
Legacy/BallanceTASEditor/Properties/Resources.resx
Normal file
117
Legacy/BallanceTASEditor/Properties/Resources.resx
Normal file
@ -0,0 +1,117 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
26
Legacy/BallanceTASEditor/Properties/Settings.Designer.cs
generated
Normal file
26
Legacy/BallanceTASEditor/Properties/Settings.Designer.cs
generated
Normal file
@ -0,0 +1,26 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 此代码由工具生成。
|
||||
// 运行时版本:4.0.30319.42000
|
||||
//
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果
|
||||
// 重新生成代码,这些更改将会丢失。
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace BallanceTASEditor.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.3.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
7
Legacy/BallanceTASEditor/Properties/Settings.settings
Normal file
7
Legacy/BallanceTASEditor/Properties/Settings.settings
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
||||
49
Legacy/BallanceTASEditor/UI/AddItem.xaml
Normal file
49
Legacy/BallanceTASEditor/UI/AddItem.xaml
Normal file
@ -0,0 +1,49 @@
|
||||
<Window x:Class="BallanceTASEditor.UI.AddItem"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:BallanceTASEditor.UI"
|
||||
xmlns:converter="clr-namespace:BallanceTASEditor.UI"
|
||||
mc:Ignorable="d"
|
||||
Title="{DynamicResource ui_AddItem_Title}" Height="200" Width="400" WindowStyle="ToolWindow" WindowStartupLocation="CenterOwner" Icon="/BallanceTASEditor;component/icon.ico">
|
||||
<Window.Resources>
|
||||
<converter:AddItemConverter x:Key="conv_addItem"/>
|
||||
<converter:FPS2DeltaTimeConverter x:Key="conv_fps2DeltaTime"/>
|
||||
</Window.Resources>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Margin="5" Grid.Column="0" Grid.Row="0" Text="{DynamicResource ui_AddItem_Count}" VerticalAlignment="Center"/>
|
||||
<TextBlock Margin="5" Grid.Column="0" Grid.Row="1" Text="{DynamicResource ui_AddItem_FPS}" VerticalAlignment="Center"/>
|
||||
<TextBlock Margin="5" Grid.Column="0" Grid.Row="2" Text="{DynamicResource ui_AddItem_DeltaTime}" VerticalAlignment="Center"/>
|
||||
|
||||
<TextBox x:Name="uiTextbox_Count" Margin="5" Padding="5" Grid.Row="0" Grid.Column="1" VerticalAlignment="Center"/>
|
||||
<TextBox x:Name="uiTextbox_FPS" Margin="5" Padding="5" Grid.Row="1" Grid.Column="1" VerticalAlignment="Center"/>
|
||||
<TextBlock x:Name="uiText_DeltaTime" Margin="5" Padding="5" Grid.Row="2" Grid.Column="1" VerticalAlignment="Center"
|
||||
Text="{Binding Converter={StaticResource conv_fps2DeltaTime}, Mode=OneWay, ElementName=uiTextbox_FPS, Path=Text}"/>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Margin="5" HorizontalAlignment="Right" Grid.ColumnSpan="2" Grid.Row="4">
|
||||
<Button x:Name="uiBtn_OK" Margin="5" Padding="5" Content="{DynamicResource ui_AddItem_OK}" MinWidth="50" Click="funcBtn_OK">
|
||||
<Button.IsEnabled>
|
||||
<MultiBinding Converter="{StaticResource conv_addItem}" Mode="OneWay">
|
||||
<Binding ElementName="uiTextbox_Count" Path="Text"/>
|
||||
<Binding ElementName="uiTextbox_FPS" Path="Text"/>
|
||||
</MultiBinding>
|
||||
</Button.IsEnabled>
|
||||
</Button>
|
||||
<Button x:Name="uiBtn_Cancel" Margin="5" Padding="5" Content="{DynamicResource ui_AddItem_Cancel}" MinWidth="50" Click="funcBtn_Cancel"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Window>
|
||||
42
Legacy/BallanceTASEditor/UI/AddItem.xaml.cs
Normal file
42
Legacy/BallanceTASEditor/UI/AddItem.xaml.cs
Normal file
@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace BallanceTASEditor.UI {
|
||||
/// <summary>
|
||||
/// AddItem.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class AddItem : Window {
|
||||
public AddItem() {
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public int Output_Count { get; private set; }
|
||||
public float Output_DeltaTime { get; private set; }
|
||||
|
||||
private void funcBtn_OK(object sender, RoutedEventArgs e) {
|
||||
int count;
|
||||
float fps;
|
||||
if (!int.TryParse(uiTextbox_Count.Text, out count)) return;
|
||||
if (!float.TryParse(uiTextbox_FPS.Text, out fps)) return;
|
||||
|
||||
Output_Count = count;
|
||||
Output_DeltaTime = 1000f / fps;
|
||||
|
||||
this.DialogResult = true;
|
||||
}
|
||||
|
||||
private void funcBtn_Cancel(object sender, RoutedEventArgs e) {
|
||||
this.DialogResult = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
62
Legacy/BallanceTASEditor/UI/DialogUtil.cs
Normal file
62
Legacy/BallanceTASEditor/UI/DialogUtil.cs
Normal file
@ -0,0 +1,62 @@
|
||||
using Microsoft.VisualBasic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using BallanceTASEditor.Core;
|
||||
|
||||
namespace BallanceTASEditor.UI {
|
||||
public class DialogUtil {
|
||||
|
||||
public static string OpenFileDialog() {
|
||||
Microsoft.Win32.OpenFileDialog op = new Microsoft.Win32.OpenFileDialog();
|
||||
op.RestoreDirectory = true;
|
||||
op.Multiselect = false;
|
||||
op.Filter = I18NProcessor.GetI18N("code_DialogUtil_FileFilter");
|
||||
if (!(bool)op.ShowDialog()) return "";
|
||||
return op.FileName;
|
||||
}
|
||||
|
||||
public static string SaveFileDialog() {
|
||||
Microsoft.Win32.SaveFileDialog op = new Microsoft.Win32.SaveFileDialog();
|
||||
op.RestoreDirectory = true;
|
||||
op.Filter = I18NProcessor.GetI18N("code_DialogUtil_FileFilter");
|
||||
if (!(bool)op.ShowDialog()) return "";
|
||||
return op.FileName;
|
||||
}
|
||||
|
||||
public static bool ConfirmDialog(string str) {
|
||||
var result = MessageBox.Show(str, I18NProcessor.GetI18N("code_DialogUtil_Warning"), MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
||||
return (result == MessageBoxResult.Yes);
|
||||
}
|
||||
|
||||
public static bool InputNumber(string title, int min, int max, ref int result) {
|
||||
while (true) {
|
||||
var dialog = Interaction.InputBox(title, I18NProcessor.GetI18N("code_DialogUtil_InputNumber_Title"), "");
|
||||
if (dialog == "") return false;
|
||||
if (int.TryParse(dialog, out result)) {
|
||||
if (result <= max && result >= min) break;
|
||||
}
|
||||
MessageBox.Show(I18NProcessor.GetI18N("code_DialogUtil_InputNumber_Wrong"),
|
||||
I18NProcessor.GetI18N("code_DialogUtil_Warning"),
|
||||
MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool AddItemDialog(out int count, out float deltaTime) {
|
||||
var win = new AddItem();
|
||||
if (!(bool)win.ShowDialog()) {
|
||||
count = 0;
|
||||
deltaTime = 0f;
|
||||
return false;
|
||||
}
|
||||
|
||||
count = win.Output_Count;
|
||||
deltaTime = win.Output_DeltaTime;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
22
Legacy/BallanceTASEditor/UI/OperationEnum.cs
Normal file
22
Legacy/BallanceTASEditor/UI/OperationEnum.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace BallanceTASEditor.UI {
|
||||
public enum OperationEnum {
|
||||
Set,
|
||||
Unset,
|
||||
Cut,
|
||||
Copy,
|
||||
PasteAfter,
|
||||
PasteBefore,
|
||||
Delete,
|
||||
DeleteAfter,
|
||||
DeleteBefore,
|
||||
AddAfter,
|
||||
AddBefore,
|
||||
Undo,
|
||||
Redo
|
||||
}
|
||||
}
|
||||
137
Legacy/BallanceTASEditor/UI/SelectionHelp.cs
Normal file
137
Legacy/BallanceTASEditor/UI/SelectionHelp.cs
Normal file
@ -0,0 +1,137 @@
|
||||
using BallanceTASEditor.Core.TASStruct;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using BallanceTASEditor.Core;
|
||||
|
||||
namespace BallanceTASEditor.UI {
|
||||
public class SelectionHelp {
|
||||
public SelectionHelp() {
|
||||
SetMode(ToolMode.Cursor);
|
||||
}
|
||||
|
||||
public event Action SelectionChanged;
|
||||
|
||||
ToolMode mMode;
|
||||
FrameDataField mStartField;
|
||||
FrameDataField mEndField;
|
||||
long mStart;
|
||||
bool mIsStartConfirmed;
|
||||
long mEnd;
|
||||
bool mIsEndConfirmed;
|
||||
|
||||
public void SetMode(ToolMode mode) {
|
||||
switch (mode) {
|
||||
case ToolMode.Cursor:
|
||||
mStart = 0;
|
||||
mEnd = 0;
|
||||
mIsStartConfirmed = false;
|
||||
mIsEndConfirmed = false;
|
||||
break;
|
||||
case ToolMode.Fill:
|
||||
mStartField = FrameDataField.Key_Up;
|
||||
mEndField = FrameDataField.Key_Up;
|
||||
mStart = 0;
|
||||
mEnd = 0;
|
||||
mIsStartConfirmed = false;
|
||||
mIsEndConfirmed = false;
|
||||
break;
|
||||
case ToolMode.Overwrite:
|
||||
mStartField = FrameDataField.Key_Up;
|
||||
mStart = 0;
|
||||
mIsStartConfirmed = false;
|
||||
break;
|
||||
}
|
||||
|
||||
mMode = mode;
|
||||
OnSelectionChanged();
|
||||
}
|
||||
|
||||
public void FirstClick(long index, FrameDataField field) {
|
||||
mStartField = field;
|
||||
mStart = index;
|
||||
mIsStartConfirmed = true;
|
||||
mIsEndConfirmed = false;
|
||||
|
||||
OnSelectionChanged();
|
||||
}
|
||||
|
||||
public void LastClick(long index, FrameDataField field) {
|
||||
if (mMode == ToolMode.Overwrite) return;
|
||||
if (!mIsStartConfirmed) return;
|
||||
|
||||
mEndField = field;
|
||||
mEnd = index;
|
||||
mIsEndConfirmed = true;
|
||||
OnSelectionChanged();
|
||||
}
|
||||
|
||||
public void Reset() {
|
||||
// reuse set mode to reset
|
||||
SetMode(mMode);
|
||||
}
|
||||
|
||||
// onnly used for delete prev one / next one shift.
|
||||
public void ShiftTo(bool toNext) {
|
||||
if (!IsDataPartialReady()) throw new Exception("Shift operation with wrong condition.");
|
||||
FirstClick(GetPoint() + (toNext ? 1 : -1), mStartField);
|
||||
}
|
||||
|
||||
public SelectionRange GetRange() {
|
||||
if (mMode == ToolMode.Overwrite) throw new Exception("Read with wrong mode.");
|
||||
if (!(mIsStartConfirmed && mIsEndConfirmed)) throw new Exception("Data is not ready to read");
|
||||
return new SelectionRange(mStart, mEnd);
|
||||
}
|
||||
|
||||
public SelectionRange GetFieldRange() {
|
||||
if (mMode != ToolMode.Fill) throw new Exception("Read with wrong mode.");
|
||||
if (!(mIsStartConfirmed && mIsEndConfirmed)) throw new Exception("Data is not ready to read");
|
||||
return new SelectionRange((int)mStartField, (int)mEndField);
|
||||
}
|
||||
|
||||
public long GetPoint() {
|
||||
if (mMode == ToolMode.Fill) throw new Exception("Read with wrong mode.");
|
||||
if (!mIsStartConfirmed) throw new Exception("Data is not ready to read");
|
||||
|
||||
if (mMode == ToolMode.Overwrite) return mStart;
|
||||
else {
|
||||
// cursor mode
|
||||
if (mIsStartConfirmed) return mStart;
|
||||
else throw new Exception("Data is not ready to read");
|
||||
}
|
||||
}
|
||||
|
||||
public FrameDataField GetPointField() {
|
||||
if (mMode != ToolMode.Overwrite) throw new Exception("Read with wrong mode.");
|
||||
if (!mIsStartConfirmed) throw new Exception("Data is not ready to read");
|
||||
|
||||
return mStartField;
|
||||
}
|
||||
|
||||
public bool IsDataReady() {
|
||||
switch (mMode) {
|
||||
case ToolMode.Cursor:
|
||||
case ToolMode.Fill:
|
||||
return (mIsStartConfirmed && mIsEndConfirmed);
|
||||
case ToolMode.Overwrite:
|
||||
return mIsStartConfirmed;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsDataPartialReady() {
|
||||
return (mMode == ToolMode.Cursor && mIsStartConfirmed && !mIsEndConfirmed);
|
||||
}
|
||||
|
||||
public ToolMode GetToolMode() {
|
||||
return mMode;
|
||||
}
|
||||
|
||||
private void OnSelectionChanged() {
|
||||
SelectionChanged?.Invoke();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
47
Legacy/BallanceTASEditor/UI/StyleConverter.cs
Normal file
47
Legacy/BallanceTASEditor/UI/StyleConverter.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace BallanceTASEditor.UI {
|
||||
|
||||
public class AddItemConverter : IMultiValueConverter {
|
||||
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) {
|
||||
try {
|
||||
var textCount = values[0] as string;
|
||||
var textFps = values[1] as string;
|
||||
|
||||
var count = int.Parse(textCount);
|
||||
var fps = float.Parse(textFps);
|
||||
|
||||
if (count <= 0 || fps <= 0) return false;
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public class FPS2DeltaTimeConverter : IValueConverter {
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
|
||||
var text = value as string;
|
||||
if (text == null) return "0";
|
||||
|
||||
float data;
|
||||
if (!float.TryParse(text, out data)) return "0";
|
||||
return (1000f / data).ToString();
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
401
Legacy/BallanceTASEditor/UI/TASFlow.cs
Normal file
401
Legacy/BallanceTASEditor/UI/TASFlow.cs
Normal file
@ -0,0 +1,401 @@
|
||||
using BallanceTASEditor.Core;
|
||||
using BallanceTASEditor.Core.TASStruct;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace BallanceTASEditor.UI {
|
||||
public partial class TASFlow {
|
||||
public TASFlow(Grid coreWindow, TextBlock[] headers) {
|
||||
uiCoreWindow = coreWindow;
|
||||
mHeaders = headers;
|
||||
mItemList = new List<TASFlowUIItem>();
|
||||
mRectMap = new Dictionary<Rectangle, CellPosition>();
|
||||
mItemCount = 0;
|
||||
mIsHorizontalLayout = true;
|
||||
SetItemCount(1);
|
||||
}
|
||||
|
||||
public event Action Click;
|
||||
|
||||
private readonly TextBlock[] mHeaders;
|
||||
private bool mIsHorizontalLayout;
|
||||
private Grid uiCoreWindow;
|
||||
private int mItemCount;
|
||||
private List<TASFlowUIItem> mItemList;
|
||||
private Dictionary<Rectangle, CellPosition> mRectMap;
|
||||
public SelectionHelp SelectionHelp { get; set; }
|
||||
public List<FrameDataDisplay> DataSources { get; set; }
|
||||
|
||||
public void ChangeLayout(bool isHorizontal) {
|
||||
if (isHorizontal == mIsHorizontalLayout) return;
|
||||
|
||||
// the layout changed, re-construct elements
|
||||
mIsHorizontalLayout = isHorizontal;
|
||||
|
||||
// delete original grid layout
|
||||
var lenHeader = mHeaders.Length;
|
||||
uiCoreWindow.ColumnDefinitions.Clear();
|
||||
uiCoreWindow.RowDefinitions.Clear();
|
||||
|
||||
// add header layout
|
||||
if (mIsHorizontalLayout) {
|
||||
// horizontal layout
|
||||
// row is header count
|
||||
// column is tas unit
|
||||
|
||||
// header
|
||||
layout_row_adder(GridLength.Auto);
|
||||
for (int r = 0; r < lenHeader; r++) {
|
||||
layout_row_adder(GridLength.Auto);
|
||||
}
|
||||
layout_row_adder(new GridLength(1, GridUnitType.Star));
|
||||
|
||||
// tas unit
|
||||
layout_column_adder(GridLength.Auto);
|
||||
for (int c = 0; c < mItemCount; c++) {
|
||||
layout_column_adder(new GridLength(1, GridUnitType.Star));
|
||||
}
|
||||
} else {
|
||||
// vertical layout
|
||||
// row is tas unit
|
||||
// column is header count (use start to split, not auto)
|
||||
|
||||
// header
|
||||
layout_column_adder(GridLength.Auto);
|
||||
for (int r = 0; r < lenHeader; r++) {
|
||||
if (r == 0 || r == 1)
|
||||
layout_column_adder(GridLength.Auto);
|
||||
else
|
||||
layout_column_adder(new GridLength(1, GridUnitType.Star));
|
||||
}
|
||||
//layout_column_adder(new GridLength(1, GridUnitType.Star));
|
||||
|
||||
// tas unit
|
||||
layout_row_adder(GridLength.Auto);
|
||||
for (int c = 0; c < mItemCount; c++) {
|
||||
layout_row_adder(new GridLength(1, GridUnitType.Star));
|
||||
}
|
||||
}
|
||||
|
||||
// now, change items attach prop
|
||||
// just swap Grid.Row and Grid.Column's number
|
||||
foreach (var item in mHeaders) {
|
||||
var swap = Grid.GetColumn(item);
|
||||
Grid.SetColumn(item, Grid.GetRow(item));
|
||||
Grid.SetRow(item, swap);
|
||||
}
|
||||
foreach (var item in mItemList) {
|
||||
item.FlipUnit();
|
||||
}
|
||||
|
||||
}
|
||||
private void layout_row_adder(GridLength size) {
|
||||
UI.Util.GridRowAdder(uiCoreWindow, size);
|
||||
}
|
||||
private void layout_column_adder(GridLength size) {
|
||||
UI.Util.GridColumnAdder(uiCoreWindow, size);
|
||||
}
|
||||
|
||||
public void RefreshDataSources() {
|
||||
if (DataSources == null) return;
|
||||
|
||||
for (int i = 0; i < mItemCount; i++) {
|
||||
mItemList[i].Reload(DataSources[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetItemCount(int newCount) {
|
||||
var offset = newCount - mItemCount;
|
||||
var abs = Math.Abs(offset);
|
||||
if (offset == 0) return;
|
||||
|
||||
// change column defination first
|
||||
if (offset > 0) {
|
||||
for (int i = 0; i < abs; i++) {
|
||||
if (mIsHorizontalLayout) {
|
||||
layout_column_adder(new GridLength(1, GridUnitType.Star));
|
||||
} else {
|
||||
layout_row_adder(new GridLength(1, GridUnitType.Star));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mIsHorizontalLayout) {
|
||||
uiCoreWindow.ColumnDefinitions.RemoveRange(newCount + 1, abs); // the first col is sheet header, so add 1 additionally
|
||||
} else {
|
||||
uiCoreWindow.RowDefinitions.RemoveRange(newCount + 1, abs); // the first col is sheet header, so add 1 additionally
|
||||
}
|
||||
}
|
||||
|
||||
// add / remove item
|
||||
if (offset > 0) {
|
||||
for (int i = 0; i < abs; i++) {
|
||||
var newItem = new TASFlowUIItem(mItemCount + 1 + i, mIsHorizontalLayout); // the first col is sheet header, so add 1 additionally
|
||||
newItem.Add(uiCoreWindow, mRectMap, Rectangle_MouseDown);
|
||||
mItemList.Add(newItem);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < abs; i++) {
|
||||
mItemList[newCount + i].Remove(uiCoreWindow, mRectMap, Rectangle_MouseDown);
|
||||
}
|
||||
mItemList.RemoveRange(newCount, abs);
|
||||
}
|
||||
|
||||
// apply new count
|
||||
mItemCount = newCount;
|
||||
}
|
||||
|
||||
public void RefreshSelectionHighlight() {
|
||||
ToolMode mode = SelectionHelp.GetToolMode();
|
||||
|
||||
if (mode == ToolMode.Cursor) {
|
||||
if (SelectionHelp.IsDataReady()) {
|
||||
var data = SelectionHelp.GetRange();
|
||||
foreach (var item in mItemList) {
|
||||
if (data.Within(item.rawFrame)) {
|
||||
item.SelectFull();
|
||||
} else {
|
||||
item.Unselect();
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else if (SelectionHelp.IsDataPartialReady()) {
|
||||
var data = SelectionHelp.GetPoint();
|
||||
foreach (var item in mItemList) {
|
||||
if (data == item.rawFrame) {
|
||||
item.SelectFull();
|
||||
} else {
|
||||
item.Unselect();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else if (mode == ToolMode.Fill) {
|
||||
if (SelectionHelp.IsDataReady()) {
|
||||
var data = SelectionHelp.GetRange();
|
||||
var field = SelectionHelp.GetFieldRange();
|
||||
foreach (var item in mItemList) {
|
||||
if (data.Within(item.rawFrame)) {
|
||||
item.SelectField(field);
|
||||
} else {
|
||||
item.Unselect();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// fail if prog run into this position, clear
|
||||
foreach (var item in mItemList) {
|
||||
item.Unselect();
|
||||
}
|
||||
}
|
||||
|
||||
private void Rectangle_MouseDown(object sender, MouseButtonEventArgs e) {
|
||||
if (SelectionHelp == null) return;
|
||||
|
||||
// because the first column is header
|
||||
// so all pos.column should -1
|
||||
var rect = sender as Rectangle;
|
||||
var pos = mRectMap[rect];
|
||||
if (!mItemList[pos.column - 1].rawIsEnable) return;
|
||||
if (e.MouseDevice.LeftButton == MouseButtonState.Pressed) {
|
||||
if (KeyboardState.IsKeyPressed(KeyboardState.VirtualKeyStates.VK_SHIFT)) {
|
||||
SelectionHelp.LastClick(mItemList[pos.column - 1].rawFrame, pos.field);
|
||||
} else {
|
||||
SelectionHelp.FirstClick(mItemList[pos.column - 1].rawFrame, pos.field);
|
||||
}
|
||||
} else if (e.MouseDevice.RightButton == MouseButtonState.Pressed) {
|
||||
// if we click right button and there are no full selection in cursor mode
|
||||
// try to add a first selection
|
||||
if (SelectionHelp.GetToolMode() == ToolMode.Cursor) {
|
||||
if (!SelectionHelp.IsDataReady()) {
|
||||
SelectionHelp.FirstClick(mItemList[pos.column - 1].rawFrame, pos.field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// note main window to process it.
|
||||
OnClick();
|
||||
}
|
||||
|
||||
// only raised in overwrite mode
|
||||
private void OnClick() {
|
||||
if (SelectionHelp.GetToolMode() == ToolMode.Overwrite)
|
||||
Click?.Invoke();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class TASFlowUIItem {
|
||||
private static readonly Thickness DEFAULT_MARGIN = new Thickness(2);
|
||||
private static readonly Thickness RECT_MARGIN = new Thickness(1);
|
||||
private static readonly SolidColorBrush SEL_RECT_NORMAL_BRUSH = new SolidColorBrush(Colors.White);
|
||||
private static readonly SolidColorBrush SEL_RECT_SELECTED_BRUSH = new SolidColorBrush(Colors.OrangeRed);
|
||||
private static readonly SolidColorBrush SEL_RECT_STROKE = new SolidColorBrush(Colors.LightGray);
|
||||
private static readonly Color COLOR_SET = Color.FromRgb(30, 144, 255);
|
||||
private static readonly Color COLOR_UNSET = Color.FromArgb(0, 255, 255, 255);
|
||||
private static readonly Color COLOR_SELECTED = Colors.OrangeRed;
|
||||
private static readonly Color COLOR_UNSELECTED = Colors.LightGray;
|
||||
private const double SELECTION_HEADER_HEIGHT = 10.0f;
|
||||
private const int KEY_COUNT = 9;
|
||||
|
||||
public TASFlowUIItem(int column, bool useHorizontalLayout) {
|
||||
// basic item
|
||||
sel_rect = new Rectangle();
|
||||
frame = new TextBlock();
|
||||
deltaTime = new TextBlock();
|
||||
|
||||
if (useHorizontalLayout) {
|
||||
Grid.SetRow(sel_rect, 0);
|
||||
Grid.SetRow(frame, 1);
|
||||
Grid.SetRow(deltaTime, 2);
|
||||
Grid.SetColumn(sel_rect, column);
|
||||
Grid.SetColumn(frame, column);
|
||||
Grid.SetColumn(deltaTime, column);
|
||||
} else {
|
||||
Grid.SetColumn(sel_rect, 0);
|
||||
Grid.SetColumn(frame, 1);
|
||||
Grid.SetColumn(deltaTime, 2);
|
||||
Grid.SetRow(sel_rect, column);
|
||||
Grid.SetRow(frame, column);
|
||||
Grid.SetRow(deltaTime, column);
|
||||
}
|
||||
|
||||
sel_rect.Margin = RECT_MARGIN;
|
||||
frame.Margin = DEFAULT_MARGIN;
|
||||
deltaTime.Margin = DEFAULT_MARGIN;
|
||||
|
||||
sel_rect.StrokeThickness = 2;
|
||||
sel_rect.Stroke = SEL_RECT_STROKE;
|
||||
if (useHorizontalLayout)
|
||||
sel_rect.Height = SELECTION_HEADER_HEIGHT;
|
||||
else
|
||||
sel_rect.Width = SELECTION_HEADER_HEIGHT;
|
||||
|
||||
// keystates item
|
||||
keystates = new Rectangle[KEY_COUNT];
|
||||
keystatesFill = new SolidColorBrush[KEY_COUNT];
|
||||
keystatesStroke = new SolidColorBrush[KEY_COUNT];
|
||||
for (int i = 0; i < KEY_COUNT; i++) {
|
||||
keystates[i] = new Rectangle();
|
||||
keystatesFill[i] = new SolidColorBrush(COLOR_UNSET);
|
||||
keystatesStroke[i] = new SolidColorBrush(COLOR_UNSELECTED);
|
||||
if (useHorizontalLayout) {
|
||||
Grid.SetRow(keystates[i], 3 + i);
|
||||
Grid.SetColumn(keystates[i], column);
|
||||
} else {
|
||||
Grid.SetColumn(keystates[i], 3 + i);
|
||||
Grid.SetRow(keystates[i], column);
|
||||
}
|
||||
keystates[i].Margin = RECT_MARGIN;
|
||||
keystates[i].StrokeThickness = 3;
|
||||
keystates[i].Stroke = keystatesStroke[i];
|
||||
keystates[i].Fill = keystatesFill[i];
|
||||
}
|
||||
|
||||
this.column = column;
|
||||
rawFrame = 0;
|
||||
rawIsEnable = false;
|
||||
}
|
||||
|
||||
public void FlipUnit() {
|
||||
UI.Util.SwapGridItemRC(sel_rect);
|
||||
UI.Util.SwapGridItemRC(frame);
|
||||
UI.Util.SwapGridItemRC(deltaTime);
|
||||
for (int i = 0; i < KEY_COUNT; i++) {
|
||||
UI.Util.SwapGridItemRC(keystates[i]);
|
||||
}
|
||||
|
||||
// swap sel_rect height and width
|
||||
var swap = sel_rect.Height;
|
||||
sel_rect.Height = sel_rect.Width;
|
||||
sel_rect.Width = swap;
|
||||
}
|
||||
|
||||
public void Add(Grid target, Dictionary<Rectangle, CellPosition> map, MouseButtonEventHandler func) {
|
||||
target.Children.Add(sel_rect);
|
||||
target.Children.Add(frame);
|
||||
target.Children.Add(deltaTime);
|
||||
for (int i = 0; i < KEY_COUNT; i++) {
|
||||
target.Children.Add(keystates[i]);
|
||||
keystates[i].MouseDown += func;
|
||||
map.Add(keystates[i], new CellPosition(column, (FrameDataField)i));
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove(Grid target, Dictionary<Rectangle, CellPosition> map, MouseButtonEventHandler func) {
|
||||
target.Children.Remove(sel_rect);
|
||||
target.Children.Remove(frame);
|
||||
target.Children.Remove(deltaTime);
|
||||
for (int i = 0; i < KEY_COUNT; i++) {
|
||||
target.Children.Remove(keystates[i]);
|
||||
keystates[i].MouseDown -= func;
|
||||
map.Remove(keystates[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void Reload(FrameDataDisplay fdd) {
|
||||
var isEnable = fdd.isEnable;
|
||||
frame.Text = isEnable ? fdd.index.ToString() : "";
|
||||
deltaTime.Text = isEnable ? fdd.deltaTime.ToString() : "";
|
||||
keystatesFill[0].Color = isEnable && fdd.key_up ? COLOR_SET : COLOR_UNSET;
|
||||
keystatesFill[1].Color = isEnable && fdd.key_down ? COLOR_SET : COLOR_UNSET;
|
||||
keystatesFill[2].Color = isEnable && fdd.key_left ? COLOR_SET : COLOR_UNSET;
|
||||
keystatesFill[3].Color = isEnable && fdd.key_right ? COLOR_SET : COLOR_UNSET;
|
||||
keystatesFill[4].Color = isEnable && fdd.key_shift ? COLOR_SET : COLOR_UNSET;
|
||||
keystatesFill[5].Color = isEnable && fdd.key_space ? COLOR_SET : COLOR_UNSET;
|
||||
keystatesFill[6].Color = isEnable && fdd.key_q ? COLOR_SET : COLOR_UNSET;
|
||||
keystatesFill[7].Color = isEnable && fdd.key_esc ? COLOR_SET : COLOR_UNSET;
|
||||
keystatesFill[8].Color = isEnable && fdd.key_enter ? COLOR_SET : COLOR_UNSET;
|
||||
|
||||
sel_rect.Visibility = isEnable ? Visibility.Visible : Visibility.Collapsed;
|
||||
frame.Visibility = isEnable ? Visibility.Visible : Visibility.Collapsed;
|
||||
deltaTime.Visibility = isEnable ? Visibility.Visible : Visibility.Collapsed;
|
||||
for (int i = 0; i < KEY_COUNT; i++) {
|
||||
keystates[i].Visibility = isEnable ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
rawIsEnable = isEnable;
|
||||
rawFrame = fdd.index;
|
||||
}
|
||||
|
||||
public void SelectFull() {
|
||||
sel_rect.Fill = SEL_RECT_SELECTED_BRUSH;
|
||||
}
|
||||
|
||||
public void SelectField(SelectionRange range) {
|
||||
for (int i = 0; i < KEY_COUNT; i++) {
|
||||
keystatesStroke[i].Color = range.Within(i) ? COLOR_SELECTED : COLOR_UNSELECTED;
|
||||
}
|
||||
}
|
||||
|
||||
public void Unselect() {
|
||||
sel_rect.Fill = SEL_RECT_NORMAL_BRUSH;
|
||||
for (int i = 0; i < KEY_COUNT; i++) {
|
||||
keystatesStroke[i].Color = COLOR_UNSELECTED;
|
||||
}
|
||||
}
|
||||
|
||||
public long rawFrame;
|
||||
public bool rawIsEnable;
|
||||
|
||||
public Rectangle sel_rect;
|
||||
public TextBlock frame;
|
||||
public TextBlock deltaTime;
|
||||
public Rectangle[] keystates;
|
||||
private SolidColorBrush[] keystatesFill;
|
||||
private SolidColorBrush[] keystatesStroke;
|
||||
private int column;
|
||||
}
|
||||
}
|
||||
117
Legacy/BallanceTASEditor/UI/TASSlider.cs
Normal file
117
Legacy/BallanceTASEditor/UI/TASSlider.cs
Normal file
@ -0,0 +1,117 @@
|
||||
using BallanceTASEditor.Core;
|
||||
using BallanceTASEditor.Core.TASStruct;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace BallanceTASEditor.UI {
|
||||
public class TASSlider {
|
||||
public TASSlider(TASSliderComponents _components) {
|
||||
components = _components;
|
||||
components.mSlider.Minimum = 0;
|
||||
mIsHorizontalLayout = true;
|
||||
|
||||
components.mSlider.ValueChanged += func_SliderValueChanged;
|
||||
}
|
||||
|
||||
public event Action<long> ValueChanged;
|
||||
TASSliderComponents components;
|
||||
bool mIsHorizontalLayout;
|
||||
|
||||
public void MoveSliderManually(bool isPrev, bool isFast, int fastCount) {
|
||||
var step = isFast ? fastCount : 1;
|
||||
components.mSlider.Value = Core.Util.Clamp(components.mSlider.Value.ToInt32() + (isPrev ? -1 : 1) * step, components.mSlider.Minimum.ToInt32(), components.mSlider.Maximum.ToInt32());
|
||||
}
|
||||
|
||||
public void UpdateRange(TASFile mFile) {
|
||||
components.mSlider.Maximum = mFile.mFrameCount == 0 ? 0 : mFile.mFrameCount - 1;
|
||||
var index = mFile.GetPointerIndex();
|
||||
if (index >= 0) {
|
||||
components.mSlider.Value = mFile.GetPointerIndex();
|
||||
components.mSlider.IsEnabled = true;
|
||||
} else {
|
||||
// invalid index, mean slider is useless, disable it
|
||||
components.mSlider.Value = components.mSlider.Maximum;
|
||||
components.mSlider.IsEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void func_SliderValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) {
|
||||
ValueChanged?.Invoke(e.NewValue.ToInt64());
|
||||
}
|
||||
|
||||
public void ChangeLayout(bool isHorizontal) {
|
||||
if (isHorizontal == mIsHorizontalLayout) return;
|
||||
|
||||
// the layout changed, re-construct elements
|
||||
mIsHorizontalLayout = isHorizontal;
|
||||
|
||||
// change container
|
||||
components.container.RowDefinitions.Clear();
|
||||
components.container.ColumnDefinitions.Clear();
|
||||
if (mIsHorizontalLayout) {
|
||||
for(int i = 0; i < 4; i++) {
|
||||
UI.Util.GridColumnAdder(components.container, GridLength.Auto);
|
||||
}
|
||||
UI.Util.GridColumnAdder(components.container, new GridLength(1, GridUnitType.Star));
|
||||
} else {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
UI.Util.GridRowAdder(components.container, GridLength.Auto);
|
||||
}
|
||||
UI.Util.GridRowAdder(components.container, new GridLength(1, GridUnitType.Star));
|
||||
}
|
||||
|
||||
// flip elements
|
||||
UI.Util.SwapGridItemRC(components.btnFastPrev);
|
||||
UI.Util.SwapGridItemRC(components.btnPrev);
|
||||
UI.Util.SwapGridItemRC(components.btnNext);
|
||||
UI.Util.SwapGridItemRC(components.btnFastNext);
|
||||
UI.Util.SwapGridItemRC(components.mSlider);
|
||||
|
||||
// change transform
|
||||
if (mIsHorizontalLayout) {
|
||||
// clear all btn's transform and set slider as horizontal style
|
||||
components.btnFastPrev.RenderTransform = Transform.Identity;
|
||||
components.btnPrev.RenderTransform = Transform.Identity;
|
||||
components.btnNext.RenderTransform = Transform.Identity;
|
||||
components.btnFastNext.RenderTransform = Transform.Identity;
|
||||
|
||||
components.mSlider.RenderTransform = Transform.Identity;
|
||||
components.mSlider.Orientation = Orientation.Horizontal;
|
||||
components.mSlider.VerticalAlignment = VerticalAlignment.Center;
|
||||
components.mSlider.HorizontalAlignment = HorizontalAlignment.Stretch;
|
||||
} else {
|
||||
components.btnFastPrev.RenderTransform = new RotateTransform(90);
|
||||
components.btnPrev.RenderTransform = new RotateTransform(90);
|
||||
components.btnNext.RenderTransform = new RotateTransform(90);
|
||||
components.btnFastNext.RenderTransform = new RotateTransform(90);
|
||||
|
||||
components.mSlider.RenderTransform = new RotateTransform(180);
|
||||
components.mSlider.Orientation = Orientation.Vertical;
|
||||
components.mSlider.VerticalAlignment = VerticalAlignment.Stretch;
|
||||
components.mSlider.HorizontalAlignment = HorizontalAlignment.Center;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class TASSliderComponents {
|
||||
public Grid container;
|
||||
public Button btnFastPrev;
|
||||
public Button btnPrev;
|
||||
public Button btnNext;
|
||||
public Button btnFastNext;
|
||||
public Slider mSlider;
|
||||
}
|
||||
}
|
||||
253
Legacy/BallanceTASEditor/UI/TASViewer.cs
Normal file
253
Legacy/BallanceTASEditor/UI/TASViewer.cs
Normal file
@ -0,0 +1,253 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using BallanceTASEditor.Core;
|
||||
using BallanceTASEditor.Core.TASStruct;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows;
|
||||
|
||||
namespace BallanceTASEditor.UI {
|
||||
public class TASViewer : IDisposable {
|
||||
public TASViewer(TASFile file, TASSlider slider, TASFlow datagrid) {
|
||||
mFile = file;
|
||||
mSlider = slider;
|
||||
mDataGrid = datagrid;
|
||||
|
||||
// restore slider
|
||||
mSlider.UpdateRange(mFile);
|
||||
|
||||
// init selection
|
||||
mSelectionHelp = new SelectionHelp();
|
||||
mSelectionHelp.SelectionChanged += funcSelectionHelp_SelectionChanged;
|
||||
|
||||
// init data
|
||||
INVALID_FRAME_DATA = new FrameData(-1f, 0);
|
||||
mDataSource = new List<FrameDataDisplay>();
|
||||
mListLength = 0;
|
||||
mOverwrittenPaste = false;
|
||||
|
||||
// bind event and source
|
||||
mDataGrid.DataSources = mDataSource;
|
||||
mDataGrid.SelectionHelp = mSelectionHelp;
|
||||
|
||||
mDataGrid.Click += funcDataMenu_Click;
|
||||
mSlider.ValueChanged += funcSlider_ValueChanged;
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
mDataGrid.DataSources = null;
|
||||
|
||||
mDataGrid.Click -= funcDataMenu_Click;
|
||||
mSlider.ValueChanged -= funcSlider_ValueChanged;
|
||||
}
|
||||
|
||||
//const int DATA_LIST_LENGTH = 15;
|
||||
FrameData INVALID_FRAME_DATA;
|
||||
TASFile mFile;
|
||||
TASSlider mSlider;
|
||||
TASFlow mDataGrid;
|
||||
SelectionHelp mSelectionHelp;
|
||||
int mListLength;
|
||||
List<FrameDataDisplay> mDataSource;
|
||||
bool mOverwrittenPaste;
|
||||
|
||||
#region self event
|
||||
public event Action<bool, bool, bool> UpdateDataUI;
|
||||
public event Action<ToolMode> UpdateToolMode;
|
||||
public event Action<SelectionHelp> UpdateSelection;
|
||||
|
||||
private void OnUpdateDataUI() {
|
||||
ToolMode mode = mSelectionHelp.GetToolMode();
|
||||
bool showCursorPasteAddDeleteOne = mode == ToolMode.Cursor && mSelectionHelp.IsDataPartialReady();
|
||||
bool showFill = mode == ToolMode.Fill && mSelectionHelp.IsDataReady();
|
||||
bool showCursorCopyDelete = mode == ToolMode.Cursor && mSelectionHelp.IsDataReady();
|
||||
|
||||
UpdateDataUI?.Invoke(showCursorPasteAddDeleteOne, showFill, showCursorCopyDelete);
|
||||
}
|
||||
|
||||
private void OnUpdateToolMode() {
|
||||
UpdateToolMode?.Invoke(mSelectionHelp.GetToolMode());
|
||||
}
|
||||
|
||||
private void OnUpdateSelection() {
|
||||
UpdateSelection?.Invoke(mSelectionHelp);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region process event
|
||||
|
||||
private void funcSlider_ValueChanged(long pos) {
|
||||
mFile.Shift(pos);
|
||||
RefreshDisplay();
|
||||
}
|
||||
|
||||
private void funcSelectionHelp_SelectionChanged() {
|
||||
mDataGrid.RefreshSelectionHighlight();
|
||||
OnUpdateDataUI();
|
||||
OnUpdateSelection();
|
||||
}
|
||||
|
||||
private void funcDataMenu_Click() {
|
||||
var data = mSelectionHelp.GetPoint();
|
||||
var field = (int)mSelectionHelp.GetPointField();
|
||||
mFile.Set(new SelectionRange(field, field), new SelectionRange(data, data), null);
|
||||
RefreshDisplay();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public void ChangeOverwrittenMode(bool isOverwritten) {
|
||||
mOverwrittenPaste = isOverwritten;
|
||||
}
|
||||
|
||||
public void ChangeListLength(int newLen) {
|
||||
if (newLen < 5 || newLen > 200) return;
|
||||
int offset = newLen - mListLength;
|
||||
int abs = Math.Abs(offset);
|
||||
if (offset == 0) return;
|
||||
|
||||
// change mDataSource first
|
||||
|
||||
if (offset > 0) {
|
||||
for (int i = 0; i < abs; i++) {
|
||||
mDataSource.Add(new FrameDataDisplay(0, INVALID_FRAME_DATA));
|
||||
}
|
||||
} else {
|
||||
mDataSource.RemoveRange(newLen, abs);
|
||||
}
|
||||
|
||||
// then change viewer control
|
||||
mDataGrid.SetItemCount(newLen);
|
||||
|
||||
// apply new value
|
||||
mListLength = newLen;
|
||||
|
||||
// then refresh
|
||||
RefreshDisplay();
|
||||
}
|
||||
|
||||
public void RefreshDisplay() {
|
||||
mFile.Get(mDataSource, mListLength);
|
||||
mDataGrid.RefreshDataSources();
|
||||
mDataGrid.RefreshSelectionHighlight();
|
||||
}
|
||||
|
||||
public void ChangeToolMode(ToolMode mode) {
|
||||
mSelectionHelp.SetMode(mode);
|
||||
OnUpdateToolMode();
|
||||
}
|
||||
|
||||
public int GetItemCountInPage() {
|
||||
return mListLength;
|
||||
}
|
||||
|
||||
public void ProcessOperation(OperationEnum oper) {
|
||||
switch (oper) {
|
||||
case OperationEnum.Set:
|
||||
case OperationEnum.Unset: {
|
||||
mFile.Set(mSelectionHelp.GetFieldRange(), mSelectionHelp.GetRange(), oper == OperationEnum.Set);
|
||||
RefreshDisplay();
|
||||
}
|
||||
break;
|
||||
case OperationEnum.Cut: {
|
||||
// cut is a hybrid operation, first, do copy
|
||||
// then delete selected item
|
||||
// due to copy is not affect TASFile and only delete oper affect it
|
||||
// so this is a revocable oper
|
||||
var data = new LinkedList<FrameData>();
|
||||
mFile.Copy(mSelectionHelp.GetRange(), data);
|
||||
if (!ClipboardUtil.SetFrameData(data)) {
|
||||
MessageBox.Show("Fail to cut due to unknow reason!");
|
||||
break; // if fail to cut, do not delete selected items.
|
||||
}
|
||||
|
||||
// do delete
|
||||
mFile.Remove(mSelectionHelp.GetRange());
|
||||
mSelectionHelp.Reset();
|
||||
mSlider.UpdateRange(mFile);
|
||||
RefreshDisplay();
|
||||
}
|
||||
break;
|
||||
case OperationEnum.Copy: {
|
||||
var data = new LinkedList<FrameData>();
|
||||
mFile.Copy(mSelectionHelp.GetRange(), data);
|
||||
if (!ClipboardUtil.SetFrameData(data))
|
||||
MessageBox.Show("Fail to copy due to unknow reason!");
|
||||
}
|
||||
break;
|
||||
case OperationEnum.PasteAfter:
|
||||
case OperationEnum.PasteBefore: {
|
||||
var data = new LinkedList<FrameData>();
|
||||
if (ClipboardUtil.GetFrameData(data)) {
|
||||
mFile.Insert(mSelectionHelp.GetPoint(), data, oper == OperationEnum.PasteBefore, mOverwrittenPaste);
|
||||
mSelectionHelp.Reset();
|
||||
mSlider.UpdateRange(mFile);
|
||||
RefreshDisplay();
|
||||
} else MessageBox.Show("Fail to paste due to unknow reason or blank clipboard!");
|
||||
}
|
||||
break;
|
||||
case OperationEnum.Delete: {
|
||||
mFile.Remove(mSelectionHelp.GetRange());
|
||||
mSelectionHelp.Reset();
|
||||
mSlider.UpdateRange(mFile);
|
||||
RefreshDisplay();
|
||||
}
|
||||
break;
|
||||
case OperationEnum.DeleteAfter:
|
||||
case OperationEnum.DeleteBefore: {
|
||||
var pos = mSelectionHelp.GetPoint();
|
||||
if (oper == OperationEnum.DeleteBefore) pos -= 1; // delete after mean delete current selected item
|
||||
if (pos < 0 || pos >= mFile.mFrameCount) return;
|
||||
|
||||
// delete before need shift selection
|
||||
// delete before couldn't cause empty list, so we just need to directly shift
|
||||
if (oper == OperationEnum.DeleteBefore)
|
||||
mSelectionHelp.ShiftTo(false);
|
||||
// also, if we use delete after and delete the tail of item list, we also need to shift pos(use `else if` to prevent double shift)
|
||||
else if (oper == OperationEnum.DeleteAfter && pos == mFile.mFrameCount - 1) {
|
||||
// but delete after may cause empty list error(delete the item within only 1 item list)
|
||||
// so we need prevent this situation
|
||||
if (mFile.mFrameCount == 1) mSelectionHelp.Reset(); //yes, reset selection to prevent error
|
||||
else mSelectionHelp.ShiftTo(false); //no, shift selection.
|
||||
}
|
||||
|
||||
// do real operation
|
||||
mFile.Remove(new SelectionRange(pos, pos));
|
||||
|
||||
mSlider.UpdateRange(mFile);
|
||||
RefreshDisplay();
|
||||
}
|
||||
break;
|
||||
case OperationEnum.AddAfter:
|
||||
case OperationEnum.AddBefore: {
|
||||
if (!DialogUtil.AddItemDialog(out int count, out float deltaTime)) return;
|
||||
|
||||
var pos = mSelectionHelp.GetPoint();
|
||||
mFile.Add(pos, count, deltaTime, oper == OperationEnum.AddBefore);
|
||||
mSelectionHelp.Reset();
|
||||
mSlider.UpdateRange(mFile);
|
||||
RefreshDisplay();
|
||||
}
|
||||
break;
|
||||
case OperationEnum.Undo: {
|
||||
mFile.Undo();
|
||||
mSelectionHelp.Reset();
|
||||
mSlider.UpdateRange(mFile);
|
||||
RefreshDisplay();
|
||||
}
|
||||
break;
|
||||
case OperationEnum.Redo: {
|
||||
mFile.Redo();
|
||||
mSelectionHelp.Reset();
|
||||
mSlider.UpdateRange(mFile);
|
||||
RefreshDisplay();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
52
Legacy/BallanceTASEditor/UI/Util.cs
Normal file
52
Legacy/BallanceTASEditor/UI/Util.cs
Normal file
@ -0,0 +1,52 @@
|
||||
using BallanceTASEditor.Core.TASStruct;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace BallanceTASEditor.UI {
|
||||
|
||||
public static class Util {
|
||||
public static void GridRowAdder(Grid container, GridLength size) {
|
||||
var item = new RowDefinition();
|
||||
item.Height = size;
|
||||
container.RowDefinitions.Add(item);
|
||||
}
|
||||
|
||||
public static void GridColumnAdder(Grid container, GridLength size) {
|
||||
var item = new ColumnDefinition();
|
||||
item.Width = size;
|
||||
container.ColumnDefinitions.Add(item);
|
||||
}
|
||||
|
||||
public static void SwapGridItemRC(UIElement item) {
|
||||
var swap = Grid.GetColumn(item);
|
||||
Grid.SetColumn(item, Grid.GetRow(item));
|
||||
Grid.SetRow(item, swap);
|
||||
}
|
||||
}
|
||||
|
||||
public enum ToolMode {
|
||||
Cursor,
|
||||
Fill,
|
||||
Overwrite
|
||||
}
|
||||
|
||||
public struct CellPosition {
|
||||
public CellPosition(int column, FrameDataField field) {
|
||||
this.column = column;
|
||||
this.field = field;
|
||||
}
|
||||
public int column;
|
||||
public FrameDataField field;
|
||||
}
|
||||
}
|
||||
3
Legacy/BallanceTASEditor/app.config
Normal file
3
Legacy/BallanceTASEditor/app.config
Normal file
@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration>
|
||||
BIN
Legacy/BallanceTASEditor/icon.ico
Normal file
BIN
Legacy/BallanceTASEditor/icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 264 KiB |
5
Legacy/BallanceTASEditor/packages.config
Normal file
5
Legacy/BallanceTASEditor/packages.config
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="DotNetZip" version="1.9.1.8" targetFramework="net45" />
|
||||
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net45" />
|
||||
</packages>
|
||||
108
Legacy/BallanceTASEditorTests/BallanceTASEditorTests.csproj
Normal file
108
Legacy/BallanceTASEditorTests/BallanceTASEditorTests.csproj
Normal file
@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\packages\MSTest.TestAdapter.2.2.5\build\net45\MSTest.TestAdapter.props" Condition="Exists('..\packages\MSTest.TestAdapter.2.2.5\build\net45\MSTest.TestAdapter.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{EC35111D-6259-4C69-B7E4-F4E727AC0E1A}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>BallanceTASEditorTests</RootNamespace>
|
||||
<AssemblyName>BallanceTASEditorTests</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
|
||||
<IsCodedUITest>False</IsCodedUITest>
|
||||
<TestProjectType>UnitTest</TestProjectType>
|
||||
<TargetFrameworkProfile />
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\MSTest.TestFramework.2.2.5\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\MSTest.TestFramework.2.2.5\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
</ItemGroup>
|
||||
<Choose>
|
||||
<When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
|
||||
</ItemGroup>
|
||||
</When>
|
||||
<Otherwise />
|
||||
</Choose>
|
||||
<ItemGroup>
|
||||
<Compile Include="Core\TASFileTests.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BallanceTASEditor\BallanceTASEditor.csproj">
|
||||
<Project>{3127A635-B9E5-4C78-8414-0B9B196EC25E}</Project>
|
||||
<Name>BallanceTASEditor</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Choose>
|
||||
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
</When>
|
||||
</Choose>
|
||||
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.2.2.5\build\net45\MSTest.TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.2.2.5\build\net45\MSTest.TestAdapter.props'))" />
|
||||
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.2.2.5\build\net45\MSTest.TestAdapter.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.2.2.5\build\net45\MSTest.TestAdapter.targets'))" />
|
||||
</Target>
|
||||
<Import Project="..\packages\MSTest.TestAdapter.2.2.5\build\net45\MSTest.TestAdapter.targets" Condition="Exists('..\packages\MSTest.TestAdapter.2.2.5\build\net45\MSTest.TestAdapter.targets')" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
171
Legacy/BallanceTASEditorTests/Core/TASFileTests.cs
Normal file
171
Legacy/BallanceTASEditorTests/Core/TASFileTests.cs
Normal file
@ -0,0 +1,171 @@
|
||||
using BallanceTASEditor.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using BallanceTASEditor.Core.TASStruct;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace BallanceTASEditor.Core.Tests {
|
||||
[TestClass()]
|
||||
public class TASFileTests {
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow("1,2,3,4,5", 0, "15;0;15,15,15,4,5,", FrameDataField.Key_Up, FrameDataField.Key_Right, 0, 2, true)]
|
||||
[DataRow("1,2,3,4,5", 0, "0;0;0,0,0,4,5,", FrameDataField.Key_Up, FrameDataField.Key_Right, 0, 2, false)]
|
||||
[DataRow("1,2,3,4,5", 0, "14;0;14,13,12,4,5,", FrameDataField.Key_Up, FrameDataField.Key_Right, 0, 2, null)]
|
||||
public void SetTest(string originStr, long prevShift, string expectedStr, FrameDataField field_start, FrameDataField field_end, long absoluteRange_start, long absoluteRange_end, bool? isSet) {
|
||||
var test = new TASFile(dataGenerator(originStr));
|
||||
test.Shift(prevShift);
|
||||
var originalText = test.Output2TestString();
|
||||
|
||||
// test function
|
||||
test.Set(new SelectionRange((long)field_start, (long)field_end), new SelectionRange(absoluteRange_start, absoluteRange_end), isSet);
|
||||
var changedText = test.Output2TestString();
|
||||
Assert.AreEqual(expectedStr, changedText);
|
||||
|
||||
// test undo
|
||||
test.Undo();
|
||||
Assert.AreEqual(originalText, test.Output2TestString());
|
||||
|
||||
// test redo
|
||||
test.Redo();
|
||||
Assert.AreEqual(changedText, test.Output2TestString());
|
||||
|
||||
// test undo
|
||||
test.Undo();
|
||||
Assert.AreEqual(originalText, test.Output2TestString());
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow("1,2,3,4,5", 0, "3;0;3,4,5,", 0, 1)]
|
||||
[DataRow("1,2,3,4,5", 0, "null;-1;", 0, 4)]
|
||||
[DataRow("1,2,3,4,5", 0, "1;0;1,2,3,", 3, 4)]
|
||||
[DataRow("1,2,3,4,5", 0, "2;0;2,3,4,5,", 0, 0)]
|
||||
[DataRow("1,2,3,4,5", 0, "1;0;1,2,3,4,", 4, 4)]
|
||||
[DataRow("1,2,3,4,5", 2, "1;0;1,5,", 1, 3)]
|
||||
[DataRow("1,2,3,4,5", 2, "5;0;5,", 0, 3)]
|
||||
[DataRow("1,2,3,4,5", 2, "1;0;1,", 1, 4)]
|
||||
[DataRow("1,2,3,4,5", 3, "4;0;4,5,", 0, 2)]
|
||||
[DataRow("1,2,3,4,5", 4, "5;1;4,5,", 0, 2)]
|
||||
public void RemoveTest(string originStr, long prevShift, string expectedStr, long absoluteRange_start, long absoluteRange_end) {
|
||||
var test = new TASFile(dataGenerator(originStr));
|
||||
test.Shift(prevShift);
|
||||
var originalText = test.Output2TestString();
|
||||
|
||||
// test function
|
||||
test.Remove(new SelectionRange(absoluteRange_start, absoluteRange_end));
|
||||
var changedText = test.Output2TestString();
|
||||
Assert.AreEqual(expectedStr, changedText);
|
||||
|
||||
// test undo
|
||||
test.Undo();
|
||||
Assert.AreEqual(originalText, test.Output2TestString());
|
||||
|
||||
// test redo
|
||||
test.Redo();
|
||||
Assert.AreEqual(changedText, test.Output2TestString());
|
||||
|
||||
// test undo
|
||||
test.Undo();
|
||||
Assert.AreEqual(originalText, test.Output2TestString());
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow("1,2,3,4,5", 0, "1;0;1,2,0,0,0,3,4,5,", 2, 3, 240 / 1f, true)]
|
||||
[DataRow("1,2,3,4,5", 0, "1;0;1,2,3,0,0,0,4,5,", 2, 3, 240 / 1f, false)]
|
||||
[DataRow("1,2,3,4,5", 2, "3;5;1,2,0,0,0,3,4,5,", 2, 3, 240 / 1f, true)]
|
||||
[DataRow("1,2,3,4,5", 2, "3;2;1,2,3,0,0,0,4,5,", 2, 3, 240 / 1f, false)]
|
||||
|
||||
[DataRow("1,2,3,4,5", 0, "1;3;0,0,0,1,2,3,4,5,", 0, 3, 240 / 1f, true)]
|
||||
[DataRow("1,2,3,4,5", 0, "1;0;1,2,3,4,5,0,0,0,", 4, 3, 240 / 1f, false)]
|
||||
public void AddTest(string originStr, long prevShift, string expectedStr, long absolutePos, long count, float deltaTime, bool isAddBefore) {
|
||||
var test = new TASFile(dataGenerator(originStr));
|
||||
test.Shift(prevShift);
|
||||
var originalText = test.Output2TestString();
|
||||
|
||||
// test function
|
||||
test.Add(absolutePos, count, deltaTime, isAddBefore);
|
||||
var changedText = test.Output2TestString();
|
||||
Assert.AreEqual(expectedStr, changedText);
|
||||
|
||||
// test undo
|
||||
test.Undo();
|
||||
Assert.AreEqual(originalText, test.Output2TestString());
|
||||
|
||||
// test redo
|
||||
test.Redo();
|
||||
Assert.AreEqual(changedText, test.Output2TestString());
|
||||
|
||||
// test undo
|
||||
test.Undo();
|
||||
Assert.AreEqual(originalText, test.Output2TestString());
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow("1,2,3,4,5", 0, "6;0;6,7,8,9,10,", 0, "6,7,8,9,10", false, true)]
|
||||
[DataRow("1,2,3,4,5", 0, "6;0;6,7,8,9,10,", 4, "6,7,8,9,10", true, true)]
|
||||
|
||||
[DataRow("1,2,3,4,5", 0, "1;0;1,2,6,7,8,3,4,5,", 2, "6,7,8", true, false)]
|
||||
[DataRow("1,2,3,4,5", 0, "1;0;1,2,3,6,7,8,4,5,", 2, "6,7,8", false, false)]
|
||||
|
||||
[DataRow("1,2,3,4,5", 0, "1;0;1,2,3,4,5,6,7,", 4, "6,7", false, false)]
|
||||
[DataRow("1,2,3,4,5", 0, "1;2;6,7,1,2,3,4,5,", 0, "6,7", true, false)]
|
||||
|
||||
[DataRow("1,2,3,4,5", 0, "1;0;1,6,7,4,5,", 2, "6,7", true, true)]
|
||||
[DataRow("1,2,3,4,5", 0, "1;0;1,2,6,7,5,", 2, "6,7", false, true)]
|
||||
[DataRow("1,2,3,4,5", 0, "4;3;6,7,8,4,5,", 2, "6,7,8", true, true)]
|
||||
[DataRow("1,2,3,4,5", 0, "1;0;1,2,6,7,8,", 2, "6,7,8", false, true)]
|
||||
[DataRow("1,2,3,4,5", 0, "4;4;6,7,8,9,4,5,", 2, "6,7,8,9", true, true)]
|
||||
[DataRow("1,2,3,4,5", 0, "1;0;1,2,6,7,8,9,", 2, "6,7,8,9", false, true)]
|
||||
|
||||
[DataRow("1,2,3,4,5", 2, "1;0;1,6,7,4,5,", 2, "6,7", true, true)]
|
||||
[DataRow("1,2,3,4,5", 2, "2;1;1,2,6,7,5,", 2, "6,7", false, true)]
|
||||
[DataRow("1,2,3,4,5", 2, "4;3;6,7,8,4,5,", 2, "6,7,8", true, true)]
|
||||
[DataRow("1,2,3,4,5", 2, "2;1;1,2,6,7,8,", 2, "6,7,8", false, true)]
|
||||
[DataRow("1,2,3,4,5", 2, "4;4;6,7,8,9,4,5,", 2, "6,7,8,9", true, true)]
|
||||
[DataRow("1,2,3,4,5", 2, "2;1;1,2,6,7,8,9,", 2, "6,7,8,9", false, true)]
|
||||
|
||||
[DataRow("1,2,3,4,5", 4, "5;4;1,6,7,4,5,", 2, "6,7", true, true)]
|
||||
[DataRow("1,2,3,4,5", 4, "5;4;1,2,6,7,5,", 2, "6,7", false, true)]
|
||||
[DataRow("1,2,3,4,5", 4, "5;4;6,7,8,4,5,", 2, "6,7,8", true, true)]
|
||||
[DataRow("1,2,3,4,5", 4, "2;1;1,2,6,7,8,", 2, "6,7,8", false, true)]
|
||||
[DataRow("1,2,3,4,5", 4, "5;5;6,7,8,9,4,5,", 2, "6,7,8,9", true, true)]
|
||||
[DataRow("1,2,3,4,5", 4, "2;1;1,2,6,7,8,9,", 2, "6,7,8,9", false, true)]
|
||||
|
||||
[DataRow("1,2,3,4,5", 2, "3;5;1,2,6,7,8,3,4,5,", 2, "6,7,8", true, false)]
|
||||
[DataRow("1,2,3,4,5", 2, "3;2;1,2,3,6,7,8,4,5,", 2, "6,7,8", false, false)]
|
||||
public void InsertTest(string originStr, long prevShift, string expectedStr, long absolutePos, string insertedData, bool isInsertBefore, bool isOverwritten) {
|
||||
var test = new TASFile(dataGenerator(originStr));
|
||||
test.Shift(prevShift);
|
||||
var originalText = test.Output2TestString();
|
||||
|
||||
// test function
|
||||
test.Insert(absolutePos, dataGenerator(insertedData), isInsertBefore, isOverwritten);
|
||||
var changedText = test.Output2TestString();
|
||||
Assert.AreEqual(expectedStr, changedText);
|
||||
|
||||
// test undo
|
||||
test.Undo();
|
||||
Assert.AreEqual(originalText, test.Output2TestString());
|
||||
|
||||
// test redo
|
||||
test.Redo();
|
||||
Assert.AreEqual(changedText, test.Output2TestString());
|
||||
|
||||
// test undo
|
||||
test.Undo();
|
||||
Assert.AreEqual(originalText, test.Output2TestString());
|
||||
}
|
||||
|
||||
// example input: 1,2,3,4,5
|
||||
private LinkedList<FrameData> dataGenerator(string inputData) {
|
||||
var ls = new LinkedList<FrameData>();
|
||||
foreach (var item in inputData.Split(',')) {
|
||||
ls.AddLast(new FrameData(float.Parse(item), uint.Parse(item)));
|
||||
}
|
||||
return ls;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
36
Legacy/BallanceTASEditorTests/Properties/AssemblyInfo.cs
Normal file
36
Legacy/BallanceTASEditorTests/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 有关程序集的一般信息由以下
|
||||
// 控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle("BallanceTASEditorTests")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("BallanceTASEditorTests")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2021")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
//将 ComVisible 设置为 false 将使此程序集中的类型
|
||||
//对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
|
||||
//请将此类型的 ComVisible 特性设置为 true。
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
||||
[assembly: Guid("ec35111d-6259-4c69-b7e4-f4e727ac0e1a")]
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 生成号
|
||||
// 修订号
|
||||
//
|
||||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
|
||||
//通过使用 "*",如下所示:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
5
Legacy/BallanceTASEditorTests/packages.config
Normal file
5
Legacy/BallanceTASEditorTests/packages.config
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="MSTest.TestAdapter" version="2.2.5" targetFramework="net45" />
|
||||
<package id="MSTest.TestFramework" version="2.2.5" targetFramework="net45" />
|
||||
</packages>
|
||||
Reference in New Issue
Block a user