From 701fd9662d00f82fd39e3cbebdea8024ffb632aa Mon Sep 17 00:00:00 2001 From: Benjamin Popp Date: Fri, 29 May 2020 18:59:05 -0500 Subject: [PATCH] Add palette copy/paste functions --- .../ViewModels/Tools/PaletteCollection.cs | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/src/HexManiac.Core/ViewModels/Tools/PaletteCollection.cs b/src/HexManiac.Core/ViewModels/Tools/PaletteCollection.cs index 728aed37..217895b2 100644 --- a/src/HexManiac.Core/ViewModels/Tools/PaletteCollection.cs +++ b/src/HexManiac.Core/ViewModels/Tools/PaletteCollection.cs @@ -1,10 +1,13 @@ using HavenSoft.HexManiac.Core.Models; using HavenSoft.HexManiac.Core.Models.Runs.Sprites; +using HavenSoft.HexManiac.Core.ViewModels.DataFormats; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; +using System.Globalization; using System.Linq; +using System.Windows.Input; namespace HavenSoft.HexManiac.Core.ViewModels.Tools { public class PaletteCollection : ViewModelCore { @@ -44,6 +47,12 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Tools { } } + private StubCommand copy; + public ICommand Copy => StubCommand(ref copy, ExecuteCopy, CanExecuteCopy); + + private StubCommand paste; + public ICommand Paste => StubCommand(ref paste, ExecutePaste, CanExecutePaste); + public PaletteCollection(ViewPort viewPort, ChangeHistory history) { this.viewPort = viewPort; this.history = history; @@ -133,6 +142,69 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Tools { viewPort.Refresh(); for (int i = 0; i < Elements.Count; i++) Elements[i].Selected = newElements[i].Selected; } + + private void ExecuteCopy(IFileSystem fileSystem) { + var start = Math.Min(selectionStart, selectionEnd) + 1; + var end = Math.Max(selectionStart, selectionEnd) + 1; + var result = UncompressedPaletteColor.Convert(Elements[start - 1].Color); + for (int i = start; i < end; i++) { + result += " " + UncompressedPaletteColor.Convert(Elements[i].Color); + } + fileSystem.CopyText = result; + } + + private bool CanExecuteCopy(IFileSystem fileSystem) => 0 <= selectionStart && selectionStart < Elements.Count; + + private static IReadOnlyList ParseColor(string stream) { + var results = new List(); + var parts = stream.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); + for (int i = 0; i < parts.Length; i++) { + if (parts[i].Contains(":")) { + var channels = parts[i].Split(':'); + if (channels.Length != 3) return null; + if (!int.TryParse(channels[0], out var red) || !int.TryParse(channels[1], out var green) || !int.TryParse(channels[2], out var blue)) return null; + results.Add(UncompressedPaletteColor.Pack(red, green, blue)); + } else if (parts[i].Length == 4) { + if (!short.TryParse(parts[i], NumberStyles.HexNumber, CultureInfo.CurrentCulture, out var color)) return null; + results.Add(color); + } else if (parts[i].Length == 2 && i + 1 < parts.Length && parts[i + 1].Length == 2) { + if (!byte.TryParse(parts[i + 0], NumberStyles.HexNumber, CultureInfo.CurrentCulture, out var low)) return null; + if (!byte.TryParse(parts[i + 1], NumberStyles.HexNumber, CultureInfo.CurrentCulture, out var high)) return null; + i += 1; + results.Add((byte)((high << 8) | low)); + } else { + return null; + } + } + return results; + } + + private void ExecutePaste(IFileSystem fileSystem) { + var model = viewPort.Model; + if (!(model.GetNextRun(sourcePalette) is IPaletteRun source)) return; + + // paste data into elements + var colors = ParseColor(fileSystem.CopyText); + if (colors == null) return; + var start = Math.Min(selectionStart, selectionEnd); + for (int i = 0; i < colors.Count; i++) { + Elements[start].Color = colors[i]; + if (start < Elements.Count - 1) start += 1; + } + + // update model + var newPalette = source; + for (int page = 0; page < source.Pages; page++) { + newPalette = newPalette.SetPalette(model, history.CurrentChange, page, Elements.Select(e => e.Color).ToList()); + } + if (source.Start != newPalette.Start) viewPort.RaiseMessage($"Palette was moved to {newPalette.Start:X6}. Pointers were updated."); + + // update UI + viewPort.Refresh(); + SelectionStart = start; + } + + private bool CanExecutePaste(IFileSystem fileSystem) => CanExecuteCopy(fileSystem) && ParseColor(fileSystem.CopyText) != null; } [DebuggerDisplay("{Index}:{Color}")]