Skip to content

Commit 613be85

Browse files
TMHSDigitalclaude
andauthored
fix(site): correct landing-page claims and render README tables on gallery pages (#208)
A review of the live Pages site found the landing page naming Blender 5.1 as the primary target and calling every render a CI artifact, when CI checks 5.2 LTS and 4.5 LTS and renders only swatch-grid. The Rules table's Scope column was empty because the parser stopped at `description`, and render cards showed no keyboard focus ring. On the gallery, the README converter had no table, emphasis, ordered-list or image support, so all 182 budget tables printed as raw pipe text. - template: 5.2 LTS / 4.5 LTS wording, accurate render claim, visible focus on render cards, showcase CTA links to #tag=showcase, rules and templates copy match the repo, stats rendered server-side - build_site: parse `globs` YAML lists for the rule scope column; HUD example count includes check-only examples (plugin.json) - build_gallery: pipe tables, *emphasis*, ordered lists, inline images; drop the README's own preview image, which duplicates the hero Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent 3a1d501 commit 613be85

83 files changed

Lines changed: 841 additions & 362 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎docs/gallery/anvil/index.html‎

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,13 @@
191191
.md h1, .md h2, .md h3 { letter-spacing: -0.01em; margin: 1.4rem 0 0.6rem; line-height: 1.25; }
192192
.md h1 { font-size: 1.35rem; } .md h2 { font-size: 1.15rem; } .md h3 { font-size: 1rem; }
193193
.md p { margin: 0.7rem 0; }
194-
.md ul { margin: 0.7rem 0 0.7rem 1.4rem; }
194+
.md ul, .md ol { margin: 0.7rem 0 0.7rem 1.4rem; }
195195
.md li { margin: 0.3rem 0; }
196+
.md .table-wrap { overflow-x: auto; margin: 0.9rem 0; }
197+
.md table { border-collapse: collapse; font-size: 0.86rem; min-width: 100%; }
198+
.md th, .md td { text-align: left; vertical-align: top; padding: 0.4rem 0.75rem 0.4rem 0;
199+
border-bottom: 1px solid var(--border); }
200+
.md th { color: var(--text-dim); font-weight: 600; white-space: nowrap; }
196201
.md code { background: var(--surface-2); border: 1px solid var(--border); padding: 0.08rem 0.35rem;
197202
border-radius: 4px; font-family: var(--font-mono); font-size: 0.84em; }
198203
.md pre { background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius);
@@ -265,17 +270,17 @@ <h1>anvil</h1>
265270
<p><strong>Composes</strong> skills <code>mesh-editing-and-bmesh</code>, <code>bake-high-to-low</code>, <code>depsgraph-and-evaluated-data</code>, <code>engine-export-presets</code>, and snippets <code>bake_normal_high_to_low.py</code>, <code>setup_bake_target_image.py</code>, <code>lod_chain.py</code> / <code>decimate_to_budget.py</code>, <code>convex_hull_collider.py</code>, <code>export_preset_unity.py</code> (helpers copied, not imported as a package).</p>
266271
<h2>Budgets</h2>
267272
<p>Declared as named constants; every gate <strong>recomputes</strong> from the mesh, materials, UVs, evaluated LOD, collider, or export file.</p>
268-
<p>| Axis | Declared | Measured (4.5.11 / 5.1.2 / 5.2.1) | | --- | --- | --- | | Base triangles | 2500–4500 | 2988 / 2988 / 2988 | | LOD1 ratio | 0.32–0.62 of base | 0.5000 / 0.5000 / 0.5000 | | LOD2 ratio | 0.10–0.35 of base | 0.2195 / 0.2195 / 0.2195 | | Materials | exactly 2 distinct; ≥400 wood, ≥400 metal faces | 2 slots; 1040 / 822 | | UVs | in <code>0..1</code>, AABB overlap ≤ 1e-5 | in range, overlap 0 | | Outer AABB | (0.621, 0.414, 0.489) m ± 0.015 | (0.6210, 0.4137, 0.4890), zmin 0 | | Collider tris | ≤ 280 | 134 | | Export | written, size &gt; 0 | 244052 / 244052 / 244036 bytes |</p>
273+
<div class="table-wrap"><table><thead><tr><th scope="col">Axis</th><th scope="col">Declared</th><th scope="col">Measured (4.5.11 / 5.1.2 / 5.2.1)</th></tr></thead><tbody><tr><td>Base triangles</td><td>2500–4500</td><td>2988 / 2988 / 2988</td></tr><tr><td>LOD1 ratio</td><td>0.32–0.62 of base</td><td>0.5000 / 0.5000 / 0.5000</td></tr><tr><td>LOD2 ratio</td><td>0.10–0.35 of base</td><td>0.2195 / 0.2195 / 0.2195</td></tr><tr><td>Materials</td><td>exactly 2 distinct; ≥400 wood, ≥400 metal faces</td><td>2 slots; 1040 / 822</td></tr><tr><td>UVs</td><td>in <code>0..1</code>, AABB overlap ≤ 1e-5</td><td>in range, overlap 0</td></tr><tr><td>Outer AABB</td><td>(0.621, 0.414, 0.489) m ± 0.015</td><td>(0.6210, 0.4137, 0.4890), zmin 0</td></tr><tr><td>Collider tris</td><td>≤ 280</td><td>134</td></tr><tr><td>Export</td><td>written, size &gt; 0</td><td>244052 / 244052 / 244036 bytes</td></tr></tbody></table></div>
269274
<p>Base triangles dropped from <strong>6616 to 2988</strong> in the quality pass: overlapping face boxes and a beveled superellipse horn became one slotted slab plus a circular oval loft. Hidden coincident faces were the waste.</p>
270275
<p>DECIMATE COLLAPSE triangle counts are <strong>not</strong> identical across series — the gate is a ratio band, not an exact count. Bake pixels are stochastic; the gate is <code>has_data</code> plus operator <code>FINISHED</code>, not byte-identity. Stave-width jitter uses fixed seed 17. Export byte counts differ by 16 B on 5.2.1 (glTF serializer), not a gated axis.</p>
271276
<h3>Hygiene</h3>
272277
<p>Recomputed from the generated mesh, not asserted about the script.</p>
273-
<p>| Axis | Declared | Measured (all three) | | --- | --- | --- | | Non-manifold edges | 0 | 0 | | Loose verts / edges | 0 / 0 | 0 / 0 | | Doubles merged at 1e-5 | 0 | 0 | | Zero-area faces | 0 | 0 | | N-gons | 0 | 0 | | Coplanar disjoint face pairs | 0 | 0 | | Grounded: <code>zmin</code> | within 1e-4 of 0 | 0.0000 | | Named supports: 16 staves | each <code>zmin</code> ≤ 0.001 | 16, stave_z 0.00000 | | Body plan | 0.621 m long × 0.180 m high ± 0.05 | 0.6210 × 0.1800 |</p>
278+
<div class="table-wrap"><table><thead><tr><th scope="col">Axis</th><th scope="col">Declared</th><th scope="col">Measured (all three)</th></tr></thead><tbody><tr><td>Non-manifold edges</td><td>0</td><td>0</td></tr><tr><td>Loose verts / edges</td><td>0 / 0</td><td>0 / 0</td></tr><tr><td>Doubles merged at 1e-5</td><td>0</td><td>0</td></tr><tr><td>Zero-area faces</td><td>0</td><td>0</td></tr><tr><td>N-gons</td><td>0</td><td>0</td></tr><tr><td>Coplanar disjoint face pairs</td><td>0</td><td>0</td></tr><tr><td>Grounded: <code>zmin</code></td><td>within 1e-4 of 0</td><td>0.0000</td></tr><tr><td>Named supports: 16 staves</td><td>each <code>zmin</code> ≤ 0.001</td><td>16, stave_z 0.00000</td></tr><tr><td>Body plan</td><td>0.621 m long × 0.180 m high ± 0.05</td><td>0.6210 × 0.1800</td></tr></tbody></table></div>
274279
<h3>Joint fit and seat</h3>
275-
<p>| Axis | Declared | Measured (all three) | | --- | --- | --- | | Foot-on-head BVH gap | ≤ 0.006 m | 0.00300 | | Hoop bite (host r − inner hoop r) | 0.0012–0.008 m | 0.00300 |</p>
280+
<div class="table-wrap"><table><thead><tr><th scope="col">Axis</th><th scope="col">Declared</th><th scope="col">Measured (all three)</th></tr></thead><tbody><tr><td>Foot-on-head BVH gap</td><td>≤ 0.006 m</td><td>0.00300</td></tr><tr><td>Hoop bite (host r − inner hoop r)</td><td>0.0012–0.008 m</td><td>0.00300</td></tr></tbody></table></div>
276281
<h3>Falsifiers</h3>
277282
<p>Each violates one named budget. All six were run on 4.5.11, 5.1.2 and 5.2.1 and returned the same code on each.</p>
278-
<p>| Flag | Budget violated | Exit | | --- | --- | --- | | <code>--skip-decimate</code> | LOD1 ratio band | 9 | | <code>--stray-vert</code> | loose vertex count is 0 | 15 | | <code>--lift-z</code> | bounding box <code>zmin</code> is 0 | 16 | | <code>--short-staves</code> | named stave supports at Z=0 | 16 | | <code>--float-anvil</code> | foot-on-head gap | 17 | | <code>--round-band</code> | hoop bite band | 18 |</p>
283+
<div class="table-wrap"><table><thead><tr><th scope="col">Flag</th><th scope="col">Budget violated</th><th scope="col">Exit</th></tr></thead><tbody><tr><td><code>--skip-decimate</code></td><td>LOD1 ratio band</td><td>9</td></tr><tr><td><code>--stray-vert</code></td><td>loose vertex count is 0</td><td>15</td></tr><tr><td><code>--lift-z</code></td><td>bounding box <code>zmin</code> is 0</td><td>16</td></tr><tr><td><code>--short-staves</code></td><td>named stave supports at Z=0</td><td>16</td></tr><tr><td><code>--float-anvil</code></td><td>foot-on-head gap</td><td>17</td></tr><tr><td><code>--round-band</code></td><td>hoop bite band</td><td>18</td></tr></tbody></table></div>
279284
<h2>Run</h2>
280285
<pre><code>blender --background --python anvil.py --
281286
blender --background --python anvil.py -- --skip-decimate
@@ -288,7 +293,7 @@ <h2>Run</h2>
288293
<p>Smoke passes no flags.</p>
289294
<h2>Exit codes</h2>
290295
<p>File-local. <code>9</code> is a valid check code. <code>10</code> is reserved for <code>gallery_framing.check_framing</code> on the <code>--output</code> path. <code>15</code>–<code>19</code> are the hygiene and joint-fit family.</p>
291-
<p>| Code | Meaning | | --- | --- | | 0 | Success | | 1 | Uncaught exception (FATAL wrapper) | | 2 | argparse / usage | | 3 | Mesh did not build / no UV layer | | 4 | Base triangle count outside range | | 5 | Material count ≠ 2 distinct slots, or a face-count floor missed | | 6 | UVs outside 0..1 | | 7 | UV AABB overlap above tolerance | | 8 | World AABB off declared outer size | | 9 | LOD ratio band (<code>--skip-decimate</code> lands here) | | 10 | Framing gate (render path only) | | 11 | Collider triangle count above ceiling | | 12 | Bake did not finish or image has no data | | 13 | Export file missing or empty | | 14 | <code>--output</code> produced no file | | 15 | Mesh hygiene: loose, non-manifold, zero-area, doubles, n-gons, z-fight | | 16 | Not grounded: bounding box <code>zmin</code> off 0, or a named stave floats | | 17 | Joint fit: foot-on-head gap (<code>--float-anvil</code>) | | 18 | Seat: hoop bite band (<code>--round-band</code>) | | 19 | Body length or height off the stated real-world size |</p>
296+
<div class="table-wrap"><table><thead><tr><th scope="col">Code</th><th scope="col">Meaning</th></tr></thead><tbody><tr><td>0</td><td>Success</td></tr><tr><td>1</td><td>Uncaught exception (FATAL wrapper)</td></tr><tr><td>2</td><td>argparse / usage</td></tr><tr><td>3</td><td>Mesh did not build / no UV layer</td></tr><tr><td>4</td><td>Base triangle count outside range</td></tr><tr><td>5</td><td>Material count ≠ 2 distinct slots, or a face-count floor missed</td></tr><tr><td>6</td><td>UVs outside 0..1</td></tr><tr><td>7</td><td>UV AABB overlap above tolerance</td></tr><tr><td>8</td><td>World AABB off declared outer size</td></tr><tr><td>9</td><td>LOD ratio band (<code>--skip-decimate</code> lands here)</td></tr><tr><td>10</td><td>Framing gate (render path only)</td></tr><tr><td>11</td><td>Collider triangle count above ceiling</td></tr><tr><td>12</td><td>Bake did not finish or image has no data</td></tr><tr><td>13</td><td>Export file missing or empty</td></tr><tr><td>14</td><td><code>--output</code> produced no file</td></tr><tr><td>15</td><td>Mesh hygiene: loose, non-manifold, zero-area, doubles, n-gons, z-fight</td></tr><tr><td>16</td><td>Not grounded: bounding box <code>zmin</code> off 0, or a named stave floats</td></tr><tr><td>17</td><td>Joint fit: foot-on-head gap (<code>--float-anvil</code>)</td></tr><tr><td>18</td><td>Seat: hoop bite band (<code>--round-band</code>)</td></tr><tr><td>19</td><td>Body length or height off the stated real-world size</td></tr></tbody></table></div>
292297
</section>
293298
<section class="detail-section src">
294299
<h2>Source</h2>

‎docs/gallery/armature-bend/index.html‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,13 @@
191191
.md h1, .md h2, .md h3 { letter-spacing: -0.01em; margin: 1.4rem 0 0.6rem; line-height: 1.25; }
192192
.md h1 { font-size: 1.35rem; } .md h2 { font-size: 1.15rem; } .md h3 { font-size: 1rem; }
193193
.md p { margin: 0.7rem 0; }
194-
.md ul { margin: 0.7rem 0 0.7rem 1.4rem; }
194+
.md ul, .md ol { margin: 0.7rem 0 0.7rem 1.4rem; }
195195
.md li { margin: 0.3rem 0; }
196+
.md .table-wrap { overflow-x: auto; margin: 0.9rem 0; }
197+
.md table { border-collapse: collapse; font-size: 0.86rem; min-width: 100%; }
198+
.md th, .md td { text-align: left; vertical-align: top; padding: 0.4rem 0.75rem 0.4rem 0;
199+
border-bottom: 1px solid var(--border); }
200+
.md th { color: var(--text-dim); font-weight: 600; white-space: nowrap; }
196201
.md code { background: var(--surface-2); border: 1px solid var(--border); padding: 0.08rem 0.35rem;
197202
border-radius: 4px; font-family: var(--font-mono); font-size: 0.84em; }
198203
.md pre { background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius);
@@ -261,7 +266,7 @@ <h1>armature-bend</h1>
261266
<section class="detail-section md">
262267
<p>A runnable example that rigs a tapered, segmented tube with a four-bone armature chain — <code>edit_bones</code> construction, name-bound vertex groups with smoothstep blend zones, a posed curl — and checks the depsgraph-evaluated result against closed-form linear blend skinning, following <a href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/skills/mesh-editing-and-bmesh/SKILL.md"><code>mesh-editing-and-bmesh</code></a> and <a href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/skills/depsgraph-and-evaluated-data/SKILL.md"><code>depsgraph-and-evaluated-data</code></a>.</p>
263268
<p><strong>What it witnesses:</strong> the three contracts AI-generated rigging code most often gets wrong.</p>
264-
<p>1. <code>edit_bones</code> only exists in edit mode — the collection is asserted empty in object mode and holding the full chain (heads/tails at closed-form positions) inside <code>mode_set(mode=&#x27;EDIT&#x27;)</code>. Outside edit mode, reads silently return nothing. 2. Vertex groups bind to bones <strong>by name</strong>; a typo deforms nothing without erroring. Every group here is named after its bone and the deform proves the binding. 3. The armature modifier is exactly linear blend skinning: for *every* vertex, <code>evaluated == Σ wᵢ · (pose_bone.matrix @ bone.matrix_local.inverted()) @ rest</code>. The check re-implements LBS from the pose matrices and compares the whole evaluated mesh (max error ~5e-7). The root ring must stay pinned and the tip must deflect — a straight tube is a failure.</p>
269+
<ol><li><code>edit_bones</code> only exists in edit mode — the collection is asserted empty in object mode and holding the full chain (heads/tails at closed-form positions) inside <code>mode_set(mode=&#x27;EDIT&#x27;)</code>. Outside edit mode, reads silently return nothing.</li><li>Vertex groups bind to bones <strong>by name</strong>; a typo deforms nothing without erroring. Every group here is named after its bone and the deform proves the binding.</li><li>The armature modifier is exactly linear blend skinning: for <em>every</em> vertex, <code>evaluated == Σ wᵢ · (pose_bone.matrix @ bone.matrix_local.inverted()) @ rest</code>. The check re-implements LBS from the pose matrices and compares the whole evaluated mesh (max error ~5e-7). The root ring must stay pinned and the tip must deflect — a straight tube is a failure.</li></ol>
265270
<p>The armature API is identical on Blender 4.5 LTS and 5.1 — no version gate needed. One portability hazard is baked in as a comment: interleaving <code>color_attributes</code> writes with <code>VertexGroup.add()</code> dangles the attribute reference when the deform layer is allocated (hard crash on 4.5, silent luck on 5.1), so the script finishes all weight writes before creating the color attribute.</p>
266271
<p>The render shows rest → half curl → full curl left to right, with per-bone weight bands visualized through a <code>BoneTint</code> color attribute — the smooth color blends at the joints are the same weights the LBS check asserts.</p>
267272
<h2>Run</h2>
@@ -276,7 +281,7 @@ <h2>Run</h2>
276281
blender --background --python armature_bend.py -- --output bend.png --engine cycles</code></pre>
277282
<h2>Exit codes</h2>
278283
<p>Per-script sequential checks. <code>9</code> is a valid check code; there is no rule against it.</p>
279-
<p>| Code | Meaning | | --- | --- | | 0 | Success | | 1 | Uncaught exception (FATAL wrapper) | | 2 | argparse / usage | | 3 | <code>edit_bones</code> populated in object mode | | 4 | Edit-mode bone chain off closed form | | 5 | Evaluated vertex count changed | | 6 | Evaluated mesh off closed-form LBS | | 7 | Root ring moved | | 8 | Tip did not deflect (<code>--zero-curl</code> lands here) | | 9 | <code>--output</code> produced no file |</p>
284+
<div class="table-wrap"><table><thead><tr><th scope="col">Code</th><th scope="col">Meaning</th></tr></thead><tbody><tr><td>0</td><td>Success</td></tr><tr><td>1</td><td>Uncaught exception (FATAL wrapper)</td></tr><tr><td>2</td><td>argparse / usage</td></tr><tr><td>3</td><td><code>edit_bones</code> populated in object mode</td></tr><tr><td>4</td><td>Edit-mode bone chain off closed form</td></tr><tr><td>5</td><td>Evaluated vertex count changed</td></tr><tr><td>6</td><td>Evaluated mesh off closed-form LBS</td></tr><tr><td>7</td><td>Root ring moved</td></tr><tr><td>8</td><td>Tip did not deflect (<code>--zero-curl</code> lands here)</td></tr><tr><td>9</td><td><code>--output</code> produced no file</td></tr></tbody></table></div>
280285
<p>The <code>blender-smoke</code> workflow runs the check on Blender 5.2 LTS and 4.5 LTS (5.1 on the weekly cron, the <code>needs-5.1</code> PR label, or manual dispatch). Smoke does not pass <code>--output</code> or <code>--zero-curl</code>.</p>
281286
</section>
282287
<section class="detail-section src">

0 commit comments

Comments
 (0)