Skip to content

Commit fa93b52

Browse files
author
David Khristepher Santos
committed
Improved selection drawing
1 parent f2fba01 commit fa93b52

File tree

6 files changed

+264
-85
lines changed

6 files changed

+264
-85
lines changed

PSXPackagerGUI/Controls/AutoDisableImage.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ protected override void OnRender(DrawingContext dc)
3737

3838
}
3939

40-
dc.DrawImage(bitmapSource, new Rect(new Point(), RenderSize));
40+
dc.DrawImage(bitmapSource, new Rect(new System.Windows.Point(), RenderSize));
4141
}
4242
}
4343
}

PSXPackagerGUI/Controls/Point.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using PSXPackagerGUI.Models;
2+
3+
namespace PSXPackagerGUI.Controls;
4+
5+
public class Point : BaseNotifyModel
6+
{
7+
private double _x;
8+
private double _y;
9+
10+
public double X
11+
{
12+
get => _x;
13+
set => SetProperty(ref _x, value);
14+
}
15+
16+
public double Y
17+
{
18+
get => _y;
19+
set => SetProperty(ref _y, value);
20+
}
21+
}

PSXPackagerGUI/Controls/ResourceControl.xaml

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
<Button Grid.Column="2" x:Name="MoreButton" IsEnabled="{Binding IsEnabled, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl, AncestorLevel=1}}" Click="More_OnClick">...</Button>
5252
</Grid>
5353

