This commit is contained in:
2021-05-13 22:18:51 +08:00
parent 7259c36da1
commit 1d700a02e3
10 changed files with 298 additions and 198 deletions

33
UI/DialogUtil.cs Normal file
View File

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
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 = "TAS file(*.tas)|*.tas|All file(*.*)|*.*";
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 = "TAS file(*.tas)|*.tas|All file(*.*)|*.*";
if (!(bool)op.ShowDialog()) return "";
return op.FileName;
}
public static bool ConfirmDialog(string str) {
var result = MessageBox.Show(str, "Warning", MessageBoxButton.YesNo, MessageBoxImage.Warning);
return (result == MessageBoxResult.Yes);
}
}
}

61
UI/StyleConverter.cs Normal file
View File

@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Windows.Data;
using System.Windows.Media;
namespace BallanceTASEditor.UI {
[ValueConversion(typeof(bool), typeof(Color))]
public class BackgroundConverter : IValueConverter {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
try {
bool bl = System.Convert.ToBoolean(value);
if (bl) return Color.FromRgb(30, 144, 255);
else return Color.FromArgb(0, 255, 255, 255);
} catch {
return Color.FromArgb(0, 255, 255, 255);
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
return null;
}
}
[ValueConversion(typeof(float), typeof(string))]
public class FloatConverter : IValueConverter {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
try {
float bl = System.Convert.ToSingle(value);
if (bl < 0) return "";
else return bl.ToString();
} catch {
return "";
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
return null;
}
}
[ValueConversion(typeof(long), typeof(string))]
public class LongConverter : IValueConverter {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
try {
float bl = System.Convert.ToInt64(value);
if (bl < 0) return "";
else return bl.ToString();
} catch {
return "";
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
return null;
}
}
}

56
UI/TASFlow.xaml Normal file
View File

@ -0,0 +1,56 @@
<UserControl x:Class="BallanceTASEditor.UI.TASFlow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:BallanceTASEditor.UI"
mc:Ignorable="d"
d:DesignHeight="400" d:DesignWidth="800">
<Grid x:Name="uiCoreWindow">
<Grid.ContextMenu>
<ContextMenu>
<MenuItem x:Name="uiDataMenu_Set" Header="Set"/>
<MenuItem x:Name="uiDataMenu_Unset" Header="Unset"/>
<Separator/>
<MenuItem x:Name="uiDataMenu_Copy" Header="Copy"/>
<MenuItem x:Name="uiDataMenu_Delete" Header="Delete"/>
<Separator/>
<MenuItem x:Name="uiDataMenu_PasteAfter" Header="Paste after this"/>
<MenuItem x:Name="uiDataMenu_PasteBefore" Header="Paste before this"/>
<Separator/>
<MenuItem x:Name="uiDataMenu_AddAfter" Header="Add blank item after this"/>
<MenuItem x:Name="uiDataMenu_AddBefore" Header="Add blank item before this"/>
</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="*"/>
</Grid.RowDefinitions>
<TextBlock Padding="2" Background="#afafaf" Grid.Column="0" Grid.Row="0" Text="Frame"/>
<TextBlock Padding="2" Background="#afafaf" Grid.Column="0" Grid.Row="1" Text="Delta Time"/>
<TextBlock Padding="2" Background="#afafaf" Grid.Column="0" Grid.Row="2" Text="^"/>
<TextBlock Padding="2" Background="#afafaf" Grid.Column="0" Grid.Row="3" Text="v"/>
<TextBlock Padding="2" Background="#afafaf" Grid.Column="0" Grid.Row="4" Text="&lt;"/>
<TextBlock Padding="2" Background="#afafaf" Grid.Column="0" Grid.Row="5" Text="&gt;"/>
<TextBlock Padding="2" Background="#afafaf" Grid.Column="0" Grid.Row="6" Text="shift"/>
<TextBlock Padding="2" Background="#afafaf" Grid.Column="0" Grid.Row="7" Text="space"/>
<TextBlock Padding="2" Background="#afafaf" Grid.Column="0" Grid.Row="8" Text="q"/>
<TextBlock Padding="2" Background="#afafaf" Grid.Column="0" Grid.Row="9" Text="esc"/>
<TextBlock Padding="2" Background="#afafaf" Grid.Column="0" Grid.Row="10" Text="enter"/>
</Grid>
</UserControl>

154
UI/TASFlow.xaml.cs Normal file
View File

