using Microsoft.Win32; using Ollama; using RDTKEditor.AIAssistant; using RDTKEditor.Models; using RhythmBase.RhythmDoctor.Components; using RhythmBase.RhythmDoctor.Events; using SkiaSharp; using SkiaSharp.Views.Desktop; using System.ComponentModel; using System.Reflection; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Shapes; using RhythmBase.Control.WPF; namespace RDTKEditor { /// /// Interaction logic for MainWindow.xaml /// public partial class MainWindow : Window { private readonly Assistant Assistant = new(Assistant.Qwen_3); private SKSizeI _vsScale = new(1600, 900); private readonly RDTKView viewModel = new(); private readonly List _selectedEvents = []; internal readonly Dictionary _eventPanel = []; public MainWindow() { InitializeComponent(); timeLine.Level = RDLevel.Default; } 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) { if (_selectedEvents.Count == 0) { MessageBox.Show("请先选择一个事件。", "提示", MessageBoxButton.OK, MessageBoxImage.Information); return; } if (_selectedEvents.Count == 1) { OnUpdateEventProperties(_selectedEvents[0], GetProperties(_selectedEvents[0])); } else { } } 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, }; case "Int32": return new() { Verifier = new RDTKPropertyVerifierDefault(), Name = property.Name, Value = property.GetValue(obj)?.ToString() ?? "null", Type = RDPropertyType.Integer, }; case "Single": return new() { Verifier = new RDTKPropertyVerifierDefault(), Name = property.Name, Value = property.GetValue(obj)?.ToString() ?? "null", Type = RDPropertyType.Float, }; case "RDColor": return new() { Verifier = new RDTKPropertyVerifierDefault(), Name = property.Name, Value = property.GetValue(obj)?.ToString() ?? "null", Type = RDPropertyType.Color, }; } return new() { Verifier = new RDTKPropertyVerifierDefault(), Name = property.Name, Value = property.GetValue(obj)?.ToString() ?? "null", Type = RDPropertyType.String, }; } private readonly List selectedEvents = new(); internal void OnUpdateEventProperties(BaseEvent baseEvent, RDTKProperty[] properties) { ItemProperties.Items.Clear(); StackPanel[] panel = new StackPanel[properties.Length]; if (_eventPanel.ContainsKey(baseEvent.GetType())) { } else { foreach (var property in properties) { StackPanel stackPanel = property.Type switch { RDPropertyType.Bool => new() { Orientation = Orientation.Horizontal, FlowDirection = FlowDirection.LeftToRight, Children = { new Label(){Content = property.Name}, new CheckBox() { IsChecked = bool.Parse( property.Value), } }, }, RDPropertyType.Enum => 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, } }, }, RDPropertyType.String => new() { AllowDrop = true, Orientation = Orientation.Horizontal, FlowDirection = FlowDirection.LeftToRight, Children = { new Label(){Content = property.Name}, new TextBox() { Text = property.Value, } }, }, RDPropertyType.Integer => new() { AllowDrop = true, Orientation = Orientation.Horizontal, FlowDirection = FlowDirection.LeftToRight, Children = { new Label(){Content = property.Name}, new TextBox() { Text = property.Value, } }, }, RDPropertyType.Float => new() { AllowDrop = true, Orientation = Orientation.Horizontal, FlowDirection = FlowDirection.LeftToRight, Children = { new Label(){Content = property.Name}, new TextBox() { Text = property.Value, } }, }, RDPropertyType.Color => new() { AllowDrop = true, Orientation = Orientation.Horizontal, FlowDirection = FlowDirection.LeftToRight, Children = { new Label(){Content = property.Name}, new TextBox() { Text = property.Value, } }, }, _ => new() { Orientation = Orientation.Horizontal, Children = { new Label(){Content = property.Name}, new Label(){Content = property.Value} } }, }; 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() { if (_selectedEvents.Count == 0) return; else if (_selectedEvents.Count == 1) { var e = _selectedEvents[0]; foreach (var property in ItemProperties.Items) { if (property is StackPanel stackPanel) { foreach (var child in stackPanel.Children) { switch (child) { case CheckBox checkBox: e.GetType().GetProperty(stackPanel.Name)?.SetValue(e, checkBox.IsChecked); break; case TextBox textBox: e.GetType().GetProperty(stackPanel.Name)?.SetValue(e, textBox.Text); break; case ComboBox comboBox: e.GetType().GetProperty(stackPanel.Name)?.SetValue(e, comboBox.SelectedValue); break; default: break; } } } } } else { } } private void UpdateTimeLine() { } /*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((float)info.Width / _vsScale.Width, (float)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 void CheckBox_Checked(object sender, RoutedEventArgs e) { MessageBox.Show("已确认"); } 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; private bool _isButtonEnabled = true; public bool IsButtonEnabled { get => _isButtonEnabled; set { _isButtonEnabled = value; } } } }