54-
<Grid Grid.Row="1" Grid.Column="0">
54+
<Grid x:Name="Grid" Tag="{Binding .}" Grid.Row="1" Grid.Column="0" MouseDown="UIElement_OnMouseDown" MouseMove="UIElement_OnMouseMove" MouseUp="UIElement_OnMouseUp">
5555
<Grid.Background>
5656
<DrawingBrush TileMode="Tile"
5757
Viewport="0,0,16,16"
@@ -68,30 +68,60 @@
6868
</DrawingBrush.Drawing>
6969
</DrawingBrush>
7070
</Grid.Background>
71-
<Border Tag="{Binding .}" Width="{Binding Composite.Width}" Height="{Binding Composite.Height}" BorderThickness="1" BorderBrush="#000000"
71+
<Grid.ContextMenu>
72+
<ContextMenu IsEnabled="{Binding PlacementTarget.Tag.Composite.HasLayers, RelativeSource={RelativeSource Self}}">
73+
<MenuItem Header="Fit to bounds"></MenuItem>
74+
<MenuItem Header="Fit to width"></MenuItem>
75+
<MenuItem Header="Fit to height"></MenuItem>
76+
<Separator></Separator>
77+
<MenuItem Header="Insert image layer" Click="InsertImageLayer_OnClick"></MenuItem>
78+
<MenuItem Header="Insert text layer" Click="InsertTextLayer_OnClick"></MenuItem>
79+
<MenuItem Header="Remove layer" Click="RemoveLayer_OnClick"></MenuItem>
80+
<Separator></Separator>
81+
<MenuItem Header="Move up" Click="MoveUpLayer_OnClick"></MenuItem>
82+
<MenuItem Header="Move down" Click="MoveDownLayer_OnClick"></MenuItem>
83+
<Separator></Separator>
84+
<MenuItem Header="Reset layer" Click="ResetLayer_OnClick"></MenuItem>
85+
</ContextMenu>
86+
</Grid.ContextMenu>
87+
<Border Width="{Binding Composite.Width}" Height="{Binding Composite.Height}" BorderThickness="1" BorderBrush="#000000"
7288
Focusable="True"
7389
KeyboardNavigation.IsTabStop="True"
7490
PreviewKeyDown="ResourceControl_OnPreviewKeyDown"
7591
MouseDown="Border_OnMouseDown"
7692
>
77-
<Border.ContextMenu>
78-
<ContextMenu IsEnabled="{Binding PlacementTarget.Tag.Composite.HasLayers, RelativeSource={RelativeSource Self}}">
79-
<MenuItem Header="Insert Image Layer" Click="InsertImageLayer_OnClick"></MenuItem>
80-
<MenuItem Header="Insert Text Layer" Click="InsertTextLayer_OnClick"></MenuItem>
81-
<MenuItem Header="Remove Layer" Click="RemoveLayer_OnClick"></MenuItem>
82-
<MenuItem Header="Replace Layer" Click="ReplaceLayer_OnClick"></MenuItem>
83-
<Separator></Separator>
84-
<MenuItem Header="Move up" Click="MoveUpLayer_OnClick"></MenuItem>
85-
<MenuItem Header="Move down" Click="MoveDownLayer_OnClick"></MenuItem>
86-
<Separator></Separator>
87-
<MenuItem Header="Reset Layer" Click="ResetLayer_OnClick"></MenuItem>
88-
</ContextMenu>
89-
</Border.ContextMenu>
90-
<Grid>
91-
<Image Stretch="None" VerticalAlignment="Center" Source="{Binding Composite.CompositeBitmap}" AllowDrop="True" MouseDown="UIElement_OnMouseDown" MouseMove="UIElement_OnMouseMove" MouseUp="UIElement_OnMouseUp" ></Image>
92-
<Image Stretch="None" VerticalAlignment="Center" Source="{Binding Composite.SelectionBitmap}" IsHitTestVisible="False"></Image>
93-
</Grid>
93+
<Image Stretch="None" VerticalAlignment="Center" Source="{Binding Composite.CompositeBitmap}" AllowDrop="True"></Image>
9494
</Border>
95+
<Canvas DataContext="{Binding Selection, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl, AncestorLevel=1}}"
96+
Visibility="{Binding Visibility}"
97+
ClipToBounds="True"
98+
IsHitTestVisible="False"
99+
>
100+
<Line X1="{Binding E1.X}" Y1="{Binding E1.Y}" X2="{Binding E2.X}" Y2="{Binding E2.Y}" Stroke="#70A0FF"></Line>
101+
<Line X1="{Binding E2.X}" Y1="{Binding E2.Y}" X2="{Binding E3.X}" Y2="{Binding E3.Y}" Stroke="#70A0FF"></Line>
102+
<Line X1="{Binding E3.X}" Y1="{Binding E3.Y}" X2="{Binding E4.X}" Y2="{Binding E4.Y}" Stroke="#70A0FF"></Line>
103+
<Line X1="{Binding E4.X}" Y1="{Binding E4.Y}" X2="{Binding E1.X}" Y2="{Binding E1.Y}" Stroke="#70A0FF"></Line>
104+
<Rectangle
105+
Canvas.Left="{Binding C1.X}"
106+
Canvas.Top="{Binding C1.Y}"
107+
Width="5" Height="5" Fill="White" Stroke="#70A0FF">
108+
</Rectangle>
109+
<Rectangle
110+
Canvas.Left="{Binding C2.X}"
111+
Canvas.Top="{Binding C2.Y}"
112+
Width="5" Height="5" Fill="White" Stroke="#70A0FF">
113+
</Rectangle>
114+
<Rectangle
115+
Canvas.Left="{Binding C3.X}"
116+
Canvas.Top="{Binding C3.Y}"
117+
Width="5" Height="5" Fill="White" Stroke="#70A0FF">
118+
</Rectangle>
119+
<Rectangle
120+
Canvas.Left="{Binding C4.X}"
121+
Canvas.Top="{Binding C4.Y}"
122+
Width="5" Height="5" Fill="White" Stroke="#70A0FF">
123+
</Rectangle>
124+
</Canvas>
95125
</Grid>
96126

97127
<Grid Grid.Row="1" Grid.Column="0">

PSXPackagerGUI/Controls/ResourceControl.xaml.cs

Lines changed: 109 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using Popstation.Pbp;
33
using PSXPackagerGUI.Models.Resource;
44
using PSXPackagerGUI.Pages;
5+
using PSXPackagerGUI.Templates;
56
using System;
67
using System.ComponentModel;
78
using System.IO;
@@ -11,10 +12,12 @@
1112
using System.Windows.Controls;
1213
using System.Windows.Input;
1314
using System.Windows.Media;
15+
using ImageLayer = PSXPackagerGUI.Models.Resource.ImageLayer;
16+
using Layer = PSXPackagerGUI.Models.Resource.Layer;
17+
using TextLayer = PSXPackagerGUI.Models.Resource.TextLayer;
1418

1519
namespace PSXPackagerGUI.Controls
1620
{
17-
1821
/// <summary>
1922
/// Interaction logic for Resource.xaml
2023
/// </summary>
@@ -90,9 +93,21 @@ public string Text
9093
}
9194
}
9295

