@rig-c/parts 1.19.0 → 1.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -37,7 +37,7 @@ config beside the values it replaced: the two outer skirt chains were moved out
37
37
  against 1.4725; moved, 2.425). One input-stage edit: <code>hair_back</code> is taken
38
38
  from the full run, because the twin tails leave the head crop sideways (a plan edit).
39
39
  <code>check</code> printed, verbatim:<br/>
40
- <code>51 assertions: 25 measured (25 passed, 0 failed), 26 skipped, 0 not in profile "spine-html"</code><br/>
40
+ <code>50 assertions: 24 measured (24 passed, 0 failed), 26 skipped, 0 not in profile "rig-play"</code><br/>
41
41
  <code>loop: idle 41 frame(s) at 12 fps, f0000 vs f0040 (t = 3.333333333333333s) with the rig's 29 physics constraint(s) left out (named on the `loop physics:` line; rendered with them, the ends need not meet — `build --loop --lead-in &lt;n&gt;`): max |d| 0 (0 required)</code><br/>
42
42
  <code>seam: setup pose at 654x1216, scale 0.9438: mean |d| 0.147 (&lt;= 1.0), 0 px over 40, 0.00 rig px (the count / s²; &lt;= 50), 0 px over 80 (reported)</code><br/>
43
43
  <code>pack: skeleton.png 1051x972, 23 region(s), 96.9% covered, padding 2, page edges free, shape polygon</code><br/>
@@ -250,7 +250,9 @@ rig-parts assemble --source painting.png --full layers/full --head layers/head -
250
250
  # -> a large red hole neither run holds? add an assemble.patches entry (cut from the painting) and assemble again
251
251
  rig-parts propose --parts work/rig --source painting.png --out work
252
252
  # -> proposal.json, basis.json (what each bone rests on) and render/landmarks.png; per-bone coverage lines;
253
- # correct it, copy bones/meshes/regions/motion into config.json
253
+ # correct it, copy bones/meshes/regions/limbs/motion/constraints/turn into config.json, each it wrote
254
+ # (limbs only with --keypoints, constraints only with --cloth, turn only with --full/--head;
255
+ # a limbs block left out is refused next)
254
256
  rig-parts propose --parts work/rig --source painting.png --out work --from-config config.json
255
257
  # -> LINT lines; exit 1 while any remain
256
258
  rig-parts build --config config.json --source painting.png --full layers/full --head layers/head --out out --loop
@@ -264,7 +266,18 @@ from a config holding only what the first step reads (`RL01`). On `demo` the
264
266
  proposal pasted uncorrected stops at the last step, naming its `bottomwear` on
265
267
  `CHECK_TIP_OVER_ROOT` — the correction its tracked config records there, the two outer
