Appendix G The part table’s fields, at a glance
work/<name>/parts.py, an ordinary Python module; a missing field is a hard error (config.REQUIRED). The template is dtp/templates/project/parts.py — copy it into the subproject.
| field | which stages it governs | format | how to write it | change it, rerun from |
|---|---|---|---|---|
ASSIGN | segment (1); the one-shot route uses only this one; with the lines as walls (ASSIGN_FROM) it inherits the previous step’s | [("sub-part", [region number, …]), …] | written against the regions.png of the first segment; the order is the occlusion order, bottom -> top | all of it, from segment |
ORDER | segment, and the one-shot route’s tree | [n for n, _ in ASSIGN] | never edited | — |
CLASSES | the majority vote in segment | [("class", ["word", …], ["sub-part", …]), …] | the order is the priority: small and specific first | from segment |
SAM_WORDS | segment | ["hair", "red bow", …] | the more specific the word the better; a word whose mask covers more than 40% of the subject is useless | from segment |
KEEP_ASSIGN_REGION | segment | ["sub-part", …] | the sub-parts that skip the vote and keep the whole region the hand-written table gave them | from segment |
GROUPS | complete (3), per-layer lineart, draft (5), paint | [("group", ["sub-part", ...]), ...] | a group is one layer, the union of its sub-parts; the order is the occlusion order, which is the order of the groups in the .kra. Written by looking at the region image and the lineart image | from complete |
SHARED_FLAT_COLOR | draft (5) | {"group": "shared name", …} | the groups that share one local colour | from draft |
GROUPS_FROM_MASK | per-layer lineart (4), draft (5) | [("group", "mask_x.png", "after which group", "the sub-part it depends on")] | a layer split out of another group with an AI mask | from lines |
LINES | lineart (2) | [("Line_X", ["sub-part", …]), …] | the lineart layers; every sub-part belongs to exactly one of them | from lineart |
LINE_LAYER_OF_GROUP | per-layer lineart (4) | {"group": "Line_X", …} | which lineart layer each layer’s lines go to, the GROUPS_FROM_MASK groups included; a group that is not listed gets no lines | from lines |
STRAND_GROUPS | paint (6), one-shot | {"group", …} | the groups that grow strands. Empty in the template; the one-shot route also needs strands=True | paint / trace |
HATCH_GROUPS | one-shot (8) | {"sub-part", …} | the sub-parts that get hatching. Empty in the template; the one-shot route also needs hatch=True | trace |
SEETHROUGH | complete (3) | {"group": ["its layers", …], …} | which See-through layers each group takes as candidates for its whole shape (only the occluded part is used); a group that is not listed only gets its seam filled; the layer names are in the template’s comments | from complete |
LINE_DROP_BY_LAYER | paint (6) | {"Line_X": 6.0, …} | one lineart layer’s own threshold: a line that is not darker than its surroundings by at least this much is not painted; a layer that is not listed uses the line_drop knob of the paint step | paint |
PAINT | paint (6) | {"group": dict(method=..., ...), "*": dict(method="generic")} | which method paints each group (method is a name in dtp.paint.METHODS, one page per body part: shadow_tier skin - eye eyes - hair hair - generic the baseline “copy” - eight placeholders) and its knobs; "*" is mandatory; a misspelled name fails the part table, and a group that picked a placeholder raises “not decided yet” at paint time | paint |
CROPS | review (7) | {"face": (x, y), "neck": …, …} | the centres of the 1:1 close-ups, in 8x coordinates; at least the face, the neck, the hands and the feet | the next painting run |