write shit

This commit is contained in:
2021-05-15 16:23:16 +08:00
parent 1d700a02e3
commit dac0c36483
10 changed files with 564 additions and 54 deletions

View File

@ -34,6 +34,7 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Microsoft.VisualBasic" />
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
@ -56,11 +57,13 @@
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</ApplicationDefinition> </ApplicationDefinition>
<Compile Include="UI\SelectionHelp.cs" />
<Compile Include="UI\StyleConverter.cs" /> <Compile Include="UI\StyleConverter.cs" />
<Compile Include="UI\TASFlow.xaml.cs"> <Compile Include="UI\TASFlow.xaml.cs">
<DependentUpon>TASFlow.xaml</DependentUpon> <DependentUpon>TASFlow.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="UI\TASViewer.cs" /> <Compile Include="UI\TASViewer.cs" />
<Compile Include="UI\Util.cs" />
<Page Include="MainWindow.xaml"> <Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>

View File

@ -131,16 +131,16 @@ namespace BallanceTASEditor.Core.TASStruct {
public const int FRAMEDATA_OFFSET_KEY_STATES = 4; public const int FRAMEDATA_OFFSET_KEY_STATES = 4;
} }
public enum FrameDataField { public enum FrameDataField : int {
Key_Up, Key_Up = 0,
Key_Down, Key_Down = 1,
Key_Left, Key_Left = 2,
Key_Right, Key_Right = 3,
Key_Shift, Key_Shift = 4,
Key_Space, Key_Space = 5,
Key_Q, Key_Q = 6,
Key_Esc, Key_Esc = 7,
Key_Enter Key_Enter = 8
} }
} }

View File

@ -23,7 +23,7 @@
<MenuItem x:Name="uiMenu_File_Close" Header="Close" Click="funcMenu_File_Close"/> <MenuItem x:Name="uiMenu_File_Close" Header="Close" Click="funcMenu_File_Close"/>
</MenuItem> </MenuItem>
<MenuItem Header="Display"> <MenuItem Header="Display">
<MenuItem x:Name="uiMenu_Display_ItemCount" Header="Item Count"/> <MenuItem x:Name="uiMenu_Display_ItemCount" Header="Item Count" Click="funcMenu_Display_ItemCount"/>
</MenuItem> </MenuItem>
<MenuItem Header="Help"> <MenuItem Header="Help">
<MenuItem x:Name="uiMenu_Help_ReportBugs" Header="Report bugs" Click="funcMenu_Help_ReportBugs"/> <MenuItem x:Name="uiMenu_Help_ReportBugs" Header="Report bugs" Click="funcMenu_Help_ReportBugs"/>
@ -41,7 +41,7 @@
</Grid.RowDefinitions> </Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Grid.Row="0" Grid.ColumnSpan="2"> <StackPanel Orientation="Horizontal" Grid.Row="0" Grid.ColumnSpan="2">
<Button x:Name="uiBtn_Select" Margin="5" Padding="5"> <Button x:Name="uiBtn_Cursor" Margin="5" Padding="5" Click="funcBtn_Cursor">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Viewbox Width="24" Height="24"> <Viewbox Width="24" Height="24">
<Canvas Width="24" Height="24"> <Canvas Width="24" Height="24">
@ -51,7 +51,7 @@
<TextBlock Text="Select mode" VerticalAlignment="Center"/> <TextBlock Text="Select mode" VerticalAlignment="Center"/>
</StackPanel> </StackPanel>
</Button> </Button>
<Button x:Name="uiBtn_Fill" Margin="5" Padding="5"> <Button x:Name="uiBtn_Fill" Margin="5" Padding="5" Click="funcBtn_Fill">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Viewbox Width="24" Height="24"> <Viewbox Width="24" Height="24">
<Canvas Width="24" Height="24"> <Canvas Width="24" Height="24">
@ -61,7 +61,7 @@
<TextBlock Text="Fill mode" VerticalAlignment="Center"/> <TextBlock Text="Fill mode" VerticalAlignment="Center"/>
</StackPanel> </StackPanel>
</Button> </Button>
<Button x:Name="uiBtn_Draw" Margin="5" Padding="5"> <Button x:Name="uiBtn_Overwrite" Margin="5" Padding="5" Click="funcBtn_Overwrite">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Viewbox Width="24" Height="24"> <Viewbox Width="24" Height="24">
<Canvas Width="24" Height="24"> <Canvas Width="24" Height="24">
@ -127,13 +127,13 @@
</Grid> </Grid>
<StatusBar Grid.Row="2"> <StatusBar x:Name="uiStatusbar" Grid.Row="2">
<TextBlock Text="Select mode"/> <TextBlock x:Name="uiStatusbar_Mode_Cursor" Text="Select mode"/>
<TextBlock Text="Fill mode"/> <TextBlock x:Name="uiStatusbar_Mode_Fill" Text="Fill mode"/>
<TextBlock Text="Draw mode"/> <TextBlock x:Name="uiStatusbar_Mode_Overwrite" Text="Draw mode"/>
<Separator/> <Separator/>
<TextBlock Text="Selected: "/> <TextBlock Text="Selected: "/>
<TextBlock Text="aaa"/> <TextBlock x:Name="uiStatusbar_Selected" Text="-"/>
</StatusBar> </StatusBar>
</Grid> </Grid>