266
268
  skirt chains moved (issue #227, [its README](examples/demo/README.md)); on `scarf`,
267
- since issue #262, it builds green.
269
+ since issue #262, it builds green, and on `wind` too. `wind`'s config declares the cloth
270
+ recipe and its limbs, so the block runs on it again with that `cloth` block authored,
271
+ `--cloth config.json` on the drafting `propose` line and its tracked `keypoints.json` on both
272
+ `propose --parts` lines (`RL05`): it pastes `limbs` and `constraints` with the rest and gives
273
+ back the tracked config, section for section ([its README](examples/wind/README.md)).
274
+ On `demo`, which tracks the pose file it was painted on, the block runs again with
275
+ `--keypoints` on both `propose --parts` lines (`RL03`): the proposal then also drafts
276
+ `limbs`, the step's list carries them, and the run ends where `RL01` ends. The joints
277
+ are that pose file scaled to the painting, not read off it, so this shows what the
278
+ loop carries, not where the joints are. On `wind`, which tracks the joints read off its
279
+ painting (`keypoints.json`), `RL03` runs with those. The list as it stood before issue #375, four
280
+ sections, stops at `--from-config` naming every limb part (`RL04`).
268
281
 
269
282
  `propose` is deliberately not a step of `build`: the proposal is a draft to correct
270
283
  against its overlay, and a config with bones is `build`'s input. `rig`, `check` and
package/cli.ts CHANGED
@@ -19,7 +19,7 @@ import { DEFAULT_PROJECT_RULE, DEFAULT_SEAM_RULE, HOLES_LISTED, PROJECT_RULES, t
19
19
  import { assembleStage, build, checkStage, ERROR_MAP_FILE, loopStage, readRuns, readSource, rigStage, suppliedCheckFlag } from './src/build.ts';
20
20
  import { ACCEPTABLE_BARS, DEFAULT_PACK_SHAPE, DEFAULT_PAGE_EDGES, findRigc, PACK_SHAPES, rigcRunnerAt, type PackShape, PAGE_EDGES, type PageEdges, PARTS_HOME_SENTENCE, RIGC_GEOMETRY_VERSION, type RigcRunner, NO_PARTS_SENTENCE, SEAM_MEAN_BAR, SOURCE_SENTENCE, SEAM_PX_BAR, SEAM_PX_LEVEL, SPINEBOY_YARDSTICK, TEXTURE_STRETCH_CEILING } from './src/check.ts';
21
21
  import { ComfyClient, resolveHost, runPainting, runSeeThrough } from './src/comfy/index.ts';
22
- import { type CharacterConfig, loadConfig, loadEarlyConfig, loadPaintConfig } from './src/config.ts';
22
+ import { type CharacterConfig, loadClothConfig, loadConfig, loadEarlyConfig, loadPaintConfig } from './src/config.ts';
23
23
  import { failLine, guidePointer, PartsError } from './src/errors.ts';
24
24
  import { GUIDE_DOC, type GuideAnswer, guideRule, guideSection } from './src/guide.ts';
25
25
  import { proposeHeadBox } from './src/headbox.ts';
@@ -197,6 +197,20 @@ usage:
197
197
  reference's rule, a tenth of the part's short side clamped to 5..36.
198
198
  r is the part rule's under both.
199
199
 
200
+ rig-parts propose … [--cloth <config.json>]
201
+ Draft cloth and hair as trees that answer the world (issue #364), from
202
+ the config's "cloth" block — a recipe per tag, bottomwear, back hair
203
+ and front hair (AUTHORING §3, *Recipe: cloth and hair*). Each tagged
204
+ piece hangs "chains" trees of "links" links from its attachment bone
205
+ (hip, or head), forked by "split", the links shortening toward the tip;
206
+ proposal.json's "constraints" puts a physics constraint on every link,
207
+ its strength by trunk, branch or edge, its wind and gravity response
208
+ on a ramp from the declared root value to the tip value (multipliers
209
+ of the consumer's environment — no direction is drafted), and drafts no
210
+ idle key on them. A bottomwear recipe's "swing" drives each tree's
211
+ first link from one shared pendulum. A recipe that drafts nothing is
212
+ refused (PROPOSE_CLOTH_DRAFTED). Without --cloth nothing changes.
213
+
200
214
  rig-parts propose --parts <dir> --source <painting.png> --out <dir> --from-config <config.json>
201
215
  Draw the config's CURRENT bones instead (<out>/render/landmarks_config.png
202
216
  and _head) and LINT them (by the joints too, given --keypoints), with the
@@ -262,7 +276,7 @@ usage:
262
276
  written into motion.json as read, for rigc's gate to judge (AUTHORING
263
277
  §3). --parts is the
264
278
  directory holding parts.json and parts/<name>.png. The result is built
265
- through rig-c (profile spine-html, packed with --page-edges and
279
+ through rig-c (profile rig-play, packed with --page-edges and
266
280
  --pack-shape as for check; rigc's build gates the compile and the packed pages on disk) in a
267
281
  scratch directory first, and --out receives images/*.png, rig.json,
268
282
  motion.json and mesh_report.json only when it is green. Prints one line
@@ -323,7 +337,7 @@ usage:
323
337
  builds); an "idle" in it is not.
324
338
  ${PARTS_HOME_SENTENCE}; ${NO_PARTS_SENTENCE}.
325
339
  Both are only read. Into --out:
326
- build/ (rigc build --profile spine-html --pack --page-edges <value>
340
+ build/ (rigc build --profile rig-play --pack --page-edges <value>
327
341
  --pack-shape <value>: the packed atlas is the artifact), gate_spine-html.txt (the gate lines
328
342
  verbatim), idle_frames/ (rigc render --animation idle --fps 12 --max 640
329
343
  --geometry: the frames and geometry.json, the skinned vertices and
@@ -617,7 +631,7 @@ usage:
617
631
  another character without its prefix (SCENE_NAME_PREFIXED); a plate not
618
632
  of the canvas size; idles of different durations; a key in a build's
619
633
  rig or motion compose does not know. The result is gated through
620
- rig-c as rig gates its own (build --profile spine-html --pack, the
634
+ rig-c as rig gates its own (build --profile rig-play --pack, the
621
635
  compile and the packed pages on disk); --out receives rig/ (rig.json,
622
636
  motion.json, images/) and ${SCENE_REPORT_FILE} (spec "${SCENE_REPORT_SPEC}":
623
637
  every setting, each character's offset, scale, bounds and shift (and what it
@@ -763,7 +777,7 @@ const TAKES = {
763
777
  layers: { valued: ['--export', '--template', '--canvas'], switches: [] },
764
778
  sheet: { valued: ['--source', '--layers', '--out', '--cell', '--cols'], switches: [] },
765
779
  rig: { valued: ['--config', '--parts', '--out', '--idle-keys', '--page-edges', '--pack-shape'], switches: [] },
766
- propose: { valued: ['--parts', '--source', '--out', '--from-config', '--compare', '--full', '--head', '--canvas', '--keypoints', '--person', '--wrist-snap', '--grid-rule'], switches: ['--head-box'] },
780
+ propose: { valued: ['--parts', '--source', '--out', '--from-config', '--compare', '--full', '--head', '--canvas', '--keypoints', '--person', '--wrist-snap', '--grid-rule', '--cloth'], switches: ['--head-box'] },
767
781
  compare: { valued: ['--left', '--right', '--map'], switches: [] },
768
782
  check: { valued: ['--rig', '--out', '--parts', '--source', '--page-edges', '--pack-shape', '--requirements'], switches: ['--seam-pairs', '--keep-stills'] },
769
783
  loop: { valued: ['--frames', '--out'], switches: ['--palette'] },
@@ -1124,6 +1138,10 @@ function cmdPropose(args: string[]): number {
1124
1138
  if (ruleArg !== undefined && flags.has('--from-config')) return usage('--grid-rule chooses the drafted spacing; --from-config proposes nothing');
1125
1139
  if (ruleArg !== undefined && !(GRID_RULES as readonly string[]).includes(ruleArg)) return usage(`--grid-rule ${ruleArg}; one of ${GRID_RULES.join(', ')} is required`);
1126
1140
  const gridRule = (ruleArg ?? DEFAULT_GRID_RULE) as GridRule;
1141
+ // Issue #364: the cloth and hair recipe, read from a config's cloth block; without it nothing changes.
1142
+ const clothArg = flags.get('--cloth');
1143
+ if (clothArg !== undefined && flags.has('--from-config')) return usage('--cloth drafts trees while proposing; --from-config proposes nothing');
1144
+ const cloth = clothArg === undefined ? null : loadClothConfig(clothArg).cloth;
1127
1145
  const partsDir = existsSync(partsArg) && statSync(partsArg).isFile() ? dirname(partsArg) : partsArg;
1128
1146
  if (!existsSync(source)) {
1129
1147
  throw new PartsError([{ code: 'PROPOSE_SOURCE_PRESENT', object: source, detail: 'no such file; the painting is drawn under the overlay' }]);
@@ -1151,7 +1169,7 @@ function cmdPropose(args: string[]): number {
1151
1169
  }
1152
1170
  const cmpPath = flags.get('--compare');
1153
1171
  const cfg = cmpPath === undefined ? null : loadConfig(cmpPath);
1154
- const { proposal: drafted, basis } = proposeWithBasis(P, joints, wristSnap, gridRule);
1172
+ const { proposal: drafted, basis } = proposeWithBasis(P, joints, wristSnap, gridRule, cloth);
1155
1173
  const fullRun = flags.get('--full');
1156
1174
  const headRun = flags.get('--head');
1157
1175
  const prop =