96+
public Selection? Selection
97+
{
98+
get => _selection;
99+
set
100+
{
101+
_selection = value;
102+
OnPropertyChanged();
103+
}
104+
}
105+
93106
public ResourceControl()
94107
{
95108
InitializeComponent();
109+
Selection = new Selection();
110+
SizeChanged += (s, e) => UpdateSelection();
96111
}
97112

98113
private void More_OnClick(object sender, RoutedEventArgs e)
@@ -118,10 +133,7 @@ public Layer? SelectedLayer
118133
{
119134
get => _selectedLayer;
120135
set { _selectedLayer = value;
121-
if (Resource.Composite != null)
122-
{
123-
Resource.Composite.SelectedLayer = _selectedLayer;
124-
}
136+
UpdateSelection();
125137
OnPropertyChanged();
126138
}
127139
}
@@ -131,6 +143,50 @@ public Layer? SelectedLayer
131143
private Layer? _selectedLayer;
132144
private bool resizeMode;
133145
private bool dragStarted;
146+
private Selection? _selection;
147+
148+
private void UpdateSelection()
149+
{
150+
if (SelectedLayer == null)
151+
{
152+
Selection.Visibility = Visibility.Hidden;
153+
return;
154+
}
155+
156+
Selection.Visibility = Visibility.Visible;
157+
var offsetX = (Grid.ActualWidth - Resource.Composite.Width) / 2;
158+
var offsetY = (Grid.ActualHeight - Resource.Composite.Height) / 2;
159+
160+
var left = offsetX + SelectedLayer.OffsetX;
161+
var top = offsetY + SelectedLayer.OffsetY;
162+
var width = SelectedLayer.Width;
163+
var height = SelectedLayer.Height;
164+
165+
Selection.C1.X = left - 2;
166+
Selection.C1.Y = top - 2;
167+
168+
Selection.C2.X = left + width - 2;
169+
Selection.C2.Y = top - 2;
170+
171+
Selection.C3.X = left + width - 2;
172+
Selection.C3.Y = top + height - 2;
173+
174+
Selection.C4.X = left - 2;
175+
Selection.C4.Y = top + height - 2;
176+
177+
Selection.E1.X = left;
178+
Selection.E1.Y = top;
179+
180+
Selection.E2.X = left + width;
181+
Selection.E2.Y = top;
182+
183+
Selection.E3.X = left + width;
184+
Selection.E3.Y = top + height;
185+
186+
Selection.E4.X = left;
187+
Selection.E4.Y = top + height;
188+
189+
}
134190

135191
private void UIElement_OnMouseDown(object sender, MouseButtonEventArgs e)
136192
{
@@ -160,13 +216,18 @@ private void UIElement_OnMouseDown(object sender, MouseButtonEventArgs e)
160216

161217
var slayer = SelectedLayer;
162218

219+
var offsetX = (Grid.ActualWidth - Resource.Composite.Width) / 2;
220+
var offsetY = (Grid.ActualHeight - Resource.Composite.Height) / 2;
221+
222+
163223
if (slayer != null)
164224
{
165-
var cornerX = slayer.OffsetX + slayer.Width;
166-
var cornerY = slayer.OffsetY + slayer.Height;
167225

168-
if (pos.X >= cornerX - 2 && pos.X <= cornerX + 2 &&
169-
pos.Y >= cornerY - 2 && pos.Y <= cornerY + 2)
226+
var cornerX = offsetX + slayer.OffsetX + slayer.Width;
227+
var cornerY = offsetY + slayer.OffsetY + slayer.Height;
228+
229+
if (pos.X >= cornerX - 4 && pos.X <= cornerX + 4 &&
230+
pos.Y >= cornerY - 4 && pos.Y <= cornerY + 4)
170231
{
171232
resizeMode = true;
172233
}
@@ -177,11 +238,10 @@ private void UIElement_OnMouseDown(object sender, MouseButtonEventArgs e)
177238
{
178239
foreach (var layer in Resource.Composite.Layers.Reverse())
179240
{
180-
if (pos.X >= layer.OffsetX && pos.X <= layer.OffsetX + layer.Width &&
181-
pos.Y >= layer.OffsetY && pos.Y <= layer.OffsetY + layer.Height)
241+
if (pos.X >= offsetX + layer.OffsetX && pos.X <= offsetX + layer.OffsetX + layer.Width &&
242+
pos.Y >= offsetY + layer.OffsetY && pos.Y <= offsetY + layer.OffsetY + layer.Height)
182243
{
183244
SelectedLayer = layer;
184-
Resource.RefreshIcon();
185245
break;
186246
}
187247
}
@@ -218,7 +278,7 @@ private void UIElement_OnMouseMove(object sender, MouseEventArgs e)
218278

219279
if (resizeMode || dragStarted)
220280
{
221-
Resource.Composite.Render();
281+
UpdateSelection();
222282
Resource.RefreshIcon();
223283
}
224284
}
@@ -243,7 +303,6 @@ private void Layer_OnMouseDown(object sender, MouseButtonEventArgs e)
243303
Resource.RefreshIcon();
244304
}
245305
}
246-
Resource.RefreshIcon();
247306
}
248307