View File

@ -22,15 +22,27 @@ namespace BallanceTASEditor {
public partial class MainWindow : Window { public partial class MainWindow : Window {
public MainWindow() { public MainWindow() {
InitializeComponent(); InitializeComponent();
// bind event without xaml due to xaml shit design
uiTASData.uiDataMenu_Set.Click += funcDataMenu_Set;
uiTASData.uiDataMenu_Unset.Click += funcDataMenu_Unset;
uiTASData.uiDataMenu_Copy.Click += funcDataMenu_Copy;
uiTASData.uiDataMenu_Delete.Click += funcDataMenu_Delete;
uiTASData.uiDataMenu_PasteAfter.Click += funcDataMenu_PasteAfter;
uiTASData.uiDataMenu_PasteBefore.Click += funcDataMenu_PasteBefore;
uiTASData.uiDataMenu_AddAfter.Click += funcDataMenu_AddAfter;
uiTASData.uiDataMenu_AddBefore.Click += funcDataMenu_AddBefore;
RefreshUI(false); RefreshUI(false);
} }
TASFile mFile; TASFile mFile;
TASViewer mViewer; TASViewer mViewer;
#region ui func #region ui func
// menu // =========================== menu
private void funcMenu_Help_ReportBugs(object sender, RoutedEventArgs e) { private void funcMenu_Help_ReportBugs(object sender, RoutedEventArgs e) {
System.Diagnostics.Process.Start("https://github.com/yyc12345/BallanceTASEditor/issues"); System.Diagnostics.Process.Start("https://github.com/yyc12345/BallanceTASEditor/issues");
} }
@ -43,8 +55,9 @@ namespace BallanceTASEditor {
var file = DialogUtil.OpenFileDialog(); var file = DialogUtil.OpenFileDialog();
if (file == "") return; if (file == "") return;
mFile = new TASFile(file); mFile = new TASFile(file);
mViewer = new TASViewer(mFile, uiTASSlider, uiTASData); mViewer = new TASViewer(mFile, uiTASSlider, uiTASData, uiStatusbar_Selected);
RefreshUI(true); RefreshUI(true);
ChangeToolMode(ToolMode.Cursor);
} }
private void funcMenu_File_Save(object sender, RoutedEventArgs e) { private void funcMenu_File_Save(object sender, RoutedEventArgs e) {
@ -65,9 +78,98 @@ namespace BallanceTASEditor {
RefreshUI(false); RefreshUI(false);
} }
private void funcMenu_Display_ItemCount(object sender, RoutedEventArgs e) {
int newvalue = 0;
if (DialogUtil.InputNumber("Input new count (>=5 && <=30)", 5, 30, ref newvalue)) {
mViewer.ChangeListLength(newvalue);
}
}
// =========================== btn
private void funcBtn_Cursor(object sender, RoutedEventArgs e) {
ChangeToolMode(ToolMode.Cursor);
}
private void funcBtn_Fill(object sender, RoutedEventArgs e) {
ChangeToolMode(ToolMode.Fill);
}
private void funcBtn_Overwrite(object sender, RoutedEventArgs e) {
ChangeToolMode(ToolMode.Overwrite);
}
#endregion #endregion
#region data menu
private void funcDataMenu_AddBefore(object sender, RoutedEventArgs e) {
throw new NotImplementedException();
}
private void funcDataMenu_AddAfter(object sender, RoutedEventArgs e) {
throw new NotImplementedException();
}
private void funcDataMenu_PasteBefore(object sender, RoutedEventArgs e) {
throw new NotImplementedException();
}
private void funcDataMenu_PasteAfter(object sender, RoutedEventArgs e) {
throw new NotImplementedException();
}
private void funcDataMenu_Delete(object sender, RoutedEventArgs e) {
throw new NotImplementedException();
}
private void funcDataMenu_Copy(object sender, RoutedEventArgs e) {
throw new NotImplementedException();
}
private void funcDataMenu_Unset(object sender, RoutedEventArgs e) {
throw new NotImplementedException();
}
private void funcDataMenu_Set(object sender, RoutedEventArgs e) {
throw new NotImplementedException();
}
#endregion
private void ChangeToolMode(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;
}
mViewer.ChangeToolMode(mode);
}
private void RefreshUI(bool isFileOpened) { private void RefreshUI(bool isFileOpened) {
if (isFileOpened) { if (isFileOpened) {
uiEditorPanel.Visibility = Visibility.Visible; uiEditorPanel.Visibility = Visibility.Visible;
@ -77,6 +179,10 @@ namespace BallanceTASEditor {
uiMenu_File_Save.IsEnabled = true; uiMenu_File_Save.IsEnabled = true;
uiMenu_File_SaveAs.IsEnabled = true; uiMenu_File_SaveAs.IsEnabled = true;
uiMenu_File_Close.IsEnabled = true; uiMenu_File_Close.IsEnabled = true;
uiMenu_Display_ItemCount.IsEnabled = true;
uiStatusbar.Visibility = Visibility.Visible;
} else { } else {
uiEditorPanel.Visibility = Visibility.Collapsed; uiEditorPanel.Visibility = Visibility.Collapsed;
uiEditorNote.Visibility = Visibility.Visible; uiEditorNote.Visibility = Visibility.Visible;
@ -85,6 +191,10 @@ namespace BallanceTASEditor {
uiMenu_File_Save.IsEnabled = false; uiMenu_File_Save.IsEnabled = false;
uiMenu_File_SaveAs.IsEnabled = false; uiMenu_File_SaveAs.IsEnabled = false;
uiMenu_File_Close.IsEnabled = false; uiMenu_File_Close.IsEnabled = false;
uiMenu_Display_ItemCount.IsEnabled = false;
uiStatusbar.Visibility = Visibility.Collapsed;
} }
} }

View File

@ -1,4 +1,5 @@
using System; using Microsoft.VisualBasic;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -29,5 +30,17 @@ namespace BallanceTASEditor.UI {
return (result == MessageBoxResult.Yes); return (result == MessageBoxResult.Yes);
} }
public static bool InputNumber(string title, int min, int max, ref int result) {
while (true) {
var dialog = Interaction.InputBox(title, "Input number", "");
if (dialog == "") return false;
if (int.TryParse(dialog, out result)) {
if (result <= max && result >= min) break;
}
MessageBox.Show("Invalid number. Please input again", "Warning", MessageBoxButton.OK, MessageBoxImage.Warning);
}
return true;
}
} }
} }

