Skip to content

Commit 1d72ed8

Browse files
authored
Merge pull request #745 from dastels/pypaint
Add a second brush size
2 parents 7bd1a5c + ec40851 commit 1d72ed8

1 file changed

Lines changed: 122 additions & 49 deletions

File tree

CircuitPython_PyPaint/code.py

Lines changed: 122 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -72,17 +72,17 @@ def __init__(self, splash, cursor_bmp):
7272
self._y_offset = cursor_bmp.height // 2
7373

7474

75-
7675
def poll(self):
77-
"""Check for input. Returns contact (a bool) and it's location ((x,y) or None)"""
76+
"""Check for input. Returns contact (a bool), False (no button B),
77+
and it's location ((x,y) or None)"""
7878

7979
p = self._touchscreen.touch_point
8080
if p is not None:
8181
self._cursor_grp.x = p[0] - self._x_offset
8282
self._cursor_grp.y = p[1] - self._y_offset
83-
return True, p
83+
return True, False, p
8484
else:
85-
return False, None
85+
return False, False, None
8686

8787
def poke(self, location=None):
8888
"""Force a bitmap refresh."""
@@ -92,6 +92,17 @@ def poke(self, location=None):
9292
self._cursor_grp.y = location[1] - self._y_offset
9393
self._display_grp.append(self._cursor_grp)
9494

95+
def set_cursor_bitmap(self, bmp):
96+
"""Update the cursor bitmap.
97+
98+
:param bmp: the new cursor bitmap
99+
"""
100+
self._cursor_grp.remove(self._cur_sprite)
101+
self._cur_sprite = displayio.TileGrid(bmp,
102+
pixel_shader=self._cur_palette)
103+
self._cursor_grp.append(self._cur_sprite)
104+
self.poke()
105+
95106
################################################################################
96107

97108
class CursorPoller(object):
@@ -109,14 +120,15 @@ def __init__(self, splash, cursor_bmp):
109120
self._logger = logging.getLogger('Paint')
110121

111122
def poll(self):
112-
"""Check for input. Returns press (a bool) and it's location ((x,y) or None)"""
123+
"""Check for input. Returns press of A (a bool), B,
124+
and the cursor location ((x,y) or None)"""
113125
location = None
114126
self._cursor.update()
115-
button = self._cursor.held
116-
if button:
127+
a_button = self._cursor.held
128+
if a_button:
117129
location = (self._mouse_cursor.x + self._x_offset,
118130
self._mouse_cursor.y + self._y_offset)
119-
return button, location
131+
return a_button, location
120132

121133
#pylint:disable=unused-argument
122134
def poke(self, x=None, y=None):
@@ -125,6 +137,14 @@ def poke(self, x=None, y=None):
125137
self._mouse_cursor.show()
126138
#pylint:enable=unused-argument
127139

140+
def set_cursor_bitmap(self, bmp):
141+
"""Update the cursor bitmap.
142+
143+
:param bmp: the new cursor bitmap
144+
"""
145+
self._mouse_cursor.cursor_bitmap = bmp
146+
self.poke()
147+
128148
################################################################################
129149

130150
class Paint(object):
@@ -166,61 +186,109 @@ def __init__(self, display=board.DISPLAY):
166186
x=0, y=0)
167187
self._splash.append(self._fg_sprite)
168188

169-
self._color_palette = self._make_color_palette()
170-
self._splash.append(self._color_palette)
189+
self._number_of_palette_options = len(Color.colors) + 2
190+
self._swatch_height = self._h // self._number_of_palette_options
191+
self._swatch_width = self._w // 10
192+
self._logger.debug('Height: %d', self._h)
193+
self._logger.debug('Swatch height: %d', self._swatch_height)
194+
195+
self._palette = self._make_palette()
196+
self._splash.append(self._palette)
171197

172198
self._display.show(self._splash)
173199
self._display.refresh_soon()
174200
gc.collect()
175201
self._display.wait_for_frame()
176202

