Skip to content

Commit 978b961

Browse files
Apply tools to all frames (#24)
1 parent c1a12ff commit 978b961

File tree

12 files changed

+102
-47
lines changed

12 files changed

+102
-47
lines changed

Pixed/Controls/MainWindowSections/ToolsSection.axaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
</controls:ToolRadioButton>
2929
<controls:ToolRadioButton Theme="{StaticResource ToolRadio}" Source="avares://Pixed/Resources/Icons/tools/tool-colorswap.png" Name="tool_colorswap" IsCheckedChanged="ToolRadioButton_IsCheckedChanged">
3030
<ToolTip.Tip>
31-
<controls:TooltipWithButton Title="Paint all pixels of the same color" ButtonText="Ctrl" ButtonTextHelper="Apply to all layers"/>
31+
<controls:TooltipWith2Buttons Title="Paint all pixels of the same color" ButtonText1="Ctrl" ButtonTextHelper1="Apply to all layers" ButtonText2="Shift" ButtonTextHelper2="Apply to all frames"/>
3232
</ToolTip.Tip>
3333
</controls:ToolRadioButton>
3434
<controls:ToolRadioButton Theme="{StaticResource ToolRadio}" Source="avares://Pixed/Resources/Icons/tools/tool-eraser.png" Name="tool_eraser" IsCheckedChanged="ToolRadioButton_IsCheckedChanged">
@@ -53,7 +53,7 @@
5353
</controls:ToolRadioButton>
5454
<controls:ToolRadioButton Theme="{StaticResource ToolRadio}" Source="avares://Pixed/Resources/Icons/tools/tool-move.png" Name="tool_move" IsCheckedChanged="ToolRadioButton_IsCheckedChanged">
5555
<ToolTip.Tip>
56-
<controls:TooltipWith2Buttons Title="Move tool" ButtonText1="Ctrl" ButtonTextHelper1="Apply to all layers" ButtonText2="Alt" ButtonTextHelper2="Wrap canvas borders"/>
56+
<controls:TooltipWith3Buttons Title="Move tool" ButtonText1="Ctrl" ButtonTextHelper1="Apply to all layers" ButtonText2="Shift" ButtonTextHelper2="Apply to all frames" ButtonText3="Alt" ButtonTextHelper3="Wrap canvas borders"/>
5757
</ToolTip.Tip>
5858
</controls:ToolRadioButton>
5959
<controls:ToolRadioButton Theme="{StaticResource ToolRadio}" Source="avares://Pixed/Resources/Icons/tools/tool-shape-select.png" Name="tool_shape_select" IsCheckedChanged="ToolRadioButton_IsCheckedChanged">

Pixed/Models/Frame.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,14 @@ public Layer AddLayer(Layer layer)
9696
return layer;
9797
}
9898

99+
public void RefreshLayerRenderSources()
100+
{
101+
foreach (var layer in _layers)
102+
{
103+
layer.Rerender();
104+
}
105+
}
106+
99107
public void RefreshRenderSource()
100108
{
101109
RenderSource = Render().ToAvaloniaBitmap();

Pixed/Models/Layer.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,12 @@ public void MergeLayers(Layer layer2)
114114
_needRerender = true;
115115
}
116116

117+
public void Rerender()
118+
{
119+
_needRerender = true;
120+
RefreshRenderSource();
121+
}
122+
117123
public void RefreshRenderSource()
118124
{
119125
RenderSource = Render().ToAvaloniaBitmap();

Pixed/Models/PixedModel.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Pixed.Services.History;
2+
using System;
23
using System.Collections.Generic;
34
using System.Collections.ObjectModel;
45
using System.Linq;
@@ -21,6 +22,28 @@ public PixedModel()
2122
_history = [];
2223
}
2324

