Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
"examples/shape-key-blend",
"examples/sky-texture-sun-elevation",
"examples/soccer-ball-goldberg",
"examples/socket-attach-points",
"examples/swatch-grid",
"examples/temp-override-join",
"examples/text-version-stamp",
Expand Down
16 changes: 16 additions & 0 deletions .github/workflows/blender-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -593,3 +593,19 @@ jobs:
# non-zero on failure.
xvfb-run -a "$BLENDER" --background \
--python examples/lightmap-uv-channel/lightmap_uv_channel.py --

- name: Shipped example - socket attach points (spawn mount contract)
run: |
set -euo pipefail
# Check only (no render): a 21-part survey drone with 7 SKT_ socket
# empties and 7 seated modules; asserts every socket's evaluated
# world matrix equals the authored transform within 1e-6 with an
# orthonormal right-handed basis, socket +Z == the mount pad's
# Newell normal and origin == that face's centroid (two independent
# derivations), the documented up-axis fallback rule, modules seated
# with a strictly identity local transform, rigid invariance under a
# re-pose, and that freezing the root transform preserves world
# matrices while clearing all 7 parent-inverses and pushing the
# root scale down into the children. Exits non-zero on failure.
xvfb-run -a "$BLENDER" --background \
--python examples/socket-attach-points/socket_attach_points.py --
27 changes: 25 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
</p>

<p align="center">
<strong>12 skills</strong> &nbsp;&bull;&nbsp; <strong>6 rules</strong> &nbsp;&bull;&nbsp; <strong>2 templates</strong> &nbsp;&bull;&nbsp; <strong>17 snippets</strong> &nbsp;&bull;&nbsp; <strong>42 examples</strong>
<strong>12 skills</strong> &nbsp;&bull;&nbsp; <strong>6 rules</strong> &nbsp;&bull;&nbsp; <strong>2 templates</strong> &nbsp;&bull;&nbsp; <strong>17 snippets</strong> &nbsp;&bull;&nbsp; <strong>43 examples</strong>
</p>

<p align="center">
Expand All @@ -36,7 +36,7 @@

## Overview

This repository ships **12 skills, 6 rules, 2 templates, 17 snippets, and 38 runnable examples** for Blender Python development targeting Blender 5.1 (current stable) with Blender 4.5 LTS fallback support.
This repository ships **12 skills, 6 rules, 2 templates, 17 snippets, and 43 runnable examples** for Blender Python development targeting Blender 5.1 (current stable) with Blender 4.5 LTS fallback support.

The content is consumed by AI coding agents (Cursor, Claude Code, any MCP-capable client) when working on Blender add-ons, geometry nodes scripts, batch pipelines, or animation tooling. There is no build step. Edit the markdown and Python files directly.

Expand Down Expand Up @@ -820,6 +820,29 @@ by an independent SAT scan, and a measured min island distance of
[`uv-layer-grid`](examples/uv-layer-grid/) (UV authoring) and
[`triangulate-tangents`](examples/triangulate-tangents/) (tangents from UVs).

</td>
</tr>
<tr>
<td width="46%" valign="middle">
<a href="examples/socket-attach-points/"><img src="examples/socket-attach-points/preview.webp" alt="Socket attach points: a dark carbon survey quadcopter hovering on a studio stage, orange mount pads ringing each canted rotor, a gimbal camera pod under the belly and a sensor mast on the deck — every module seated exactly on its named socket" /></a>
</td>
<td valign="middle">

### [socket-attach-points](examples/socket-attach-points/)

Named `SKT_` empties as the spawn contract, on a reusable survey drone. All
**7** socket world matrices land within **1.788e-07** of the authored
transform with orthonormal right-handed bases, each socket's **+Z** equals its
mount pad's **Newell normal** (**1.794e-07**) by a derivation independent of
the basis construction, and modules seat at offset **exactly 0.0** with
identity local transforms. Freezing the root preserves world matrices but
clears **7/7** parent-inverses and pushes the root scale into the children —
both halves asserted. The no-parent-inverse probe jumps **0.690128 m**.
Companion to [`prop-origin-transform`](examples/prop-origin-transform/)
(pivot discipline) and
[`parent-inverse-orrery`](examples/parent-inverse-orrery/) (parent-inverse
under animation).

