Rigify: support executing an arbitrary script after generation.

Just in case the user wants to apply some custom changes to the
generated rig, allow executing a text datablock as a python script
after generation completes.

The script is executed with the generated rig active and in object
mode. When executed by rigify, the generator instance is available
via `rigify.get_generator()`. Outside of Rigify generation the return
value is None.
This commit is contained in:
Alexander Gavrilov 2021-09-19 19:16:20 +03:00
parent e7f2213435
commit ecf30de46c
4 changed files with 29 additions and 1 deletions

View File

@ -140,6 +140,11 @@ from bpy.props import (
)
def get_generator():
"""Returns the currently active generator instance."""
return base_generate.BaseGenerator.instance
class RigifyFeatureSets(bpy.types.PropertyGroup):
name: bpy.props.StringProperty()
module_name: bpy.props.StringProperty()
@ -534,6 +539,10 @@ def register():
name="Rigify Target Rig UI",
description="Defines the UI to overwrite. If unset, 'rig_ui.py' will be used")
bpy.types.Armature.rigify_finalize_script = PointerProperty(type=bpy.types.Text,
name="Finalize Script",
description="Run this script after generation to apply user-specific changes")
bpy.types.Armature.rigify_rig_basename = StringProperty(name="Rigify Rig Name",
description="Defines the name of the Rig. If unset, in 'new' mode 'rig' will be used, in 'overwrite' mode the target rig name will be used",
default="")

View File

@ -189,6 +189,8 @@ class LegacyRig(base_rig.BaseRig):
class BaseGenerator:
"""Base class for the main generator object. Contains rig and plugin management code."""
instance = None
def __init__(self, context, metarig):
self.context = context
self.scene = context.scene

View File

@ -573,6 +573,14 @@ class Generator(base_generate.BaseGenerator):
# Clear any transient errors in drivers
refresh_all_drivers()
#----------------------------------
# Execute the finalize script
if metarig.data.rigify_finalize_script:
bpy.ops.object.mode_set(mode='OBJECT')
exec(metarig.data.rigify_finalize_script.as_string(), {})
bpy.ops.object.mode_set(mode='OBJECT')
#----------------------------------
# Restore active collection
view_layer.active_layer_collection = self.layer_collection
@ -587,7 +595,11 @@ def generate_rig(context, metarig):
metarig.data.pose_position = 'REST'
try:
Generator(context, metarig).generate()
generator = Generator(context, metarig)
base_generate.BaseGenerator.instance = generator
generator.generate()
metarig.data.pose_position = rest_backup
@ -601,6 +613,9 @@ def generate_rig(context, metarig):
# Continue the exception
raise e
finally:
base_generate.BaseGenerator.instance = None
def create_selection_set_for_rig_layer(
rig: bpy.types.Object,

View File

@ -177,6 +177,8 @@ class DATA_PT_rigify_buttons(bpy.types.Panel):
if armature_id_store.rigify_generate_mode == 'new':
row.enabled = False
col.prop(armature_id_store, "rigify_finalize_script", text="Run Script")
elif obj.mode == 'EDIT':
# Build types list
build_type_list(context, id_store.rigify_types)