25+
public void Process(bool allFrames, bool allLayers, Func<Frame, Layer, HistoryEntry?> action)
26+
{
27+
Frame[] frames = allFrames ? Frames.ToArray() : [Global.CurrentFrame];
28+
29+
foreach (Frame frame in frames)
30+
{
31+
Layer[] layers = allLayers ? frame.Layers.ToArray() : [Global.CurrentLayer];
32+
33+
foreach (Layer layer in layers)
34+
{
35+
var entry = action?.Invoke(frame, layer);
36+
37+
if(entry.HasValue && entry.Value.OldColor.Length > 0)
38+
{
39+
AddHistory(entry.Value);
40+
}
41+
}
42+
43+
Subjects.FrameModified.OnNext(frame);
44+
}
45+
}
46+
2447
public List<int> GetAllColors()
2548
{
2649
return [.. _frames.SelectMany(f => f.Layers).Select(l => l.GetPixels()).SelectMany(p => p).Where(p => p != UniColor.Transparent).Distinct().Order()];

Pixed/Subjects.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ internal static class Subjects
1111
public static Subject<object?> RefreshCanvas { get; } = new Subject<object?>();
1212

1313
public static Subject<Frame> FrameChanged { get; } = new Subject<Frame>();
14+
public static Subject<Frame> FrameModified { get; } = new Subject<Frame>();
1415
public static Subject<Frame> FrameAdded { get; } = new Subject<Frame>();
1516
public static Subject<Frame> FrameRemoved { get; } = new Subject<Frame>();
1617

Pixed/Tools/ToolColorSwap.cs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,25 @@ public override void ApplyTool(int x, int y, Frame frame, ref Bitmap overlay)
1616
var newColor = GetToolColor();
1717

1818
bool allLayers = Keyboard.Modifiers.HasFlag(Avalonia.Input.KeyModifiers.Control);
19+
bool allFrames = Keyboard.Modifiers.HasFlag(Avalonia.Input.KeyModifiers.Shift);
1920

20-
SwapColors(oldColor, newColor, allLayers);
21+
SwapColors(oldColor, newColor, allLayers, allFrames);
2122
Subjects.RefreshCanvas.OnNext(null);
2223
}
2324
}
2425

25-
private void SwapColors(int oldColor, int newColor, bool allLayers)
26+
private void SwapColors(int oldColor, int newColor, bool allLayers, bool allFrames)
2627
{
27-
Frame frame = Global.CurrentFrame;
28-
Layer[] layers = allLayers ? frame.Layers.ToArray() : [Global.CurrentLayer];
29-
30-
foreach (Layer layer in layers)
28+
Global.CurrentModel.Process(allFrames, allLayers, (frame, layer) =>
3129
{
3230
DynamicHistoryEntry entry = new()
3331
{
3432
FrameId = frame.Id,
3533
LayerId = layer.Id
3634
};
3735
ApplyToolOnLayer(layer, oldColor, newColor, ref entry);
38-
Global.CurrentModel.AddHistory(entry.ToEntry());
39-
}
36+
return entry.ToEntry();
37+
});
4038
}
4139

4240
private void ApplyToolOnLayer(Layer layer, int oldColor, int newColor, ref DynamicHistoryEntry historyEntry)

Pixed/Tools/ToolMove.cs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Pixed.Input;
22
using Pixed.Models;
3+
using Pixed.Services.History;
34
using System.Drawing;
45
using System.Linq;
56

@@ -28,18 +29,27 @@ public override void MoveTool(int x, int y, Frame frame, ref Bitmap overlay)
2829
ShiftLayer(frame.Layers[frame.SelectedLayer], _currentLayerClone, diffX, diffY);
2930
}
3031

31-
public override void ReleaseTool(int x, int y, Frame frame, ref Bitmap overlay)
32+
public override void ReleaseTool(int x, int y, Frame _, ref Bitmap overlay)
3233
{
3334
int diffX = x - _startX;
3435
int diffY = y - _startY;
3536

3637
bool ctrlKey = Keyboard.Modifiers.HasFlag(Avalonia.Input.KeyModifiers.Control);
37-
Layer[] layers = ctrlKey ? frame.Layers.ToArray() : [Global.CurrentLayer];
38+
bool shiftKey = Keyboard.Modifiers.HasFlag(Avalonia.Input.KeyModifiers.Control);
3839

39-
foreach (Layer layer in layers)
40+
Frame[] frames = shiftKey ? Global.CurrentModel.Frames.ToArray() : [Global.CurrentFrame];
41+
42+
foreach (Frame frame in frames)
4043
{
41-
var reference = this._currentLayer == layer ? this._currentLayerClone : layer.Clone();
42-
ShiftLayer(layer, reference, diffX, diffY);
44+
Layer[] layers = ctrlKey ? frame.Layers.ToArray() : [Global.CurrentLayer];
45+
46+
foreach (Layer layer in layers)
47+
{
48+
var reference = this._currentLayer == layer ? this._currentLayerClone : layer.Clone();
49+
ShiftLayer(layer, reference, diffX, diffY);
50+
}
51+
52+
Subjects.FrameModified.OnNext(frame);
4353
}
4454
}
4555

