Skip to content

Commit 1e4b09d

Browse files
committed
add better line drawing (click, then shift down and click again), fix offset issues for custom resolutions
1 parent 5120e16 commit 1e4b09d

File tree

1 file changed

+144
-100
lines changed

1 file changed

+144
-100
lines changed

PixelArtTool/MainWindow.xaml.cs

Lines changed: 144 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ public partial class MainWindow : Window, INotifyPropertyChanged
2929
int canvasResolutionY = 16;
3030
int paletteResolutionX = 4;
3131
int paletteResolutionY = 16;
32-
int canvasScaleX = 1;
32+
float canvasScaleX = 1;
3333
int paletteScaleX = 1;
3434
int paletteScaleY = 1;
3535
int dpiX = 96;
3636
int dpiY = 96;
37-
byte gridAlpha = 16;
37+
byte gridAlpha = 32;
3838

3939
// simple undo
4040
Stack<WriteableBitmap> undoStack = new Stack<WriteableBitmap>();
@@ -53,14 +53,9 @@ public partial class MainWindow : Window, INotifyPropertyChanged
5353
int prevY;
5454

5555
// drawing lines
56-
bool firstPixel = true;
57-
int startPixelX = 0;
58-
int startPixelY = 0;
59-
bool verticalLine = false;
60-
bool horizontalLine = false;
61-
bool diagonalLine = false;
62-
int lockedX = 0;
63-
int lockedY = 0;
56+
bool leftShiftDown = false;
57+
private readonly int ddaMODIFIER_X = 0x7fff;
58+
private readonly int ddaMODIFIER_Y = 0x7fff;
6459

6560
// smart fill with double click
6661
bool wasDoubleClick = false;
@@ -105,8 +100,7 @@ public bool IsModified
105100
{
106101
window.Title = window.Title + "*";
107102
}
108-
}
109-
else // not modified, remove mark
103+
} else // not modified, remove mark
110104
{
111105
if (window.Title.IndexOf("*") > -1)
112106
{
@@ -143,7 +137,7 @@ void Start()
143137
// build drawing area
144138
canvasBitmap = new WriteableBitmap(canvasResolutionX, canvasResolutionY, dpiX, dpiY, PixelFormats.Bgra32, null);
145139
drawingImage.Source = canvasBitmap;
146-
canvasScaleX = (int)drawingImage.Width / canvasResolutionX;
140+
canvasScaleX = (float)drawingImage.Width / (float)canvasResolutionX;
147141

148142
// setup outline bitmap
149143
outlineBitmap = new WriteableBitmap(canvasResolutionX, canvasResolutionY, dpiX, dpiY, PixelFormats.Bgra32, null);
@@ -199,71 +193,6 @@ void DrawPixel(int x, int y)
199193
if (x < 0 || x > canvasResolutionX - 1) return;
200194
if (y < 0 || y > canvasResolutionY - 1) return;
201195

202-
// is using straight lines
203-
if (leftShiftDown == true)
204-
{
205-
// get first pixel, to measure direction
206-
if (firstPixel == true)
207-
{
208-
startPixelX = x;
209-
startPixelY = y;
210-
firstPixel = false;
211-
}
212-
else // already drew before
213-
{
214-
// have detected linemode
215-
if (horizontalLine == false && verticalLine == false && diagonalLine == false)
216-
{
217-
// vertical
218-
if (x == startPixelX && y != startPixelY)
219-
{
220-
verticalLine = true;
221-
lockedX = x;
222-
}
223-
// horizontal
224-
else if (y == startPixelY && x != startPixelX)
225-
{
226-
horizontalLine = true;
227-
lockedY = y;
228-
}
229-
// diagonal
230-
else if (y != startPixelY && x != startPixelX)
231-
{
232-
diagonalLine = true;
233-
}
234-
}
235-
236-
// lock coordinates if straight lines
237-
if (verticalLine == true)
238-
{
239-
x = lockedX;
240-
}
241-
else if (horizontalLine == true)
242-
{
243-
y = lockedY;
244-
}
245-
else if (diagonalLine == true)
246-
{
247-
// force diagonal
248-
int xx = x - startPixelX;
249-
int yy = y - startPixelY;
250-
251-
// stop drawing, if not in diagonal cell
252-
if (Math.Abs(xx) - Math.Abs(yy) != 0)
253-
{
254-
return;
255-
}
256-
}
257-
}
258-
}
259-
else // left shift not down
260-
{
261-
verticalLine = false;
262-
horizontalLine = false;
263-
diagonalLine = false;
264-
firstPixel = true;
265-
}
266-
267196
PixelColor draw = new PixelColor();
268197

269198
switch (blendMode)
@@ -472,8 +401,7 @@ void DrawingLeftButtonDown(object sender, MouseButtonEventArgs e)
472401
previousToolMode = CurrentTool;
473402
CurrentTool = ToolMode.Fill;
474403
wasDoubleClick = true;
475-
}
476-
else // keep old color
404+
} else // keep old color
477405
{
478406
previousPixelColor = GetPixel(x, y);
479407
}
@@ -482,7 +410,18 @@ void DrawingLeftButtonDown(object sender, MouseButtonEventArgs e)
482410
switch (CurrentTool)
483411
{
484412
case ToolMode.Draw:
413+
414+
// check if shift is down, then do line to previous point
415+
if (leftShiftDown == true)
416+
{
417+
//DrawLine(prevX, prevY, x, y);
418+
DrawLine(prevX, prevY, x, y);
419+
}
420+
485421
DrawPixel(x, y);
422+
prevX = x;
423+
prevY = y;
424+
486425
// mirror
487426
if (chkMirrorX.IsChecked == true)
488427
{
@@ -569,17 +508,15 @@ void DrawingAreaMouseMoved(object sender, MouseEventArgs e)
569508
break;
570509
}
571510

572-
}
573-
else if (e.RightButton == MouseButtonState.Pressed)
511+
} else if (e.RightButton == MouseButtonState.Pressed)
574512
{
575513
ErasePixel(x, y);
576514
// mirror
577515
if (chkMirrorX.IsChecked == true)
578516
{
579517
ErasePixel(canvasResolutionX - x, y);
580518
}
581-
}
582-
else if (e.MiddleButton == MouseButtonState.Pressed)
519+
} else if (e.MiddleButton == MouseButtonState.Pressed)
583520
{
584521
currentColor = GetPixel(x, y);
585522
ResetCurrentBrightnessPreview(currentColor);
@@ -594,11 +531,13 @@ void DrawingAreaMouseMoved(object sender, MouseEventArgs e)
594531
}
595532

