Skip to content

Commit f293573

Browse files
TMHSDigitalclaude
andcommitted
fix(rules): bulk-data and bmesh rules name only attributes that exist and are writable
Verified on .scratch/blender-4.5.11-windows-x64 and blender-5.2.1 (same on both): MeshLoop.normal is read-only; MeshEdge has no `crease` and no `use_sharp` (the property is use_edge_sharp); Mesh.vertex_layers_int does not exist; normals_split_custom_set exists; a crease_edge FLOAT and sharp_edge BOOLEAN edge attribute take foreach_set("value", ...); mesh.attributes["missing"] raises KeyError. - use-foreach-set-for-bulk-data: the flagged-pattern list no longer offers `loop.normal = ...` (unwritable); "where else it works" now says read loop normals with foreach_get and write custom normals with normals_split_custom_set, lists use_edge_sharp, and moves crease to the crease_edge attribute; adds generic mesh.attributes[name].data. - always-free-bmesh: the example exception is mesh.attributes["missing"] (KeyError) instead of the removed vertex_layers_int (whose .get() would not have raised anyway). Closes #330 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 2d4e769 commit f293573

2 files changed

Lines changed: 13 additions & 7 deletions

File tree

‎rules/always-free-bmesh.mdc‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ finally:
7373

7474
The `try`/`finally` covers the case where any operation between `bmesh.new()`
7575
and `bm.free()` raises. Without it, a `KeyError` reading
76-
`mesh.vertex_layers_int.get("missing")` skips the `free()`, and the BMesh
77-
leaks for the remaining session.
76+
`mesh.attributes["missing"]` skips the `free()`, and the BMesh leaks for the
77+
remaining session.
7878

7979
For the edit-mode case where the bmesh comes from `bmesh.from_edit_mesh()`,
8080
**do not call `bm.free()`**. Edit-mode bmeshes are owned by Blender and

‎rules/use-foreach-set-for-bulk-data.mdc‎

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Any of these patterns:
2222

2323
- `for v in mesh.vertices: v.co = ...`
2424
- `for i, v in enumerate(mesh.vertices): v.co = coords[i]`
25-
- `for loop in mesh.loops: loop.normal = ...`
25+
- `for e in mesh.edges: e.use_seam = ...`
2626
- `for face in mesh.polygons: face.use_smooth = True`
2727
- Manual `enumerate` loops that index into a parallel array of values
2828

@@ -99,11 +99,17 @@ Pre-allocate the buffer; do not let `foreach_get` allocate per call.
9999

100100
Same pattern applies to:
101101

102-
- `mesh.loops` (per-loop normals, custom split normals, UV coordinates
103-
via the UV layer's `data`)
102+
- `mesh.loops`: `foreach_get("normal", ...)` to read per-loop normals
103+
(`MeshLoop.normal` is read-only; write custom normals in bulk with
104+
`mesh.normals_split_custom_set(...)` instead), and UV coordinates via the
105+
UV layer's `data`
104106
- `mesh.polygons` (per-face material index, smooth flag, area)
105-
- `mesh.edges` (per-edge use_seam, use_sharp, crease)
106-
- `bpy.types.MeshUVLoopLayer.data` and other layer collections
107+
- `mesh.edges` (per-edge `use_seam`, `use_edge_sharp`). Edge crease is not
108+
an edge property on 4.5 LTS or 5.x; it is the `crease_edge` FLOAT
109+
attribute: `mesh.attributes["crease_edge"].data.foreach_set("value", buf)`
110+
(create it with `mesh.attributes.new("crease_edge", "FLOAT", "EDGE")`).
111+
- `mesh.attributes[name].data` for any generic attribute (`"value"`,
112+
`"vector"` or `"color"` key by type), and `MeshUVLoopLayer.data`
107113

108114
For example, batch-flag every face as smooth-shaded:
109115

0 commit comments

Comments
 (0)