PME code is most useful when it removes a specific piece of Blender workflow friction. Start with a goal below; use the syntax collection when you need to understand or adapt the command itself.

The archive often uses compact names such as C, L, E, and U. PME Terms You Will Meet explains where each name is available before you copy a snippet into a different slot type.

Choose what you want to build

Focused recipes

Use these after you know which kind of behavior or interface you are building.

Context and availability

Calling and integrating automation

Custom-layout details

Essential syntax collection

The compact patterns below are retained because PME’s standard Command, Custom, and Poll authoring fields are single-line controls. Use semicolons and expressions for short commands; use an external script when the logic deserves normal multiline Python.

Standard PME command fields use one line

Keep short commands in the field; move longer or reusable logic into a Python file.

  • Use ; (semicolon) to separate statements
  • Use ternary expressions a if condition else b instead of if/else blocks
  • Use list comprehensions [x for x in items] instead of for loops
  • Use and/or for short-circuit evaluation instead of conditionals

The multi-line examples in this guide are for readability only. Convert them to a single line before entering them into a standard PME command field.

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 (requires an active object):

# Readable:
obj = C.active_object
obj.show_wire = True
obj.show_all_edges = True
 
# PME format:
obj = C.active_object; obj.show_wire = True; obj.show_all_edges = True

Understanding PME Code Slots

PME has several places where you can write Python code:

LocationPurposeExample
Command slotExecute operators or short codebpy.ops.mesh.subdivide()
Custom slotDraw UI with UILayoutLabels, properties, operators
Poll tabGate menu or item visibilityreturn C.mode == 'EDIT_MESH'
Property editorExpose a reusable valueScene/object settings

PME Global Variables

PME provides shorthand variables for common Blender modules:

VariableEquivalentDescription
Cbpy.contextCurrent context
Dbpy.dataBlender data
Obpy.opsOperators
Tbpy.typesType definitions
LUILayoutCurrent layout (Custom slot)
EEventCurrent scoped event, when available
UUserDataSession-scoped scratch data

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 in a valid object context:
C.mode == 'OBJECT' and 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 is not None:
    obj.show_wire = not obj.show_wire
 
# PME format:
obj = C.active_object; obj is not None and setattr(obj, "show_wire", not obj.show_wire)

Undo Boundaries for Multi-Step Actions

Undo behavior varies by operator, mode, and Blender version. Test the sequence before adding a manual undo push; Plan undo boundaries for multi-step PME actions explains the historical observation and test procedure.


Running External Python Files

Call External Script

If you need to run a .py file, use the execute_script() function. This is essential for complex scripts that cannot fit in a single line.

execute_script() Function

execute_script(path, **kwargs)
  • path: A scripts/... path checks the user scripts directory first and then PME’s bundled scripts; other relative paths use the add-on directory, and absolute paths are accepted
  • kwargs: Additional keyword arguments passed to the script
  • Returns: Value of return_value variable in script, or True by 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:

  • PME globals for the current execution context (C, D, O, L, U, and E when a scoped event exists)
  • kwargs - Passed keyword arguments
  • __file__ - Script file path
  • return_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 None

Only 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")

Generate UI Rows with a List Comprehension

# Draw one row for each selected object:
[L.label(text=obj.name, icon='OBJECT_DATA') for obj in C.selected_objects]

Accessing Addon Preferences

prefs = C.preferences.addons['my_addon'].preferences; value = prefs.my_property

Using UserData (U) for Session-Scoped Scratch State

U is a scratch container shared by PME commands during one registered session. Disabling PME or restarting Blender recreates it. Use a PME Property or Blender data when the value must persist.

# Store data for the current PME session:
U.my_value = 42; U.update(foo="bar", count=10)
 
# Retrieve data:
value = U.get("my_value", 0)

Debugging Tips

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

  1. Open Edit → Preferences → Interface
  2. Enable “Developer Extras”
  3. Right-click any button → “Edit Source” or hover to see operator ID

Quick Reference Card

PatternPME Syntax
Multiple statementsstmt1; stmt2; stmt3
If/elsea if cond else b
If onlycond and action
Loop[action for x in items]
Get with defaultobj.get("key", default)
Safe attributegetattr(obj, "attr", None)
External scriptexecute_script("path.py", **kwargs)

Where next

External references