Pixed/Tools/Transform/AbstractTransformTool.cs

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,11 @@ public virtual void ApplyTransformation()
1616
}
1717
public virtual void ApplyTool(bool altKey, bool allFrames, bool allLayers)
1818
{
19-
var model = Global.CurrentModel;
20-
ObservableCollection<Frame> frames = allFrames ? model.Frames : [Global.CurrentFrame];
21-
22-
foreach (Frame frame in frames)
19+
Global.CurrentModel.Process(allFrames, allLayers, (frame, layer) =>
2320
{
24-
ObservableCollection<Layer> layers = allLayers ? frame.Layers : [Global.CurrentLayer];
25-
26-
foreach (Layer layer in layers)
27-
{
28-
ApplyToolOnLayer(layer, altKey);
29-
}
30-
}
21+
ApplyToolOnLayer(layer, altKey);
22+
return null;
23+
});
3124
}
3225

3326
public abstract void ApplyToolOnLayer(Layer layer, bool altKey);

Pixed/Tools/Transform/Crop.cs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,21 @@ internal class Crop : AbstractTransformTool
1010
{
1111
public override void ApplyTransformation()
1212
{
13-
14-
var layers = Getlayers();
15-
1613
int[] boundaries;
1714
if (Global.SelectionManager.HasSelection)
1815
{
1916
boundaries = TransformUtils.GetBoundariesFromSelection(Global.SelectionManager.Selection);
2017
}
2118
else
2219
{
23-
boundaries = TransformUtils.GetBoundaries([.. layers]);
20+
boundaries = TransformUtils.GetBoundaries([.. Global.CurrentFrame.Layers]);
2421
}
2522

26-
bool applied = ApplyTool(layers, boundaries);
23+
bool applied = ApplyTool(boundaries);
2724

2825
if (applied)
2926
{
3027
Subjects.RefreshCanvas.OnNext(null);
31-
Global.CurrentFrame.RefreshRenderSource();
32-
Subjects.FrameChanged.OnNext(Global.CurrentFrame);
3328
//TODO undo/redo
3429
}
3530
}
@@ -42,12 +37,7 @@ public override void ApplyToolOnLayer(Layer layer, bool altKey)
4237
throw new NotImplementedException();
4338
}
4439

45-
private static ObservableCollection<Layer> Getlayers()
46-
{
47-
return new ObservableCollection<Layer>(Global.CurrentModel.Frames.SelectMany(f => f.Layers));
48-
}
49-
50-
private static bool ApplyTool(ObservableCollection<Layer> layers, int[] boundaries)
40+
private static bool ApplyTool(int[] boundaries)
5141
{
5242
//return [minx, miny, maxx, maxy];
5343

@@ -65,14 +55,24 @@ private static bool ApplyTool(ObservableCollection<Layer> layers, int[] boundari
6555
return false;
6656
}
6757

68-
foreach (var layer in layers)
58+
foreach (var frame in Global.CurrentModel.Frames)
6959
{
70-
TransformUtils.MoveLayerFixes(layer, -boundaries[0], -boundaries[1]);
60+
foreach (var layer in frame.Layers)
61+
{
62+
TransformUtils.MoveLayerFixes(layer, -boundaries[0], -boundaries[1]);
63+
}
7164
}
72-
65+
7366
var newModel = ResizeUtils.ResizeModel(model, 1 + boundaries[2] - boundaries[0], 1 + boundaries[3] - boundaries[1], false, ResizeUtils.Origin.TopLeft);
7467
Subjects.SelectionDismissed.OnNext(null);
7568
Global.Models[Global.CurrentModelIndex] = newModel;
69+
70+
foreach(var frame in Global.CurrentModel.Frames)
71+
{
72+
frame.RefreshLayerRenderSources();
73+
frame.RefreshRenderSource();
74+
Subjects.FrameModified.OnNext(frame);
75+
}
7676
return true;
7777
}
7878
}

Pixed/ViewModels/FramesSectionViewModel.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,13 @@ public FramesSectionViewModel()
5151

5252
Subjects.FrameChanged.Subscribe(f =>
5353
{
54-
OnPropertyChanged(nameof(ViewModels.FramesSectionViewModel.Frames));
54+
OnPropertyChanged(nameof(Frames));
55+
});
56+
Subjects.FrameModified.Subscribe(f =>
57+
{
58+
f.RefreshRenderSource();
59+
Subjects.RefreshCanvas.OnNext(null);
60+
OnPropertyChanged(nameof(Frames));
5561
});
5662

5763
Subjects.FrameAdded.Subscribe(_ => RemoveFrameEnabled = Global.CurrentModel.Frames.Count != 1);

0 commit comments

Comments
 (0)