</td>
</tr>
</table>
Expand Down
1 change: 1 addition & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ Not committed; target list for the next content version. (v0.3.0 shipped the smo
- ~~Degenerate-bevel weld hazard~~ **SHIPPED** as `examples/degenerate-bevel-weld/` — at `offset == min_dim/2` the bevel band collapses to exactly 12 zero-area faces (4 min-axis edges × 3 segments) with 16 coincident verts (4 × (segments+1)) and min_area down 3.2e5×; a stdlib GLB re-parse counts **32 degenerate triangles crossing the export boundary** (MEASURED regression constant) versus 0 for the safe mesh — the loops an engine merge-by-distance welds; byte-identical on 4.5.11 and 5.1.2
- ~~Modular kit snap witness~~ **SHIPPED** as `examples/modular-kit-snap/` — tiling corridor segment: 16 boundary verts on `x ∈ {0, TILE}` within 1e-6 m, end rings coincident under the tile offset (nearest-key match), linked-duplicate joint deviation 0.0, shell bbox == declared tile (dev 0.0), manifold except the 16 open-end edges, 20 detail parts contained inside the tile; unsnapped probe (3 mm skew, 2 mm nudge) fails at exits 3/4 with measured errors; sorted-zip ring matching mispairs displaced verts — match by nearest key (authoring hazard, fixed); byte-identical on 4.5.11 and 5.1.2
- ~~Lightmap UV channel witness~~ **SHIPPED** as `examples/lightmap-uv-channel/` — two-channel UV contract on a market cart: per-part `UVMap`/`UVLight` with `active`/`active_render` re-asserted after the ops (edit-mode UV ops clear both flags; `uv_layers.new()` never moves them), UV0 drift 0.0 (clobber trap measured 2.068), every UV1 loop in [0,1], 0 overlapping islands via independent binned strict-SAT (15 hits when falsified), min island distance 0.00401 vs nominal margin 0.002 (`MARGIN_DIV × 0.01` semantics measured live); held `MeshUVLoopLayer.data` after edit-mode UV ops segfaults 4.5.11 (5/5, EXCEPTION_ACCESS_VIOLATION), silent no-op pack without prior unwrap; byte-identical on 4.5.11 and 5.1.2 (3680 islands)
- ~~Socket attach-point witness~~ **SHIPPED** as `examples/socket-attach-points/` — named `SKT_` empties as the spawn contract on a survey drone: 7 socket world matrices within 1.788e-07 of the authored transform with orthonormal right-handed bases (Gram 3.576e-07, det err 2.980e-07), socket +Z == the mount pad's Newell normal (1.794e-07) by a quaternion-swing construction independent of the Gram-Schmidt basis, origin on the mount-face centroid (6.687e-08), documented up-axis fallback for the +Z/−Z mounts, module seating offset exactly 0.0 with strictly identity local matrices, rigid invariance under a re-pose (2.384e-07); `transform_apply` on an **Empty** root preserves world matrices (2.235e-07) but clears **7/7** `matrix_parent_inverse` and pushes the root scale down into every child (0.35 for an applied 1.35) — both halves asserted; a child left selected during the apply drifts sockets **2.335 m**; `bm.normal_update()` does not fix inward winding (`recalc_face_normals` does — the lofted fuselage rendered as a flat white panel); no-parent-inverse probe jumps 0.690128 m; byte-identical on 4.5.11 and 5.1.2
- UV atlas **utilization** witness — coverage/wasted-texel closed forms for a packed lightmap atlas (the non-overlap, unit-square, margin, and active/active_render contracts shipped in `lightmap-uv-channel`; utilization is the remaining unbuilt slice of the old "UV atlas pack" candidate)
- ~~GAMMA_CROSS blend-curve witness~~ **SHIPPED** as `examples/vse-gamma-cross/` — the cross blends in a gamma-0.5 space: `((1-t)·√A + t·√B)²` with `t = (frame − start)/duration`, never 1 inside the effect; mid-cross dips 0.115 below the sRGB lerp from crimson/teal (closed form (0.341, 0.349, 0.463) confirmed per frame); AgX-default sampling poisons the fit (0.146 red-channel error, `view_transform='Standard'` mandatory); deleting a consumed input orphans-and-deletes the effect — follow-up to `vse-cut-list`
- Falsy `bpy_prop_collection` trap snippet: an empty collection is falsy, so `editor.strips or editor.sequences` silently falls through to the legacy accessor on an empty timeline — always branch on `hasattr`; likely generalizes across the API (found authoring `vse-cut-list`)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 12 additions & 1 deletion docs/gallery/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ <h1>Examples Gallery</h1>
autocomplete="off" spellcheck="false" aria-label="Search examples" />
<button class="q-clear" id="qClear" type="button" aria-label="Clear search" hidden>&times;</button>
</div>
<span class="count" id="count" role="status" aria-live="polite">42 examples</span>
<span class="count" id="count" role="status" aria-live="polite">43 examples</span>
<div class="density" role="group" aria-label="Card density">
<button class="density-btn" data-density="compact" type="button" aria-pressed="false">Compact</button>
<button class="density-btn" data-density="detailed" type="button" aria-pressed="false">Detailed</button>
Expand Down Expand Up @@ -784,6 +784,17 @@ <h2><a href="lightmap-uv-channel/">lightmap-uv-channel</a></h2>
<a class="card-link" href="lightmap-uv-channel/">View example <span aria-hidden="true">&rarr;</span></a>
</div>
</article>
<article class="card" data-tags="mesh transforms game-pipeline instancing">
<a class="card-media" href="socket-attach-points/" aria-label="socket-attach-points example detail page">
<img src="assets/socket-attach-points-hero.webp" alt="socket-attach-points — A survey drone whose named SKT_ empties are the spawn contract: modules parented with an identity local transform seat exactly on their mount pads." loading="lazy" decoding="async" />
</a>
<div class="card-body">
<h2><a href="socket-attach-points/">socket-attach-points</a></h2>
<p class="teaches">A survey drone whose named SKT_ empties are the spawn contract: modules parented with an identity local transform seat exactly on their mount pads.</p>
<p class="witnesses"><span class="tag">witnesses</span> 7 socket world matrices within 1.788e-07 of the authored transform, socket +Z == the pad&#x27;s Newell normal (1.794e-07), seating offset 0.0; the no-parent-inverse probe jumps 0.690128 m.</p>
<a class="card-link" href="socket-attach-points/">View example <span aria-hidden="true">&rarr;</span></a>
</div>
</article>
</div>
<p class="noresults" id="noResults" hidden>No examples match the current filters.
<button class="chip" id="resetFilters" type="button">Clear search and tags</button></p>
Expand Down
Loading
Loading