Auto create gradient

This commit is contained in:
Benjamin Popp 2020-06-01 14:08:29 -05:00
parent b8c3b91070
commit 9ef2c573ef
5 changed files with 72 additions and 17 deletions

View File

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO.Packaging;
using System.Linq;
using System.Windows.Input;
@ -45,6 +46,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Tools {
var first = Math.Min(selectionStart, selectionEnd);
var last = Math.Max(selectionStart, selectionEnd);
for (int i = 0; i < Elements.Count; i++) Elements[i].Selected = first <= i && i <= last;
createGradient.CanExecuteChanged.Invoke(createGradient, EventArgs.Empty);
}
}
@ -54,6 +56,9 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Tools {
private StubCommand paste;
public ICommand Paste => StubCommand<IFileSystem>(ref paste, ExecutePaste, CanExecutePaste);
private StubCommand createGradient;
public ICommand CreateGradient => StubCommand(ref createGradient, ExecuteCreateGradient, CanExecuteCreateGradient);
public PaletteCollection(ViewPort viewPort, ChangeHistory<ModelDelta> history) {
this.viewPort = viewPort;
this.history = history;
@ -164,6 +169,8 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Tools {
for (int i = 0; i < Elements.Count; i++) Elements[i].Selected = newElements[i].Selected;
}
#region Commands
private void ExecuteCopy(IFileSystem fileSystem) {
var start = Math.Min(selectionStart, selectionEnd) + 1;
var end = Math.Max(selectionStart, selectionEnd) + 1;
@ -218,6 +225,36 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Tools {
}
private bool CanExecutePaste(IFileSystem fileSystem) => CanExecuteCopy(fileSystem) && ParseColor(fileSystem.CopyText) != null;
private void ExecuteCreateGradient() {
var left = Math.Min(SelectionStart, SelectionEnd);
var leftRGB = UncompressedPaletteColor.ToRGB(Elements[left].Color);
var leftHSB = Theme.ToHSB((byte)(leftRGB.r << 3), (byte)(leftRGB.g << 3), (byte)(leftRGB.b << 3));
var right = Math.Max(SelectionStart, SelectionEnd);
var rightRGB = UncompressedPaletteColor.ToRGB(Elements[right].Color);
var rightHSB = Theme.ToHSB((byte)(rightRGB.r << 3), (byte)(rightRGB.g << 3), (byte)(rightRGB.b << 3));
var deltaHue = rightHSB.hue - leftHSB.hue;
var deltaSat = rightHSB.sat - leftHSB.sat;
var deltaBright = rightHSB.bright - leftHSB.bright;
var distance = right - left;
for (int i = 1; i < distance; i++) {
var part = (double)i / distance;
var hue = leftHSB.hue + deltaHue * part;
var sat = leftHSB.sat + deltaSat * part;
var bright = leftHSB.bright + deltaBright * part;
var rgb = Theme.FromHSB(hue, sat, bright);
Elements[left + i].Color = UncompressedPaletteColor.Pack(rgb.red >> 3, rgb.green >> 3, rgb.blue >> 3);
}
PushColorsToModel();
}
private bool CanExecuteCreateGradient() => Elements.Count(element => element.Selected) > 2;
#endregion
}
[DebuggerDisplay("{Index}:{Color}")]

View File

@ -1696,6 +1696,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
Tools.Schedule(Tools.TableTool.DataForCurrentRunChanged);
}
if (run is ITableRun || run is IStreamRun) Tools.Schedule(Tools.StringTool.DataForCurrentRunChanged);
if (run is IPaletteRun) tools.Schedule(Tools.SpriteTool.DataForCurrentRunChanged);
if (completeEditOperation.MessageText != null) OnMessage?.Invoke(this, completeEditOperation.MessageText);
if (completeEditOperation.ErrorText != null) OnError?.Invoke(this, completeEditOperation.ErrorText);

View File

@ -442,6 +442,18 @@ namespace HavenSoft.HexManiac.Tests {
Assert.Equal(0x11, Model[1]); // 00 changes to 11
}
[Fact]
public void CanCreateGradientForSelectedColors() {
ViewPort.Edit("^palette`ucp4` 0:0:0 0:0:0 30:30:30 ");
ViewPort.Tools.SpriteTool.Colors.SelectionStart = 0;
ViewPort.Tools.SpriteTool.Colors.SelectionEnd = 2;
ViewPort.Tools.SpriteTool.Colors.CreateGradient.Execute();
var color = (UncompressedPaletteColor)ViewPort[2, 0].Format;
Assert.Equal("15:15:15", color.ToString());
}
private void CreateLzRun(int start, params byte[] data) {
for (int i = 0; i < data.Length; i++) Model[start + i] = data[i];
var run = new LZRun(Model, start);

View File

@ -8,17 +8,19 @@
<UserControl.Resources>
<hsg3hv:PaletteColorConverter x:Key="PaletteColorConverter"/>
</UserControl.Resources>
<UserControl.ContextMenu>
<ContextMenu>
<MenuItem Header="Copy" InputGestureText="Ctrl+C" Command="{Binding Copy}" CommandParameter="{DynamicResource FileSystem}"/>
<MenuItem Header="Paste" InputGestureText="Ctrl+V" Command="{Binding Paste}" CommandParameter="{DynamicResource FileSystem}"/>
<MenuItem Header="Create Gradient" InputGestureText="Ctrl+M" Command="{Binding CreateGradient}" />
</ContextMenu>
</UserControl.ContextMenu>
<UserControl.InputBindings>
<KeyBinding Modifiers="Ctrl" Key="C" Command="{Binding Copy}" CommandParameter="{DynamicResource FileSystem}"/>
<KeyBinding Modifiers="Ctrl" Key="V" Command="{Binding Paste}" CommandParameter="{DynamicResource FileSystem}"/>
<KeyBinding Modifiers="Ctrl" Key="M" Command="{Binding CreateGradient}"/>
</UserControl.InputBindings>
<ItemsControl Name="ItemsControl" HorizontalAlignment="Center" SnapsToDevicePixels="True" ItemsSource="{Binding Elements}">
<ItemsControl.ContextMenu>
<ContextMenu>
<MenuItem Header="Copy" InputGestureText="Ctrl+C" Command="{Binding Copy}" CommandParameter="{DynamicResource FileSystem}"/>
<MenuItem Header="Paste" InputGestureText="Ctrl+V" Command="{Binding Paste}" CommandParameter="{DynamicResource FileSystem}"/>
</ContextMenu>
</ItemsControl.ContextMenu>
<ItemsControl.InputBindings>
<KeyBinding Modifiers="Ctrl" Key="C" Command="{Binding Copy}" CommandParameter="{DynamicResource FileSystem}"/>
<KeyBinding Modifiers="Ctrl" Key="V" Command="{Binding Paste}" CommandParameter="{DynamicResource FileSystem}"/>
</ItemsControl.InputBindings>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="{Binding ColorWidth}" Rows="{Binding ColorHeight}"/>

View File

@ -15,7 +15,7 @@ namespace HavenSoft.HexManiac.WPF.Controls {
private const int ExpectedElementWidth = 16, ExpectedElementHeight = 16;
private static readonly Duration span = new Duration(TimeSpan.FromMilliseconds(100));
private readonly Popup swatchPopup = new Popup { Placement = PlacementMode.Top, PopupAnimation = PopupAnimation.Fade, AllowsTransparency = true };
private readonly Popup swatchPopup = new Popup { Placement = PlacementMode.Bottom, PopupAnimation = PopupAnimation.Fade, AllowsTransparency = true };
private readonly Swatch swatch = new Swatch { Width = 230, Height = 200 };
private Point interactionPoint;
@ -50,12 +50,10 @@ namespace HavenSoft.HexManiac.WPF.Controls {
protected override void OnLostKeyboardFocus(KeyboardFocusChangedEventArgs e) {
swatchPopup.IsOpen = false;
swatch.ResultChanged -= SwatchResultChanged;
ViewModel.SelectionStart = -1;
base.OnLostKeyboardFocus(e);
}
private void StartPaletteColorMove(object sender, MouseButtonEventArgs e) {
if (e.LeftButton == MouseButtonState.Released) return;
swatch.ResultChanged -= SwatchResultChanged;
Focus();
@ -64,8 +62,7 @@ namespace HavenSoft.HexManiac.WPF.Controls {
if (Keyboard.Modifiers == ModifierKeys.Shift) {
ViewModel.SelectionEnd = tileIndex;
} else if (ViewModel.SelectionStart == tileIndex) {
ViewModel.SelectionStart = -1;
} else if (ViewModel.SelectionStart == tileIndex && e.LeftButton == MouseButtonState.Pressed && ViewModel.SelectionEnd == tileIndex && swatchPopup.IsOpen) {
e.Handled = true;
swatchPopup.IsOpen = false;
return;
@ -78,10 +75,12 @@ namespace HavenSoft.HexManiac.WPF.Controls {
if (Keyboard.Modifiers != ModifierKeys.Shift) {
swatch.Result = ColorFor(tileIndex);
swatchPopup.IsOpen = true;
initialColors = CollectColorList();
activeSelection = tileIndex;
swatch.ResultChanged += SwatchResultChanged;
if (e.LeftButton == MouseButtonState.Pressed) {
swatchPopup.IsOpen = true;
swatch.ResultChanged += SwatchResultChanged;
}
} else {
swatchPopup.IsOpen = false;
}
@ -95,6 +94,10 @@ namespace HavenSoft.HexManiac.WPF.Controls {
var newTileIndex = InteractionTileIndex;
var tilesToAnimate = ViewModel.HandleMove(oldTileIndex, newTileIndex);
if (oldTileIndex != newTileIndex) {
swatch.ResultChanged -= SwatchResultChanged;
swatchPopup.IsOpen = false;
}
foreach (var (index, direction) in tilesToAnimate) {
var tile = MainWindow.GetChild(ItemsControl, "PaletteColor", ViewModel.Elements[index]);