Skip to content

Commit 4d4c678

Browse files
author
Juan Segura
committed
Undo & Redo working in sprite editor
1 parent 63060b8 commit 4d4c678

5 files changed

Lines changed: 291 additions & 68 deletions

File tree

ZXBStudio/DocumentEditors/ZXGraphics/PaletteBuilderDialog.axaml

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
<Grid Grid.Row="3" Grid.ColumnDefinitions="Auto,*" Grid.RowDefinitions="Auto,Auto,Auto,Auto,Auto">
4848
<CheckBox Grid.Row="0" Name="chkUseCurrent" IsChecked="True" HorizontalAlignment="Right"/>
4949
<TextBlock Grid.Row="0" Grid.Column="1" Classes="dialog" VerticalAlignment="Center">Convert to current palette</TextBlock>
50-
50+
5151
<CheckBox Grid.Row="1" Name="chkAppend" IsChecked="False" HorizontalAlignment="Right"/>
5252
<TextBlock Grid.Row="1" Grid.Column="1" Classes="dialog" VerticalAlignment="Center">Append new colors to current palette</TextBlock>
5353

@@ -78,10 +78,12 @@
7878
<NumericUpDown Classes="dialog" Name="txtBlue" Minimum="0" Increment="36" Maximum="255" Width="60" VerticalAlignment="Center" Value="0"/>
7979
</Border>
8080

81-
<Border Grid.Row="1" Grid.Column="3" Grid.RowSpan="3" HorizontalAlignment="Center" VerticalAlignment="Center" BorderThickness="1" BorderBrush="Red">
81+
<Border Grid.Row="1" Grid.Column="3" Grid.RowSpan="2" HorizontalAlignment="Center" VerticalAlignment="Center" BorderThickness="1" BorderBrush="Red">
8282
<Grid Name="grdSelectedColor" Width="50" Height="50"></Grid>
8383
</Border>
8484

85+
<Button Name="btnColorPicker" Grid.Row="3" Grid.Column="8" IsVisible="False">Pick</Button>
86+
8587
<StackPanel Grid.Row="5" Grid.ColumnSpan="4" Orientation="Horizontal">
8688
<Button Name="btnResetPalette" Classes="dialog">Reset to default</Button>
8789
<Button Name="btnLoadPalette" Classes="dialog">Load palette</Button>
@@ -93,10 +95,21 @@
9395
<Button Name="btnRefresh" Classes="dialog" HorizontalAlignment="Right">Refresh</Button>
9496
<Button Grid.Row="2" Name="btnSaveImage" Classes="dialog" HorizontalAlignment="Right">Save image</Button>
9597
</Grid>
96-
98+
9799
<StackPanel Grid.Row="4" Grid.ColumnSpan="5" Orientation="Horizontal" HorizontalAlignment="Right">
98100
<Button Name="btnClose" Classes="dialog">Close</Button>
99101
</StackPanel>
102+
103+
<Grid Name="grdColorPicker" Grid.ColumnSpan="5" Grid.RowSpan="5" IsVisible="False"
104+
Margin="10" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
105+
<Canvas x:Name="ColorWheelCanvas" Width="500" Height="500" Background="Black"
106+
HorizontalAlignment="Center" VerticalAlignment="Center"
107+
PointerPressed="ColorWheelCanvas_PointerPressed"/>
108+
<Border Width="100" Height="30" Background="White"
109+
HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10">
110+
<Rectangle x:Name="SelectedColorPreview" Fill="Transparent"/>
111+
</Border>
112+
</Grid>
100113

101114
</Grid>
102115
</Window>

ZXBStudio/DocumentEditors/ZXGraphics/PaletteBuilderDialog.axaml.cs

Lines changed: 172 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
using Avalonia.Controls.Shapes;
3434
using static CommunityToolkit.Mvvm.ComponentModel.__Internals.__TaskExtensions.TaskAwaitableWithoutEndValidation;
3535
using FFmpeg.AutoGen;
36+
using System.Diagnostics;
3637

3738
namespace ZXBasicStudio.DocumentEditors.ZXGraphics
3839
{
@@ -44,6 +45,7 @@ public partial class PaletteBuilderDialog : Window, IDisposable
4445

4546
private Rectangle[] rectangulos = new Rectangle[256];
4647
private PaletteColor[] palette = null;
48+
private PaletteColor[] palette512 = null;
4749
private string sourceFile = null;
4850
private string convertedFile = null;
4951
private bool imgSourceLoaded = false;
@@ -68,8 +70,9 @@ public PaletteBuilderDialog()
6870

6971
// Set the palette
7072
palette = ServiceLayer.GetPalette(GraphicsModes.Next);
71-
selectedColorIndex = 0;
73+
selectedColorIndex = 0;
7274
DrawPalette();
75+
DrawColorPicker();
7376

7477
btnFileSource.Tapped += BtnFileSource_Tapped;
7578
btnResetPalette.Click += BtnResetPalette_Click;
@@ -85,7 +88,10 @@ public PaletteBuilderDialog()
8588
btnRefresh.Click += BtnRefresh_Click;
8689
btnSaveImage.Click += BtnSaveImage_Click;
8790

91+
btnColorPicker.Click += BtnColorPicker_Click;
92+
8893
btnClose.Click += BtnClose_Click;
94+
8995
}
9096

