3939#include "shared-bindings/displayio/Shape.h"
4040#include "supervisor/shared/translate.h"
4141
42- static void unpack_position (mp_obj_t position_obj , int16_t * x , int16_t * y ) {
43- // TODO(tannewt): Support any value sequence such as bytearray or bytes.
44- mp_obj_tuple_t * position = MP_OBJ_TO_PTR (position_obj );
45- if (MP_OBJ_IS_TYPE (position_obj , & mp_type_tuple ) && position -> len == 2 ) {
46- * x = mp_obj_get_int (position -> items [0 ]);
47- * y = mp_obj_get_int (position -> items [1 ]);
48- } else if (position != mp_const_none ) {
49- mp_raise_TypeError (translate ("position must be 2-tuple" ));
50- }
51- }
52-
5342//| .. currentmodule:: displayio
5443//|
5544//| :class:`TileGrid` -- A grid of tiles sourced out of one bitmap
@@ -60,7 +49,7 @@ static void unpack_position(mp_obj_t position_obj, int16_t* x, int16_t* y) {
6049//|
6150//| A single tile grid is also known as a Sprite.
6251//|
63- //| .. class:: TileGrid(bitmap, *, pixel_shader, position, width=1, height=1, tile_width=None, tile_height=None, default_tile=0)
52+ //| .. class:: TileGrid(bitmap, *, pixel_shader, width=1, height=1, tile_width=None, tile_height=None, default_tile=0, x=0, y =0)
6453//|
6554//| Create a TileGrid object. The bitmap is source for 2d pixels. The pixel_shader is used to
6655//| convert the value and its location to a display native pixel color. This may be a simple color
@@ -70,24 +59,26 @@ static void unpack_position(mp_obj_t position_obj, int16_t* x, int16_t* y) {
7059//|
7160//| :param displayio.Bitmap bitmap: The bitmap storing one or more tiles.
7261//| :param displayio.Palette pixel_shader: The pixel shader that produces colors from values
73- //| :param tuple position: Upper left corner of the grid
7462//| :param int width: Width of the grid in tiles.
7563//| :param int height: Height of the grid in tiles.
7664//| :param int tile_width: Width of a single tile in pixels. Defaults to the full Bitmap and must evenly divide into the Bitmap's dimensions.
7765//| :param int tile_height: Height of a single tile in pixels. Defaults to the full Bitmap and must evenly divide into the Bitmap's dimensions.
7866//| :param in default_tile: Default tile index to show.
67+ //| :param int x: Initial x position of the left edge within the parent.
68+ //| :param int y: Initial y position of the top edge within the parent.
7969//|
8070STATIC mp_obj_t displayio_tilegrid_make_new (const mp_obj_type_t * type , size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
81- enum { ARG_bitmap , ARG_pixel_shader , ARG_position , ARG_width , ARG_height , ARG_tile_width , ARG_tile_height , ARG_default_tile };
71+ enum { ARG_bitmap , ARG_pixel_shader , ARG_width , ARG_height , ARG_tile_width , ARG_tile_height , ARG_default_tile , ARG_x , ARG_y };
8272 static const mp_arg_t allowed_args [] = {
8373 { MP_QSTR_bitmap , MP_ARG_REQUIRED | MP_ARG_OBJ },
8474 { MP_QSTR_pixel_shader , MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED },
85- { MP_QSTR_position , MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED },
8675 { MP_QSTR_width , MP_ARG_INT | MP_ARG_KW_ONLY , {.u_int = 1 } },
8776 { MP_QSTR_height , MP_ARG_INT | MP_ARG_KW_ONLY , {.u_int = 1 } },
8877 { MP_QSTR_tile_width , MP_ARG_INT | MP_ARG_KW_ONLY , {.u_int = 0 } },
8978 { MP_QSTR_tile_height , MP_ARG_INT | MP_ARG_KW_ONLY , {.u_int = 0 } },
9079 { MP_QSTR_default_tile , MP_ARG_INT | MP_ARG_KW_ONLY , {.u_int = 0 } },
80+ { MP_QSTR_x , MP_ARG_INT | MP_ARG_KW_ONLY , {.u_int = 0 } },
81+ { MP_QSTR_y , MP_ARG_INT | MP_ARG_KW_ONLY , {.u_int = 0 } },
9182 };
9283 mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
9384 mp_arg_parse_all (n_args , pos_args , kw_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
@@ -129,10 +120,8 @@ STATIC mp_obj_t displayio_tilegrid_make_new(const mp_obj_type_t *type, size_t n_
129120 mp_raise_ValueError (translate ("Tile height must exactly divide bitmap height" ));
130121 }
131122
132- int16_t x = 0 ;
133- int16_t y = 0 ;
134- mp_obj_t position_obj = args [ARG_position ].u_obj ;
135- unpack_position (position_obj , & x , & y );
123+ int16_t x = args [ARG_x ].u_int ;
124+ int16_t y = args [ARG_y ].u_int ;
136125
137126 displayio_tilegrid_t * self = m_new_obj (displayio_tilegrid_t );
138127 self -> base .type = & displayio_tilegrid_type ;
@@ -142,41 +131,61 @@ STATIC mp_obj_t displayio_tilegrid_make_new(const mp_obj_type_t *type, size_t n_
142131 return MP_OBJ_FROM_PTR (self );
143132}
144133
145- //| .. attribute:: position
134+ // Helper to ensure we have the native super class instead of a subclass.
135+ static displayio_tilegrid_t * native_tilegrid (mp_obj_t tilegrid_obj ) {
136+ mp_obj_t native_tilegrid = mp_instance_cast_to_native_base (tilegrid_obj , & displayio_tilegrid_type );
137+ return MP_OBJ_TO_PTR (native_tilegrid );
138+ }
139+
140+ //| .. attribute:: x
146141//|
147- //| The position of the top- left corner of the tilegrid .
142+ //| X position of the left edge in the parent .
148143//|
149- STATIC mp_obj_t displayio_tilegrid_obj_get_position (mp_obj_t self_in ) {
150- displayio_tilegrid_t * self = MP_OBJ_TO_PTR (self_in );
151- int16_t x ;
152- int16_t y ;
153- common_hal_displayio_tilegrid_get_position ( self , & x , & y );
144+ STATIC mp_obj_t displayio_tilegrid_obj_get_x (mp_obj_t self_in ) {
145+ displayio_tilegrid_t * self = native_tilegrid (self_in );
146+ return MP_OBJ_NEW_SMALL_INT ( common_hal_displayio_tilegrid_get_x ( self )) ;
147+ }
148+ MP_DEFINE_CONST_FUN_OBJ_1 ( displayio_tilegrid_get_x_obj , displayio_tilegrid_obj_get_x );
154149
155- mp_obj_t coords [2 ];
156- coords [0 ] = mp_obj_new_int (x );
157- coords [1 ] = mp_obj_new_int (y );
150+ STATIC mp_obj_t displayio_tilegrid_obj_set_x (mp_obj_t self_in , mp_obj_t x_obj ) {
151+ displayio_tilegrid_t * self = native_tilegrid (self_in );
158152
159- return mp_obj_new_tuple (2 , coords );
153+ mp_int_t x = mp_obj_get_int (x_obj );
154+ common_hal_displayio_tilegrid_set_x (self , x );
155+ return mp_const_none ;
160156}
161- MP_DEFINE_CONST_FUN_OBJ_1 ( displayio_tilegrid_get_position_obj , displayio_tilegrid_obj_get_position );
157+ MP_DEFINE_CONST_FUN_OBJ_2 ( displayio_tilegrid_set_x_obj , displayio_tilegrid_obj_set_x );
162158
163- STATIC mp_obj_t displayio_tilegrid_obj_set_position (mp_obj_t self_in , mp_obj_t value ) {
164- displayio_tilegrid_t * self = MP_OBJ_TO_PTR (self_in );
159+ const mp_obj_property_t displayio_tilegrid_x_obj = {
160+ .base .type = & mp_type_property ,
161+ .proxy = {(mp_obj_t )& displayio_tilegrid_get_x_obj ,
162+ (mp_obj_t )& displayio_tilegrid_set_x_obj ,
163+ (mp_obj_t )& mp_const_none_obj },
164+ };
165165
166- int16_t x = 0 ;
167- int16_t y = 0 ;
168- unpack_position (value , & x , & y );
166+ //| .. attribute:: y
167+ //|
168+ //| Y position of the top edge in the parent.
169+ //|
170+ STATIC mp_obj_t displayio_tilegrid_obj_get_y (mp_obj_t self_in ) {
171+ displayio_tilegrid_t * self = native_tilegrid (self_in );
172+ return MP_OBJ_NEW_SMALL_INT (common_hal_displayio_tilegrid_get_y (self ));
173+ }
174+ MP_DEFINE_CONST_FUN_OBJ_1 (displayio_tilegrid_get_y_obj , displayio_tilegrid_obj_get_y );
169175
170- common_hal_displayio_tilegrid_set_position (self , x , y );
176+ STATIC mp_obj_t displayio_tilegrid_obj_set_y (mp_obj_t self_in , mp_obj_t y_obj ) {
177+ displayio_tilegrid_t * self = native_tilegrid (self_in );
171178
179+ mp_int_t y = mp_obj_get_int (y_obj );
180+ common_hal_displayio_tilegrid_set_y (self , y );
172181 return mp_const_none ;
173182}
174- MP_DEFINE_CONST_FUN_OBJ_2 (displayio_tilegrid_set_position_obj , displayio_tilegrid_obj_set_position );
183+ MP_DEFINE_CONST_FUN_OBJ_2 (displayio_tilegrid_set_y_obj , displayio_tilegrid_obj_set_y );
175184
176- const mp_obj_property_t displayio_tilegrid_position_obj = {
185+ const mp_obj_property_t displayio_tilegrid_y_obj = {
177186 .base .type = & mp_type_property ,
178- .proxy = {(mp_obj_t )& displayio_tilegrid_get_position_obj ,
179- (mp_obj_t )& displayio_tilegrid_set_position_obj ,
187+ .proxy = {(mp_obj_t )& displayio_tilegrid_get_y_obj ,
188+ (mp_obj_t )& displayio_tilegrid_set_y_obj ,
180189 (mp_obj_t )& mp_const_none_obj },
181190};
182191
@@ -185,13 +194,13 @@ const mp_obj_property_t displayio_tilegrid_position_obj = {
185194//| The pixel shader of the tilegrid.
186195//|
187196STATIC mp_obj_t displayio_tilegrid_obj_get_pixel_shader (mp_obj_t self_in ) {
188- displayio_tilegrid_t * self = MP_OBJ_TO_PTR (self_in );
197+ displayio_tilegrid_t * self = native_tilegrid (self_in );
189198 return common_hal_displayio_tilegrid_get_pixel_shader (self );
190199}
191200MP_DEFINE_CONST_FUN_OBJ_1 (displayio_tilegrid_get_pixel_shader_obj , displayio_tilegrid_obj_get_pixel_shader );
192201
193202STATIC mp_obj_t displayio_tilegrid_obj_set_pixel_shader (mp_obj_t self_in , mp_obj_t pixel_shader ) {
194- displayio_tilegrid_t * self = MP_OBJ_TO_PTR (self_in );
203+ displayio_tilegrid_t * self = native_tilegrid (self_in );
195204 if (!MP_OBJ_IS_TYPE (pixel_shader , & displayio_palette_type ) && !MP_OBJ_IS_TYPE (pixel_shader , & displayio_colorconverter_type )) {
196205 mp_raise_TypeError (translate ("pixel_shader must be displayio.Palette or displayio.ColorConverter" ));
197206 }
@@ -209,9 +218,72 @@ const mp_obj_property_t displayio_tilegrid_pixel_shader_obj = {
209218 (mp_obj_t )& mp_const_none_obj },
210219};
211220
221+ //| .. method:: __getitem__(index)
222+ //|
223+ //| Returns the tile index at the given index. The index can either be an x,y tuple or an int equal
224+ //| to ``y * width + x``.
225+ //|
226+ //| This allows you to::
227+ //|
228+ //| print(grid[0])
229+ //|
230+ //| .. method:: __setitem__(index, tile_index)
231+ //|
232+ //| Sets the tile index at the given index. The index can either be an x,y tuple or an int equal
233+ //| to ``y * width + x``.
234+ //|
235+ //| This allows you to::
236+ //|
237+ //| grid[0] = 10
238+ //|
239+ //| or::
240+ //|
241+ //| grid[0,0] = 10
242+ //|
243+ STATIC mp_obj_t tilegrid_subscr (mp_obj_t self_in , mp_obj_t index_obj , mp_obj_t value_obj ) {
244+ displayio_tilegrid_t * self = native_tilegrid (self_in );
245+
246+
247+ if (MP_OBJ_IS_TYPE (index_obj , & mp_type_slice )) {
248+ mp_raise_NotImplementedError (translate ("Slices not supported" ));
249+ } else {
250+ uint16_t x = 0 ;
251+ uint16_t y = 0 ;
252+ if (MP_OBJ_IS_SMALL_INT (index_obj )) {
253+ mp_int_t i = MP_OBJ_SMALL_INT_VALUE (index_obj );
254+ uint16_t width = common_hal_displayio_tilegrid_get_width (self );
255+ x = i % width ;
256+ y = i / width ;
257+ } else {
258+ mp_obj_t * items ;
259+ mp_obj_get_array_fixed_n (index_obj , 2 , & items );
260+ x = mp_obj_get_int (items [0 ]);
261+ y = mp_obj_get_int (items [1 ]);
262+ if (x >= common_hal_displayio_tilegrid_get_width (self ) || y >= common_hal_displayio_tilegrid_get_height (self )) {
263+ mp_raise_IndexError (translate ("tile index out of bounds" ));
264+ }
265+ }
266+
267+ if (value_obj == MP_OBJ_SENTINEL ) {
268+ // load
269+ return MP_OBJ_NEW_SMALL_INT (common_hal_displayio_tilegrid_get_tile (self , x , y ));
270+ } else if (value_obj == mp_const_none ) {
271+ return MP_OBJ_NULL ; // op not supported
272+ } else {
273+ mp_int_t value = mp_obj_get_int (value_obj );
274+ if (value < 0 || value > 255 ) {
275+ mp_raise_ValueError (translate ("Tile indices must be 0 - 255" ));
276+ }
277+ common_hal_displayio_tilegrid_set_tile (self , x , y , value );
278+ }
279+ }
280+ return mp_const_none ;
281+ }
282+
212283STATIC const mp_rom_map_elem_t displayio_tilegrid_locals_dict_table [] = {
213284 // Properties
214- { MP_ROM_QSTR (MP_QSTR_position ), MP_ROM_PTR (& displayio_tilegrid_position_obj ) },
285+ { MP_ROM_QSTR (MP_QSTR_x ), MP_ROM_PTR (& displayio_tilegrid_x_obj ) },
286+ { MP_ROM_QSTR (MP_QSTR_y ), MP_ROM_PTR (& displayio_tilegrid_y_obj ) },
215287 { MP_ROM_QSTR (MP_QSTR_pixel_shader ), MP_ROM_PTR (& displayio_tilegrid_pixel_shader_obj ) },
216288};
217289STATIC MP_DEFINE_CONST_DICT (displayio_tilegrid_locals_dict , displayio_tilegrid_locals_dict_table );
@@ -220,5 +292,6 @@ const mp_obj_type_t displayio_tilegrid_type = {
220292 { & mp_type_type },
221293 .name = MP_QSTR_TileGrid ,
222294 .make_new = displayio_tilegrid_make_new ,
295+ .subscr = tilegrid_subscr ,
223296 .locals_dict = (mp_obj_dict_t * )& displayio_tilegrid_locals_dict ,
224297};
0 commit comments