596533
// snap preview rectangle to grid
597-
var left = x * canvasScaleX;
598-
var top = y * canvasScaleX;
534+
int fix = 256 / canvasResolutionX;
535+
var off = ((float)256 / (float)canvasResolutionX) - fix;
536+
var left = x * canvasScaleX + ((x * (16 / canvasResolutionX)) * (off > 0 ? 1 : 0));
537+
var top = y * canvasScaleX + ((y * (16 / canvasResolutionY)) * (off > 0 ? 1 : 0));
538+
599539
// NOTE: this causes palette pixels to distort/move?
600540
rectPixelPos.Margin = new Thickness(89 + left, 50 + top, 0, 0);
601-
602541
} // drawingareamousemoved
603542

604543
void ShowMousePos(int x, int y)
@@ -701,8 +640,7 @@ private void OnSaveButton(object sender, RoutedEventArgs e)
701640
{
702641
SaveImageAsPng(saveFile);
703642
IsModified = false;
704-
}
705-
else // save as
643+
} else // save as
706644
{
707645
if (saveFileDialog.ShowDialog() == true)
708646
{
@@ -751,7 +689,7 @@ private void OnModeSelectionChanged(object sender, SelectionChangedEventArgs e)
751689
blendMode = (BlendMode)s.SelectedIndex;
752690
}
753691

754-
bool leftShiftDown = false;
692+
755693

756694
// if key is pressed down globally
757695
void OnKeyDown(object sender, KeyEventArgs e)
@@ -807,10 +745,6 @@ private void OnKeyUp(object sender, KeyEventArgs e)
807745
case Key.LeftShift:
808746
lblToolInfo.Content = "";
809747
leftShiftDown = false;
810-
verticalLine = false;
811-
horizontalLine = false;
812-
diagonalLine = false;
813-
firstPixel = true;
814748
break;
815749
default:
816750
break;
@@ -1097,13 +1031,11 @@ void UpdateOutline()
10971031
if (centerPix == 0)
10981032
{
10991033
c.Alpha = 255;
1100-
}
1101-
else
1034+
} else
11021035
{
11031036
c.Alpha = 0;
11041037
}
1105-
}
1106-
else
1038+
} else
11071039
{
11081040
c.Alpha = 0;
11091041
}
@@ -1198,8 +1130,7 @@ private void chkOutline_Click(object sender, RoutedEventArgs e)
11981130
if (chkOutline.IsChecked == true)
11991131
{
12001132
UpdateOutline();
1201-
}
1202-
else // clear
1133+
} else // clear
12031134
{
12041135
ClearImage(outlineBitmap, emptyRect, emptyPixels, emptyStride);
12051136
}
@@ -1301,6 +1232,119 @@ private void OnHueRectangleMouseMoved(object sender, MouseEventArgs e)
13011232
if (rectHueBar.IsMouseOver == false) return;
13021233
if (e.LeftButton == MouseButtonState.Pressed) rectHueBar_MouseDown(null, null);
13031234
}
1235+
1236+
1237+
private void DrawLine(int startX, int startY, int endX, int endY)
1238+
{
1239+
int dx = endX - startX;
1240+
int dy = endY - startY;
1241+
1242+
int nx = Math.Abs(dx);
1243+
int ny = Math.Abs(dy);
1244+
1245+
// Calculate octant value
1246+
int octant = ((dy < 0) ? 4 : 0) | ((dx < 0) ? 2 : 0) | ((ny > nx) ? 1 : 0);
1247+
int move = 0;
1248+
int frac = 0;
1249+
int mn = Math.Max(nx, ny);
1250+
1251+
if (mn == 0)
1252+
{
1253+
//yield return new Coord(startX, startY);
1254+
//yield break;
1255+
return;
1256+
}
1257+
1258+
if (ny == 0)
1259+
{
1260+
if (dx > 0)
1261+
for (int x = startX; x <= endX; x++)
1262+
DrawPixel(x, startY);
1263+
//yield return new Coord(x, startY);
1264+
else
1265+
for (int x = startX; x >= endX; x--)
1266+
DrawPixel(x, startY);
1267+
//yield return new Coord(x, startY);
1268+
1269+
//yield break;
1270+
return;
1271+
}
1272+
1273+
if (nx == 0)
1274+
{
1275+
if (dy > 0)
1276+
for (int y = startY; y <= endY; y++)
1277+
DrawPixel(startX, y);
1278+
//yield return new Coord(startX, y);
1279+
else
1280+
for (int y = startY; y >= endY; y--)
1281+
DrawPixel(startX, y);
1282+
// yield return new Coord(startX, y);
1283+
1284+
// yield break;
1285+
return;
1286+
}
1287+
1288+
switch (octant)
1289+
{
1290+
case 0: // +x, +y
1291+
move = (ny << 16) / nx;
1292+
for (int primary = startX; primary <= endX; primary++, frac += move)
1293+
//yield return new Coord(primary, startY + ((frac + MODIFIER_Y) >> 16));
1294+
DrawPixel(primary, startY + ((frac + ddaMODIFIER_Y) >> 16));
1295+
break;
1296+
1297+
case 1:
1298+
move = (nx << 16) / ny;
1299+
for (int primary = startY; primary <= endY; primary++, frac += move)
1300+
//yield return new Coord(startX + ((frac + MODIFIER_X) >> 16), primary);
1301+
DrawPixel(startX + ((frac + ddaMODIFIER_X) >> 16), primary);
1302+
break;
1303+
1304+
case 2: // -x, +y
1305+
move = (ny << 16) / nx;
1306+
for (int primary = startX; primary >= endX; primary--, frac += move)
1307+
// yield return new Coord(primary, startY + ((frac + MODIFIER_Y) >> 16));
1308+
DrawPixel(primary, startY + ((frac + ddaMODIFIER_Y) >> 16));
1309+
break;
1310+
1311+
case 3:
1312+
move = (nx << 16) / ny;
1313+
for (int primary = startY; primary <= endY; primary++, frac += move)
1314+
// yield return new Coord(startX - ((frac + MODIFIER_X) >> 16), primary);
1315+
DrawPixel(startX - ((frac + ddaMODIFIER_X) >> 16), primary);
1316+
break;
1317+
1318+
case 6: // -x, -y
1319+
move = (ny << 16) / nx;
1320+
for (int primary = startX; primary >= endX; primary--, frac += move)
1321+
// yield return new Coord(primary, startY - ((frac + MODIFIER_Y) >> 16));
1322+
DrawPixel(primary, startY - ((frac + ddaMODIFIER_Y) >> 16));
1323+
break;
1324+
1325+
case 7:
1326+
move = (nx << 16) / ny;
1327+
for (int primary = startY; primary >= endY; primary--, frac += move)
1328+
// yield return new Coord(startX - ((frac + MODIFIER_X) >> 16), primary);
1329+
DrawPixel(startX - ((frac + ddaMODIFIER_X) >> 16), primary);
1330+
break;
1331+
1332+
case 4: // +x, -y
1333+
move = (ny << 16) / nx;
1334+
for (int primary = startX; primary <= endX; primary++, frac += move)
1335+
// yield return new Coord(primary, startY - ((frac + MODIFIER_Y) >> 16));
1336+
DrawPixel(primary, startY - ((frac + ddaMODIFIER_Y) >> 16));
1337+
break;
1338+
1339+
case 5:
1340+
move = (nx << 16) / ny;
1341+
for (int primary = startY; primary >= endY; primary--, frac += move)
1342+
DrawPixel(startX + ((frac + ddaMODIFIER_X) >> 16), primary);
1343+
// yield return new Coord(startX + ((frac + MODIFIER_X) >> 16), primary);
1344+
break;
1345+
}
1346+
}
1347+
13041348
} // class
13051349

13061350
} // namespace

0 commit comments

Comments
 (0)