9197

@@ -893,5 +899,170 @@ private void CrearPaletaGPL9bits()
893899
}
894900

895901
#endregion
902+
903+
904+
#region Color Picker
905+
906+
private int Circles = 8; //16;
907+
private int Sectors = 32;
908+
private double Radius = 200;
909+
910+
private void BtnColorPicker_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
911+
{
912+
grdColorPicker.IsVisible = true;
913+
}
914+
915+
916+
private void DrawColorPicker()
917+
{
918+
Create512Palette();
919+
920+
ColorWheelCanvas.Children.Clear();
921+
double ringWidth = Radius / Circles;
922+
double angleStep = 360.0 / Sectors;
923+
double cx = Radius;
924+
double cy = Radius;
925+
926+
for (int circle = 0; circle < Circles; circle++)
927+
{
928+
double r1 = ringWidth * circle;
929+
double r2 = ringWidth * (circle + 1);
930+
double value = (circle + 1) / (double)Circles;
931+
932+
for (int sector = 0; sector < Sectors; sector++)
933+
{
934+
double hue = sector * angleStep;
935+
Color color = FromHSV(hue, 1.0, value);
936+
int idx=ServiceLayer.GetColor(color.R, color.G, color.B, palette512, 5);
937+
var p = palette512[idx];
938+
var color512=Color.FromRgb(p.Red, p.Green, p.Blue);
939+
DrawSegment(cx, cy, r1, r2, hue, angleStep, color512);
940+
}
941+
}
942+
}
943+
944+
private void DrawSegment(double cx, double cy, double r1, double r2, double startAngle, double angleSize, Color color)
945+
{
946+
var startRad = Math.PI * startAngle / 180.0;
947+
var endRad = Math.PI * (startAngle + angleSize) / 180.0;
948+
949+
var p1 = new Point(cx + r1 * Math.Cos(startRad), cy + r1 * Math.Sin(startRad));
950+
var p2 = new Point(cx + r2 * Math.Cos(startRad), cy + r2 * Math.Sin(startRad));
951+
var p3 = new Point(cx + r2 * Math.Cos(endRad), cy + r2 * Math.Sin(endRad));
952+
var p4 = new Point(cx + r1 * Math.Cos(endRad), cy + r1 * Math.Sin(endRad));
953+
954+
var path = new Avalonia.Controls.Shapes.Path
955+
{
956+
Fill = new SolidColorBrush(color),
957+
StrokeThickness = 0,
958+
Data = new PathGeometry
959+
{
960+
Figures = new PathFigures
961+
{
962+
new PathFigure
963+
{
964+
StartPoint = p1,
965+
Segments = new PathSegments
966+
{
967+
new LineSegment { Point = p2 },
968+
new ArcSegment
969+
{
970+
Point = p3,
971+
Size = new Size(r2, r2),
972+
SweepDirection = SweepDirection.Clockwise,
973+
IsLargeArc = angleSize > 180
974+
},
975+
new LineSegment { Point = p4 },
976+
new ArcSegment
977+
{
978+
Point = p1,
979+
Size = new Size(r1, r1),
980+
SweepDirection = SweepDirection.CounterClockwise,
981+
IsLargeArc = angleSize > 180
982+
}
983+
}
984+
}
985+
}
986+
}
987+
};
988+
989+
ColorWheelCanvas.Children.Add(path);
990+
}
991+
992+
private void ColorWheelCanvas_PointerPressed(object? sender, PointerPressedEventArgs e)
993+
{
994+
var pos = e.GetPosition(ColorWheelCanvas);
995+
double dx = pos.X - Radius;
996+
double dy = pos.Y - Radius;
997+
double distance = Math.Sqrt(dx * dx + dy * dy);
998+
if (distance > Radius) return;
999+
1000+
double angle = Math.Atan2(dy, dx) * 180 / Math.PI;
1001+
if (angle < 0) angle += 360;
1002+
1003+
int sector = (int)(angle / (360.0 / Sectors));
1004+
int circle = (int)(distance / (Radius / Circles));
1005+
1006+
double hue = sector * (360.0 / Sectors);
1007+
double value = (circle + 1) / (double)Circles;
1008+
Color color = FromHSV(hue, 1.0, value);
1009+
1010+
SelectedColorPreview.Fill = new SolidColorBrush(color);
1011+
}
1012+
1013+
private static Color FromHSV(double hue, double saturation, double value)
1014+
{
1015+
double c = value * saturation;
1016+
double x = c * (1 - Math.Abs((hue / 60.0 % 2) - 1));
1017+
double m = value - c;
1018+
1019+
double r = 0, g = 0, b = 0;
1020+
1021+
if (hue < 60) { r = c; g = x; }
1022+
else if (hue < 120) { r = x; g = c; }
1023+
else if (hue < 180) { g = c; b = x; }
1024+
else if (hue < 240) { g = x; b = c; }
1025+
else if (hue < 300) { r = x; b = c; }
1026+
else { r = c; b = x; }
1027+
1028+
byte R = (byte)((r + m) * 255);
1029+
byte G = (byte)((g + m) * 255);
1030+
byte B = (byte)((b + m) * 255);
1031+
1032+
return Color.FromRgb(R, G, B);
1033+
}
1034+
1035+
private void Create512Palette()
1036+
{
1037+
palette512 = new PaletteColor[512];
1038+
for (int i = 0; i < 512; i++)
1039+
{
1040+
int r = ((i & 0b111000000) >> 6)*36;
1041+
int g = ((i & 0b000111000) >> 3)*36;
1042+
int b = (i & 0b000000111)*36;
1043+
if (r > 250)
1044+
{
1045+
r = 255;
1046+
}
1047+
if (g > 250)
1048+
{
1049+
g = 255;
1050+
}
1051+
if (b > 250)
1052+
{
1053+
b = 255;
1054+
}
1055+
1056+
palette512[i] = new PaletteColor()
1057+
{
1058+
Red = (byte)r,
1059+
Green = (byte)g,
1060+
Blue = (byte)b,
1061+
HasPriority = false
1062+
};
1063+
}
1064+
}
1065+
1066+
#endregion
8961067
}
8971068
}