148
UI/SelectionHelp.cs Normal file
View File

@ -0,0 +1,148 @@
using BallanceTASEditor.Core.TASStruct;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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);
}
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.Cursor) return mStart;
else {
// cursor mode
if (mIsStartConfirmed) return mStart;
else throw new Exception("Data is not ready to read");
}
}
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();
}
}
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;
}
}
}

View File

@ -38,19 +38,20 @@
<RowDefinition Height="auto"/> <RowDefinition Height="auto"/>
<RowDefinition Height="auto"/> <RowDefinition Height="auto"/>
<RowDefinition Height="auto"/> <RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/> <RowDefinition Height="*"/>
</Grid.RowDefinitions> </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="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="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="^"/>
<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="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="&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="&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="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="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="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="esc"/>
<TextBlock Padding="2" Background="#afafaf" Grid.Column="0" Grid.Row="10" Text="enter"/> <TextBlock Padding="2" Background="#afafaf" Grid.Column="0" Grid.Row="11" Text="enter"/>
</Grid> </Grid>
</UserControl> </UserControl>

View File

@ -21,12 +21,15 @@ namespace BallanceTASEditor.UI {
public TASFlow() { public TASFlow() {
InitializeComponent(); InitializeComponent();
mItemList = new List<TASFlowUIItem>(); mItemList = new List<TASFlowUIItem>();
mRectMap = new Dictionary<Rectangle, CellPosition>();
mItemCount = 0; mItemCount = 0;
SetItemCount(1); SetItemCount(1);
} }
private int mItemCount; private int mItemCount;
private List<TASFlowUIItem> mItemList; private List<TASFlowUIItem> mItemList;
private Dictionary<Rectangle, CellPosition> mRectMap;
public SelectionHelp SelectionHelp { get; set; }
public List<FrameDataDisplay> DataSources { get; set; } public List<FrameDataDisplay> DataSources { get; set; }
public void RefreshDataSources() { public void RefreshDataSources() {
@ -57,12 +60,12 @@ namespace BallanceTASEditor.UI {
if (offset > 0) { if (offset > 0) {
for (int i = 0; i < abs; i++) { for (int i = 0; i < abs; i++) {
var newItem = new TASFlowUIItem(mItemCount + 1 + i); // the first col is sheet header, so add 1 additionally var newItem = new TASFlowUIItem(mItemCount + 1 + i); // the first col is sheet header, so add 1 additionally
newItem.Add(uiCoreWindow); newItem.Add(uiCoreWindow, mRectMap, Rectangle_MouseDown);
mItemList.Add(newItem); mItemList.Add(newItem);
} }
} else { } else {
for(int i = 0; i < abs; i++) { for(int i = 0; i < abs; i++) {
mItemList[mItemCount].Remove(uiCoreWindow); mItemList[newCount + i].Remove(uiCoreWindow, mRectMap, Rectangle_MouseDown);
} }
mItemList.RemoveRange(newCount, abs); mItemList.RemoveRange(newCount, abs);
} }
@ -71,57 +74,161 @@ namespace BallanceTASEditor.UI {
mItemCount = newCount; mItemCount = newCount;
} }
public void RefreshDataMenu() {
if (SelectionHelp == null) return;
ToolMode mode = SelectionHelp.GetToolMode();
bool showCursorPasteAdd = mode == ToolMode.Cursor && SelectionHelp.IsDataPartialReady();
bool showFill = mode == ToolMode.Fill && SelectionHelp.IsDataReady();
bool showCursorCopyDelete = mode == ToolMode.Cursor && SelectionHelp.IsDataReady();
uiDataMenu_Set.IsEnabled = showFill;
uiDataMenu_Unset.IsEnabled = showFill;
uiDataMenu_Copy.IsEnabled = showCursorCopyDelete;
uiDataMenu_Delete.IsEnabled = showCursorCopyDelete;
uiDataMenu_PasteAfter.IsEnabled = showCursorPasteAdd;
uiDataMenu_PasteBefore.IsEnabled = showCursorPasteAdd;
uiDataMenu_AddAfter.IsEnabled = showCursorPasteAdd;
uiDataMenu_AddBefore.IsEnabled = showCursorPasteAdd;
}
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) {
SelectionHelp.FirstClick(mItemList[pos.column - 1].rawFrame, pos.field);
} else if (e.MouseDevice.RightButton == MouseButtonState.Pressed) {
SelectionHelp.LastClick(mItemList[pos.column - 1].rawFrame, pos.field);
}
}
} }
public class TASFlowUIItem { public class TASFlowUIItem {
private static readonly Thickness DEFAULT_MARGIN = new Thickness(2); private static readonly Thickness DEFAULT_MARGIN = new Thickness(2);
private static readonly Thickness RECT_MARGIN = new Thickness(1); private static readonly Thickness RECT_MARGIN = new Thickness(1);
private static readonly SolidColorBrush RECT_STROKE = new SolidColorBrush(Colors.Gray); private static readonly SolidColorBrush SEL_RECT_NORMAL_BRUSH = new SolidColorBrush(Colors.White);
private static readonly SolidColorBrush SEL_RECT_SELECTED_BRUSH = new SolidColorBrush(Colors.Orange);
private static readonly SolidColorBrush SEL_RECT_STROKE = new SolidColorBrush(Colors.Gray);
private static readonly Color COLOR_SET = Color.FromRgb(30, 144, 255); 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_UNSET = Color.FromArgb(0, 255, 255, 255);
private static readonly Color COLOR_SELECTED = Colors.Orange;
private static readonly Color COLOR_UNSELECTED = Colors.Gray;
private const int KEY_COUNT = 9; private const int KEY_COUNT = 9;
private const double SELECTION_HEADER_HEIGHT = 10.0f;
public TASFlowUIItem(int column) { public TASFlowUIItem(int column) {
// basic item // basic item
sel_rect = new Rectangle();
frame = new TextBlock(); frame = new TextBlock();
deltaTime = new TextBlock(); deltaTime = new TextBlock();
Grid.SetRow(frame, 0); Grid.SetRow(sel_rect, 0);
Grid.SetRow(deltaTime, 1); Grid.SetRow(frame, 1);
Grid.SetRow(deltaTime, 2);
Grid.SetColumn(sel_rect, column);
Grid.SetColumn(frame, column); Grid.SetColumn(frame, column);
Grid.SetColumn(deltaTime, column); Grid.SetColumn(deltaTime, column);
sel_rect.Margin = RECT_MARGIN;
frame.Margin = DEFAULT_MARGIN; frame.Margin = DEFAULT_MARGIN;
deltaTime.Margin = DEFAULT_MARGIN; deltaTime.Margin = DEFAULT_MARGIN;
sel_rect.StrokeThickness = 3;
sel_rect.Stroke = SEL_RECT_STROKE;
sel_rect.Height = SELECTION_HEADER_HEIGHT;
// keystates item // keystates item
keystates = new Rectangle[KEY_COUNT]; keystates = new Rectangle[KEY_COUNT];
keystatesFill = new SolidColorBrush[KEY_COUNT]; keystatesFill = new SolidColorBrush[KEY_COUNT];
keystatesStroke = new SolidColorBrush[KEY_COUNT];
for (int i = 0; i < KEY_COUNT; i++) { for (int i = 0; i < KEY_COUNT; i++) {
keystates[i] = new Rectangle(); keystates[i] = new Rectangle();
keystatesFill[i] = new SolidColorBrush(COLOR_UNSET); keystatesFill[i] = new SolidColorBrush(COLOR_UNSET);
Grid.SetRow(keystates[i], 2 + i); keystatesStroke[i] = new SolidColorBrush(COLOR_UNSELECTED);
Grid.SetRow(keystates[i], 3 + i);
Grid.SetColumn(keystates[i], column); Grid.SetColumn(keystates[i], column);
keystates[i].Margin = RECT_MARGIN; keystates[i].Margin = RECT_MARGIN;
keystates[i].StrokeThickness = 1; keystates[i].StrokeThickness = 3;
keystates[i].Stroke = RECT_STROKE; keystates[i].Stroke = keystatesStroke[i];
keystates[i].Fill = keystatesFill[i]; keystates[i].Fill = keystatesFill[i];
} }
this.column = column;
rawFrame = 0;
rawIsEnable = false;
} }
public void Add(Grid target) { public void Add(Grid target, Dictionary<Rectangle, CellPosition> map, MouseButtonEventHandler func) {
target.Children.Add(sel_rect);
target.Children.Add(frame); target.Children.Add(frame);
target.Children.Add(deltaTime); target.Children.Add(deltaTime);
for (int i = 0; i < KEY_COUNT; i++) { for (int i = 0; i < KEY_COUNT; i++) {
target.Children.Add(keystates[i]); target.Children.Add(keystates[i]);
keystates[i].MouseDown += func;
map.Add(keystates[i], new CellPosition(column, (FrameDataField)i));
} }
} }
public void Remove(Grid target) { public void Remove(Grid target, Dictionary<Rectangle, CellPosition> map, MouseButtonEventHandler func) {
target.Children.Remove(sel_rect);
target.Children.Remove(frame); target.Children.Remove(frame);
target.Children.Remove(deltaTime); target.Children.Remove(deltaTime);
for (int i = 0; i < KEY_COUNT; i++) { for (int i = 0; i < KEY_COUNT; i++) {
target.Children.Remove(keystates[i]); target.Children.Remove(keystates[i]);
keystates[i].MouseDown -= func;
map.Remove(keystates[i]);
} }
} }
@ -144,11 +251,37 @@ namespace BallanceTASEditor.UI {
for (int i = 0; i < KEY_COUNT; i++) { for (int i = 0; i < KEY_COUNT; i++) {
keystates[i].Visibility = isEnable ? Visibility.Visible : Visibility.Collapsed; 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 frame;
public TextBlock deltaTime; public TextBlock deltaTime;
public Rectangle[] keystates; public Rectangle[] keystates;
private SolidColorBrush[] keystatesFill; private SolidColorBrush[] keystatesFill;
private SolidColorBrush[] keystatesStroke;
private int column;
} }
} }

View File

@ -10,30 +10,35 @@ using System.Windows;
namespace BallanceTASEditor.UI { namespace BallanceTASEditor.UI {
public class TASViewer : IDisposable { public class TASViewer : IDisposable {
public TASViewer(TASFile file, Slider slider, TASFlow datagrid) { public TASViewer(TASFile file, Slider slider, TASFlow datagrid, TextBlock statusbar) {
mFile = file; mFile = file;
mSlider = slider; mSlider = slider;
mDataGrid = datagrid; mDataGrid = datagrid;
mStatusbar = statusbar;
// restore slider // restore slider
mSlider.Minimum = 0; mSlider.Minimum = 0;
updateSliderRange(); updateSliderRange();
// init selection
mSelectionHelp = new SelectionHelp();
mSelectionHelp.SelectionChanged += funcSelectionHelp_SelectionChanged;
// init data // init data
mPosition = 0; mPosition = 0;
mDataSource = new List<FrameDataDisplay>();
INVALID_FRAME_DATA = new FrameData(-1f, 0); INVALID_FRAME_DATA = new FrameData(-1f, 0);
for (int i = 0; i < DATA_LIST_LENGTH; i++) { mDataSource = new List<FrameDataDisplay>();
mDataSource.Add(new FrameDataDisplay(0, INVALID_FRAME_DATA)); mListLength = 0;
}
mFile.Get(mDataSource, 0, DATA_LIST_LENGTH);
// bind event and source // bind event and source
mDataGrid.SetItemCount(DATA_LIST_LENGTH);
mDataGrid.DataSources = mDataSource; mDataGrid.DataSources = mDataSource;
mDataGrid.RefreshDataSources(); mDataGrid.SelectionHelp = mSelectionHelp;
mSlider.ValueChanged += sliderValueChanged; mSlider.ValueChanged += sliderValueChanged;
// display data
ChangeListLength(DATA_LIST_LENGTH);
} }
public void Dispose() { public void Dispose() {
mDataGrid.DataSources = null; mDataGrid.DataSources = null;
mSlider.ValueChanged -= sliderValueChanged; mSlider.ValueChanged -= sliderValueChanged;
@ -43,18 +48,20 @@ namespace BallanceTASEditor.UI {
FrameData INVALID_FRAME_DATA; FrameData INVALID_FRAME_DATA;
TASFile mFile; TASFile mFile;
Slider mSlider; Slider mSlider;
TextBlock mStatusbar;
TASFlow mDataGrid; TASFlow mDataGrid;
SelectionHelp mSelectionHelp;
long mPosition; long mPosition;
int mListLength;
List<FrameDataDisplay> mDataSource; List<FrameDataDisplay> mDataSource;
private void sliderValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) { private void sliderValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) {
long pos = Convert.ToInt64(Math.Floor(e.NewValue)); long pos = Convert.ToInt64(Math.Floor(e.NewValue));
long offset = pos - mPosition; long offset = pos - mPosition;
mFile.Shift(offset); mFile.Shift(offset);
mFile.Get(mDataSource, pos, DATA_LIST_LENGTH);
RefreshDisplay(pos);
mPosition = pos; mPosition = pos;
mDataGrid.RefreshDataSources();
} }
private void updateSliderRange() { private void updateSliderRange() {
@ -63,5 +70,76 @@ namespace BallanceTASEditor.UI {
mSlider.Value = newSize; mSlider.Value = newSize;
mSlider.Maximum = newSize; mSlider.Maximum = newSize;
} }
private void funcSelectionHelp_SelectionChanged() {
mDataGrid.RefreshDataMenu();
mDataGrid.RefreshSelectionHighlight();
OnStatusbarSelectionChanged();
}
private void OnStatusbarSelectionChanged() {
var mode = mSelectionHelp.GetToolMode();
switch (mode) {
case ToolMode.Cursor:
if (mSelectionHelp.IsDataReady()) {
var data = mSelectionHelp.GetRange();
mStatusbar.Text = $"{data.start} - {data.end}";
} else if (mSelectionHelp.IsDataPartialReady()) {
var data2 = mSelectionHelp.GetPoint();
mStatusbar.Text = data2.ToString();
} else mStatusbar.Text = "-";
break;
case ToolMode.Fill:
if (mSelectionHelp.IsDataReady()) {
var data3 = mSelectionHelp.GetRange();
mStatusbar.Text = $"{data3.start} - {data3.end}";
} else mStatusbar.Text = "-";
break;
case ToolMode.Overwrite:
if (mSelectionHelp.IsDataReady()) {
var data4 = mSelectionHelp.GetPoint();
mStatusbar.Text = data4.ToString();
} else mStatusbar.Text = "-";
break;
}
}
public void ChangeListLength(int newLen) {
if (newLen < 5 || newLen > 30) 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(mPosition);
}
public void RefreshDisplay(long pos) {
mFile.Get(mDataSource, pos, mListLength);
mDataGrid.RefreshDataSources();
mDataGrid.RefreshSelectionHighlight();
}
public void ChangeToolMode(ToolMode mode) {
mSelectionHelp.SetMode(mode);
}
} }
} }

24
UI/Util.cs Normal file
View File

@ -0,0 +1,24 @@
using BallanceTASEditor.Core.TASStruct;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BallanceTASEditor.UI {
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;
}
}