@ -0,0 +1,154 @@
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 {
/// <summary>
/// TASFlow.xaml 的交互逻辑
/// </summary>
public partial class TASFlow : UserControl {
public TASFlow() {
InitializeComponent();
mItemList = new List<TASFlowUIItem>();
mItemCount = 0;
SetItemCount(1);
}
private int mItemCount;
private List<TASFlowUIItem> mItemList;
public List<FrameDataDisplay> DataSources { get; set; }
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++) {
var item = new ColumnDefinition();
item.Width = GridLength.Auto;
uiCoreWindow.ColumnDefinitions.Add(item);
}
} else {
uiCoreWindow.ColumnDefinitions.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); // the first col is sheet header, so add 1 additionally
newItem.Add(uiCoreWindow);
mItemList.Add(newItem);
}
} else {
for(int i = 0; i < abs; i++) {
mItemList[mItemCount].Remove(uiCoreWindow);
}
mItemList.RemoveRange(newCount, abs);
}
// apply new count
mItemCount = newCount;
}
}
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 RECT_STROKE = new SolidColorBrush(Colors.Gray);
private static readonly Color COLOR_SET = Color.FromRgb(30, 144, 255);
private static readonly Color COLOR_UNSET = Color.FromArgb(0, 255, 255, 255);
private const int KEY_COUNT = 9;
public TASFlowUIItem(int column) {
// basic item
frame = new TextBlock();
deltaTime = new TextBlock();
Grid.SetRow(frame, 0);
Grid.SetRow(deltaTime, 1);
Grid.SetColumn(frame, column);
Grid.SetColumn(deltaTime, column);
frame.Margin = DEFAULT_MARGIN;
deltaTime.Margin = DEFAULT_MARGIN;
// keystates item
keystates = new Rectangle[KEY_COUNT];
keystatesFill = new SolidColorBrush[KEY_COUNT];
for (int i = 0; i < KEY_COUNT; i++) {
keystates[i] = new Rectangle();
keystatesFill[i] = new SolidColorBrush(COLOR_UNSET);
Grid.SetRow(keystates[i], 2 + i);
Grid.SetColumn(keystates[i], column);
keystates[i].Margin = RECT_MARGIN;
keystates[i].StrokeThickness = 1;
keystates[i].Stroke = RECT_STROKE;
keystates[i].Fill = keystatesFill[i];
}
}
public void Add(Grid target) {
target.Children.Add(frame);
target.Children.Add(deltaTime);
for (int i = 0; i < KEY_COUNT; i++) {
target.Children.Add(keystates[i]);
}
}
public void Remove(Grid target) {
target.Children.Remove(frame);
target.Children.Remove(deltaTime);
for (int i = 0; i < KEY_COUNT; i++) {
target.Children.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;
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;
}
}
public TextBlock frame;
public TextBlock deltaTime;
public Rectangle[] keystates;
private SolidColorBrush[] keystatesFill;
}
}

67
UI/TASViewer.cs Normal file
View File

@ -0,0 +1,67 @@
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, Slider slider, TASFlow datagrid) {
mFile = file;
mSlider = slider;
mDataGrid = datagrid;
// restore slider
mSlider.Minimum = 0;
updateSliderRange();
// init data
mPosition = 0;
mDataSource = new List<FrameDataDisplay>();
INVALID_FRAME_DATA = new FrameData(-1f, 0);
for (int i = 0; i < DATA_LIST_LENGTH; i++) {
mDataSource.Add(new FrameDataDisplay(0, INVALID_FRAME_DATA));
}
mFile.Get(mDataSource, 0, DATA_LIST_LENGTH);
// bind event and source
mDataGrid.SetItemCount(DATA_LIST_LENGTH);
mDataGrid.DataSources = mDataSource;
mDataGrid.RefreshDataSources();
mSlider.ValueChanged += sliderValueChanged;
}
public void Dispose() {
mDataGrid.DataSources = null;
mSlider.ValueChanged -= sliderValueChanged;
}
const int DATA_LIST_LENGTH = 15;
FrameData INVALID_FRAME_DATA;
TASFile mFile;
Slider mSlider;
TASFlow mDataGrid;
long mPosition;
List<FrameDataDisplay> mDataSource;
private void sliderValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) {
long pos = Convert.ToInt64(Math.Floor(e.NewValue));
long offset = pos - mPosition;
mFile.Shift(offset);
mFile.Get(mDataSource, pos, DATA_LIST_LENGTH);
mPosition = pos;
mDataGrid.RefreshDataSources();
}
private void updateSliderRange() {
long newSize = mFile.mFrameCount - 1;
if (mSlider.Value > newSize)
mSlider.Value = newSize;
mSlider.Maximum = newSize;
}
}
}