# Blender Syntax Properties

> >

- **Type:** Skill
- **Install:** `agentstack add skill-impertio-studio-blender-bonsai-ifcopenshell-sverchok-claude-skill-package-blender-syntax-properties`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [Impertio-Studio](https://agentstack.voostack.com/s/impertio-studio)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [Impertio-Studio](https://github.com/Impertio-Studio)
- **Source:** https://github.com/Impertio-Studio/Blender-Bonsai-ifcOpenshell-Sverchok-Claude-Skill-Package/tree/main/skills/blender/syntax/blender-syntax-properties
- **Website:** https://github.com/OpenAEC-Foundation

## Install

```sh
agentstack add skill-impertio-studio-blender-bonsai-ifcopenshell-sverchok-claude-skill-package-blender-syntax-properties
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# blender-syntax-properties

## Quick Reference

### Property Type Selection

| Need | Property Type | Python Type |
|------|---------------|-------------|
| Toggle/flag | `BoolProperty` | `bool` |
| Count/index | `IntProperty` | `int` |
| Size/factor | `FloatProperty` | `float` |
| Name/path | `StringProperty` | `str` |
| Dropdown/mode | `EnumProperty` | `str` (identifier) |
| Axis toggles (X, Y, Z) | `BoolVectorProperty` | `tuple[bool, ...]` |
| Dimensions | `IntVectorProperty` | `tuple[int, ...]` |
| Color/position/rotation | `FloatVectorProperty` | `tuple[float, ...]` |
| Link to another type | `PointerProperty` | Reference to PropertyGroup or ID |
| Dynamic list | `CollectionProperty` | List of PropertyGroup items |

### Critical Warnings

**ALWAYS** use Python annotation syntax (`:` not `=`) for property declarations in classes.

**ALWAYS** register sub-PropertyGroups BEFORE parent PropertyGroups — registration order matters.

**ALWAYS** store dynamic enum callback results in a module-level variable to prevent garbage collection crashes.

**ALWAYS** set explicit unique integer values in enum items used with `ENUM_FLAG` or getter/setter patterns.

**NEVER** modify the property that triggered an `update` callback — causes infinite recursion.

**NEVER** define `set` without a matching `get` callback — Blender raises an error.

**NEVER** call operators inside `update` callbacks — they trigger undo and corrupt state.

**NEVER** set `default` on `EnumProperty` when `items` is a callback — use `default=None` or omit it.

---

## Version-Critical Changes

| Version | Change | Impact |
|---------|--------|--------|
| 4.1 | Enum ID properties via `id_properties_ui` | Integer custom properties can display as dropdowns |
| 5.0 | `property_unset()` replaces `del obj["prop"]` | RNA properties use separate storage from custom properties |
| 5.0 | `get_transform` / `set_transform` callbacks | Faster alternative to `get`/`set` using internal storage |
| 5.0 | IDProperty storage split | `bpy.props`-defined properties no longer accessible via dict syntax |

### Blender 5.0 Property Storage Split

```python
# Blender  10:
        self.warning = "High count may impact performance"
    # UNSAFE: do NOT modify self.count here (infinite recursion)
    # UNSAFE: do NOT call bpy.ops.* here (undo corruption)

class MySettings(bpy.types.PropertyGroup):
    count: bpy.props.IntProperty(
        name="Count", default=5, update=on_count_changed,
    )
    warning: bpy.props.StringProperty()
```

### Pattern 7: Getter/Setter

```python
# Blender 3.x/4.x/5.x
def get_computed(self):
    # Compute value on read — no internal storage
    return len(bpy.data.objects)

def set_computed(self, value):
    # Handle write — must store somewhere if persistence needed
    self["_cached_count"] = value

class MySettings(bpy.types.PropertyGroup):
    object_count: bpy.props.IntProperty(
        name="Object Count",
        get=get_computed,
        set=set_computed,
    )
```

### Pattern 8: Get/Set Transform (Blender 5.0+)

```python
# Blender 5.0+ ONLY: faster than get/set, uses internal storage
def clamp_transform(self, new_value, curr_value, is_set):
    """Transform value before storing."""
    return max(0.0, min(new_value, 100.0))

def display_transform(self, curr_value, is_set):
    """Transform value on read."""
    return curr_value * 2.0 if is_set else 0.0

class MySettings(bpy.types.PropertyGroup):
    clamped: bpy.props.FloatProperty(
        name="Clamped",
        set_transform=clamp_transform,
        get_transform=display_transform,
    )
```

### Pattern 9: ENUM_FLAG (Multi-Select)

```python
# Blender 3.x/4.x/5.x: numbers MUST be powers of 2
my_flags: bpy.props.EnumProperty(
    name="Axes",
    items=[
        ('X', "X Axis", "Include X axis", 1),
        ('Y', "Y Axis", "Include Y axis", 2),
        ('Z', "Z Axis", "Include Z axis", 4),
    ],
    options={'ENUM_FLAG'},
    default={'X', 'Z'},  # Default is a SET, not a string
)
```

### Pattern 10: PointerProperty with Poll

```python
# Blender 3.x/4.x/5.x: filter selectable objects
def filter_mesh_objects(self, obj):
    return obj.type == 'MESH'

class MySettings(bpy.types.PropertyGroup):
    target: bpy.props.PointerProperty(
        type=bpy.types.Object,
        name="Target",
        poll=filter_mesh_objects,
    )
```

### Pattern 11: CollectionProperty Operations

```python
# Blender 3.x/4.x/5.x
scene = bpy.context.scene

# Add item
item = scene.my_settings.items.add()
item.name = "New Item"
item.value = 42.0

# Remove by index
scene.my_settings.items.remove(0)

# Move item (from_index, to_index)
scene.my_settings.items.move(0, 2)

# Clear all
scene.my_settings.items.clear()

# Iterate
for item in scene.my_settings.items:
    print(item.name, item.value)

# Access by index
first = scene.my_settings.items[0]

# Find by name (returns index or -1)
idx = scene.my_settings.items.find("New Item")
```

---

## Subtype and Unit Quick Reference

### Numeric Subtypes

| Subtype | Applies To | Effect |
|---------|-----------|--------|
| `'NONE'` | All | Default display |
| `'PIXEL'` | Int/Float | Pixel unit display |
| `'UNSIGNED'` | Int | Unsigned display |
| `'PERCENTAGE'` | Float | 0-100% display |
| `'FACTOR'` | Float | 0.0-1.0 slider |
| `'ANGLE'` | Float | Radians with degree display |
| `'TIME'` | Float | Scene-relative time (frames) |
| `'TIME_ABSOLUTE'` | Float | Absolute time (seconds) |
| `'DISTANCE'` | Float | Distance in scene units |
| `'POWER'` | Float | Power unit display |
| `'TEMPERATURE'` | Float | Temperature display |

### Vector Subtypes

| Subtype | Applies To | Effect |
|---------|-----------|--------|
| `'COLOR'` | FloatVector | Linear RGB color picker |
| `'COLOR_GAMMA'` | FloatVector | Gamma-space color picker |
| `'TRANSLATION'` | FloatVector | Position in scene units |
| `'DIRECTION'` | FloatVector | Normalized direction |
| `'VELOCITY'` | FloatVector | Velocity vector |
| `'ACCELERATION'` | FloatVector | Acceleration vector |
| `'EULER'` | FloatVector | Euler rotation (radians) |
| `'QUATERNION'` | FloatVector | Quaternion rotation (size=4) |
| `'AXISANGLE'` | FloatVector | Axis-angle rotation (size=4) |
| `'XYZ'` | FloatVector | Generic XYZ coordinates |
| `'MATRIX'` | FloatVector | Matrix representation |

### String Subtypes

| Subtype | Effect |
|---------|--------|
| `'NONE'` | Plain text input |
| `'FILE_PATH'` | File browser button |
| `'DIR_PATH'` | Directory browser button |
| `'FILE_NAME'` | File name field |
| `'BYTE_STRING'` | Byte string |
| `'PASSWORD'` | Masked input (***) |

### Unit Values (FloatProperty / FloatVectorProperty only)

| Unit | Display |
|------|---------|
| `'NONE'` | No unit |
| `'LENGTH'` | Scene length unit |
| `'AREA'` | Area (length²) |
| `'VOLUME'` | Volume (length³) |
| `'ROTATION'` | Degrees/radians |
| `'TIME'` | Scene-relative time |
| `'TIME_ABSOLUTE'` | Absolute seconds |
| `'VELOCITY'` | Speed |
| `'ACCELERATION'` | Acceleration |
| `'MASS'` | Mass |
| `'CAMERA'` | Camera distance |
| `'POWER'` | Power |
| `'TEMPERATURE'` | Temperature |

### Options Flags

| Flag | Applies To | Effect |
|------|-----------|--------|
| `'HIDDEN'` | All | Hidden from UI, accessible via Python |
| `'SKIP_SAVE'` | All | Value not saved between operator invocations |
| `'ANIMATABLE'` | All (default) | Can be keyframed |
| `'LIBRARY_EDITABLE'` | All | Editable on linked data-blocks |
| `'PROPORTIONAL'` | Numeric | Proportional editing support |
| `'TEXTEDIT_UPDATE'` | String | Updates on each keystroke |
| `'ENUM_FLAG'` | Enum only | Multi-select with power-of-2 values |

---

## Decision Trees

### When to Use PointerProperty vs CollectionProperty

```
Need to reference ONE item?
├── YES → PointerProperty
│   ├── Reference to another PropertyGroup? → type=MyPropertyGroup
│   └── Reference to an ID type? → type=bpy.types.Object (or Material, etc.)
└── NO → Need a LIST of items?
    └── YES → CollectionProperty(type=MyPropertyGroup)
        └── Track active selection? → Add IntProperty for active_index
```

### When to Use get/set vs get_transform/set_transform

```
Blender version?
├── =5.0
    ├── Need custom storage logic? → Use get/set
    └── Only need value transformation?
        └── Use get_transform/set_transform (faster, uses internal storage)
```

### When to Use update vs msgbus

```
Property changes on THIS class?
├── YES → Use update callback on the property
└── NO → Watching EXTERNAL property changes?
    └── YES → Use bpy.msgbus.subscribe_rna()
```

---

## Attachment Points

Properties can be attached to any Blender ID type:

```python
# Per-scene settings
bpy.types.Scene.my_prop = bpy.props.PointerProperty(type=MySettings)

# Per-object settings
bpy.types.Object.my_prop = bpy.props.PointerProperty(type=MySettings)

# Per-material settings
bpy.types.Material.my_prop = bpy.props.FloatProperty(name="Custom")

# Per-mesh settings
bpy.types.Mesh.my_prop = bpy.props.IntProperty(name="Custom")

# Per-bone settings
bpy.types.Bone.my_prop = bpy.props.StringProperty(name="Custom")

# Per-window-manager (session-only, not saved)
bpy.types.WindowManager.my_prop = bpy.props.BoolProperty(name="Temp")
```

**WindowManager** properties are session-only — they reset when Blender restarts. Use for temporary UI state.

---

## Reference Links

- [references/methods.md](references/methods.md) — Complete API signatures for all bpy.props types
- [references/examples.md](references/examples.md) — Working code examples for every property pattern
- [references/anti-patterns.md](references/anti-patterns.md) — What NOT to do, with explanations

### Official Sources

- https://docs.blender.org/api/current/bpy.props.html
- https://docs.blender.org/api/current/bpy.types.PropertyGroup.html
- https://developer.blender.org/docs/release_notes/5.0/python_api/
- https://developer.blender.org/docs/release_notes/4.1/python_api/

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [Impertio-Studio](https://github.com/Impertio-Studio)
- **Source:** [Impertio-Studio/Blender-Bonsai-ifcOpenshell-Sverchok-Claude-Skill-Package](https://github.com/Impertio-Studio/Blender-Bonsai-ifcOpenshell-Sverchok-Claude-Skill-Package)
- **License:** MIT
- **Homepage:** https://github.com/OpenAEC-Foundation

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-impertio-studio-blender-bonsai-ifcopenshell-sverchok-claude-skill-package-blender-syntax-properties
- Seller: https://agentstack.voostack.com/s/impertio-studio
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