203+
self._brush = 0
204+
self._cursor_bitmaps = [self._cursor_bitmap_1(), self._cursor_bitmap_3()]
177205
if hasattr(board, 'TOUCH_XL'):
178-
self._poller = TouchscreenPoller(self._splash, self._cursor_bitmap())
206+
self._poller = TouchscreenPoller(self._splash, self._cursor_bitmaps[0])
179207
elif hasattr(board, 'BUTTON_CLOCK'):
180-
self._poller = CursorPoller(self._splash, self._cursor_bitmap())
208+
self._poller = CursorPoller(self._splash, self._cursor_bitmaps[0])
181209
else:
182-
raise AttributeError('PYOA requires a touchscreen or cursor.')
210+
raise AttributeError('PyPaint requires a touchscreen or cursor.')
183211

184-
self._pressed = False
185-
self._last_pressed = False
212+
self._a_pressed = False
213+
self._last_a_pressed = False
186214
self._location = None
187215
self._last_location = None
188216

189217
self._pencolor = 7
190218

191-
def _make_color_palette(self):
219+
def _make_palette(self):
192220
self._palette_bitmap = displayio.Bitmap(self._w // 10, self._h, 5)
193221
self._palette_palette = displayio.Palette(len(Color.colors))
194-
swatch_height = self._h // len(Color.colors)
195222
for i, c in enumerate(Color.colors):
196223
self._palette_palette[i] = c
197-
for y in range(swatch_height):
198-
for x in range(self._w // 10):
199-
self._palette_bitmap[x, swatch_height * i + y] = i
200-
self._palette_bitmap[self._w // 10 - 1, swatch_height * i + y] = 7
224+
for y in range(self._swatch_height):
225+
for x in range(self._swatch_width):
226+
self._palette_bitmap[x, self._swatch_height * i + y] = i
201227

228+
swatch_x_offset = (self._swatch_width - 9) // 2
229+
swatch_y_offset = (self._swatch_height - 9) // 2
230+
swatch_y = self._swatch_height * len(Color.colors) + swatch_y_offset
231+
for i in range(9):
232+
self._palette_bitmap[swatch_x_offset + 4, swatch_y + i] = 1
233+
self._palette_bitmap[swatch_x_offset + i, swatch_y + 4] = 1
234+
self._palette_bitmap[swatch_x_offset + 4, swatch_y + 4] = 0
235+
236+
swatch_y += self._swatch_height
237+
for i in range(9):
238+
self._palette_bitmap[swatch_x_offset + 3, swatch_y + i] = 1
239+
self._palette_bitmap[swatch_x_offset + 4, swatch_y + i] = 1
240+
self._palette_bitmap[swatch_x_offset + 5, swatch_y + i] = 1
241+
self._palette_bitmap[swatch_x_offset + i, swatch_y + 3] = 1
242+
self._palette_bitmap[swatch_x_offset + i, swatch_y + 4] = 1
243+
self._palette_bitmap[swatch_x_offset + i, swatch_y + 5] = 1
244+
for i in range(swatch_x_offset + 3, swatch_x_offset + 6):
245+
for j in range(swatch_y + 3, swatch_y + 6):
246+
self._palette_bitmap[i, j] = 0
247+
248+
for i in range(self._h):
249+
self._palette_bitmap[self._swatch_width - 1, i] = 7
202250

203251
return displayio.TileGrid(self._palette_bitmap,
204252
pixel_shader=self._palette_palette,
205253
x=0, y=0)
206254

207-
def _cursor_bitmap(self):
255+
def _cursor_bitmap_1(self):
208256
bmp = displayio.Bitmap(9, 9, 3)
209257
for i in range(9):
210258
bmp[4, i] = 1
211259
bmp[i, 4] = 1
212260
bmp[4, 4] = 0
213261
return bmp
214262

263+
def _cursor_bitmap_3(self):
264+
bmp = displayio.Bitmap(9, 9, 3)
265+
for i in range(9):
266+
bmp[3, i] = 1
267+
bmp[4, i] = 1
268+
bmp[5, i] = 1
269+
bmp[i, 3] = 1
270+
bmp[i, 4] = 1
271+
bmp[i, 5] = 1
272+
for i in range(3, 6):
273+
for j in range(3, 6):
274+
bmp[i, j] = 0
275+
return bmp
276+
215277
def _plot(self, x, y, c):
216-
try:
217-
self._fg_bitmap[int(x), int(y)] = c
218-
except IndexError:
219-
pass
278+
if self._brush == 0:
279+
r = [0]
280+
else:
281+
r = [-1, 0, 1]
282+
for i in r:
283+
for j in r:
284+
try:
285+
self._fg_bitmap[int(x + i), int(y + j)] = c
286+
except IndexError:
287+
pass
220288

221289
#pylint:disable=too-many-branches,too-many-statements
222290

223-
def _goto(self, start, end):
291+
def _draw_line(self, start, end):
224292
"""Draw a line from the previous position to the current one.
225293
226294
:param start: a tuple of (x, y) coordinatess to fram from
@@ -280,36 +348,41 @@ def _goto(self, start, end):
280348

281349
#pylint:enable=too-many-branches,too-many-statements
282350

283-
284-
def _pick_color(self, location):
285-
swatch_height = self._h // len(Color.colors)
286-
picked = location[1] // swatch_height
287-
self._pencolor = picked
351+
def _handle_palette_selection(self, location):
352+
selected = location[1] // self._swatch_height
353+
if selected >= self._number_of_palette_options:
354+
return
355+
self._logger.debug('Palette selection: %d', selected)
356+
if selected < len(Color.colors):
357+
self._pencolor = selected
358+
else:
359+
self._brush = selected - len(Color.colors)
360+
self._poller.set_cursor_bitmap(self._cursor_bitmaps[self._brush])
288361

289362
def _handle_motion(self, start, end):
290363
self._logger.debug('Moved: (%d, %d) -> (%d, %d)', start[0], start[1], end[0], end[1])
291-
self._goto(start, end)
364+
self._draw_line(start, end)
292365

293-
def _handle_press(self, location):
294-
self._logger.debug('Pressed!')
366+
def _handle_a_press(self, location):
367+
self._logger.debug('A Pressed!')
295368
if location[0] < self._w // 10: # in color picker
296-
self._pick_color(location)
369+
self._handle_palette_selection(location)
297370
else:
298371
self._plot(location[0], location[1], self._pencolor)
299372
self._poller.poke()
300373

301374
#pylint:disable=unused-argument
302-
def _handle_release(self, location):
303-
self._logger.debug('Released!')
375+
def _handle_a_release(self, location):
376+
self._logger.debug('A Released!')
304377
#pylint:enable=unused-argument
305378

306379
@property
307-
def _was_just_pressed(self):
308-
return self._pressed and not self._last_pressed
380+
def _was_a_just_pressed(self):
381+
return self._a_pressed and not self._last_a_pressed
309382

310383
@property
311-
def _was_just_released(self):
312-
return not self._pressed and self._last_pressed
384+
def _was_a_just_released(self):
385+
return not self._a_pressed and self._last_a_pressed
313386

314387
@property
315388
def _did_move(self):
@@ -321,19 +394,19 @@ def _did_move(self):
321394
return False
322395

323396
def _update(self):
324-
self._last_pressed, self._last_location = self._pressed, self._location
325-
self._pressed, self._location = self._poller.poll()
397+
self._last_a_pressed, self._last_location = self._a_pressed, self._location
398+
self._a_pressed, self._location = self._poller.poll()
326399

327400

328401
def run(self):
329402
"""Run the painting program."""
330403
while True:
331404
self._update()
332-
if self._was_just_pressed:
333-
self._handle_press(self._location)
334-
elif self._was_just_released:
335-
self._handle_release(self._location)
336-
if self._did_move and self._pressed:
405+
if self._was_a_just_pressed:
406+
self._handle_a_press(self._location)
407+
elif self._was_a_just_released:
408+
self._handle_a_release(self._location)
409+
if self._did_move and self._a_pressed:
337410
self._handle_motion(self._last_location, self._location)
338411
time.sleep(0.1)
339412

0 commit comments

Comments
 (0)