249308
private void MoveDownLayer_OnClick(object sender, RoutedEventArgs e)
@@ -270,6 +329,7 @@ private void AppendImageLayer_OnClick(object sender, RoutedEventArgs e)
270329
Resource.Composite.AddLayer(newLayer);
271330

272331
SelectedLayer = newLayer;
332+
UpdateSelection();
273333
Resource.RefreshIcon();
274334
}
275335

@@ -292,6 +352,7 @@ private void AppendTextLayer_OnClick(object sender, RoutedEventArgs e)
292352
Resource.Composite.AddLayer(newLayer);
293353

294354
SelectedLayer = newLayer;
355+
UpdateSelection();
295356
Resource.RefreshIcon();
296357
}
297358
}
@@ -308,11 +369,41 @@ private void InsertImageLayer_OnClick(object sender, RoutedEventArgs e)
308369
return;
309370

310371
using var stream = new FileStream(openFileDialog.FileName, FileMode.Open, FileAccess.Read);
311-
var newLayer = new ImageLayer(ImageProcessing.GetBitmapImage(stream), "image", openFileDialog.FileName);
372+
373+
var image = ImageProcessing.GetBitmapImage(stream);
374+
375+
double scale = Math.Min(
376+
(double)Resource.Composite.Width / image.PixelWidth,
377+
(double)Resource.Composite.Height / image.PixelHeight);
378+
379+
int width = image.PixelWidth;
380+
int height = image.PixelHeight;
381+
382+
if (scale >= 1)
383+
{
384+
var resizeResult = MessageBox.Show(App.Current.MainWindow,
385+
"The selected image is larger than the content area. Do you want to resize it to fit?",
386+
"Load image", MessageBoxButton.YesNoCancel);
387+
388+
if (resizeResult == MessageBoxResult.Yes)
389+
{
390+
width = (int)(width * scale);
391+
height = (int)(width * scale);
392+
393+
}
394+
}
395+
396+
var newLayer = new Models.Resource.ImageLayer(image, "image", openFileDialog.FileName);
397+
398+
newLayer.Width = width;
399+
newLayer.Height = height;
400+
newLayer.OriginalWidth = width;
401+
newLayer.OriginalHeight = height;
312402

313403
Resource.Composite.InsertLayerAfter(newLayer, layer);
314404

315405
SelectedLayer = newLayer;
406+
UpdateSelection();
316407
Resource.RefreshIcon();
317408
}
318409
}
@@ -338,6 +429,7 @@ private void InsertTextLayer_OnClick(object sender, RoutedEventArgs e)
338429
Resource.Composite.InsertLayerAfter(newLayer, layer);
339430

340431
SelectedLayer = newLayer;
432+
UpdateSelection();
341433
Resource.RefreshIcon();
342434
}
343435
}
@@ -352,6 +444,7 @@ private void RemoveLayer_OnClick(object sender, RoutedEventArgs e)
352444
{
353445
SelectedLayer = null;
354446
}
447+
UpdateSelection();
355448
Resource.RefreshIcon();
356449
}
357450
}
@@ -378,6 +471,7 @@ private void ResetLayer_OnClick(object sender, RoutedEventArgs e)
378471
if (Resource.Composite != null && TryGetLayer(sender, out var layer))
379472
{
380473
layer.Reset();
474+
UpdateSelection();
381475
Resource.RefreshIcon();
382476
}
383477

0 commit comments

Comments
 (0)