Archived
forked from RDTKEditor/RDTKEditor
408 lines
10 KiB
C#
408 lines
10 KiB
C#
using Microsoft.Win32;
|
|
using Ollama;
|
|
using RDTKEditor.AIAssistant;
|
|
using RDTKEditor.Models;
|
|
using RhythmBase.Components;
|
|
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
|
|
{
|
|
/// <summary>
|
|
/// Interaction logic for MainWindow.xaml
|
|
/// </summary>
|
|
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<BaseEvent> _selectedEvents = [];
|
|
internal readonly Dictionary<Type, StackPanel[]> _eventPanel = [];
|
|
public MainWindow()
|
|
{
|
|
InitializeComponent();
|
|
RDLevel level = RDLevel.Default;
|
|
var setVfx = new SetVFXPreset();
|
|
level.Add(setVfx);
|
|
_selectedEvents = [setVfx];
|
|
}
|
|
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
|
|
{
|
|
|
|
}
|
|
|
|
//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,
|
|
};
|
|
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,
|
|
};
|
|
}
|
|
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()
|
|
{
|
|
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;
|
|
}
|
|
} |