custom_sprite 
A custom hair or markings drawing being edited: its layers share one palette, paint stays within the body's bounds, and the history is kept within limits.
Vars | |
| canvas_code_lists | Layer id -> direction -> that view's codes a pixel each, row by row, which canvas_views joins. A step's pixels are written into it, so a stroke encodes only what it painted. |
|---|---|
| canvas_codes | Pixel value -> its code in the window's canvas. |
| canvas_digits | Characters per pixel in canvas_views. |
| canvas_palette | Every pixel value the window's canvas uses, in first-use order. Null until built. |
| canvas_patches | Layer id -> direction -> the points of each step that changed that view since it was last encoded, while only they need encoding again. A view whose whole frame may have changed has none, nor one painted past CUSTOM_SPRITE_MAX_PATCH_STEPS steps or as many points as it has pixels, which is encoded whole. |
| canvas_views | Direction -> that view as codes. A null entry is rebuilt on the next update. |
| current_layer | The layer the transaction being checked paints, so an eraser outside the bounds reads that layer's pixels. |
| draw_bounds | Direction -> inclusive rectangle of editable pixels. |
| draw_mask | Direction -> limb silhouette rows, or null for rectangular bounds. |
| drawing_cache | Serialized pixels are immutable until the next edit; appearance settings only replace metadata. |
| edited_directions | Direction -> whether that canvas currently contains paint. |
| emissive | Direction -> whether this drawing emits instead of blocking light. |
| erasing | Set while an eraser stroke is validated, so already-painted pixels outside the bounds can be removed. |
| hair_context | The whitelisted base hair look this draft belongs to. Null for markings. |
| markings_context | Zone -> ordered native marking records on the whole-body canvas; null for hair. |
| next_appendage_id | The number the next appendage layer's id takes. Ids are never reused in a draft, so the window's choice of layer survives undo. |
| owner_ref | The editor this workspace belongs to, so view locks are checked as they are now. |
| palette | Opaque brush colors available to this workspace. |
| pixels_dirty | Whether serialization must rebuild the cached pixel payload. |
| saved_transactions | History entries already applied when the draft was last saved. |
| tint | Legacy drawing multiplier retained until it is baked into the palette. |
| trimmed_rotations | Rotation markers of unsaved imports and restorations that fell off the end of the history. |
| used_colors_cache | What used_colors() last found, until pixels change. |
| visible_view | The view the window shows, the only one of each appendage layer it's sent. |
Procs | |
| New | Opens drawing, or a blank canvas for null, painting within bounds and mask, and offers sampled_palette
after the drawing's own colours. canvas_width and canvas_height ask for the taur's wide canvas or tall hair's
canvas; a drawing larger than the canvas asked for keeps its own size. |
| add_appendage | Adds an empty appendage layer after the others, as an undoable step. Returns its id, or null when there's no room. |
| add_appendage_layer | Adds an appendage layer at position (the end when null), painted from appendage's views when
drawing is given, and returns it. Nothing is recorded for undo; steps that add one do that. |
| admit_colors | Sets the palette to the kept colors plus as many available ones, in order, as fit. Returns TRUE when all fit. |
| all_points_allowed | With no bounds and no mask, as graffiti's canvas has, every pixel of the canvas may be painted or erased. |
| appendage_entry | A new blank appendage layer, not yet in the draft, with appendage's name, zone, kind and emission under the next id. |
| apply_replacement | Applies or reverses a replacement step: pixels, appendage layers, base look, markings, emission and tint together. |
| apply_replacement_emissive | Restores emission as a replacement recorded it. |
| apply_step | Applies, or with forward FALSE reverses, a step this workspace records itself: a replacement, an appendage
layer added, removed or changed, or a new base hair look. Returns FALSE for anything else, a stroke or a move. |
| bake_tint | Explicit saved tints already render as a separate overlay: bake their RGB into literal colors. |
| canvas_directions | The views of layer the window's canvas carries: every view of the hair, and the visible one of an appendage. |
| canvas_ui_data | The canvas as the window receives it: every pixel value once, and each view as codes. |
| clear_direction | An explicit clear erases one layer's whole view, including pixels outside the current body bounds. |
| copy_appendage_over | Copies an under-hat appendage to a new over-hat layer right after it, as the built-in pieces pair up. Returns the copy's id, or null. |
| create_layer_data | Blank frames from one row copied, rather than every pixel appended one at a time: a draft builds a layer per appendage. |
| encode_layer | One layer's painted views as saved: its bottom saved_height rows, as palette indexes. pixel_indices caches each pixel value's index across layers. |
| frame_changes | Pixel changes that turn each current frame into the matching new frame, as list(x, y, old, new). |
| incoming_appendage_layers | A replacement's appendage layers under this draft's ids. |
| is_painted | Whether a pixel of layer holds opaque paint. |
| is_point_allowed | Pixels inside the view's bounds and mask; while erasing, also paint left anywhere else on the canvas. |
| kept_colors | Colors the current and undoable pixels use, which must stay paintable. |
| last_transaction | The last applied history entry, or null. |
| layer_edited | Direction -> whether layer has paint in that view. The hair's own map is edited_directions. |
| layer_index | The index of the layer with this id, or 0. |
| layer_painted | Whether any view of layer has paint. |
| layers_changed | An appendage layer came or went, pixels and all: the window's canvas keeps the views of the layers still there, and forgets the rest. |
| mark_saved | Remembers the history as it stands at a save, so later imports and restorations can be told apart. |
| masked_fill | Floods a fill from its point over the pixels is_point_allowed() takes; the others are boundaries. With rows,
a view's region map, only pixels of region fill. |
| new_transaction | Existing paint left outside changed bounds can always be erased; new paint stays inside. |
| paint_above | Whether any layer has paint in the top rows rows of any view. |
| pixels_changed | Pixels changed: serialization and the colours in use are worked out again, and so is the window's canvas, only that layer's view when one is named, and only the pixels a step changed when it gives its points. A view keeps the points of at most CUSTOM_SPRITE_MAX_PATCH_STEPS steps, and no more points than it has pixels: past either it is encoded whole, so a view the window doesn't show, as an appendage's hidden one, holds no more however long it is painted. |
| preprocess_new_transaction | Treat masked pixels as fill boundaries, so disconnected parts do not fill through the backdrop. |
| record_step | Applies a step the editor built itself, such as adding an appendage, and records it for undo under the same limits as any other step. |
| remove_appendage | Removes an appendage layer, paint and all, as an undoable step. |
| replace_drawing | Replaces every view, emission setting and the base hair look as one undoable action. |
| replace_hair_context | Swaps the base hair look under paint that stays exactly as it is, as one undoable step. A new hairstyle never recolors paint, so this is all it changes: replace_drawing() would rebuild every layer to find no difference, and keep whole copies of each appendage layer in the history. |
| resize_height | Grows or shrinks the canvas to new_height rows where it stands, as picking or leaving the tall
base does: rows come and go at the top, so paint keeps its place on the head and every layer keeps
its id. The caller has made sure no paint sits in rows that go. History can't span two canvas
sizes, so it starts over; imports and restorations it held still count when the draft saves. |
| restore_unpainted_appendages | Puts unpainted appendage layers back where they were, after a canvas resize rebuilt the draft from its saved form. |
| reverse_transact | Reverses a step: this workspace's own through apply_step(), and anything else as the base workspace does. |
| serialize_drawing | The draft as a canonical drawing, cached until pixels change; null when empty or over the colour limit. |
| serialize_drawing_with | The drawing serialize_drawing() would give with frames as the views of layer, for a preview of
paint that isn't placed yet. The draft and its caches are left exactly as they were. |
| set_appendage | Changes an appendage's name, zone or kind as an undoable step. The caller has already made the value canonical. Returns FALSE when nothing would change. |
| sprite_editor_ui_data | The window gets the canvas as palette indexes rather than a color string per pixel. |
| step_colors | The opaque colors one history step paints with or over, in the order it first uses them. A move or placement's own colors count, so they stay paintable while the step waits undone to be redone. |
| step_layers | Appendage layers a history step keeps whole: the one it adds or removes, or both sets a replacement swaps. |
| step_points | The pixels one history step records: its points, every view a replacement changed, and every pixel of a layer it keeps whole. Counted once and kept on the step, which never changes once it is in the history, as trim_history() counts the whole history after every stroke. |
| stroke_layer_matches | Whether a stroke names the layer it paints: appendage layers are named by id as well, so a stroke meant for one that undo just moved can't land on another. |
| stroke_mask_slots | Returns the slots a compact stroke mask is cut down to as it is read (custom_sprite_mask_points()'s allowed), for a
canvas whose mask strokes then need no check of each point. |
| transact | Applies a step: this workspace's own through apply_step(), a pencil stroke by assigning its colour, and anything else as the base workspace does. |
| trim_history | Keeps the undo history within CUSTOM_SPRITE_MAX_UNDO steps and CUSTOM_SPRITE_MAX_UNDO_POINTS recorded pixels, dropping the oldest first. |
| unpainted_appendages | The draft's unpainted appendage layers and where they sit among the others, which a drawing can't carry through a canvas resize. |
| unsaved_rotations | Rotation markers of imports and restorations applied since the last save and not undone. |
| update_edited_direction | Update only the affected direction of layer, without serializing the drawing for its UI marker. |
| update_palette | Keeps current and undoable colors paintable, then admits available colors in order while there's room. |
| used_colors | The opaque colours every layer's frames use, lowercase, in first-use order. The layers share one palette. |
| valid_layer | Whether layer is a whole number naming one of the layers, from lowest on: 2 names only appendage layers. |
| validate_palette_color | Refuses a stroke colour that isn't in the palette. |
Var Details
canvas_code_lists 
Layer id -> direction -> that view's codes a pixel each, row by row, which canvas_views joins. A step's pixels are written into it, so a stroke encodes only what it painted.
canvas_codes 
Pixel value -> its code in the window's canvas.
canvas_digits 
Characters per pixel in canvas_views.
canvas_palette 
Every pixel value the window's canvas uses, in first-use order. Null until built.
canvas_patches 
Layer id -> direction -> the points of each step that changed that view since it was last encoded, while only they need encoding again. A view whose whole frame may have changed has none, nor one painted past CUSTOM_SPRITE_MAX_PATCH_STEPS steps or as many points as it has pixels, which is encoded whole.
canvas_views 
Direction -> that view as codes. A null entry is rebuilt on the next update.
current_layer 
The layer the transaction being checked paints, so an eraser outside the bounds reads that layer's pixels.
draw_bounds 
Direction -> inclusive rectangle of editable pixels.
draw_mask 
Direction -> limb silhouette rows, or null for rectangular bounds.
drawing_cache 
Serialized pixels are immutable until the next edit; appearance settings only replace metadata.
edited_directions 
Direction -> whether that canvas currently contains paint.
emissive 
Direction -> whether this drawing emits instead of blocking light.
erasing 
Set while an eraser stroke is validated, so already-painted pixels outside the bounds can be removed.
hair_context 
The whitelisted base hair look this draft belongs to. Null for markings.
markings_context 
Zone -> ordered native marking records on the whole-body canvas; null for hair.
next_appendage_id 
The number the next appendage layer's id takes. Ids are never reused in a draft, so the window's choice of layer survives undo.
owner_ref 
The editor this workspace belongs to, so view locks are checked as they are now.
palette 
Opaque brush colors available to this workspace.
pixels_dirty 
Whether serialization must rebuild the cached pixel payload.
saved_transactions 
History entries already applied when the draft was last saved.
tint 
Legacy drawing multiplier retained until it is baked into the palette.
trimmed_rotations 
Rotation markers of unsaved imports and restorations that fell off the end of the history.
used_colors_cache 
What used_colors() last found, until pixels change.
visible_view 
The view the window shows, the only one of each appendage layer it's sent.
Proc Details
New
Opens drawing, or a blank canvas for null, painting within bounds and mask, and offers sampled_palette
after the drawing's own colours. canvas_width and canvas_height ask for the taur's wide canvas or tall hair's
canvas; a drawing larger than the canvas asked for keeps its own size.
add_appendage
Adds an empty appendage layer after the others, as an undoable step. Returns its id, or null when there's no room.
add_appendage_layer
Adds an appendage layer at position (the end when null), painted from appendage's views when
drawing is given, and returns it. Nothing is recorded for undo; steps that add one do that.
admit_colors
Sets the palette to the kept colors plus as many available ones, in order, as fit. Returns TRUE when all fit.
all_points_allowed
With no bounds and no mask, as graffiti's canvas has, every pixel of the canvas may be painted or erased.
appendage_entry
A new blank appendage layer, not yet in the draft, with appendage's name, zone, kind and emission under the next id.
apply_replacement
Applies or reverses a replacement step: pixels, appendage layers, base look, markings, emission and tint together.
apply_replacement_emissive
Restores emission as a replacement recorded it.
apply_step
Applies, or with forward FALSE reverses, a step this workspace records itself: a replacement, an appendage
layer added, removed or changed, or a new base hair look. Returns FALSE for anything else, a stroke or a move.
bake_tint
Explicit saved tints already render as a separate overlay: bake their RGB into literal colors.
canvas_directions
The views of layer the window's canvas carries: every view of the hair, and the visible one of an appendage.
canvas_ui_data
The canvas as the window receives it: every pixel value once, and each view as codes.
A code is canvas_digits characters of CUSTOM_SPRITE_INDEX_ALPHABET naming a palette entry, most
significant first, row by row from the top left. The palette only grows until the next full
rebuild, so views that didn't change keep their codes and aren't encoded again.
The hair layer sends every view, as it always has. Appendage layers send, and so encode, only
visible_view: the window shows one view at a time, and switching views asks for the next.
Returns list("palette" = pixel values, "digits" = characters per pixel, "views" = the hair's direction -> codes, "appendages" = appendage id -> direction -> codes).
clear_direction
An explicit clear erases one layer's whole view, including pixels outside the current body bounds.
copy_appendage_over
Copies an under-hat appendage to a new over-hat layer right after it, as the built-in pieces pair up. Returns the copy's id, or null.
create_layer_data
Blank frames from one row copied, rather than every pixel appended one at a time: a draft builds a layer per appendage.
encode_layer
One layer's painted views as saved: its bottom saved_height rows, as palette indexes. pixel_indices caches each pixel value's index across layers.
frame_changes
Pixel changes that turn each current frame into the matching new frame, as list(x, y, old, new).
incoming_appendage_layers
A replacement's appendage layers under this draft's ids.
With keep, the draft's painted layers take the incoming ones in order under their own ids, and
unpainted ones stay where they are, so a recolor or a new base look doesn't move or drop a layer.
Otherwise every incoming layer gets a fresh id.
is_painted
Whether a pixel of layer holds opaque paint.
is_point_allowed
Pixels inside the view's bounds and mask; while erasing, also paint left anywhere else on the canvas.
kept_colors
Colors the current and undoable pixels use, which must stay paintable.
last_transaction
The last applied history entry, or null.
layer_edited
Direction -> whether layer has paint in that view. The hair's own map is edited_directions.
layer_index
The index of the layer with this id, or 0.
layer_painted
Whether any view of layer has paint.
layers_changed
An appendage layer came or went, pixels and all: the window's canvas keeps the views of the layers still there, and forgets the rest.
mark_saved
Remembers the history as it stands at a save, so later imports and restorations can be told apart.
masked_fill
Floods a fill from its point over the pixels is_point_allowed() takes; the others are boundaries. With rows,
a view's region map, only pixels of region fill.
new_transaction
Existing paint left outside changed bounds can always be erased; new paint stays inside.
paint_above
Whether any layer has paint in the top rows rows of any view.
pixels_changed
Pixels changed: serialization and the colours in use are worked out again, and so is the window's canvas, only that layer's view when one is named, and only the pixels a step changed when it gives its points. A view keeps the points of at most CUSTOM_SPRITE_MAX_PATCH_STEPS steps, and no more points than it has pixels: past either it is encoded whole, so a view the window doesn't show, as an appendage's hidden one, holds no more however long it is painted.
Arguments:
- direction: The view that changed, or null for every view of every layer.
- layer: The layer that changed.
- points: The step's points, list(x, y, ...) each, when only they changed.
preprocess_new_transaction
Treat masked pixels as fill boundaries, so disconnected parts do not fill through the backdrop.
record_step
Applies a step the editor built itself, such as adding an appendage, and records it for undo under the same limits as any other step.
With check_palette, the palette then keeps only the colours the draft and its history use; a step
whose colours wouldn't fit is rolled back instead, leaving everything as it was, and FALSE is returned.
remove_appendage
Removes an appendage layer, paint and all, as an undoable step.
replace_drawing
Replaces every view, emission setting and the base hair look as one undoable action.
The caller has already validated the drawing for this destination, so this bypasses the per-stroke bounds checks. Colors needed by the replacement and by undo history share the normal 63-color limit. Drawings without an explicit tint keep the old hair-color filter.
Arguments:
- drawing: Canonical drawing, or null for empty art.
- new_hair_context: The base hair look that goes with it.
- name: The undo history label.
- keep_layers: The drawing is this draft's own, recolored or re-fitted, so appendage layers keep their ids and unpainted ones stay. Imports and restorations replace them outright.
Returns:
- TRUE: Replaced, or already identical.
- FALSE: The drawing is too wide or combined colors would exceed the limit. Nothing changed.
replace_hair_context
Swaps the base hair look under paint that stays exactly as it is, as one undoable step. A new hairstyle never recolors paint, so this is all it changes: replace_drawing() would rebuild every layer to find no difference, and keep whole copies of each appendage layer in the history.
resize_height
Grows or shrinks the canvas to new_height rows where it stands, as picking or leaving the tall
base does: rows come and go at the top, so paint keeps its place on the head and every layer keeps
its id. The caller has made sure no paint sits in rows that go. History can't span two canvas
sizes, so it starts over; imports and restorations it held still count when the draft saves.
restore_unpainted_appendages
Puts unpainted appendage layers back where they were, after a canvas resize rebuilt the draft from its saved form.
reverse_transact
Reverses a step: this workspace's own through apply_step(), and anything else as the base workspace does.
serialize_drawing
The draft as a canonical drawing, cached until pixels change; null when empty or over the colour limit.
serialize_drawing_with
The drawing serialize_drawing() would give with frames as the views of layer, for a preview of
paint that isn't placed yet. The draft and its caches are left exactly as they were.
set_appendage
Changes an appendage's name, zone or kind as an undoable step. The caller has already made the value canonical. Returns FALSE when nothing would change.
sprite_editor_ui_data
The window gets the canvas as palette indexes rather than a color string per pixel.
step_colors
The opaque colors one history step paints with or over, in the order it first uses them. A move or placement's own colors count, so they stay paintable while the step waits undone to be redone.
Worked out once and kept on the step, which never changes once it's in the history: a history of whole-canvas steps would otherwise be read pixel by pixel on every palette refresh.
step_layers
Appendage layers a history step keeps whole: the one it adds or removes, or both sets a replacement swaps.
step_points
The pixels one history step records: its points, every view a replacement changed, and every pixel of a layer it keeps whole. Counted once and kept on the step, which never changes once it is in the history, as trim_history() counts the whole history after every stroke.
stroke_layer_matches
Whether a stroke names the layer it paints: appendage layers are named by id as well, so a stroke meant for one that undo just moved can't land on another.
stroke_mask_slots
Returns the slots a compact stroke mask is cut down to as it is read (custom_sprite_mask_points()'s allowed), for a
canvas whose mask strokes then need no check of each point.
Returns:
- list: The slots.
- null: Strokes are read whole and checked point by point.
transact
Applies a step: this workspace's own through apply_step(), a pencil stroke by assigning its colour, and anything else as the base workspace does.
trim_history
Keeps the undo history within CUSTOM_SPRITE_MAX_UNDO steps and CUSTOM_SPRITE_MAX_UNDO_POINTS recorded pixels, dropping the oldest first.
unpainted_appendages
The draft's unpainted appendage layers and where they sit among the others, which a drawing can't carry through a canvas resize.
unsaved_rotations
Rotation markers of imports and restorations applied since the last save and not undone.
Saving with any keeps the replaced saved style as the previous one.
update_edited_direction
Update only the affected direction of layer, without serializing the drawing for its UI marker.
update_palette
Keeps current and undoable colors paintable, then admits available colors in order while there's room.
Returns TRUE when every available color fit. When the kept colors alone need more than CUSTOM_SPRITE_MAX_COLORS, or an available color is invalid, the palette is left alone.
used_colors
The opaque colours every layer's frames use, lowercase, in first-use order. The layers share one palette.
valid_layer
Whether layer is a whole number naming one of the layers, from lowest on: 2 names only appendage layers.
validate_palette_color
Refuses a stroke colour that isn't in the palette.