ZXBStudio/DocumentEditors/ZXGraphics/SpriteEditor.axaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@
2727
<Grid Grid.Column="2" Grid.Row="1" RowDefinitions="Auto,*,Auto">
2828
<WrapPanel Orientation="Horizontal" Grid.ColumnSpan="5" Margin="10" Background="#ff202020" Height="NaN">
2929

30-
<Button Classes="toolbar" Name="btnUndo" ToolTip.Tip="Undo last action" IsEnabled="False">
30+
<Button Classes="toolbar" Name="btnUndo" ToolTip.Tip="Undo last action">
3131
<svg:Svg Path="/Svg/undo.svg"></svg:Svg>
3232
</Button>
33-
<Button Classes="toolbar" Name="btnRedo" ToolTip.Tip="Redo last action" IsEnabled="False">
33+
<Button Classes="toolbar" Name="btnRedo" ToolTip.Tip="Redo last action" >
3434
<svg:Svg Path="/Svg/redo.svg"></svg:Svg>
3535
</Button>
3636

ZXBStudio/DocumentEditors/ZXGraphics/SpriteEditor.axaml.cs

Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -262,37 +262,7 @@ private void _Initialize(string fileName)
262262
Sprite[] sprites = dataS.Deserializar<Sprite[]>();
263263

264264
foreach (var sprite in sprites)
265-
{
266-
/*
267-
// Check attributes for ZX Spectrum mode
268-
if (sprite != null && sprite.GraphicMode == GraphicsModes.ZXSpectrum)
269-
{
270-
// Force ZX Spectrum palette
271-
sprite.Palette = ServiceLayer.GetPalette(GraphicsModes.ZXSpectrum);
272-
foreach (var pattern in sprite.Patterns)
273-
{
274-
int cW = sprite.Width / 8;
275-
int cH = sprite.Height / 8;
276-
int l = cW * cH;
277-
if (pattern.Attributes == null)
278-
{
279-
pattern.Attributes = new AttributeColor[cW * cH];
280-
for (int n = 0; n < pattern.Attributes.Length; n++)
281-
{
282-
pattern.Attributes[n] = new AttributeColor()
283-
{
284-
Ink = 1,
285-
Paper = 0
286-
};
287-
}
288-
}
289-
if (pattern.Attributes.Length != l)
290-
{
291-
pattern.Attributes = pattern.Attributes.Take(l).ToArray();
292-
}
293-
}
294-
}
295-
*/
265+
{
296266
// Check attributes for ZX Spectrum mode
297267
if (sprite != null && sprite.Patterns != null)
298268
{
@@ -357,7 +327,7 @@ private void _Initialize(string fileName)
357327
btnRedo.Tapped += BtnRedo_Tapped;
358328
btnInvertColorsCell.Tapped += BtnInvertColorsCell_Tapped;
359329
btnInvertPixelsCell.Tapped += BtnInvertPixelsCell_Tapped;
360-
330+
361331
Refresh();
362332

363333
if (SpritePatternsList.Count > 1)
@@ -1062,13 +1032,13 @@ private void BtnInvertColorsCell_Tapped(object? sender, TappedEventArgs e)
10621032

10631033
private void BtnRedo_Tapped(object? sender, TappedEventArgs e)
10641034
{
1065-
1035+
ctrlEditor.Redo();
10661036
}
10671037

10681038

10691039
private void BtnUndo_Tapped(object? sender, TappedEventArgs e)
10701040
{
1071-
1041+
ctrlEditor.Undo();
10721042
}
10731043

10741044
#endregion

0 commit comments

Comments
 (0)