diff --git a/ViewModels/SimulatorViewModel.cs b/ViewModels/SimulatorViewModel.cs --- a/ViewModels/SimulatorViewModel.cs +++ b/ViewModels/SimulatorViewModel.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; +using System.Reactive.Linq; using Avalonia; using Avalonia.Input.Platform; using DesertPaintCodex.Models; @@ -14,6 +15,12 @@ namespace DesertPaintCodex.ViewModels { public class SimulatorViewModel : ViewModelBase { + private RecipeLibraryViewModel? _recipeLibraryVM; + + private ViewModelBase? _recipeLibraryActivity; + public ViewModelBase? RecipeLibraryActivity { get => _recipeLibraryActivity; private set => this.RaiseAndSetIfChanged(ref _recipeLibraryActivity, value); } + + private PaintColor? _paintColor; public PaintColor? PaintColor { @@ -21,6 +28,10 @@ namespace DesertPaintCodex.ViewModels set => this.RaiseAndSetIfChanged(ref _paintColor, value); } + // Stealing the recipe view from the paint generator + private GeneratorRecipe? _existingRecipe; + public GeneratorRecipe? ExistingRecipe { get => _existingRecipe; private set => this.RaiseAndSetIfChanged(ref _existingRecipe, value); } + private bool _hasMissingReactions; public bool HasMissingReactions { @@ -35,13 +46,28 @@ namespace DesertPaintCodex.ViewModels get => _isGoodRecipe; set => this.RaiseAndSetIfChanged(ref _isGoodRecipe, value); } - + + private bool _isValidConcentration; + public bool IsValidConcentration + { + get => _isValidConcentration; + set => this.RaiseAndSetIfChanged(ref _isValidConcentration, value); + } + + private string _missingReactionList = string.Empty; + public string MissingReactionList + { + get => _missingReactionList; + set => this.RaiseAndSetIfChanged(ref _missingReactionList, value); + } + public ObservableCollection Reagents { get; } = new(); public ObservableCollection ActiveReagents { get; } = new(); public ObservableCollection RecipeItems { get; } = new(); private readonly PaintRecipe _currentRecipe = new(); + private PaintColor _tempColor = new PaintColor(0, 0,0); public SimulatorViewModel() { @@ -86,7 +112,90 @@ namespace DesertPaintCodex.ViewModels Refresh(); } - + + private void ShowRecipeLibrary() + { + _recipeLibraryVM = new RecipeLibraryViewModel(); + Observable.Merge(_recipeLibraryVM.Ok, _recipeLibraryVM.Cancel).Subscribe(_ => LoadRecipe()); + + RecipeLibraryActivity = _recipeLibraryVM; + } + + + // Show the list of recipes and allow the user to pick one to load + public void LoadRecipe() + { + // TODO: show the list of recipes + } + + public void SelectRecipeToLoad(PaintRecipe recipe) + { + // 1: Clear the current recipe + _currentRecipe.Clear(); + RecipeItems.Clear(); + + // 2: Set the recipe items from the loaded recipe + foreach (PaintRecipe.ReagentQuantity reagentQuantity in recipe.Reagents) + { + Reagent reagent = ReagentService.GetReagent(reagentQuantity.Name); + if (reagent != null) + { + RecipeItems.Add(new RecipeItem(reagent, reagentQuantity.Quantity)); + } + } + UpdateRecipe(); + } + + // Replace the recipe for a color with the current recipe + public void ReplaceRecipe() + { + if (IsGoodRecipe && IsValidConcentration) + { + if (ProfileManager.CurrentProfile == null) return; + + string colorName = PaletteService.FindNearest(_currentRecipe.ReactedColor); + _tempColor.Set(colorName, _currentRecipe.ReactedColor); + + ProfileManager.CurrentProfile.Recipes[colorName].CopyFrom(_currentRecipe); + + UpdateExistingRecipe(); + } + } + + private void UpdateExistingRecipe() + { + if (IsGoodRecipe) + { + string colorName = PaletteService.FindNearest(_currentRecipe.ReactedColor); + if ((ProfileManager.CurrentProfile != null) && (ProfileManager.CurrentProfile.Recipes.TryGetValue(colorName, out PaintRecipe? paintRecipe))) + { + System.Diagnostics.Debug.WriteLine($"Setting existing recipe for {colorName}."); + + GeneratorRecipe? existingRecipe = ExistingRecipe; + if (existingRecipe == null) + { + _tempColor.Set(colorName, _currentRecipe.ReactedColor); + existingRecipe = new GeneratorRecipe(_tempColor); + } + else + { + existingRecipe.Color.Set(colorName, _currentRecipe.ReactedColor); + } + existingRecipe.DraftRecipe(paintRecipe); + ExistingRecipe = null; + ExistingRecipe = existingRecipe; + } + else + { + ExistingRecipe = null; + } + } + else + { + ExistingRecipe = null; + } + } + private void UpdateRecipe() { _currentRecipe.Clear(); @@ -101,7 +210,20 @@ namespace DesertPaintCodex.ViewModels PaintColor = null; // TODO: Find a better way to kick the paint swatch when reassigning color from the same ref. PaintColor = _currentRecipe.ReactedColor; HasMissingReactions = _currentRecipe.HasMissingReactions(); + if (HasMissingReactions) + { + List<(string, string)> missingReactions = _currentRecipe.MissingReactionPairs(); + List missingReactionsStrings = new List(missingReactions.Count); + foreach ((string reagent1, string reagent2) in missingReactions) + { + missingReactionsStrings.Add($"{reagent1}+{reagent2}"); + } + MissingReactionList = string.Join(", ", missingReactionsStrings); + } IsGoodRecipe = !HasMissingReactions && _currentRecipe.IsValidForConcentration(10); + IsValidConcentration = _currentRecipe.IsValidForConcentration(10); + + UpdateExistingRecipe(); } private void OnActiveReagentsChanged(object? sender, NotifyCollectionChangedEventArgs e) diff --git a/Views/SimulatorView.axaml b/Views/SimulatorView.axaml --- a/Views/SimulatorView.axaml +++ b/Views/SimulatorView.axaml @@ -4,6 +4,7 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:views="clr-namespace:DesertPaintCodex.Views" + xmlns:models="clr-namespace:DesertPaintCodex.Models" mc:Ignorable="d" d:DesignWidth="600" d:DesignHeight="475" x:Class="DesertPaintCodex.Views.SimulatorView"> @@ -14,7 +15,17 @@ - + + + + + + + + + + + - - + + - - - - + + + + + + + CURRENT RECIPE + + + - + + + + + + REAGENTS