Implement brush customisation UI

This commit is contained in:
Ben Bridle 2022-09-21 12:04:31 +12:00
parent eccd3e0db4
commit 4535c81881
4 changed files with 228 additions and 85 deletions

View File

@ -53,7 +53,7 @@
%COL_2_FG { #42 } %COL_02_FG { #42 } %COL_0231_FG { #c2 }
%COL_3_FG { #43 } %COL_03_FG { #43 } %COL_0312_FG { #c3 }
%COL_10_FG { #44 } %COL_1012_FG { #c4 }
%COL_T1_FG { #45 } %COL_T123_FG { #c5 }
%COL_T_FG { #40 } %COL_T1_FG { #45 } %COL_T123_FG { #c5 }
%COL_12_FG { #46 } %COL_1231_FG { #c6 }
%COL_13_FG { #47 } %COL_1312_FG { #c7 }
%COL_20_FG { #48 } %COL_2012_FG { #c8 }

View File

@ -120,6 +120,7 @@
( Clears all of the callbacks and zones that were defined by the previous
screen, and wipes the foreground layer of the screen device. Call this
subroutine before declaring the UI for a new screen. )
@ui__initialise
@ui__clear
( Clear mouse button state, to prevent weird clicks when the new UI comes up )
#0000 DUP /I.MOUSE.PRESSED! /I.MOUSE.HELD! /I.MOUSE.RELEASED!
@ -148,25 +149,43 @@
EOR AND SWP SWP* EOR AND ( held released pressed )
/I.MOUSE.PRESSED! /I.MOUSE.RELEASED! /I.MOUSE.HELD!
,&mouse1_pressed JSR
,&mouse1_held JSR
,&mouse1_released JSR
;ui__callbacks/mouse1 LDA* ,&mouse_callback STR* BITMASK_1 ,&mouse_mask STR
;ui__start_mouse1_drag ,&start_drag_callback STR*
,&mouse_pressed JSR
,&mouse_held JSR
,&mouse_released JSR
;ui__callbacks/mouse2 LDA* ,&mouse_callback STR* BITMASK_2 ,&mouse_mask STR
;ui__start_mouse2_drag ,&start_drag_callback STR*
,&mouse_pressed JSR
,&mouse_held JSR
,&mouse_released JSR
;ui__callbacks/mouse3 LDA* ,&mouse_callback STR* BITMASK_3 ,&mouse_mask STR
;ui__start_mouse3_drag ,&start_drag_callback STR*
,&mouse_pressed JSR
,&mouse_held JSR
,&mouse_released JSR
,&process_cursor JSR
;ui__update_cursor_position CALL
BRK
&mouse1_pressed
/I.MOUSE.PRESSED? BITMASK_1 IF_NOT_MASK RETURN
&return_if_not ( byte -- )
[ LIT &mouse_mask $1 ] IF_NOT_MASK NORETURN RETURN
&mouse_callback $2
&mouse_pressed
/I.MOUSE.PRESSED? ,&return_if_not JSR
;ui__press_go ;ui__call_on_hovered_element CALL
;ui__start_mouse1_drag CALL
#00 ;ui__callbacks/mouse1 LDA* CALLRETURN
&mouse1_held
/I.MOUSE.HELD? BITMASK_1 IF_NOT_MASK RETURN
[ LIT* &start_drag_callback $2 ] CALL
#ff ;&mouse_callback LDA* CALLRETURN
&mouse_held
/I.MOUSE.HELD? ,&return_if_not JSR
,&return_if_cursor_not_moved JSR
#00 ;ui__callbacks/mouse1 LDA* CALLRETURN
&mouse1_released
/I.MOUSE.RELEASED? BITMASK_1 IF_NOT_MASK RETURN
#01 ;ui__callbacks/mouse1 LDA* CALLRETURN
#00 ;&mouse_callback LDA* CALLRETURN
&mouse_released
/I.MOUSE.RELEASED? ,&return_if_not JSR
#01 ;&mouse_callback LDA* CALLRETURN
&return_if_cursor_not_moved ( -- )
/I.CURSOR.X? /MOUSE.X? NEQ* ( diff_x? )
/I.CURSOR.Y? /MOUSE.Y? NEQ* ( diff_x? diff_y? )
@ -176,6 +195,8 @@
;ui__redraw_cursor CALL
;ui__set_active_control ;ui__call_on_hovered_element CALLRETURN
@ui__redraw_cursor
;sprite/cursor /SCREEN.ADDR!
( Erase the mouse cursor from the previous mouse position )

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

View File

@ -13,12 +13,33 @@
%/V.CANVAS.WIDTH { #04 } %/V.CANVAS.WIDTH? { #04 LDZ* } %/V.CANVAS.WIDTH! { #04 STZ* }
%/V.CANVAS.HEIGHT { #06 } %/V.CANVAS.HEIGHT? { #06 LDZ* } %/V.CANVAS.HEIGHT! { #06 STZ* }
( Canvas colour palette )
( Default screen background is colour 0x02 )
|0008 @canvas_colour_palette
%/V.CANVAS.RED { #08 } %/V.CANVAS.RED? { #08 LDZ } %/V.CANVAS.RED! { #08 STZ }
%/V.CANVAS.GREEN { #0a } %/V.CANVAS.GREEN? { #0a LDZ } %/V.CANVAS.GREEN! { #0a STZ }
%/V.CANVAS.BLUE { #0c } %/V.CANVAS.BLUE? { #0c LDZ } %/V.CANVAS.BLUE! { #0c STZ }
( The currently active drawing tool. )
%/V.ACTIVE_TOOL { #0e } %/V.ACTIVE_TOOL? { #0e LDZ } %/V.ACTIVE_TOOL! { #0e STZ }
%/V.CANVAS.RED { #08 } %/V.CANVAS.RED? { #08 LDZ* } %/V.CANVAS.RED! { #08 STZ* }
%/V.CANVAS.GREEN { #0a } %/V.CANVAS.GREEN? { #0a LDZ* } %/V.CANVAS.GREEN! { #0a STZ* }
%/V.CANVAS.BLUE { #0c } %/V.CANVAS.BLUE? { #0c LDZ* } %/V.CANVAS.BLUE! { #0c STZ* }
( UI colour palette )
|000e @ui_colour_palette
%/V.UI.RED { #0e } %/V.UI.RED? { #0e LDZ* } %/V.UI.RED! { #0e STZ* }
%/V.UI.GREEN { #10 } %/V.UI.GREEN? { #10 LDZ* } %/V.UI.GREEN! { #10 STZ* }
%/V.UI.BLUE { #12 } %/V.UI.BLUE? { #12 LDZ* } %/V.UI.BLUE! { #12 STZ* }
( The currently active and previously active drawing tools. )
%/V.ACTIVE_TOOL { #14 } %/V.ACTIVE_TOOL? { #14 LDZ } %/V.ACTIVE_TOOL! { #14 STZ }
%/V.PREV_TOOL { #15 } %/V.PREV_TOOL? { #15 LDZ } %/V.PREV_TOOL! { #15 STZ }
%/V.BRUSH1.COLOUR { #16 } %/V.BRUSH1.COLOUR? { #16 LDZ } %/V.BRUSH1.COLOUR! { #16 STZ }
%/V.BRUSH2.COLOUR { #17 } %/V.BRUSH2.COLOUR? { #17 LDZ } %/V.BRUSH2.COLOUR! { #17 STZ }
%/V.BRUSH3.COLOUR { #18 } %/V.BRUSH3.COLOUR? { #18 LDZ } %/V.BRUSH3.COLOUR! { #18 STZ }
%/V.BRUSH1.SHAPE { #19 } %/V.BRUSH1.SHAPE? { #19 LDZ } %/V.BRUSH1.SHAPE! { #19 STZ }
%/V.BRUSH2.SHAPE { #1a } %/V.BRUSH2.SHAPE? { #1a LDZ } %/V.BRUSH2.SHAPE! { #1a STZ }
%/V.BRUSH3.SHAPE { #1b } %/V.BRUSH3.SHAPE? { #1b LDZ } %/V.BRUSH3.SHAPE! { #1b STZ }
%/V.BRUSH1.PATTERN { #1c } %/V.BRUSH1.PATTERN? { #1c LDZ } %/V.BRUSH1.PATTERN! { #1c STZ }
%/V.BRUSH2.PATTERN { #1d } %/V.BRUSH2.PATTERN? { #1d LDZ } %/V.BRUSH2.PATTERN! { #1d STZ }
%/V.BRUSH3.PATTERN { #1e } %/V.BRUSH3.PATTERN? { #1e LDZ } %/V.BRUSH3.PATTERN! { #1e STZ }
%TOOL_COUNT? { #07 }
@ -26,25 +47,31 @@
( P R O G R A M S T A R T )
|0100
;ui__initialise CALL
#0080 /V.CANVAS.WIDTH! #0060 /V.CANVAS.HEIGHT! #01 /V.ACTIVE_TOOL!
;default_colour_palette ;ui__load_colour_palette CALL
;ui__clear CALL
( Seed default palettes for canvas and UI )
#1c8d /V.CANVAS.RED! #1619 /V.CANVAS.GREEN! #1010 /V.CANVAS.BLUE!
( TODO: Remove this line )
#1d4a /V.UI.RED! #2d69 /V.UI.GREEN! #3978 /V.UI.BLUE!
#1d22 /V.UI.RED! #2d8b /V.UI.GREEN! #3946 /V.UI.BLUE!
;recenter_canvas CALL
;canvas_screen GOTO
;tool_screen GOTO
~_user_interface_framework.tal
( ---------------------------------------------------------------------------- )
( P R O G R A M S C R E E N S )
@canvas_screen
;ui__clear CALL
;canvas_colour_palette ;ui__load_colour_palette CALL
;draw_canvas CALL
;canvas_screen__tool /I.CALLBACK.MOUSE1!
;canvas_screen__A /I.CALLBACK.A!
;canvas_screen__B /I.CALLBACK.B!
;canvas_screen__A /I.CALLBACK.A!
;canvas_screen__B /I.CALLBACK.B!
;canvas_screen__use_tool /I.CALLBACK.MOUSE1!
;canvas_screen__temp_pan /I.CALLBACK.MOUSE2!
;canvas_screen__chtool /I.CALLBACK.MOUSE3!
;ui__run_blank GOTO
@canvas_screen__A
( TODO: Think about having A trigger for press and release. Maybe a separate callback? A_UP and A_DOWN? )
@ -52,17 +79,31 @@
/MOUSE.VECTOR? CALL
RETURN
( Temporarily switch to the pan tool when dragging with the middle mouse button )
@canvas_screen__temp_pan ( state -- )
( If just pressed, stash the active tool and change to pan )
DUP #ff NEQ ,&call JCN
/V.ACTIVE_TOOL? /V.PREV_TOOL!
#00 /V.ACTIVE_TOOL!
( Use the current tool )
&call DUP ,canvas_screen__use_tool JSR
( If released, restore the active tool )
#01 NEQ ,&return JCN
/V.PREV_TOOL? /V.ACTIVE_TOOL!
&return RETURN
@canvas_screen__B NORETURN ;tool_screen GOTO
@canvas_screen__tool
@canvas_screen__chtool #01 IF_NOT_EQUAL RETURN
@canvas_screen__B NORETURN ;tool_screen GOTO
@canvas_screen__use_tool
( Dispatch control to the routine of the active tool )
/V.ACTIVE_TOOL? MUL4 JMP
;&pan GOTO ;&brush1 GOTO ;&brush2 GOTO ;&brush3 GOTO ;&line GOTO
&pan ,&pan_released JCN
&pan #01 EQU ,&pan_release JCN
( Erase old indicator rectangle )
/V.CANVAS.X? /SCREEN.X! /V.CANVAS.Y? /SCREEN.Y!
COL_0_FG /V.CANVAS.WIDTH? /V.CANVAS.HEIGHT? ;draw_rect_outline CALL
COL_T_FG /V.CANVAS.WIDTH? /V.CANVAS.HEIGHT? ;draw_rect_outline CALL
( Move canvas origin coordinates )
/MOUSE.X? /I.CURSOR.X? SUB* /V.CANVAS.X? ADD* /V.CANVAS.X!
/MOUSE.Y? /I.CURSOR.Y? SUB* /V.CANVAS.Y? ADD* /V.CANVAS.Y!
@ -71,8 +112,8 @@
/V.CANVAS.Y? /V.CANVAS.HEIGHT? /SCREEN.HEIGHT? ,&_pan_clamp JSR /V.CANVAS.Y!
( Draw new indicator rectangle )
/V.CANVAS.X? /SCREEN.X! /V.CANVAS.Y? /SCREEN.Y!
COL_3_FG /V.CANVAS.WIDTH? /V.CANVAS.HEIGHT? ;draw_rect_outline CALLRETURN
&pan_released
COL_1_FG /V.CANVAS.WIDTH? /V.CANVAS.HEIGHT? ;draw_rect_outline CALLRETURN
&pan_release
;clear_foreground CALL
;draw_canvas CALLRETURN
&_pan_clamp ( start* len* screen* -- start* )
@ -90,12 +131,12 @@
&line ,&line_released JCN
/I.MOUSE1.X? /I.MOUSE1.Y? /I.CURSOR.X? /I.CURSOR.Y?
COL_0_FG ;get_callback_to_draw_pixel CALL ;draw_line CALL
COL_T_FG ;get_callback_to_draw_pixel CALL ;draw_line CALL
/I.MOUSE1.X? /I.MOUSE1.Y? /MOUSE.X? /MOUSE.Y?
COL_3_FG ;get_callback_to_draw_pixel CALL ;draw_line CALLRETURN
COL_1_FG ;get_callback_to_draw_pixel CALL ;draw_line CALLRETURN
&line_released
/I.MOUSE1.X? /I.MOUSE1.Y? /I.CURSOR.X? /I.CURSOR.Y?
COL_3 ;get_callback_to_commit_pixel CALL ;draw_line CALL
COL_1 ;get_callback_to_commit_pixel CALL ;draw_line CALL
;draw_canvas CALLRETURN
&brush1 COL_1 ,&brush_colour STR ,&_brush JMP
@ -111,67 +152,136 @@
( Draws a capsule, either empty, half-filled, or solid filled )
( Doesn't preserve coordinates )
( States: unselected, inactive selected, and active selected )
@draw_colour
;sprite/capsule_half /SCREEN.ADDR!
;brush_pattern/2 /SCREEN.ADDR!
#0001 /SCREEN.AUTO!
COL_T2 /SCREEN.SPRITE!
COL_T2_X /SCREEN.SPRITE!
/SCREEN.AUTO! RETURN
@tool_screen
;ui__clear CALL
;ui_colour_palette ;ui__load_colour_palette CALL
( Draw non-interactive elements )
COL_0 ;fill_screen_with_colour CALL
( Labels )
#0039 CENTER_LEFT? /SCREEN.X! #0008 CENTER_DOWN? /SCREEN.Y!
#0043 CENTER_LEFT? /SCREEN.X! #0005 CENTER_DOWN? /SCREEN.Y!
COL_1 ;&colour_text ;draw_text CALL
#0034 CENTER_LEFT? /SCREEN.X! #0016 CENTER_DOWN? /SCREEN.Y!
#003e CENTER_LEFT? /SCREEN.X! #0013 CENTER_DOWN? /SCREEN.Y!
COL_1 ;&shape_text ;draw_text CALL
#0040 CENTER_LEFT? /SCREEN.X! #0024 CENTER_DOWN? /SCREEN.Y!
#004a CENTER_LEFT? /SCREEN.X! #0021 CENTER_DOWN? /SCREEN.Y!
COL_1 ;&pattern_text ;draw_text CALL
#0008 CENTER_LEFT? /SCREEN.X! #0008 CENTER_DOWN? /SCREEN.Y!
;sprite/capsule_half /SCREEN.ADDR!
#01 /SCREEN.AUTO!
COL_T2 /SCREEN.SPRITE! COL_T2_X /SCREEN.SPRITE!
#0003 MOVE_RIGHT
COL_T2 /SCREEN.SPRITE! COL_T2_X /SCREEN.SPRITE!
#0003 MOVE_RIGHT
COL_T2 /SCREEN.SPRITE! COL_T2_X /SCREEN.SPRITE!
#0003 MOVE_RIGHT
COL_T2 /SCREEN.SPRITE! COL_T2_X /SCREEN.SPRITE!
#00 /SCREEN.AUTO!
( Draw shape and pattern backgrounds )
#0013 CENTER_LEFT! #0011 CENTER_DOWN!
COL_1 #005a #000b ;draw_capsule CALL
#001f CENTER_DOWN!
COL_1 #005a #000c ;draw_capsule CALL
( Register inc/dec callbacks )
#00 ;tool_screen__change__palette
#01 ;ui__register_change_callbacks CALL
#00 ;tool_screen__change__tool
#01 ;tool_screen__change__colour
#02 ;tool_screen__change__shape
#03 ;tool_screen__change__pattern
#04 ;ui__register_change_callbacks CALL
( Register draw callbacks )
#00 ;tool_screen__draw__palette
#01 ;tool_screen__draw__colour
#02 ;ui__register_draw_callbacks CALL
#00 ;tool_screen__draw__tools
#01 ;tool_screen__draw__colours
#02 ;tool_screen__draw__shapes
#03 ;tool_screen__draw__patterns
#04 ;ui__register_draw_callbacks CALL
( Register raw input callbacks )
;tool_screen__B /I.CALLBACK.B!
;tool_screen__B /I.CALLBACK.B!
;tool_screen__canvas /I.CALLBACK.MOUSE3!
( Finish callback registration )
#0002 ;ui__run GOTO
#0004 ;ui__run GOTO
&colour_text "Colour: <NULL>
&shape_text "Shape: <NULL>
&pattern_text "Pattern: <NULL>
@tool_screen__B NORETURN ;canvas_screen GOTO
@tool_screen__change__palette ( delta -- )
/V.ACTIVE_TOOL? ADD TOOL_COUNT? ;clamp CALL /V.ACTIVE_TOOL! RETURN
@tool_screen__canvas #01 IF_NOT_EQUAL RETURN
@tool_screen__B NORETURN ;canvas_screen GOTO
@tool_screen__draw__colour ( active? )
POP RETURN
COL_12 COL_32 CHOOSE
#0040 CENTER_LEFT? /SCREEN.X! #002c CENTER_DOWN? /SCREEN.Y!
#0020 DUP* ;draw_text CALLRETURN
@tool_screen__change__tool ( delta -- )
/V.ACTIVE_TOOL TOOL_COUNT? ,change__variable JMP
@tool_screen__change__colour ( delta -- )
/V.BRUSH1.COLOUR #04 ,change__variable JMP
@tool_screen__change__shape ( delta -- )
/V.BRUSH1.SHAPE #08 ,change__variable JMP
@tool_screen__change__pattern ( delta -- )
/V.BRUSH1.PATTERN #08 ,change__variable JMP
@change__variable ( delta var_addr count -- )
STH LDZk ROT ADD STHr ;clamp CALL SWP STZ RETURN
@tool_screen__draw__palette ( active? )
@tool_screen__draw__colours ( active? )
#0013 CENTER_LEFT! #0005 CENTER_DOWN!
( Choose the colour of the selected colour, whether control is active or not )
COL_2 COL_3 CHOOSE ,&active_col STR
#0400 ( total i )
&loop
DUP /V.BRUSH1.COLOUR? EQU ( is_chosen? )
COL_1 [ LIT &active_col $1 ] CHOOSE
#0015 #0008 ;draw_capsule CALL
#0017 MOVE_RIGHT
INC NEQk ,&loop JCN
POP*
RETURN
@tool_screen__draw__shapes ( active? )
#0010 CENTER_LEFT! #0013 CENTER_DOWN!
( Choose the colour of the selected colour, whether control is active or not )
COL_12 COL_13 CHOOSE ,&active_col STR
;brush_shape /SCREEN.ADDR!
#05 /SCREEN.AUTO!
#0800 ( total i )
&loop
DUP /V.BRUSH1.SHAPE? EQU ( is_chosen? )
COL_10 [ LIT &active_col $1 ] CHOOSE /SCREEN.SPRITE!
#0003 MOVE_RIGHT
INC NEQk ,&loop JCN
#00 /SCREEN.AUTO!
POP*
RETURN
@tool_screen__draw__patterns ( active? )
#0010 CENTER_LEFT! #0021 CENTER_DOWN!
( Choose the colour of the selected colour, whether control is active or not )
COL_12 COL_13 CHOOSE ,&active_col STR
;brush_pattern /SCREEN.ADDR!
#05 /SCREEN.AUTO!
#0800 ( total i )
&loop
DUP /V.BRUSH1.PATTERN? EQU ( is_chosen? )
COL_10 [ LIT &active_col $1 ] CHOOSE /SCREEN.SPRITE!
#0003 MOVE_RIGHT
INC NEQk ,&loop JCN
#00 /SCREEN.AUTO!
POP*
RETURN
@tool_screen__draw__tools ( active? )
( TODO: Have the icon that the mouse is currently hovering over be
rendered in the chosen-but-not-active colour. Figure out how to do this
for all UI elements. Colours, for example. )
( Choose between the real active tool and an impossible tool number )
#ff /V.ACTIVE_TOOL? CHOOSE ,&active_tool STR
( Draw a label on top, containing the name of the active tool )
#0040 CENTER_LEFT? /SCREEN.X! #002c CENTER_UP? /SCREEN.Y!
COL_20 #0080 /V.ACTIVE_TOOL? ;get_tool_name CALL ;draw_button CALL
#0040 CENTER_LEFT! #002f CENTER_UP!
COL_01 #0080 /V.ACTIVE_TOOL? ;get_tool_name CALL ;draw_button CALL
( Draw a large capsule to use as a background for the tool icons )
#001c CENTER_UP! COL_2 ( colour -- )
#001f CENTER_UP! COL_1 ( colour -- )
;get_tool_palette_width CALL ( colour width* )
/SCREEN.WIDTH? OVR* SUB* HALVE* ( colour width* bg_x* )
/SCREEN.X! #001b ;draw_capsule CALL ( -- )
@ -208,14 +318,15 @@
( Draw a single tool icon )
@draw_tool_palette_icon ( index active? )
LITr 00 STHk* POP LITr 00 STH ( | index* active index* )
#001a CENTER_UP! /SCREEN.WIDTH? ( s_width* | index* active index* )
#001d CENTER_UP! /SCREEN.WIDTH? ( s_width* | index* active index* )
,get_tool_palette_width JSR ( s_width* width* | index* active index* )
SUB* HALVE* ADD2* ( zone_0_x* | index* active index* )
STHr* #001a MUL* ADD* /SCREEN.X! ( | index* active )
STHr STHkr /V.ACTIVE_TOOL? EQU ( active? current_tool? | index* )
COL_0 COL_1 CHOOSE COL_3 CHOOSE ( colour | index* )
( unchosen - inactive - active )
COL_0 COL_2 CHOOSE COL_3 CHOOSE ( colour | index* )
#0017 DUP* ;draw_capsule_smooth CALL ( | index* )
COL_T2 ;tool_icon STHr* #0048 MUL* ADD* ( colour 3x3_sprite_addr* )
COL_T1 ;tool_icon STHr* #0048 MUL* ADD* ( colour 3x3_sprite_addr* )
( Draw the 1-bit 3x3 sprite ) ( colour sprite_addr* )
/SCREEN.ADDR! #26 /SCREEN.AUTO!
/SCREEN.SPRITE DEOk DEOk DEO
@ -323,7 +434,6 @@
~_fill_screen.tal
~_draw_line.tal
~_draw_rect.tal
@ -334,15 +444,6 @@
~_acorn_font.tal
@default_colour_palette
14ad 269d 2689
14ac 269a 268f
14ae 269a 3780
14ac 269b 378d
1d9e 161a 1010
e19a a116 0112
@tool_icon
&pan 0000 0000 0000 0000 0000 0010 387c d610 0000 0000 0000 0000
0206 0c1f 0c06 0200 1010 10ff 1010 1010 80c0 60f0 60c0 8000
@ -366,10 +467,31 @@
0205 0a14 1008 0402 8100 0401 1224 4890 f0f0 b030 3030 2020
0100 0000 0000 0000 20c0 0000 0000 0000 2000 0000 0000 0000
@brush_shape
&1 0000 0010 0000 0000 ( 1x1 block )
&2 0000 1038 1000 0000 ( 3x3 cross )
&3 0000 3838 3800 0000 ( 3x3 block )
&4 0010 387c 3810 0000 ( 5x5 diamond )
&5 0038 7c7c 7c38 0000 ( 5x5 rounded )
&6 1038 7cfe 7c38 1000 ( 7x7 diamond )
&7 387c fefe fe7c 3800 ( 7x7 circle )
&8 7cfe fefe fefe 7c00 ( 7x7 rounded )
@brush_pattern
&1 ffff ffff ffff ffff ( 1/1 fill )
&2 aa55 aa55 aa55 aa55 ( 1/2 fill )
&3 1122 4488 1122 4488 ( 1/4 left-diag )
&4 8844 2211 8844 2211 ( 1/4 right-diag )
&5 aaaa aaaa aaaa aaaa ( 1/2 vertical )
&6 5555 5555 5555 5555 ( 1/2 horizontal )
&7 0044 0011 0044 0011 ( 1/8 sparse )
&8 40a0 4000 0000 0000 ( 1/16 clumps )
@sprite
&left_chevron 1030 70f0 7030 1000
&cursor 80c0 e0f0 f8e0 1000
&capsule_half 7f80 8080 8080 807f
&capsule_half 7f80 8080 8080 807f
&capsule_right 7f80 8080 8080 807f
&blank 0000 0000 0000 0000