PME Code Examples
Python snippets and patterns for advanced PME customization.
⚠️ Critical: PME’s One-Line Constraint
All PME code must be a single line
In PME, all code is stored in Blender’s string properties, which means your entire command must be completely on a single line.
- Use
;(semicolon) to separate statements- Use ternary expressions
a if condition else binstead ofif/elseblocks- Use list comprehensions
[x for x in items]instead offorloops- Use
and/orfor short-circuit evaluation instead of conditionalsThe multi-line examples in this guide are for readability only. You must convert them to single-line format before using in PME.
Converting Multi-Line to Single-Line
Readable format (for documentation):
if bpy.context.mode == 'EDIT_MESH':
bpy.ops.mesh.select_all(action='SELECT')
else:
bpy.ops.object.select_all(action='SELECT')Actual PME format (what you must type):
bpy.ops.mesh.select_all(action='SELECT') if C.mode == 'EDIT_MESH' else bpy.ops.object.select_all(action='SELECT')Multi-statement example:
# Readable:
obj = C.active_object
obj.data.use_auto_smooth = True
obj.data.auto_smooth_angle = 0.523599
# PME format:
obj = C.active_object; obj.data.use_auto_smooth = True; obj.data.auto_smooth_angle = 0.523599Understanding PME Code Slots
PME has several places where you can write Python code:
| Location | Purpose | Example |
|---|---|---|
| Command slot | Execute operators or code | bpy.ops.mesh.subdivide() |
| Custom slot | Complex scripts with UI | Multi-step tools |
| Poll tab | Conditional menu display | return C.mode == 'EDIT_MESH' |
| Property slot | Expose Blender properties | Scene/object settings |
PME Global Variables
PME provides shorthand variables for common Blender modules:
| Variable | Equivalent | Description |
|---|---|---|
C | bpy.context | Current context |
D | bpy.data | Blender data |
O | bpy.ops | Operators |
T | bpy.types | Type definitions |
L | UILayout | Current layout (Custom slot) |
E | Event | Current event |
U | UserData | Persistent user data storage |
Basic Patterns
Simple Operator Call
O.mesh.subdivide(number_cuts=2)Multiple Operations (Macro-style)
# Readable:
bpy.ops.object.duplicate()
bpy.ops.transform.translate(value=(1, 0, 0))
# PME format:
O.object.duplicate(); O.transform.translate(value=(1, 0, 0))Conditional Execution (Ternary)
# Instead of if/else blocks, use ternary:
O.mesh.select_all(action='SELECT') if C.mode == 'EDIT_MESH' else O.object.select_all(action='SELECT')Short-Circuit Evaluation
Use and/or for conditional execution:
# Execute only if condition is true:
C.active_object and O.object.shade_smooth()
# Execute with fallback:
C.selected_objects or message_box("No objects selected!")Common Recipes
Toggle Selection Mode
# Readable version:
ts = C.tool_settings
mode = tuple(ts.mesh_select_mode)
if mode == (True, False, False):
ts.mesh_select_mode = (False, True, False)
elif mode == (False, True, False):
ts.mesh_select_mode = (False, False, True)
else:
ts.mesh_select_mode = (True, False, False)
# PME format (using nested ternary):
ts = C.tool_settings; m = tuple(ts.mesh_select_mode); ts.mesh_select_mode = (False, True, False) if m == (True, False, False) else ((False, False, True) if m == (False, True, False) else (True, False, False))Access Active Object Properties
# Readable:
obj = C.active_object
if obj and obj.type == 'MESH':
obj.data.use_auto_smooth = True
# PME format:
obj = C.active_object; obj and obj.type == 'MESH' and setattr(obj.data, 'use_auto_smooth', True)Execute with Undo Push
From [[../Posts/2025/post_05648|Post #5648]] - important for macro reliability:
O.paint.visibility_invert("EXEC_DEFAULT"); O.ed.undo_push(message="visibility_invert")Running External Python Files
Call External Script
If you need to run a
.pyfile, use theexecute_script()function. This is essential for complex scripts that cannot fit in a single line.
execute_script() Function
execute_script(path, **kwargs)- path: Script file path relative to
pie_menu_editorfolder (recommended) or absolute path - kwargs: Additional keyword arguments passed to the script
- Returns: Value of
return_valuevariable in script, orTrueby default
Usage Examples
Basic execution:
execute_script("scripts/my_script.py")With parameters:
execute_script("scripts/my_script.py", msg="Hello World!", count=5)Inside your script (my_script.py):
# Access passed parameters via kwargs
msg = kwargs.get("msg", "Default")
count = kwargs.get("count", 1)
# PME globals are available (C, D, O, L, etc.)
for i in range(count):
print(msg)
# Return a value
return_value = "Success!"Available in script:
- All PME global variables (
C,D,O,L,E,U) kwargs- Passed keyword arguments__file__- Script file pathreturn_value- Set this to return a value
Poll Function Examples
Poll functions determine when a menu or slot is visible. They must return a boolean.
Only in Edit Mode
return C.mode == 'EDIT_MESH'Only When Object Selected
return C.active_object is not NoneOnly for Mesh Objects
return C.active_object and C.active_object.type == 'MESH'Multiple Conditions
obj = C.active_object; return obj and obj.type == 'MESH' and C.mode == 'EDIT_MESH'Advanced Patterns
Using the Layout API (Custom Slots)
# Each line separated by ; in actual PME:
L.label(text="My Custom Tool"); L.prop(C.active_object, "name"); L.operator("mesh.subdivide"); L.separator(); L.prop(C.scene.render, "engine")Dynamic Menu Items with List Comprehension
# Instead of for loops, use list comprehension:
[L.operator("object.select_all", text=obj.name).action for obj in C.selected_objects]Accessing Addon Preferences
prefs = C.preferences.addons['my_addon'].preferences; value = prefs.my_propertyUsing UserData (U) for Persistent State
# Store data:
U.my_value = 42; U.update(foo="bar", count=10)
# Retrieve data:
value = U.get("my_value", 0)Debugging Tips
Print to Console
print("Debug:", C.active_object)Message Box for User Feedback
message_box("Operation completed!", icon='INFO')Check Available Properties
In Blender’s Python Console:
dir(bpy.context.active_object)Find Operator ID
- Open
Edit → Preferences → Interface - Enable “Developer Extras”
- Right-click any button → “Edit Source” or hover to see operator ID
Quick Reference Card
| Pattern | PME Syntax |
|---|---|
| Multiple statements | stmt1; stmt2; stmt3 |
| If/else | a if cond else b |
| If only | cond and action |
| Loop | [action for x in items] |
| Get with default | obj.get("key", default) |
| Safe attribute | getattr(obj, "attr", None) |
| External script | execute_script("path.py", **kwargs) |
Related Posts
Browse code-related discussions in the archive:
- Scripting Posts (293 posts)
- Python Scripting (200 posts)
- Advanced Topics (406 posts)
- Custom Scripting (37 posts)
External Resources
- Blender Python API Docs
- Blender Stack Exchange
- Jakro’s Scripts Collection
- PME Documentation - Scripting
Related Guides
- Getting Started - PME basics
- Terminology & Concepts - Blender and PME concepts explained
- Troubleshooting - When code doesn’t work
- Hotkey Conflicts - Poll methods and keymap issues
- Best Practices - Tips from experienced users