using Microsoft.Win32; using Ollama; using RDTKEditor.AIAssistant; using RDTKEditor.Models; using RhythmBase.Events; using SkiaSharp; using SkiaSharp.Views.Desktop; using System.ComponentModel; using System.Reflection; using System.Windows; using System.Windows.Controls; using System.Windows.Shapes; namespace RDTKEditor { /// /// Interaction logic for MainWindow.xaml /// public partial class MainWindow : Window { private Assistant Assistant = new(Assistant.Qwen_3); private SKSizeI _vsScale = new(1600,900); private readonly RDTKView viewModel = new(); public MainWindow() { InitializeComponent(); } private void OpenFile(object sender, RoutedEventArgs e) { OpenFileDialog openFileDialog = new() { Filter = "关卡文件|*.rdlevel|关卡压缩包 (*.rdzip)|*.rdzip" }; if (openFileDialog.ShowDialog() == true) { string filename = openFileDialog.FileName; viewModel.UpdateLevelByPath(filename); } } private void SaveFile(object sender, RoutedEventArgs e) { OpenFileDialog openFileDialog = new() { Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*" }; if (openFileDialog.ShowDialog() == true) { string filename = openFileDialog.FileName; viewModel.SaveLevelByPath(filename); } } private void Exit(object sender, RoutedEventArgs e) { Application.Current.Shutdown(); } private void About(object sender, RoutedEventArgs e) { OnUpdateEventProperties(GetProperties(new MoveRow())); //OnUpdateEventProperties([ // new(){ // Verifier = new RDTKPropertyVerifierDefault(), // Name = "Name", // Value = "RDTK Editor", // Type = RDPropertyType.String, // }, // new(){ // Verifier = new RDTKPropertyVerifierDefault(), // Name = "Version", // Value = "1.0.0", // Type = RDPropertyType.String, // }, // new(){ // Verifier = new RDTKPropertyVerifierEnum(typeof(EventType)), // Name = "Description", // Value = "RDTK Editor 是一个简单的节奏医生关卡编辑器。", // Type = RDPropertyType.Enum, // }, // new(){ // Verifier = new RDTKPropertyVerifierBool(), // Name = "测试值", // Value = "true", // Type = RDPropertyType.Bool, // } // ]); //MessageBox.Show("RDTK Editor 是一个简单的节奏医生关卡编辑器。", "关于 RDTK Editor"); } private RDTKProperty[] GetProperties(BaseEvent e) { return [ new RDTKProperty() { Verifier = new RDTKPropertyVerifierDefault(), Name = "类型", Value = e.Type.ToString(), Type = RDPropertyType.String, }, ..e.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Select(p => GetProperty(p,e)).ToArray() ]; } private RDTKProperty GetProperty(PropertyInfo property, object obj) { switch (property.PropertyType.Name) { case "Boolean": return new() { Verifier = new RDTKPropertyVerifierBool(), Name = property.Name, Value = property.GetValue(obj)?.ToString() ?? "false", Type = RDPropertyType.Bool, }; case "Enum": return new() { Verifier = new RDTKPropertyVerifierEnum(property.PropertyType), Name = property.Name, Value = property.GetValue(obj)?.ToString() ?? "null", Type = RDPropertyType.Enum, }; case "String": return new() { Verifier = new RDTKPropertyVerifierDefault(), Name = property.Name, Value = property.GetValue(obj)?.ToString() ?? "null", Type = RDPropertyType.String, }; } return new() { Verifier = new RDTKPropertyVerifierDefault(), Name = property.Name, Value = property.GetValue(obj)?.ToString() ?? "null", Type = RDPropertyType.String, }; } internal void OnUpdateEventProperties(RDTKProperty[] properties) { ItemProperties.Items.Clear(); foreach (var property in properties) { StackPanel stackPanel; switch (property.Type) { case RDPropertyType.Bool: stackPanel = new() { Orientation = Orientation.Horizontal, FlowDirection = FlowDirection.LeftToRight, Children = { new Label(){Content = property.Name}, new CheckBox() { IsChecked = bool.Parse( property.Value), } }, }; break; case RDPropertyType.Enum: stackPanel = new() { AllowDrop = true, Orientation = Orientation.Horizontal, FlowDirection = FlowDirection.LeftToRight, Children = { new Label(){Content = property.Name}, new ComboBox() { ItemsSource = Enum.GetValues(((RDTKPropertyVerifierEnum)property.Verifier).EnumType), SelectedValue = property.Value, } }, }; break; case RDPropertyType.String: stackPanel = new() { AllowDrop = true, Orientation = Orientation.Horizontal, FlowDirection = FlowDirection.LeftToRight, Children = { new Label(){Content = property.Name}, new TextBox() { Text = property.Value, } }, }; break; default: stackPanel = new() { Orientation = Orientation.Horizontal, Children = { new Label(){Content = property.Name}, new Label(){Content = property.Value} } }; break; } foreach (var child in stackPanel.Children) { switch (child) { case CheckBox checkBox: checkBox.Checked += (sender, e) => { property.OnChanged("true"); }; checkBox.Unchecked += (sender, e) => { property.OnChanged("false"); }; break; case TextBox textBox: textBox.TextChanged += (sender, e) => { property.OnChanged(textBox.Text); }; break; case ComboBox comboBox: comboBox.SelectionChanged += (sender, e) => { property.OnChanged(comboBox.SelectedValue); }; break; default: break; } } ItemProperties.Items.Add(stackPanel); property.PropertyChanged += (e, s) => UpdateEvent(); } } private void UpdateEvent() { MessageBox.Show("Update Event"); } private void UpdateTimeLine() { Rectangle rectangle = new() { Width = 100, Height = 100, }; timelineCanvas.Children.Add(rectangle); } /*private void mainUI_PaintSurface(object sender, SkiaSharp.Views.Desktop.SKPaintSurfaceEventArgs e) { var sfc = e.Surface; var cvs = sfc.Canvas; cvs.Clear(SKColors.Black); cvs.DrawLine(0, 0, 1600, 900, new() { Color = SKColors.Red, }); }*/ private void mainUI_PaintSurface(object sender, SKPaintSurfaceEventArgs e) { var sfc = e.Surface; var cvs = sfc.Canvas; var info = e.Info; cvs.Clear(SKColors.Black); SKPoint scale = new(info.Width / _vsScale.Width, info.Height / _vsScale.Height); cvs.Save(); cvs.Scale(scale); Draw(cvs); cvs.Restore(); } private void Draw(SKCanvas canvas) { // 以 1600x900 为基准绘制 canvas.DrawLine(0, 0, _vsScale.Width, _vsScale.Height, new SKPaint { Color = SKColors.Red, StrokeWidth = 3, IsStroke = true, }); canvas.DrawLine(0, _vsScale.Height, _vsScale.Width, 0, new SKPaint { Color = SKColors.White, StrokeWidth = 3, IsStroke = true, }); } private async void AIAssistantButton_Click(object sender, RoutedEventArgs e) { string input = AIAssistantText.Text; if (string.IsNullOrEmpty(input)) return; Message responce = await Assistant.Chat.SendAsync(input); AIAssistantText.Text = responce.Content; } } public class MainViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler? PropertyChanged; } }