Register Properties#
This document describes the property registration system in the UVFlow addon_utils
module, which provides a clean way to add custom properties to any Blender type with automatic cleanup and type safety.
Overview#
The property registration system allows you to:
Add properties to any
bpy.types
class (Object, Scene, WindowManager, etc.)Batch register multiple properties at once
Automatic cleanup when the addon is disabled
Type safety with comprehensive property types
Integration with operators and UI systems
Basic Property Registration#
Single Property#
Add a single property to any Blender type:
from bpy.types import Object
from ..addon_utils import Register, Property
Register.PROP(Object, 'test_bool', Property.BOOL(name="Test", default=True))
Usage in code:
# Access the property
obj = context.active_object
print(obj.test_bool) # True
obj.test_bool = False
Multiple Properties (Batch)#
Add several properties at once to the same type:
from bpy.types import Object, WindowManager
from ..addon_utils import Register, Property
Register.PROP_BATCH(WindowManager,
test_bool = Property.BOOL(),
test_rgba = Property.COLOR_RGBA(default=(1, 1, 0, 1)),
test_vector3 = Property.VECTOR_3D(default=(0, 0, 0)),
test_filepath = Property.FILEPATH(),
test_pointer_object = Property.POINTER(Object)
)
Comprehensive Property Types#
Basic Types#
from bpy.types import Scene
from ..addon_utils import Register, Property
Register.PROP_BATCH(Scene,
# Boolean
enable_feature = Property.BOOL(
name="Enable Feature",
description="Enable this awesome feature",
default=True
),
# Integer
iteration_count = Property.INT(
name="Iterations",
description="Number of iterations to perform",
default=10,
min=1,
max=100
),
# Float
scale_factor = Property.FLOAT(
name="Scale Factor",
description="Scale factor for the operation",
default=1.0,
min=0.1,
max=10.0,
precision=2
),
# String
custom_name = Property.STRING(
name="Custom Name",
description="Enter a custom name",
default="Default Name",
maxlen=64
)
)
Color Properties#
Register.PROP_BATCH(Scene,
# RGB Color
primary_color = Property.COLOR_RGB(
name="Primary Color",
description="Primary color for the operation",
default=(1.0, 0.0, 0.0), # Red
subtype='COLOR'
),
# RGBA Color (with alpha)
secondary_color = Property.COLOR_RGBA(
name="Secondary Color",
description="Secondary color with transparency",
default=(0.0, 1.0, 0.0, 0.5), # Semi-transparent green
subtype='COLOR'
)
)
Vector Properties#
Register.PROP_BATCH(Scene,
# 2D Vector
uv_offset = Property.VECTOR_2D(
name="UV Offset",
description="UV coordinate offset",
default=(0.0, 0.0),
subtype='TRANSLATION'
),
# 3D Vector
world_position = Property.VECTOR_3D(
name="World Position",
description="Position in world space",
default=(0.0, 0.0, 0.0),
subtype='TRANSLATION'
),
# Euler angles
rotation = Property.VECTOR_3D(
name="Rotation",
description="Rotation in Euler angles",
default=(0.0, 0.0, 0.0),
subtype='EULER'
)
)
File and Directory Properties#
Register.PROP_BATCH(Scene,
# File path
export_filepath = Property.FILEPATH(
name="Export File",
description="Path to export file",
default="",
subtype='FILE_PATH'
),
# Directory path
asset_directory = Property.DIRPATH(
name="Asset Directory",
description="Directory containing assets",
default="",
subtype='DIR_PATH'
)
)
Enum Properties#
Register.PROP_BATCH(Scene,
# Simple enum
operation_mode = Property.ENUM(
name="Operation Mode",
description="Choose the operation mode",
items=[
('AUTO', 'Automatic', 'Use automatic settings'),
('MANUAL', 'Manual', 'Use manual settings'),
('ADVANCED', 'Advanced', 'Use advanced settings'),
],
default='AUTO'
),
# Enum with icons
tool_type = Property.ENUM(
name="Tool Type",
description="Select the tool type",
items=[
('SELECT', 'Select', 'Selection tool', 'RESTRICT_SELECT_OFF', 0),
('MOVE', 'Move', 'Move tool', 'ORIENTATION_GLOBAL', 1),
('ROTATE', 'Rotate', 'Rotation tool', 'ORIENTATION_GIMBAL', 2),
('SCALE', 'Scale', 'Scale tool', 'FULLSCREEN_EXIT', 3),
],
default='SELECT'
)
)
Pointer Properties#
from bpy.types import Object, Material, Image
Register.PROP_BATCH(Scene,
# Object pointer
target_object = Property.POINTER(
type=Object,
name="Target Object",
description="Object to operate on"
),
# Material pointer
active_material = Property.POINTER(
type=Material,
name="Active Material",
description="Material to use"
),
# Image pointer
reference_image = Property.POINTER(
type=Image,
name="Reference Image",
description="Reference image for the operation"
)
)
Collection Properties#
from bpy.types import PropertyGroup
# First, define a property group
@Register.PROP_GROUP
class CustomItem(PropertyGroup):
name: Property.STRING(default="Item")
value: Property.FLOAT(default=0.0)
enabled: Property.BOOL(default=True)
# Then use it in a collection
Register.PROP_BATCH(Scene,
custom_items = Property.COLLECTION(
type=CustomItem,
name="Custom Items",
description="Collection of custom items"
),
# Index for the collection
custom_items_index = Property.INT(
name="Active Item Index",
default=0,
min=0
)
)
Common Target Types#
Scene Properties#
Global settings that persist with the blend file:
from bpy.types import Scene
Register.PROP_BATCH(Scene,
global_scale = Property.FLOAT(default=1.0),
export_format = Property.ENUM(
items=[('OBJ', 'OBJ', ''), ('FBX', 'FBX', '')],
default='OBJ'
)
)
# Access: bpy.context.scene.global_scale
Object Properties#
Properties specific to individual objects:
from bpy.types import Object
Register.PROP_BATCH(Object,
custom_id = Property.STRING(default=""),
is_processed = Property.BOOL(default=False),
processing_data = Property.VECTOR_3D(default=(0, 0, 0))
)
# Access: obj.custom_id, obj.is_processed, obj.processing_data
WindowManager Properties#
Temporary properties that don’t save with the file:
from bpy.types import WindowManager
Register.PROP_BATCH(WindowManager,
temp_value = Property.FLOAT(default=0.0),
ui_state = Property.ENUM(
items=[('NORMAL', 'Normal', ''), ('ADVANCED', 'Advanced', '')],
default='NORMAL'
)
)
# Access: bpy.context.window_manager.temp_value
Mesh Properties#
Properties on mesh data:
from bpy.types import Mesh
Register.PROP_BATCH(Mesh,
uv_scale = Property.FLOAT(default=1.0),
seam_data = Property.STRING(default="")
)
# Access: obj.data.uv_scale (where obj.type == 'MESH')
Property Integration with Operators#
Using Properties in Operators#
@Register.OPS.INVOKE_PROPS
class ProcessWithSceneSettings:
# Operator properties
override_scale: Property.BOOL(
name="Override Scale",
description="Override scene scale setting",
default=False
)
custom_scale: Property.FLOAT(
name="Custom Scale",
description="Custom scale value",
default=1.0
)
def action(self, context):
# Access scene properties
scene_scale = context.scene.global_scale
# Use operator properties
if self.override_scale:
scale = self.custom_scale
else:
scale = scene_scale
# Process with the scale value
return {'FINISHED'}
Property-Driven UI#
@Register.UI.PANEL.VIEW3D
class CustomPropertiesPanel:
label = "Custom Properties"
def draw_ui(self, context, layout):
scene = context.scene
# Draw scene properties
layout.prop(scene, "global_scale")
layout.prop(scene, "export_format")
# Conditional UI based on properties
if scene.export_format == 'FBX':
layout.prop(scene, "fbx_specific_setting")
# Object properties (if object selected)
obj = context.active_object
if obj:
box = layout.box()
box.label(text="Object Properties:")
box.prop(obj, "custom_id")
box.prop(obj, "is_processed")
Best Practices#
1. Use Descriptive Names#
# Good
Register.PROP(Scene, 'uv_unwrap_angle_limit', Property.FLOAT(default=66.0))
# Avoid
Register.PROP(Scene, 'val1', Property.FLOAT(default=66.0))
2. Provide Clear Descriptions#
Register.PROP(Scene, 'export_scale',
Property.FLOAT(
name="Export Scale",
description="Scale factor applied during export (1.0 = no scaling)",
default=1.0,
min=0.001,
max=1000.0
)
)
3. Set Appropriate Limits#
# For percentages
Register.PROP(Scene, 'opacity',
Property.FLOAT(
default=1.0,
min=0.0,
max=1.0,
subtype='FACTOR' # Shows as percentage in UI
)
)
# For angles
Register.PROP(Scene, 'rotation_angle',
Property.FLOAT(
default=0.0,
subtype='ANGLE' # Shows with degree symbol
)
)
4. Choose Appropriate Target Types#
# Persistent settings → Scene
Register.PROP(Scene, 'project_settings', Property.STRING())
# Temporary UI state → WindowManager
Register.PROP(WindowManager, 'ui_mode', Property.ENUM(...))
# Object-specific data → Object
Register.PROP(Object, 'object_id', Property.STRING())
5. Use Property Groups for Complex Data#
@Register.PROP_GROUP
class ExportSettings(PropertyGroup):
format: Property.ENUM(items=[...])
scale: Property.FLOAT(default=1.0)
apply_modifiers: Property.BOOL(default=True)
Register.PROP(Scene, 'export_settings', Property.POINTER(type=ExportSettings))
# Access: context.scene.export_settings.format
Automatic Cleanup#
The property registration system automatically handles cleanup:
def register():
# Properties are automatically registered
pass
def unregister():
# Properties are automatically removed from target types
# No manual cleanup required
pass
This property registration system provides a robust foundation for adding custom data to Blender types with minimal code and automatic management.