Skip to content

Commit c3ca5d8

Browse files
TMHSDigitalclaude
andcommitted
fix(skills): procedural-materials 4.5 socket residue, Specular date, use_nodes on 5.x
- Node-group paragraph still offered `inputs`/`outputs` for 4.5 LTS; group.inputs.new was removed in 4.0 (the version table already said so). It now names interface.new_socket for every supported version. - set_specular docstring dated the 'Specular IOR Level' rename to 5.0; it was 4.0 (Principled v2). References link now points at the 4.0 notes. - `mat.use_nodes = True` is deprecated on 5.x (DeprecationWarning, removal planned for 6.0) and unnecessary there: materials.new() already builds the Principled + Output tree. On 4.5 LTS the tree is None until it is set. The skill, snippets/principled-bsdf-material.py, snippets/setup_bake_target_image.py and the bake-high-to-low skill now gate it on bpy.app.version < (5, 0, 0), and the "common mistakes" text says which version needs it. Proof (local, --factory-startup): - .scratch/blender-4.5.11-windows-x64: materials.new -> use_nodes False, node_tree None. .scratch/blender-5.2.1-windows-x64: use_nodes True, tree has ShaderNodeBsdfPrincipled + ShaderNodeOutputMaterial; setting it warns. - Both patched snippets run on 4.5.11 and 5.2.1: exit 0, Principled + Output built, bake image node active, zero use_nodes warnings captured. Closes #327 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 3b0f5a0 commit c3ca5d8

4 files changed

Lines changed: 22 additions & 12 deletions

File tree

‎skills/bake-high-to-low/SKILL.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ img = bpy.data.images.new("BakeNrm", 128, 128, alpha=True, float_buffer=False)
6262
img.colorspace_settings.name = "Non-Color"
6363

6464
mat = bpy.data.materials.new("BakeTarget")
65-
mat.use_nodes = True
65+
if bpy.app.version < (5, 0, 0):
66+
mat.use_nodes = True # 4.5 LTS only; the tree exists and use_nodes is deprecated on 5.x
6667
nodes = mat.node_tree.nodes
6768
tex = nodes.new("ShaderNodeTexImage")
6869
tex.image = img

‎skills/procedural-materials-and-shaders/SKILL.md‎

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Use this skill when the user:
2727
Every Python-built material follows the same four steps:
2828

2929
1. Create the material datablock with `bpy.data.materials.new(name=...)`.
30-
2. Enable nodes with `mat.use_nodes = True`. This populates `mat.node_tree` with a default Principled BSDF and Material Output. You can keep them or wipe them.
30+
2. Make sure the node tree exists. On 5.x, `materials.new()` already creates `mat.node_tree` with a default Principled BSDF and Material Output, and `Material.use_nodes` is deprecated (setting it warns; removal is planned for 6.0). On 4.5 LTS the tree is `None` until you set `mat.use_nodes = True`. Gate it: `if bpy.app.version < (5, 0, 0): mat.use_nodes = True`. You can keep the default nodes or wipe them.
3131
3. Add nodes to `mat.node_tree.nodes` and configure their `inputs[...].default_value`.
3232
4. Wire `mat.node_tree.links` between sockets.
3333

@@ -38,7 +38,8 @@ import bpy
3838
def make_principled_material(name, base_color=(0.8, 0.8, 0.8, 1.0), metallic=0.0, roughness=0.5):
3939
"""Create a material with a single Principled BSDF wired to Material Output."""
4040
mat = bpy.data.materials.new(name=name)
41-
mat.use_nodes = True
41+
if bpy.app.version < (5, 0, 0):
42+
mat.use_nodes = True # 4.5 LTS: no node tree until enabled; deprecated on 5.x
4243

4344
nodes = mat.node_tree.nodes
4445
links = mat.node_tree.links
@@ -91,7 +92,8 @@ import bpy
9192
def make_metal(name, base_color=(0.8, 0.8, 0.85, 1.0), roughness=0.2):
9293
"""Procedural metal with adjustable color and surface roughness."""
9394
mat = bpy.data.materials.new(name=name)
94-
mat.use_nodes = True
95+
if bpy.app.version < (5, 0, 0):
96+
mat.use_nodes = True # 4.5 LTS: no node tree until enabled; deprecated on 5.x
9597

