Growth stages as maps
A vanilla crop has four to eight growth stages. Drawing each one separately is slow, and separately drawn stages drift: the stalk moves a column, a leaf attaches somewhere new, and the plant seems to jump as it grows. TextureScript derives the stages instead.
Draw the mature plant, then say when each part appears
You draw the mature plant once. Then a stage map, a 16×16 grid of digits, labels every opaque pixel with the first stage it appears in. Stage n is the mature plant with only the pixels labelled n or lower.
This captures how vanilla crops grow. Measured on wheat, the pitcher crop and the root crops, growth is additive in silhouette: the stalk keeps its position, leaves keep their attachment points, and new parts arrive in later stages. The map makes that the default, so stages cannot drift.
Additive in silhouette, not in colour
Vanilla young stages are not just cropped copies of the mature plant. Young wheat is brighter and greener; ripening recolours most retained pixels. So a stages file adds two transformations on top of the map:
shiftdraws a stage some shades lighter within each material. Because shades come from a ramp, "two shades lighter" is well defined.recolourdraws one key as another up to a given stage, for a part that is a different material when young, like a root that reads as leaf until it swells.
When a map is not enough
Some 10 to 15% of a vanilla stage's pixels move in the next stage: a leaf tip re-angles, a
sprout is drawn lower than any mature pixel. A map cannot move pixels. For those stages you edit
the generated grid by hand and regenerate with --keep, which keeps your drawing and still
lints it. The generated stages do most of the work; hand edits handle the exceptions.
Every stage is checked
stages lints every half of every stage, checks the seam between the halves of two-block
stages, and refuses a map that does not label exactly the mature pixels. A growth design is
either complete and consistent or it is refused.