diff --git a/.gitignore b/.gitignore index 8e39392..c42e773 100644 --- a/.gitignore +++ b/.gitignore @@ -219,4 +219,12 @@ src/Web/Avalonia.Web.Blazor/Interop/Typescript/*.js # Manually Added ################## -*.sfc \ No newline at end of file +*.sfc +*.nes +*.gb +*.gbc +*.gba +*.smc +*.z64 +*.v64 +*.n64 \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index cc92fac..fabac5e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,6 +1,6 @@ variables: GIT_SUBMODULE_STRATEGY: normal - GIT_CLONE_PATH: $CI_BUILDS_DIR\smw-ml + GIT_CLONE_PATH: $CI_BUILDS_DIR\retro-ml stages: - build-dependencies @@ -33,11 +33,11 @@ build-app: - build-emu - build-sharpneat artifacts: - name: smw-ml-build + name: retro-ml-build paths: - - .\SMW-ML\bin\Release\net6.0\ + - .\Application\bin\Release\net6.0\ script: - - cd .\SMW-ML\ + - cd .\Application\ - dotnet build --configuration Release - cd .\..\ @@ -48,8 +48,8 @@ test-app: artifacts: name: test-results paths: - - .\SMW_ML_TEST\TestResults\ + - .\Retro_ML_TEST\TestResults\ script: - - cd .\SMW_ML_TEST\ + - cd .\Retro_ML_TEST\ - dotnet test --logger trx - cd .\..\ diff --git a/SMW-ML/.gitignore b/Application/.gitignore similarity index 100% rename from SMW-ML/.gitignore rename to Application/.gitignore diff --git a/SMW-ML/App.axaml b/Application/App.axaml similarity index 77% rename from SMW-ML/App.axaml rename to Application/App.axaml index c2c8e19..eebaf6a 100644 --- a/SMW-ML/App.axaml +++ b/Application/App.axaml @@ -1,7 +1,7 @@ + xmlns:local="clr-namespace:Retro_ML.Application" + x:Class="Retro_ML.Application.App"> diff --git a/SMW-ML/App.axaml.cs b/Application/App.axaml.cs similarity index 80% rename from SMW-ML/App.axaml.cs rename to Application/App.axaml.cs index ccd5d60..96d182e 100644 --- a/SMW-ML/App.axaml.cs +++ b/Application/App.axaml.cs @@ -1,12 +1,11 @@ -using Avalonia; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Markup.Xaml; -using SMW_ML.ViewModels; -using SMW_ML.Views; +using Retro_ML.Application.ViewModels; +using Retro_ML.Application.Views; -namespace SMW_ML +namespace Retro_ML.Application { - public class App : Application + public class App : Avalonia.Application { public override void Initialize() { diff --git a/SMW-ML/Assets/banner.png b/Application/Assets/banner.png similarity index 100% rename from SMW-ML/Assets/banner.png rename to Application/Assets/banner.png diff --git a/SMW-ML/Assets/logo.ico b/Application/Assets/logo.ico similarity index 100% rename from SMW-ML/Assets/logo.ico rename to Application/Assets/logo.ico diff --git a/SMW-ML/Models/Error.cs b/Application/Models/Error.cs similarity index 85% rename from SMW-ML/Models/Error.cs rename to Application/Models/Error.cs index bc8b9af..20def76 100644 --- a/SMW-ML/Models/Error.cs +++ b/Application/Models/Error.cs @@ -1,4 +1,4 @@ -namespace SMW_ML.Models +namespace Retro_ML.Application.Models { internal class Error { diff --git a/SMW-ML/Program.cs b/Application/Program.cs similarity index 95% rename from SMW-ML/Program.cs rename to Application/Program.cs index 3979d36..05a2b0a 100644 --- a/SMW-ML/Program.cs +++ b/Application/Program.cs @@ -2,7 +2,7 @@ using Avalonia.ReactiveUI; using System; -namespace SMW_ML +namespace Retro_ML.Application { internal class Program { diff --git a/SMW-ML/SMW_ML.csproj b/Application/Retro_ML.Application.csproj similarity index 71% rename from SMW-ML/SMW_ML.csproj rename to Application/Retro_ML.Application.csproj index 88f26ce..1e97e65 100644 --- a/SMW-ML/SMW_ML.csproj +++ b/Application/Retro_ML.Application.csproj @@ -6,14 +6,20 @@ true Assets/logo.ico - - - - - + + + + + + + + + + + @@ -29,16 +35,9 @@ - - - - - ..\Submodules\SharpNEAT\src\SharpNeat\bin\Release\net6.0\SharpNeat.dll - - Always @@ -46,6 +45,9 @@ + + BoolView.axaml + ScoreFactorView.axaml @@ -61,7 +63,7 @@ - PreserveNewest + PreserveNewest PreserveNewest @@ -72,6 +74,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -79,13 +84,28 @@ MSBuild:Compile + + + + + + + + + + - - + + + + + + + diff --git a/SMW-ML/Styles/MainStyles.axaml b/Application/Styles/MainStyles.axaml similarity index 100% rename from SMW-ML/Styles/MainStyles.axaml rename to Application/Styles/MainStyles.axaml diff --git a/SMW-ML/ViewLocator.cs b/Application/ViewLocator.cs similarity index 89% rename from SMW-ML/ViewLocator.cs rename to Application/ViewLocator.cs index 30bda3e..8ca2ea2 100644 --- a/SMW-ML/ViewLocator.cs +++ b/Application/ViewLocator.cs @@ -1,10 +1,10 @@ using Avalonia.Controls; using Avalonia.Controls.Templates; -using SMW_ML.ViewModels; -using SMW_ML.Views; +using Retro_ML.Application.ViewModels; +using Retro_ML.Application.Views; using System; -namespace SMW_ML +namespace Retro_ML.Application { internal class ViewLocator : IDataTemplate { diff --git a/Application/ViewModels/Components/FieldInfo/BoolViewModel.cs b/Application/ViewModels/Components/FieldInfo/BoolViewModel.cs new file mode 100644 index 0000000..615eafd --- /dev/null +++ b/Application/ViewModels/Components/FieldInfo/BoolViewModel.cs @@ -0,0 +1,31 @@ +using ReactiveUI; +using Retro_ML.Configuration.FieldInformation; + +namespace Retro_ML.Application.ViewModels.Components.FieldInfo +{ + internal class BoolViewModel : ViewModelBase + { + public BoolFieldInfo FieldInfo { get; } + public string FieldName => FieldInfo.Name; + public string DisplayName => FieldInfo.ReadableName; + + private bool isChecked; + public bool IsChecked + { + get => isChecked; + set => this.RaiseAndSetIfChanged(ref isChecked, value); + } + + public BoolViewModel() + { + this.IsChecked = true; + FieldInfo = new BoolFieldInfo("TestField", "Test Field"); + } + + public BoolViewModel(BoolFieldInfo boolFieldInfo, bool value) + { + FieldInfo = boolFieldInfo; + isChecked = value; + } + } +} diff --git a/Application/ViewModels/Components/FieldInfo/IntegerChoiceViewModel.cs b/Application/ViewModels/Components/FieldInfo/IntegerChoiceViewModel.cs new file mode 100644 index 0000000..65e13f4 --- /dev/null +++ b/Application/ViewModels/Components/FieldInfo/IntegerChoiceViewModel.cs @@ -0,0 +1,34 @@ +using ReactiveUI; +using Retro_ML.Configuration.FieldInformation; + +namespace Retro_ML.Application.ViewModels.Components.FieldInfo +{ + internal class IntegerChoiceViewModel : ViewModelBase + { + public IntegerChoiceFieldInfo FieldInfo { get; } + public string FieldName => FieldInfo.Name; + public string DisplayName => FieldInfo.ReadableName; + private int value; + public int Value + { + get => value; + set + { + this.RaiseAndSetIfChanged(ref this.value, value); + } + } + public int[] PossibleValues => FieldInfo.PossibleValues; + + public IntegerChoiceViewModel() + { + FieldInfo = new IntegerChoiceFieldInfo("TestField", "Test Field", new int[] { 1, 3, 5, 7, 10 }); + this.value = 5; + } + + public IntegerChoiceViewModel(IntegerChoiceFieldInfo fieldInfo, int value) + { + FieldInfo = fieldInfo; + this.value = value; + } + } +} diff --git a/Application/ViewModels/Components/FieldInfo/IntegerViewModel.cs b/Application/ViewModels/Components/FieldInfo/IntegerViewModel.cs new file mode 100644 index 0000000..7019421 --- /dev/null +++ b/Application/ViewModels/Components/FieldInfo/IntegerViewModel.cs @@ -0,0 +1,39 @@ +using ReactiveUI; +using Retro_ML.Configuration.FieldInformation; + +namespace Retro_ML.Application.ViewModels.Components.FieldInfo +{ + internal class IntegerViewModel : ViewModelBase + { + public IntegerFieldInfo FieldInfo { get; } + public string FieldName => FieldInfo.Name; + public string DisplayName => FieldInfo.ReadableName; + + private int value; + public int Value + { + get => value; + set + { + this.RaiseAndSetIfChanged(ref this.value, value); + } + } + public int MinimumValue => FieldInfo.MinimumValue; + public int MaximumValue => FieldInfo.MaximumValue; + public int Increment => FieldInfo.Increment; + public bool HasIncrement => FieldInfo.Increment > 0; + + public IntegerViewModel() + { + FieldInfo = new IntegerFieldInfo("TestField", "Test Field", 5, 25, 5); + Value = 15; + } + + public IntegerViewModel(IntegerFieldInfo fieldInfo, int value) + { + FieldInfo = fieldInfo; + Value = value; + } + + } +} diff --git a/SMW-ML/ViewModels/Components/InputOutputConfigViewModel.cs b/Application/ViewModels/Components/InputOutputConfigViewModel.cs similarity index 91% rename from SMW-ML/ViewModels/Components/InputOutputConfigViewModel.cs rename to Application/ViewModels/Components/InputOutputConfigViewModel.cs index e7d182d..d550c1c 100644 --- a/SMW-ML/ViewModels/Components/InputOutputConfigViewModel.cs +++ b/Application/ViewModels/Components/InputOutputConfigViewModel.cs @@ -1,7 +1,7 @@ using ReactiveUI; -using SMW_ML.Game.SuperMarioWorld; +using Retro_ML.Neural; -namespace SMW_ML.ViewModels.Components +namespace Retro_ML.Application.ViewModels.Components { internal class InputOutputConfigViewModel : ViewModelBase { diff --git a/SMW-ML/ViewModels/Components/ScoreFactorViewModel.cs b/Application/ViewModels/Components/ScoreFactorViewModel.cs similarity index 69% rename from SMW-ML/ViewModels/Components/ScoreFactorViewModel.cs rename to Application/ViewModels/Components/ScoreFactorViewModel.cs index c2b7cb3..c0441dd 100644 --- a/SMW-ML/ViewModels/Components/ScoreFactorViewModel.cs +++ b/Application/ViewModels/Components/ScoreFactorViewModel.cs @@ -1,8 +1,8 @@ using ReactiveUI; -using SMW_ML.Neural.Scoring; +using Retro_ML.Neural.Scoring; using System.Collections.ObjectModel; -namespace SMW_ML.ViewModels.Components +namespace Retro_ML.Application.ViewModels.Components { internal class ScoreFactorViewModel : ViewModelBase { @@ -11,11 +11,11 @@ internal class ScoreFactorViewModel : ViewModelBase public ScoreFactorViewModel(IScoreFactor scoreFactor) { - this.Name = scoreFactor.Name; - this.CanBeDisabled = scoreFactor.CanBeDisabled; - this.isEnabled = !scoreFactor.IsDisabled; - this.multiplier = scoreFactor.ScoreMultiplier; - this.ExtraFields = new ObservableCollection(scoreFactor.ExtraFields); + Name = scoreFactor.Name; + CanBeDisabled = scoreFactor.CanBeDisabled; + isEnabled = !scoreFactor.IsDisabled; + multiplier = scoreFactor.ScoreMultiplier; + ExtraFields = new ObservableCollection(scoreFactor.ExtraFields); } public string Name { get; } diff --git a/SMW-ML/ViewModels/Components/StopConditionViewModel.cs b/Application/ViewModels/Components/StopConditionViewModel.cs similarity index 91% rename from SMW-ML/ViewModels/Components/StopConditionViewModel.cs rename to Application/ViewModels/Components/StopConditionViewModel.cs index 3505182..cc98332 100644 --- a/SMW-ML/ViewModels/Components/StopConditionViewModel.cs +++ b/Application/ViewModels/Components/StopConditionViewModel.cs @@ -1,7 +1,7 @@ using ReactiveUI; -using SMW_ML.Neural.Training.StopCondition; +using Retro_ML.Neural.Train.StopCondition; -namespace SMW_ML.ViewModels.Components +namespace Retro_ML.Application.ViewModels.Components { internal class StopConditionViewModel : ViewModelBase { diff --git a/SMW-ML/ViewModels/ConfigurationViewModel.cs b/Application/ViewModels/ConfigurationViewModel.cs similarity index 82% rename from SMW-ML/ViewModels/ConfigurationViewModel.cs rename to Application/ViewModels/ConfigurationViewModel.cs index 4685d4c..0046ee4 100644 --- a/SMW-ML/ViewModels/ConfigurationViewModel.cs +++ b/Application/ViewModels/ConfigurationViewModel.cs @@ -1,11 +1,11 @@ using Avalonia.Controls; using ReactiveUI; -using SMW_ML.Game.SuperMarioWorld; -using SMW_ML.Models; -using SMW_ML.Models.Config; -using SMW_ML.Utils; -using SMW_ML.ViewModels.Components; -using SMW_ML.Views; +using Retro_ML.Application.Models; +using Retro_ML.Application.ViewModels.Components; +using Retro_ML.Application.ViewModels.Components.FieldInfo; +using Retro_ML.Configuration; +using Retro_ML.Configuration.FieldInformation; +using Retro_ML.Utils; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; @@ -13,7 +13,7 @@ using System.Linq; using System.Runtime.Serialization; -namespace SMW_ML.ViewModels +namespace Retro_ML.Application.ViewModels { internal class ConfigurationViewModel : ViewModelBase { @@ -46,12 +46,12 @@ private enum DispSpeedupFeaturesEnum : ushort private SharpNeatModel? SharpNeatModel; private ApplicationConfig? ApplicationConfig; - public int[] RayCounts => Raycast.POSSIBLE_RAY_COUNT; - public int[] PossibleClockLengths => new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 16 }; - public ObservableCollection ErrorList { get; set; } + public ObservableCollection GamePlugins { get; set; } public ObservableCollection DispMethodList { get; set; } + public ObservableCollection GamePluginConfigFields { get; } + private string _romPath; [DataMember] public string RomPath @@ -64,6 +64,44 @@ public string RomPath } } + private string _gamePlugin; + [DataMember] + public string GamePluginName + { + get => _gamePlugin; + set + { + this.RaiseAndSetIfChanged(ref _gamePlugin, value); + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(GamePluginName))); + ReloadGamePlugin(); + } + } + + private string _pluginGameName; + [DataMember] + public string PluginGameName + { + get => _pluginGameName; + set + { + this.RaiseAndSetIfChanged(ref _pluginGameName, value); + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(PluginGameName))); + } + } + + private string _pluginConsoleName; + [DataMember] + public string PluginConsoleName + { + get => _pluginConsoleName; + set + { + this.RaiseAndSetIfChanged(ref _pluginConsoleName, value); + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(PluginConsoleName))); + } + } + + private int _multithread; [DataMember] public int Multithread @@ -316,73 +354,32 @@ public string SaveStates private void SetSaveStates(List saveStates) { - this._saveStates = saveStates; + _saveStates = saveStates; SaveStates = string.Join("\n", saveStates); } public ObservableCollection Objectives { get; set; } - - private bool _useVisionGrid = false; - public bool UseVisionGrid - { - get => _useVisionGrid; - set => this.RaiseAndSetIfChanged(ref _useVisionGrid, value); - } - private int _viewDistanceHorizontal = 4; - public int ViewDistanceHorizontal - { - get => _viewDistanceHorizontal; - set => this.RaiseAndSetIfChanged(ref _viewDistanceHorizontal, value); - } - private int _viewDistanceVertical = 4; - public int ViewDistanceVertical - { - get => _viewDistanceVertical; - set => this.RaiseAndSetIfChanged(ref _viewDistanceVertical, value); - } - - private int _rayLength = 6; - public int RayLength - { - get => _rayLength; - set => this.RaiseAndSetIfChanged(ref _rayLength, value); - } - private int _rayCountIndex = 2; - public int RayCount - { - get => _rayCountIndex; - set => this.RaiseAndSetIfChanged(ref _rayCountIndex, value); - } - - private int _clockLength = 8; - public int ClockLength - { - get => _clockLength; - set => this.RaiseAndSetIfChanged(ref _clockLength, value); - } - private int _clockTickLength = 1; - public int ClockTickLength - { - get => _clockTickLength; - set => this.RaiseAndSetIfChanged(ref _clockTickLength, value); - } - - public ObservableCollection NeuralConfigs { get; } - public new event PropertyChangedEventHandler PropertyChanged; - protected void OnPropertyChanged(string name) - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); - } - #endregion #region Constructor public ConfigurationViewModel() { + GamePluginConfigFields = new ObservableCollection(); + + GamePlugins = new ObservableCollection(); + PluginUtils.LoadPlugins(); + foreach (var plugin in PluginUtils.GamePlugins) + { + GamePlugins.Add(plugin.PluginName); + } + _pluginConsoleName = ""; + _gamePlugin = ""; + _pluginGameName = ""; + DispMethodList = new ObservableCollection() { "OpenGL", @@ -446,7 +443,7 @@ public void CloseSettings(Window window) /// public void ShowWindow(Window mainWindow) { - var window = new Configuration + var window = new Views.Configuration { DataContext = this, Width = 700, @@ -499,6 +496,7 @@ private void SerializeConfig() if (ApplicationConfig == null) { return; } ApplicationConfig.RomPath = RomPath; + ApplicationConfig.GamePluginName = GamePluginName; ApplicationConfig.Multithread = Multithread; ApplicationConfig.ArduinoCommunicationPort = ArduinoPort!; for (int i = 0; i < StopConditions.Count; i++) @@ -509,30 +507,24 @@ private void SerializeConfig() ApplicationConfig.SaveStates = _saveStates; //Tab Objectives + var scoreFactors = ApplicationConfig.GamePluginConfig!.ScoreFactors; for (int i = 0; i < Objectives.Count; i++) { - ApplicationConfig.ScoreFactors[i].ScoreMultiplier = Objectives[i].Multiplier; - if (ApplicationConfig.ScoreFactors[i].CanBeDisabled) + scoreFactors[i].ScoreMultiplier = Objectives[i].Multiplier; + if (scoreFactors[i].CanBeDisabled) { - ApplicationConfig.ScoreFactors[i].IsDisabled = !Objectives[i].IsChecked; + scoreFactors[i].IsDisabled = !Objectives[i].IsChecked; } - for (int j = 0; j < ApplicationConfig.ScoreFactors[i].ExtraFields.Count(); j++) + for (int j = 0; j < scoreFactors[i].ExtraFields.Count(); j++) { - ApplicationConfig.ScoreFactors[i].ExtraFields[j].Value = Objectives[i].ExtraFields[j].Value; + scoreFactors[i].ExtraFields[j].Value = Objectives[i].ExtraFields[j].Value; } } - //Tab Neural - ApplicationConfig.NeuralConfig.UseGrid = UseVisionGrid; - ApplicationConfig.NeuralConfig.GridDistanceX = ViewDistanceHorizontal; - ApplicationConfig.NeuralConfig.GridDistanceY = ViewDistanceVertical; - - ApplicationConfig.NeuralConfig.RayLength = RayLength; - ApplicationConfig.NeuralConfig.RayCount = RayCount; - - ApplicationConfig.NeuralConfig.InternalClockLength = ClockLength; - ApplicationConfig.NeuralConfig.InternalClockTickLength = ClockTickLength; + //Tab Game + SaveGamePluginConfig(); + //Tab Neural int inputCount = ApplicationConfig.NeuralConfig.InputNodes.Count; int outputCount = ApplicationConfig.NeuralConfig.OutputNodes.Count; for (int i = 0; i < inputCount; i++) @@ -590,6 +582,7 @@ private void DeserializeConfig() if (ApplicationConfig == null) { return; } RomPath = ApplicationConfig.RomPath; + GamePluginName = ApplicationConfig.GamePluginName; Multithread = ApplicationConfig.Multithread; ArduinoPort = ApplicationConfig.ArduinoCommunicationPort; @@ -601,21 +594,81 @@ private void DeserializeConfig() SetSaveStates(ApplicationConfig.SaveStates); + //Tab Game + LoadGamePluginConfig(); + //Tab Objectives + LoadObjectives(); + + //Tab Neural + PopulateNeuralConfig(); + } + + public void LoadGamePluginConfig() + { + GamePluginConfigFields.Clear(); + + if (ApplicationConfig?.GamePluginConfig == null) return; + + var pluginConfig = ApplicationConfig.GamePluginConfig; + + foreach (var fieldInfo in pluginConfig.Fields) + { + switch (fieldInfo) + { + case BoolFieldInfo fi: + GamePluginConfigFields.Add(new BoolViewModel(fi, (bool)pluginConfig[fi.Name])); + break; + case IntegerChoiceFieldInfo fi: + GamePluginConfigFields.Add(new IntegerChoiceViewModel(fi, (int)pluginConfig[fi.Name])); + break; + case IntegerFieldInfo fi: + GamePluginConfigFields.Add(new IntegerViewModel(fi, (int)pluginConfig[fi.Name])); + break; + } + } + } + + private void LoadObjectives() + { Objectives.Clear(); - foreach (var obj in ApplicationConfig.ScoreFactors) + foreach (var obj in ApplicationConfig!.GamePluginConfig!.ScoreFactors) { Objectives.Add(new(obj)); } + } - //Tab Neural - PopulateNeuralConfig(); + public void SaveGamePluginConfig() + { + if (ApplicationConfig?.GamePluginConfig == null) return; + + var pluginConfig = ApplicationConfig.GamePluginConfig; + + foreach (var field in GamePluginConfigFields) + { + switch (field) + { + case BoolViewModel vm: + pluginConfig[vm.FieldName] = vm.IsChecked; + break; + case IntegerChoiceViewModel vm: + pluginConfig[vm.FieldName] = vm.Value; + break; + case IntegerViewModel vm: + pluginConfig[vm.FieldName] = vm.Value; + break; + } + } + + string pluginConfigPath = ApplicationConfig.GetGamePlugin().PluginConfigPath; + Directory.CreateDirectory(Path.GetDirectoryName(pluginConfigPath)!); + File.WriteAllText(pluginConfigPath, ApplicationConfig!.GamePluginConfig!.Serialize()); } public async void SelectRom() { OpenFileDialog fileDialog = new(); - fileDialog.Filters.Add(new FileDialogFilter() { Name = "Rom", Extensions = { "sfc" } }); + fileDialog.Filters.Add(new FileDialogFilter() { Name = "Rom", Extensions = ApplicationConfig!.GetConsolePlugin().ROMExtensions.ToList() }); fileDialog.AllowMultiple = false; fileDialog.Directory = Path.GetFullPath("."); @@ -661,6 +714,8 @@ public async void LoadNeuralConfig() string neuralConfigJson = await File.ReadAllTextAsync(paths.First()); ApplicationConfig!.NeuralConfig = NeuralConfig.Deserialize(neuralConfigJson); + ApplicationConfig.GamePluginConfig!.InitNeuralConfig(ApplicationConfig.NeuralConfig); + PopulateNeuralConfig(); } @@ -676,16 +731,18 @@ private void PopulateNeuralConfig() { NeuralConfigs.Add(new(output)); } + } - UseVisionGrid = ApplicationConfig.NeuralConfig.UseGrid; - ViewDistanceHorizontal = ApplicationConfig.NeuralConfig.GridDistanceX; - ViewDistanceVertical = ApplicationConfig.NeuralConfig.GridDistanceY; - - RayLength = ApplicationConfig.NeuralConfig.RayLength; - RayCount = ApplicationConfig.NeuralConfig.RayCount; + private void ReloadGamePlugin() + { + ApplicationConfig!.GamePluginName = GamePluginName; + var gamePlugin = ApplicationConfig!.GetGamePlugin(); + PluginGameName = gamePlugin.PluginGameName; + PluginConsoleName = ApplicationConfig.GetConsolePlugin().ConsoleName; - ClockLength = ApplicationConfig.NeuralConfig.InternalClockLength; - ClockTickLength = ApplicationConfig.NeuralConfig.InternalClockTickLength; + PopulateNeuralConfig(); + LoadGamePluginConfig(); + LoadObjectives(); } #region Validation diff --git a/SMW-ML/ViewModels/MainPageViewModel.cs b/Application/ViewModels/MainPageViewModel.cs similarity index 86% rename from SMW-ML/ViewModels/MainPageViewModel.cs rename to Application/ViewModels/MainPageViewModel.cs index c15122b..e80f5a2 100644 --- a/SMW-ML/ViewModels/MainPageViewModel.cs +++ b/Application/ViewModels/MainPageViewModel.cs @@ -1,6 +1,6 @@ using System; -namespace SMW_ML.ViewModels +namespace Retro_ML.Application.ViewModels { internal class MainPageViewModel : ViewModelBase { @@ -8,7 +8,7 @@ internal class MainPageViewModel : ViewModelBase public event Action? OnOpenPlayMode; #region Strings - public static string GreetingString => "Super Mario World - Machine Learning"; + public static string GreetingString => "Retro Games Machine Learning"; public static string TrainingString => "Training"; public static string PlayString => "Play mode"; public static string OpenSettingsString => "Configuration"; diff --git a/SMW-ML/ViewModels/MainWindowViewModel.cs b/Application/ViewModels/MainWindowViewModel.cs similarity index 87% rename from SMW-ML/ViewModels/MainWindowViewModel.cs rename to Application/ViewModels/MainWindowViewModel.cs index 3c6323f..d268a6b 100644 --- a/SMW-ML/ViewModels/MainWindowViewModel.cs +++ b/Application/ViewModels/MainWindowViewModel.cs @@ -1,13 +1,13 @@ using Avalonia.Threading; using ReactiveUI; -using SMW_ML.Models.Config; -using SMW_ML.Utils; -using SMW_ML.Views.Components; +using Retro_ML.Application.Views.Components; +using Retro_ML.Configuration; +using Retro_ML.Utils; using System; using System.IO; using System.Threading; -namespace SMW_ML.ViewModels +namespace Retro_ML.Application.ViewModels { internal class MainWindowViewModel : ViewModelBase { @@ -36,9 +36,14 @@ public MainWindowViewModel() playingPageViewModel.OnExit += HandlePlayingExit; new Thread(ErrorManagementThread).Start(); + PluginUtils.LoadPlugins(); ApplicationConfig applicationConfig = ApplicationConfig.Deserialize(File.ReadAllText(DefaultPaths.APP_CONFIG)); - if (!File.Exists(applicationConfig.RomPath)) + if (string.IsNullOrWhiteSpace(applicationConfig.RomPath)) + { + Exceptions.QueueException(new Exception($"No ROMs are currently specified. Please go into the Configuration to select a ROM before anything else.")); + } + else if (!File.Exists(applicationConfig.RomPath)) { Exceptions.QueueException(new Exception($"Could not find ROM at path {applicationConfig.RomPath}. Please go into the Configuration to select a ROM before anything else.")); } @@ -85,8 +90,6 @@ public void HandlePlayingExit() mainPageViewModel.IsEnabled = true; } - - public void ErrorManagementThread() { while (true) diff --git a/SMW-ML/ViewModels/Neural/NetworkViewModel.cs b/Application/ViewModels/Neural/NetworkViewModel.cs similarity index 94% rename from SMW-ML/ViewModels/Neural/NetworkViewModel.cs rename to Application/ViewModels/Neural/NetworkViewModel.cs index d648df0..40331e1 100644 --- a/SMW-ML/ViewModels/Neural/NetworkViewModel.cs +++ b/Application/ViewModels/Neural/NetworkViewModel.cs @@ -2,13 +2,14 @@ using Avalonia.Media; using Avalonia.Threading; using ReactiveUI; -using SMW_ML.Models.Config; +using Retro_ML.Configuration; +using Retro_ML.Game; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; -namespace SMW_ML.ViewModels.Neural +namespace Retro_ML.Application.ViewModels.Neural { /// /// View model for the network view @@ -30,8 +31,16 @@ public Node(double value, Color targetColor, double positionX, double positionY) Value = value; Color currColor; - if (value <= 0) currColor = BaseColor; + if (value <= -1) currColor = NegativeColor; else if (value >= 1) currColor = targetColor; + else if (value < 0) + { + byte r = (byte)(BaseColor.R + (NegativeColor.R - BaseColor.R) * value); + byte g = (byte)(BaseColor.G + (NegativeColor.G - BaseColor.G) * value); + byte b = (byte)(BaseColor.B + (NegativeColor.B - BaseColor.B) * value); + + currColor = Color.FromRgb(r, g, b); + } else { byte r = (byte)(BaseColor.R + (targetColor.R - BaseColor.R) * value); @@ -100,6 +109,7 @@ public NodeGroupViewModel(string name, Color targetColor, int gridWidth = 1, int } public static Color BaseColor = Color.Parse("#444"); public static Color MiddleNodeColor = Color.Parse("#ACA"); + public static Color NegativeColor = Color.Parse("#000"); public static Color DefaultActiveColor = Color.Parse("#EEE"); public static Color DangerActiveColor = Color.Parse("#E00"); public static Color GoodiesActiveColor = Color.Parse("#0E0"); @@ -198,7 +208,7 @@ private void UpdateTopologyUI((int sourceNode, int targetNode, double weight)[][ nodePositions[outputIds[i]] = outputPositions[i]; } - double middleXOffset = currConnectionLayers!.Length > 2 ? (TotalWidth / 3.0) / currConnectionLayers.Length - 2 : 0; + double middleXOffset = currConnectionLayers!.Length > 2 ? TotalWidth / 3.0 / currConnectionLayers.Length - 2 : 0; double middleStartX = TotalWidth / 3.0 - middleXOffset; //We subtract one offset, since layer 0 is usually the input nodes List<(int source, int target, double weight)> connectionsToAdd = new(); @@ -330,7 +340,7 @@ private void UpdateNodes(IEnumerable nodeGroups, double[] st { double prevValue = nodeGroup.Nodes[i].Value; double value = states[i + startIndex]; - if (nodeGroup.IsOutput) value = value > 0 ? 1 : 0; + if (nodeGroup.IsOutput) value = value > IInput.INPUT_THRESHOLD ? 1 : 0; if (prevValue != value && !(prevValue <= 0 && value <= 0) && !(prevValue >= 1 && value >= 1)) { nodeGroup.Nodes[i] = new Node(value, nodeGroup.TargetColor); diff --git a/SMW-ML/ViewModels/PlayingPageViewModel.cs b/Application/ViewModels/PlayingPageViewModel.cs similarity index 74% rename from SMW-ML/ViewModels/PlayingPageViewModel.cs rename to Application/ViewModels/PlayingPageViewModel.cs index 49ea71e..8ecb44a 100644 --- a/SMW-ML/ViewModels/PlayingPageViewModel.cs +++ b/Application/ViewModels/PlayingPageViewModel.cs @@ -1,16 +1,16 @@ using Avalonia.Controls; using ReactiveUI; -using SMW_ML.Emulator; -using SMW_ML.Models.Config; -using SMW_ML.Neural.Play; -using SMW_ML.Neural.Play.SharpNeat; -using SMW_ML.Utils; -using SMW_ML.ViewModels.Neural; +using Retro_ML.Application.ViewModels.Neural; +using Retro_ML.Configuration; +using Retro_ML.Emulator; +using Retro_ML.Neural.Play; +using Retro_ML.Plugin; +using Retro_ML.Utils; using System; using System.IO; using System.Threading; -namespace SMW_ML.ViewModels +namespace Retro_ML.Application.ViewModels { internal class PlayingPageViewModel : ViewModelBase { @@ -20,13 +20,14 @@ internal class PlayingPageViewModel : ViewModelBase public static string ExitString => "Return to main menu"; public static string StartString => "Start"; public static string StopString => "Stop"; - public static string LoadGenomeString => "Load genome"; - public static string LoadSaveStateString => "Load save state"; + public static string LoadGenomeString => "Load genomes"; + public static string LoadSaveStateString => "Load save states"; #endregion private INeuralPlayer? neuralPlayer; private EmulatorManager? emulatorManager; private NetworkViewModel? neuralNetwork; + private ApplicationConfig? appConfig; private bool loadedState = false; private bool loadedGenome = false; @@ -59,11 +60,13 @@ public PlayingPageViewModel() public void Init() { string appConfigJson = File.ReadAllText(DefaultPaths.APP_CONFIG); - ApplicationConfig appConfig = ApplicationConfig.Deserialize(appConfigJson)!; + appConfig = ApplicationConfig.Deserialize(appConfigJson)!; + IGamePlugin gamePlugin = appConfig.GetGamePlugin(); NeuralNetwork = new NetworkViewModel(appConfig.NeuralConfig); - emulatorManager = new(1, appConfig); - neuralPlayer = new SharpNeatPlayer(emulatorManager, appConfig); + emulatorManager = new(1, appConfig, gamePlugin.GetDataFetcherFactory()); + neuralPlayer = gamePlugin.GetNeuralPlayer(emulatorManager, appConfig); + neuralPlayer.FinishedPlaying += HandlePlayStopped; emulatorManager.GetFirstEmulator().LinkedNetworkActivated += NeuralNetwork.UpdateNodes; emulatorManager.GetFirstEmulator().ChangedLinkedNetwork += NeuralNetwork.UpdateTopology; } @@ -72,18 +75,17 @@ public async void LoadGenome() { OpenFileDialog fileDialog = new(); fileDialog.Filters.Add(new FileDialogFilter() { Name = "Genome", Extensions = { "genome" } }); - fileDialog.AllowMultiple = false; + fileDialog.AllowMultiple = true; fileDialog.Directory = Path.GetFullPath("."); string[]? paths = await fileDialog.ShowAsync(ViewLocator.GetMainWindow()); - string path = paths?[0] ?? ""; - if (string.IsNullOrWhiteSpace(path)) + if ((paths?.Length ?? 0) == 0) { return; } - if (neuralPlayer!.LoadGenome(path)) + if (neuralPlayer!.LoadGenomes(paths!)) { loadedGenome = true; UpdateCanStart(); @@ -94,18 +96,17 @@ public async void LoadState() { OpenFileDialog fileDialog = new(); fileDialog.Filters.Add(new FileDialogFilter() { Name = "Save State", Extensions = { "State" } }); - fileDialog.AllowMultiple = false; - fileDialog.Directory = Path.GetFullPath("./config/SaveStates"); + fileDialog.AllowMultiple = true; + fileDialog.Directory = Path.GetFullPath($"./config/SaveStates/{appConfig!.GamePluginName}"); string[]? paths = await fileDialog.ShowAsync(ViewLocator.GetMainWindow()); - string path = paths?[0] ?? ""; - if (string.IsNullOrWhiteSpace(path)) + if ((paths?.Length ?? 0) == 0) { return; } - neuralPlayer!.LoadState(path); + neuralPlayer!.LoadStates(paths!); loadedState = true; UpdateCanStart(); } @@ -140,5 +141,11 @@ public void Exit() } private void UpdateCanStart() => CanStart = loadedGenome && loadedState && !neuralPlayer!.IsPlaying; + + private void HandlePlayStopped() + { + UpdateCanStart(); + CanStop = false; + } } } diff --git a/SMW-ML/ViewModels/Statistics/TrainingChartViewModel.cs b/Application/ViewModels/Statistics/TrainingChartViewModel.cs similarity index 96% rename from SMW-ML/ViewModels/Statistics/TrainingChartViewModel.cs rename to Application/ViewModels/Statistics/TrainingChartViewModel.cs index f90f5c0..bbc1790 100644 --- a/SMW-ML/ViewModels/Statistics/TrainingChartViewModel.cs +++ b/Application/ViewModels/Statistics/TrainingChartViewModel.cs @@ -2,14 +2,14 @@ using LiveChartsCore.Kernel; using LiveChartsCore.SkiaSharpView; using ReactiveUI; -using SMW_ML.Neural.Training; +using Retro_ML.Neural.Train; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; -using static SMW_ML.Neural.Training.TrainingStatistics; +using static Retro_ML.Neural.Train.TrainingStatistics; -namespace SMW_ML.ViewModels.Statistics +namespace Retro_ML.Application.ViewModels.Statistics { internal class TrainingChartViewModel : ViewModelBase { diff --git a/SMW-ML/ViewModels/TrainingPageViewModel.cs b/Application/ViewModels/TrainingPageViewModel.cs similarity index 94% rename from SMW-ML/ViewModels/TrainingPageViewModel.cs rename to Application/ViewModels/TrainingPageViewModel.cs index c6a8603..3dff7c8 100644 --- a/SMW-ML/ViewModels/TrainingPageViewModel.cs +++ b/Application/ViewModels/TrainingPageViewModel.cs @@ -1,14 +1,14 @@ using Avalonia.Controls; using Avalonia.Threading; using ReactiveUI; -using SMW_ML.Emulator; -using SMW_ML.Models.Config; -using SMW_ML.Neural.Training; -using SMW_ML.Neural.Training.SharpNeatImpl; -using SMW_ML.Utils; -using SMW_ML.ViewModels.Neural; -using SMW_ML.ViewModels.Statistics; -using SMW_ML.Views.Components; +using Retro_ML.Application.ViewModels.Neural; +using Retro_ML.Application.ViewModels.Statistics; +using Retro_ML.Application.Views.Components; +using Retro_ML.Configuration; +using Retro_ML.Emulator; +using Retro_ML.Neural.Train; +using Retro_ML.Plugin; +using Retro_ML.Utils; using System; using System.Collections.ObjectModel; using System.IO; @@ -16,7 +16,7 @@ using System.Threading; using System.Threading.Tasks; -namespace SMW_ML.ViewModels +namespace Retro_ML.Application.ViewModels { internal class TrainingPageViewModel : ViewModelBase { @@ -100,10 +100,11 @@ public void StartTraining() CanSaveTraining = false; string appConfigJson = File.ReadAllText(DefaultPaths.APP_CONFIG); ApplicationConfig appConfig = ApplicationConfig.Deserialize(appConfigJson)!; + IGamePlugin gamePlugin = appConfig.GetGamePlugin(); NeuralNetwork = new NetworkViewModel(appConfig.NeuralConfig); - emulatorManager = new(appConfig); - trainer = new SharpNeatTrainer(emulatorManager, appConfig); + emulatorManager = new(appConfig, gamePlugin.GetDataFetcherFactory()); + trainer = gamePlugin.GetNeuralTrainer(emulatorManager, appConfig); trainer.OnStatisticsUpdated += HandleGetStats; if (populationToLoad != null) { diff --git a/SMW-ML/ViewModels/ViewModelBase.cs b/Application/ViewModels/ViewModelBase.cs similarity index 86% rename from SMW-ML/ViewModels/ViewModelBase.cs rename to Application/ViewModels/ViewModelBase.cs index 3823bab..9cbc20b 100644 --- a/SMW-ML/ViewModels/ViewModelBase.cs +++ b/Application/ViewModels/ViewModelBase.cs @@ -1,6 +1,6 @@ using ReactiveUI; -namespace SMW_ML.ViewModels +namespace Retro_ML.Application.ViewModels { internal class ViewModelBase : ReactiveObject { diff --git a/Application/Views/Components/FieldInfo/BoolView.axaml b/Application/Views/Components/FieldInfo/BoolView.axaml new file mode 100644 index 0000000..75d9d54 --- /dev/null +++ b/Application/Views/Components/FieldInfo/BoolView.axaml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/Application/Views/Components/FieldInfo/BoolView.axaml.cs b/Application/Views/Components/FieldInfo/BoolView.axaml.cs new file mode 100644 index 0000000..1810161 --- /dev/null +++ b/Application/Views/Components/FieldInfo/BoolView.axaml.cs @@ -0,0 +1,18 @@ +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace Retro_ML.Application.Views.Components.FieldInfo +{ + public partial class BoolView : UserControl + { + public BoolView() + { + InitializeComponent(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + } +} diff --git a/Application/Views/Components/FieldInfo/IntegerChoiceView.axaml b/Application/Views/Components/FieldInfo/IntegerChoiceView.axaml new file mode 100644 index 0000000..cc28447 --- /dev/null +++ b/Application/Views/Components/FieldInfo/IntegerChoiceView.axaml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + diff --git a/Application/Views/Components/FieldInfo/IntegerChoiceView.axaml.cs b/Application/Views/Components/FieldInfo/IntegerChoiceView.axaml.cs new file mode 100644 index 0000000..bd97b35 --- /dev/null +++ b/Application/Views/Components/FieldInfo/IntegerChoiceView.axaml.cs @@ -0,0 +1,19 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace Retro_ML.Application.Views.Components.FieldInfo +{ + public partial class IntegerChoiceView : UserControl + { + public IntegerChoiceView() + { + InitializeComponent(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + } +} diff --git a/Application/Views/Components/FieldInfo/IntegerView.axaml b/Application/Views/Components/FieldInfo/IntegerView.axaml new file mode 100644 index 0000000..b9e0c08 --- /dev/null +++ b/Application/Views/Components/FieldInfo/IntegerView.axaml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + diff --git a/Application/Views/Components/FieldInfo/IntegerView.axaml.cs b/Application/Views/Components/FieldInfo/IntegerView.axaml.cs new file mode 100644 index 0000000..7b69b88 --- /dev/null +++ b/Application/Views/Components/FieldInfo/IntegerView.axaml.cs @@ -0,0 +1,19 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace Retro_ML.Application.Views.Components.FieldInfo +{ + public partial class IntegerView : UserControl + { + public IntegerView() + { + InitializeComponent(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + } +} diff --git a/SMW-ML/Views/Components/InputOutputConfigView.axaml b/Application/Views/Components/InputOutputConfigView.axaml similarity index 86% rename from SMW-ML/Views/Components/InputOutputConfigView.axaml rename to Application/Views/Components/InputOutputConfigView.axaml index b0557f4..b668f91 100644 --- a/SMW-ML/Views/Components/InputOutputConfigView.axaml +++ b/Application/Views/Components/InputOutputConfigView.axaml @@ -3,8 +3,8 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" - xmlns:vm="clr-namespace:SMW_ML.ViewModels.Components;assembly=SMW_ML" - x:Class="SMW_ML.Views.Components.InputOutputConfigView"> + xmlns:vm="clr-namespace:Retro_ML.Application.ViewModels.Components;assembly=Retro_ML.Application" + x:Class="Retro_ML.Application.Views.Components.InputOutputConfigView"> diff --git a/SMW-ML/Views/Components/InputOutputConfigView.axaml.cs b/Application/Views/Components/InputOutputConfigView.axaml.cs similarity index 87% rename from SMW-ML/Views/Components/InputOutputConfigView.axaml.cs rename to Application/Views/Components/InputOutputConfigView.axaml.cs index aa3c5d5..7d7b1ab 100644 --- a/SMW-ML/Views/Components/InputOutputConfigView.axaml.cs +++ b/Application/Views/Components/InputOutputConfigView.axaml.cs @@ -1,7 +1,7 @@ using Avalonia.Controls; using Avalonia.Markup.Xaml; -namespace SMW_ML.Views.Components +namespace Retro_ML.Application.Views.Components { public partial class InputOutputConfigView : UserControl { diff --git a/SMW-ML/Views/Components/MessageBox.axaml b/Application/Views/Components/MessageBox.axaml similarity index 86% rename from SMW-ML/Views/Components/MessageBox.axaml rename to Application/Views/Components/MessageBox.axaml index aacd58d..00ffe9e 100644 --- a/SMW-ML/Views/Components/MessageBox.axaml +++ b/Application/Views/Components/MessageBox.axaml @@ -3,7 +3,7 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" - x:Class="SMW_ML.Views.Components.MessageBox" SizeToContent="WidthAndHeight" CanResize="False"> + x:Class="Retro_ML.Application.Views.Components.MessageBox" SizeToContent="WidthAndHeight" CanResize="False"> diff --git a/SMW-ML/Views/Components/MessageBox.axaml.cs b/Application/Views/Components/MessageBox.axaml.cs similarity index 98% rename from SMW-ML/Views/Components/MessageBox.axaml.cs rename to Application/Views/Components/MessageBox.axaml.cs index b4f31db..e6d7980 100644 --- a/SMW-ML/Views/Components/MessageBox.axaml.cs +++ b/Application/Views/Components/MessageBox.axaml.cs @@ -2,7 +2,7 @@ using Avalonia.Markup.Xaml; using System.Threading.Tasks; -namespace SMW_ML.Views.Components +namespace Retro_ML.Application.Views.Components { /// /// Thanks to diff --git a/SMW-ML/Views/Components/ScoreFactorView.axaml b/Application/Views/Components/ScoreFactorView.axaml similarity index 89% rename from SMW-ML/Views/Components/ScoreFactorView.axaml rename to Application/Views/Components/ScoreFactorView.axaml index 095743f..5a4187d 100644 --- a/SMW-ML/Views/Components/ScoreFactorView.axaml +++ b/Application/Views/Components/ScoreFactorView.axaml @@ -3,8 +3,8 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="600" d:DesignHeight="200" - xmlns:vm="clr-namespace:SMW_ML.ViewModels.Components;assembly=SMW_ML" - x:Class="SMW_ML.Views.Components.ScoreFactorView"> + xmlns:vm="clr-namespace:Retro_ML.Application.ViewModels.Components;assembly=Retro_ML.Application" + x:Class="Retro_ML.Application.Views.Components.ScoreFactorView"> diff --git a/SMW-ML/Views/Components/ScoreFactorView.axaml.cs b/Application/Views/Components/ScoreFactorView.axaml.cs similarity index 87% rename from SMW-ML/Views/Components/ScoreFactorView.axaml.cs rename to Application/Views/Components/ScoreFactorView.axaml.cs index 70ad5b4..9964573 100644 --- a/SMW-ML/Views/Components/ScoreFactorView.axaml.cs +++ b/Application/Views/Components/ScoreFactorView.axaml.cs @@ -1,7 +1,7 @@ using Avalonia.Controls; using Avalonia.Markup.Xaml; -namespace SMW_ML.Views.Components +namespace Retro_ML.Application.Views.Components { public partial class ScoreFactorView : UserControl { diff --git a/SMW-ML/Views/Components/StopConditionView.axaml b/Application/Views/Components/StopConditionView.axaml similarity index 86% rename from SMW-ML/Views/Components/StopConditionView.axaml rename to Application/Views/Components/StopConditionView.axaml index ff1fa46..9b24451 100644 --- a/SMW-ML/Views/Components/StopConditionView.axaml +++ b/Application/Views/Components/StopConditionView.axaml @@ -3,8 +3,8 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="600" d:DesignHeight="200" - xmlns:vm="clr-namespace:SMW_ML.ViewModels.Components;assembly=SMW_ML" - x:Class="SMW_ML.Views.Components.StopConditionView"> + xmlns:vm="clr-namespace:Retro_ML.Application.ViewModels.Components;assembly=Retro_ML.Application" + x:Class="Retro_ML.Application.Views.Components.StopConditionView"> diff --git a/SMW-ML/Views/Components/StopConditionView.axaml.cs b/Application/Views/Components/StopConditionView.axaml.cs similarity index 86% rename from SMW-ML/Views/Components/StopConditionView.axaml.cs rename to Application/Views/Components/StopConditionView.axaml.cs index c8bf77a..b71a5e6 100644 --- a/SMW-ML/Views/Components/StopConditionView.axaml.cs +++ b/Application/Views/Components/StopConditionView.axaml.cs @@ -1,8 +1,7 @@ -using Avalonia; using Avalonia.Controls; using Avalonia.Markup.Xaml; -namespace SMW_ML.Views.Components +namespace Retro_ML.Application.Views.Components { public partial class StopConditionView : UserControl { diff --git a/SMW-ML/Views/Configuration.axaml b/Application/Views/Configuration.axaml similarity index 84% rename from SMW-ML/Views/Configuration.axaml rename to Application/Views/Configuration.axaml index 00ec26d..3794085 100644 --- a/SMW-ML/Views/Configuration.axaml +++ b/Application/Views/Configuration.axaml @@ -2,9 +2,9 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:vm="clr-namespace:SMW_ML.ViewModels;assembly=SMW_ML" + xmlns:vm="clr-namespace:Retro_ML.Application.ViewModels;assembly=Retro_ML.Application" mc:Ignorable="d" d:DesignWidth="700" d:DesignHeight="500" - x:Class="SMW_ML.Views.Configuration" + x:Class="Retro_ML.Application.Views.Configuration" Title="Configuration" Name="ConfigurationWindow" IsEnabled="{Binding IsEnabled}" @@ -23,6 +23,10 @@