9698
nodes = mat.node_tree.nodes
9799
links = mat.node_tree.links
@@ -125,7 +127,8 @@ for name, color in [
125127
```python
126128
def make_emissive(name, color=(1.0, 0.4, 0.1, 1.0), strength=5.0):
127129
mat = bpy.data.materials.new(name=name)
128-
mat.use_nodes = True
130+
if bpy.app.version < (5, 0, 0):
131+
mat.use_nodes = True # 4.5 LTS: no node tree until enabled; deprecated on 5.x
129132
nodes = mat.node_tree.nodes
130133
links = mat.node_tree.links
131134
nodes.clear()
@@ -144,17 +147,17 @@ def make_emissive(name, color=(1.0, 0.4, 0.1, 1.0), strength=5.0):
144147

145148
## Reusing graphs via node groups
146149

147-
When the same subgraph appears across multiple materials, factor it into a `ShaderNodeTree` group. Create the group once with `bpy.data.node_groups.new(name='MyGroup', type='ShaderNodeTree')`, build its internal nodes and `interface` (5.x) or `inputs`/`outputs` (4.5 LTS) sockets, then instantiate it inside any material's tree as a `ShaderNodeGroup` with `node.node_tree = my_group`. See snippet `shader-node-group.py`.
150+
When the same subgraph appears across multiple materials, factor it into a `ShaderNodeTree` group. Create the group once with `bpy.data.node_groups.new(name='MyGroup', type='ShaderNodeTree')`, build its internal nodes and its sockets with `group.interface.new_socket(...)` (the same API on 4.5 LTS and 5.x; `group.inputs.new` was removed in 4.0), then instantiate it inside any material's tree as a `ShaderNodeGroup` with `node.node_tree = my_group`. See snippet `shader-node-group.py`.
148151

149152
## Common AI mistakes
150153

151-
- **Forgetting `mat.use_nodes = True`**. Without nodes enabled, `mat.node_tree` is `None` and any node access raises `AttributeError`.
154+
- **Forgetting `mat.use_nodes = True` on 4.5 LTS**. There, a new material's `mat.node_tree` is `None` until nodes are enabled, and any node access raises `AttributeError`. On 5.x the tree exists from `materials.new()` and setting `use_nodes` only emits a `DeprecationWarning`, so gate the line on `bpy.app.version < (5, 0, 0)`.
152155
- **Using indices for sockets**. `bsdf.inputs[0]` is fragile. The Principled BSDF input order has shifted across Blender releases. Always use string keys.
153156
- **Setting RGB without alpha**. Color sockets expect 4-tuples. `(0.5, 0.5, 0.5)` raises a length error.
154157
- **Targeting Layered Textures**. The Layered Textures roadmap is deferred to 2027. Do not generate code that imports from `bpy.types.LayeredTextureNode` or similar; these do not exist in 5.1 stable. Stick with classic `ShaderNodeTex*` (ShaderNodeTexImage, ShaderNodeTexNoise, etc.) for 5.1.
155158
- **Calling `bpy.ops.material.new()`** to create a material when `bpy.data.materials.new()` works headlessly and is faster.
156159
- **Trying to wire sockets across material boundaries**. Each material has its own `node_tree`. To share logic, use a shader node group.
157-
- **Forgetting to clear default nodes**. After `mat.use_nodes = True`, Blender adds a Principled BSDF and an Output. If you also add your own and link, you end up with two BSDFs feeding the output and the visible behavior is undefined. Either reuse the defaults or `nodes.clear()` first.
160+
- **Forgetting to clear default nodes**. A new material's tree (5.x, or 4.5 after `use_nodes = True`) holds a Principled BSDF and an Output. If you also add your own and link, you end up with two BSDFs feeding the output and the visible behavior is undefined. Either reuse the defaults or `nodes.clear()` first.
158161

159162
## Version correctness
160163

@@ -173,7 +176,11 @@ When writing code that must run on both 4.5 LTS and 5.x, look up sockets defensi
173176

174177
```python
175178
def set_specular(bsdf, value):
176-
"""Specular socket renamed to 'Specular IOR Level' in Blender 5.0."""
179+
"""Specular socket renamed to 'Specular IOR Level' in Blender 4.0.
180+
181+
Every supported version (4.5 LTS, 5.x) has the new name; the fallback
182+
branch only matters for files that must also run on 3.x.
183+
"""
177184
if 'Specular IOR Level' in bsdf.inputs:
178185
bsdf.inputs['Specular IOR Level'].default_value = value
179186
elif 'Specular' in bsdf.inputs:
@@ -198,5 +205,5 @@ Almost everything you want to do with materials has a `bpy.data` path. The two n
198205
- `bpy.types.Material`: https://docs.blender.org/api/current/bpy.types.Material.html
199206
- `bpy.types.ShaderNodeBsdfPrincipled`: https://docs.blender.org/api/current/bpy.types.ShaderNodeBsdfPrincipled.html
200207
- `bpy.types.ShaderNodeTree`: https://docs.blender.org/api/current/bpy.types.ShaderNodeTree.html
201-
- Blender 5.0 release notes (Specular rename): https://developer.blender.org/docs/release_notes/5.0/python_api/
208+
- Blender 4.0 release notes (Principled v2, Specular rename): https://developer.blender.org/docs/release_notes/4.0/
202209
- Blender 5.1 EEVEE Next: https://developer.blender.org/docs/release_notes/5.1/eevee/

‎snippets/principled-bsdf-material.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77

88
def make_principled_material(name, base_color=(0.8, 0.8, 0.8, 1.0), metallic=0.0, roughness=0.5):
99
mat = bpy.data.materials.new(name=name)
10-
mat.use_nodes = True
10+
if bpy.app.version < (5, 0, 0):
11+
mat.use_nodes = True # 4.5 LTS only; the tree exists and use_nodes is deprecated on 5.x
1112

1213
nodes = mat.node_tree.nodes
1314
links = mat.node_tree.links

‎snippets/setup_bake_target_image.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ def setup_bake_target_image(obj, name="BakeNrm", size=128):
1717
img = bpy.data.images.new(name, size, size, alpha=True, float_buffer=False)
1818
img.colorspace_settings.name = "Non-Color"
1919
mat = bpy.data.materials.new(name + "Mat")
20-
mat.use_nodes = True
20+
if bpy.app.version < (5, 0, 0):
21+
mat.use_nodes = True # 4.5 LTS only; the tree exists and use_nodes is deprecated on 5.x
2122
nodes = mat.node_tree.nodes
2223
tex = nodes.new("ShaderNodeTexImage")
2324
tex.image = img

0 commit comments

Comments
 (0)