Rigify: annotate and fix warnings in basic rig components.

Introduce a method to annotate types and names of entries in the
`bones` container of rig components and apply it, and other type
annotations, to a number of not very complex rig classes.

- Introduce BaseRigMixin as a typed base class for mixins intended
  for use in rig classes (using BaseRig as a parent causes issues).
- Introduce TypedBoneDict that does not suppress the unknown attribute
  analysis in PyCharm, and use it in a system of subclasses to
  annotate the bones in various rigs. BaseBoneDict is necessary
  because the annotation affects all subclasses, so TypedBoneDict
  cannot inherit from BoneDict with the annotation.
- Add or adjust other type annotations of rig methods and utilities.
- Fix other warnings, e.g. undeclared attributes, excessively long
  lines, whitespace style issues and typos.
This commit is contained in:
Alexander Gavrilov 2022-11-12 23:54:17 +02:00
parent 68419fb365
commit 01e8af3348
20 changed files with 931 additions and 446 deletions

View File

@ -2,11 +2,11 @@
import collections
from bpy.types import PoseBone
from typing import TYPE_CHECKING, Any, Callable, Optional
from bpy.types import PoseBone, UILayout, Context
from typing import TYPE_CHECKING, Any, Callable, Optional, TypeVar, Generic
from .utils.errors import RaiseErrorMixin
from .utils.bones import BoneDict, BoneUtilityMixin
from .utils.bones import BoneDict, BoneUtilityMixin, TypedBoneDict, BaseBoneDict
from .utils.mechanism import MechanismUtilityMixin
from .utils.metaclass import BaseStagedClass
from .utils.misc import ArmatureObject
@ -144,14 +144,19 @@ class GenerateCallbackHost(BaseStagedClass, define_stages=True):
pass
class BaseRig(GenerateCallbackHost, RaiseErrorMixin, BoneUtilityMixin, MechanismUtilityMixin):
_Org = TypeVar('_Org', bound=str | list[str] | BaseBoneDict)
_Ctrl = TypeVar('_Ctrl', bound=str | list[str] | BaseBoneDict)
_Mch = TypeVar('_Mch', bound=str | list[str] | BaseBoneDict)
_Deform = TypeVar('_Deform', bound=str | list[str] | BaseBoneDict)
class BaseRigMixin(RaiseErrorMixin, BoneUtilityMixin, MechanismUtilityMixin):
generator: 'BaseGenerator'
obj: ArmatureObject
script: 'ScriptGenerator'
base_bone: str
params: Any
bones: BoneDict
rigify_parent: Optional['BaseRig']
rigify_children: list['BaseRig']
@ -160,6 +165,28 @@ class BaseRig(GenerateCallbackHost, RaiseErrorMixin, BoneUtilityMixin, Mechanism
rigify_new_bones: dict[str, Optional[str]]
rigify_derived_bones: dict[str, set[str]]
##############################################
# Annotated bone containers
class ToplevelBones(TypedBoneDict, Generic[_Org, _Ctrl, _Mch, _Deform]):
org: _Org
ctrl: _Ctrl
mch: _Mch
deform: _Deform
class CtrlBones(TypedBoneDict):
pass
class MchBones(TypedBoneDict):
pass
bones: ToplevelBones[str | list[str] | BoneDict,
str | list[str] | BoneDict, # Use CtrlBones in overrides
str | list[str] | BoneDict, # Use MchBones in overrides
str | list[str] | BoneDict]
class BaseRig(GenerateCallbackHost, BaseRigMixin):
"""
Base class for all rigs.
@ -182,7 +209,7 @@ class BaseRig(GenerateCallbackHost, RaiseErrorMixin, BoneUtilityMixin, Mechanism
self.params = get_rigify_params(pose_bone)
# Collection of bone names for use in implementing the rig
self.bones = BoneDict(
self.bones = self.ToplevelBones(
# ORG bone names
org=self.find_org_bones(pose_bone),
# Control bone names
@ -205,7 +232,7 @@ class BaseRig(GenerateCallbackHost, RaiseErrorMixin, BoneUtilityMixin, Mechanism
self.rigify_new_bones = dict()
self.rigify_derived_bones = collections.defaultdict(set)
def register_new_bone(self, new_name, old_name=None):
def register_new_bone(self, new_name: str, old_name: Optional[str] = None):
"""Registers this rig as the owner of this new bone."""
self.rigify_new_bones[new_name] = old_name
self.generator.bone_owners[new_name] = self
@ -216,7 +243,7 @@ class BaseRig(GenerateCallbackHost, RaiseErrorMixin, BoneUtilityMixin, Mechanism
###########################################################
# Bone ownership
def find_org_bones(self, pose_bone: PoseBone) -> str | list[str] | BoneDict:
def find_org_bones(self, pose_bone: PoseBone) -> str | list[str] | BaseBoneDict:
"""
Select bones directly owned by the rig. Returning the
same bone from multiple rigs is an error.
@ -240,7 +267,7 @@ class BaseRig(GenerateCallbackHost, RaiseErrorMixin, BoneUtilityMixin, Mechanism
pass
@classmethod
def parameters_ui(cls, layout, params):
def parameters_ui(cls, layout: UILayout, params):
"""
This method draws the UI of the rigify_parameters defined on the pose_bone
:param layout:
@ -250,7 +277,7 @@ class BaseRig(GenerateCallbackHost, RaiseErrorMixin, BoneUtilityMixin, Mechanism
pass
@classmethod
def on_parameter_update(cls, context, pose_bone, params, param_name):
def on_parameter_update(cls, context: Context, pose_bone: PoseBone, params, param_name: str):
"""
A callback invoked whenever a parameter value is changed by the user.
"""
@ -267,7 +294,7 @@ class RigUtility(BoneUtilityMixin, MechanismUtilityMixin):
self.owner = owner
self.obj = owner.obj
def register_new_bone(self, new_name, old_name=None):
def register_new_bone(self, new_name: str, old_name: Optional[str] = None):
self.owner.register_new_bone(new_name, old_name)

View File

@ -119,21 +119,21 @@ class ActionSlot(PropertyGroup, ActionSlotBase):
trans_min: FloatProperty(
name="Min",
default=-0.05,
description="Value that the transformation value must reach to put the action's timeline"
description="Value that the transformation value must reach to put the action's timeline "
"to the first frame. Rotations are in degrees"
)
trans_max: FloatProperty(
name="Max",
default=0.05,
description="Value that the transformation value must reach to put the action's timeline"
description="Value that the transformation value must reach to put the action's timeline "
"to the last frame. Rotations are in degrees"
)
is_corrective: BoolProperty(
name="Corrective",
description="Indicate that this is a corrective action. Corrective actions will activate"
"based on the activation of two other actions (using End Frame if both inputs"
description="Indicate that this is a corrective action. Corrective actions will activate "
"based on the activation of two other actions (using End Frame if both inputs "
"are at their End Frame, and Start Frame if either is at Start Frame)"
)

View File

@ -11,6 +11,10 @@ class Rig(SimpleChainRig):
and constrain it.
This is a control and deformation rig.
"""
make_controls: bool
make_deforms: bool
def initialize(self):
super().initialize()
@ -72,15 +76,17 @@ class Rig(SimpleChainRig):
# Parameter UI
@classmethod
def add_parameters(self, params):
def add_parameters(cls, params):
""" Add the parameters of this rig type to the
RigifyParameters PropertyGroup
"""
params.make_controls = bpy.props.BoolProperty(name="Controls", default=True, description="Create control bones for the copy")
params.make_deforms = bpy.props.BoolProperty(name="Deform", default=True, description="Create deform bones for the copy")
params.make_controls = bpy.props.BoolProperty(
name="Controls", default=True, description="Create control bones for the copy")
params.make_deforms = bpy.props.BoolProperty(
name="Deform", default=True, description="Create deform bones for the copy")
@classmethod
def parameters_ui(self, layout, params):
def parameters_ui(cls, layout, params):
""" Create the ui for the rig parameters.
"""
r = layout.row()

View File

@ -13,15 +13,27 @@ from ...utils.switch_parent import SwitchParentBuilder
class Rig(BaseRig):
""" A rig providing a rotation pivot control that can be moved. """
def find_org_bones(self, pose_bone):
return pose_bone.name
class CtrlBones(BaseRig.CtrlBones):
master: str
pivot: str
class MchBones(BaseRig.MchBones):
pass
bones: BaseRig.ToplevelBones[str, CtrlBones, MchBones, str]
make_control: bool
make_pivot: bool
make_deform: bool
def find_org_bones(self, pose_bone) -> str:
return pose_bone.name
def initialize(self):
self.make_control = self.params.make_extra_control
self.make_pivot = self.params.make_control or not self.make_control
self.make_deform = self.params.make_extra_deform
self.make_deform = self.params.make_extra_deform
def generate_bones(self):
org = self.bones.org
@ -44,8 +56,7 @@ class Rig(BaseRig):
if self.make_deform:
self.bones.deform = self.copy_bone(org, make_derived_name(org, 'def'), bbone=True)
def build_parent_switch(self, master_name):
def build_parent_switch(self, master_name: str):
pbuilder = SwitchParentBuilder(self.generator)
org_parent = self.get_bone_parent(self.bones.org)
@ -68,7 +79,7 @@ class Rig(BaseRig):
tags.discard('')
return tags
def register_parent(self, master_name, tags):
def register_parent(self, master_name: str, tags: set[str]):
pbuilder = SwitchParentBuilder(self.generator)
inject = self.rigify_parent if 'injected' in tags else None
@ -78,7 +89,6 @@ class Rig(BaseRig):
inject_into=inject, tags=tags
)
def parent_bones(self):
ctrl = self.bones.ctrl
@ -94,7 +104,6 @@ class Rig(BaseRig):
if self.make_deform:
self.set_bone_parent(self.bones.deform, self.bones.org, use_connect=False)
def configure_bones(self):
org = self.bones.org
ctrl = self.bones.ctrl
@ -102,7 +111,6 @@ class Rig(BaseRig):
self.copy_bone_properties(org, main_ctl, ui_controls=True)
def rig_bones(self):
if self.make_pivot:
self.make_constraint(
@ -110,7 +118,6 @@ class Rig(BaseRig):
space='LOCAL', invert_xyz=(True,)*3
)
def generate_widgets(self):
if self.make_pivot:
create_pivot_widget(self.obj, self.bones.ctrl.pivot, square=True, axis_size=2.0)
@ -118,56 +125,55 @@ class Rig(BaseRig):
if self.make_control:
set_bone_widget_transform(self.obj, self.bones.ctrl.master, self.bones.org)
create_registered_widget(self.obj, self.bones.ctrl.master, self.params.pivot_master_widget_type or 'cube')
create_registered_widget(self.obj, self.bones.ctrl.master,
self.params.pivot_master_widget_type or 'cube')
@classmethod
def add_parameters(self, params):
def add_parameters(cls, params):
params.make_control = bpy.props.BoolProperty(
name = "Control",
default = True,
description = "Create a control bone for the copy"
name="Control",
default=True,
description="Create a control bone for the copy"
)
params.pivot_master_widget_type = bpy.props.StringProperty(
name = "Widget Type",
default = 'cube',
description = "Choose the type of the widget to create"
name="Widget Type",
default='cube',
description="Choose the type of the widget to create"
)
params.make_parent_switch = bpy.props.BoolProperty(
name = "Switchable Parent",
default = False,
description = "Allow switching the parent of the master control"
name="Switchable Parent",
default=False,
description="Allow switching the parent of the master control"
)
params.register_parent = bpy.props.BoolProperty(
name = "Register Parent",
default = False,
description = "Register the control as a switchable parent candidate"
name="Register Parent",
default=False,
description="Register the control as a switchable parent candidate"
)
params.register_parent_tags = bpy.props.StringProperty(
name = "Parent Tags",
default = "",
description = "Comma-separated tags to use for the registered parent"
name="Parent Tags",
default="",
description="Comma-separated tags to use for the registered parent"
)
params.make_extra_control = bpy.props.BoolProperty(
name = "Extra Control",
default = False,
description = "Create an optional control"
name="Extra Control",
default=False,
description="Create an optional control"
)
params.make_extra_deform = bpy.props.BoolProperty(
name = "Extra Deform",
default = False,
description = "Create an optional deform bone"
name="Extra Deform",
default=False,
description="Create an optional deform bone"
)
@classmethod
def parameters_ui(self, layout, params):
def parameters_ui(cls, layout, params):
r = layout.row()
r.prop(params, "make_extra_control", text="Master Control")

View File

@ -2,15 +2,17 @@
import bpy
from ...utils.naming import strip_org, strip_prefix, choose_derived_bone, is_control_bone
from bpy.types import Constraint, ArmatureConstraint, UILayout
from ...utils.naming import choose_derived_bone, is_control_bone
from ...utils.mechanism import copy_custom_properties_with_ui, move_all_constraints
from ...utils.widgets import layout_widget_dropdown, create_registered_widget
from ...base_rig import BaseRig
from ...base_generate import SubstitutionRig
from ...base_rig import BaseRig, BaseRigMixin
from itertools import repeat
'''
Due to T80764, bone name handling for 'limbs.raw_copy' was hard-coded in generate.py
@ -25,18 +27,18 @@ class Rig(SubstitutionRig):
return [ self.instantiate_rig(InstanceRig, new_name) ]
'''
class RelinkConstraintsMixin:
class RelinkConstraintsMixin(BaseRigMixin):
""" Utilities for constraint relinking. """
def relink_bone_constraints(self, bone_name):
def relink_bone_constraints(self, bone_name: str):
if self.params.relink_constraints:
for con in self.get_bone(bone_name).constraints:
self.relink_single_constraint(con)
relink_unmarked_constraints = False
def relink_single_constraint(self, con):
def relink_single_constraint(self, con: Constraint):
if self.params.relink_constraints:
parts = con.name.split('@')
@ -45,13 +47,11 @@ class RelinkConstraintsMixin:
elif self.relink_unmarked_constraints:
self.relink_constraint(con, [''])
def relink_move_constraints(self, from_bone, to_bone, *, prefix=''):
def relink_move_constraints(self, from_bone: str, to_bone: str, *, prefix=''):
if self.params.relink_constraints:
move_all_constraints(self.obj, from_bone, to_bone, prefix=prefix)
def relink_bone_parent(self, bone_name):
def relink_bone_parent(self, bone_name: str):
if self.params.relink_constraints:
self.generator.disable_auto_parent(bone_name)
@ -62,13 +62,13 @@ class RelinkConstraintsMixin:
self.set_bone_parent(bone_name, new_parent)
return new_parent
def relink_constraint(self, con, specs):
if con.type == 'ARMATURE':
def relink_constraint(self, con: Constraint, specs: list[str]):
if isinstance(con, ArmatureConstraint):
if len(specs) == 1:
specs = repeat(specs[0])
elif len(specs) != len(con.targets):
self.raise_error("Constraint {} actually has {} targets", con.name, len(con.targets))
self.raise_error("Constraint {} actually has {} targets",
con.name, len(con.targets))
for tgt, spec in zip(con.targets, specs):
if tgt.target == self.obj:
@ -76,44 +76,49 @@ class RelinkConstraintsMixin:
elif hasattr(con, 'subtarget'):
if len(specs) > 1:
self.raise_error("Only the Armature constraint can have multiple '@' targets: {}", con.name)
self.raise_error("Only the Armature constraint can have multiple '@' targets: {}",
con.name)
# noinspection PyUnresolvedReferences
if con.target == self.obj:
con.subtarget = self.find_relink_target(specs[0], con.subtarget)
def find_relink_target(self, spec, old_target):
def find_relink_target(self, spec: str, old_target: str):
if spec == '':
return old_target
elif spec in {'CTRL', 'DEF', 'MCH'}:
result = choose_derived_bone(self.generator, old_target, spec.lower())
if not result:
result = choose_derived_bone(self.generator, old_target, spec.lower(), by_owner=False)
result = choose_derived_bone(self.generator, old_target,
spec.lower(), by_owner=False)
if not result:
self.raise_error("Cannot find derived {} bone of bone '{}' for relinking", spec, old_target)
self.raise_error("Cannot find derived {} bone of bone '{}' for relinking",
spec, old_target)
return result
else:
if spec not in self.obj.pose.bones:
self.raise_error("Cannot find bone '{}' for relinking", spec)
return spec
@classmethod
def add_relink_constraints_params(self, params):
def add_relink_constraints_params(cls, params):
params.relink_constraints = bpy.props.BoolProperty(
name = "Relink Constraints",
default = False,
description = "For constraints with names formed like 'base@bonename', use the part after '@' as the new subtarget after all bones are created. Use '@CTRL', '@DEF' or '@MCH' to simply replace the prefix"
name="Relink Constraints",
default=False,
description="For constraints with names formed like 'base@bonename', use the part "
"after '@' as the new subtarget after all bones are created. Use '@CTRL', "
"'@DEF' or '@MCH' to simply replace the prefix"
)
params.parent_bone = bpy.props.StringProperty(
name = "Parent",
default = "",
description = "Replace the parent with a different bone after all bones are created. Using simply CTRL, DEF or MCH will replace the prefix instead"
name="Parent",
default="",
description="Replace the parent with a different bone after all bones are created. "
"Using simply CTRL, DEF or MCH will replace the prefix instead"
)
@classmethod
def add_relink_constraints_ui(self, layout, params):
def add_relink_constraints_ui(cls, layout: UILayout, params):
r = layout.row()
r.prop(params, "relink_constraints")
@ -125,7 +130,11 @@ class RelinkConstraintsMixin:
class Rig(BaseRig, RelinkConstraintsMixin):
def find_org_bones(self, pose_bone):
bones: BaseRig.ToplevelBones[str, BaseRig.CtrlBones, BaseRig.MchBones, str]
relink: bool
def find_org_bones(self, pose_bone) -> str:
return pose_bone.name
def initialize(self):
@ -149,23 +158,22 @@ class Rig(BaseRig, RelinkConstraintsMixin):
create_registered_widget(self.obj, org, widget)
@classmethod
def add_parameters(self, params):
self.add_relink_constraints_params(params)
def add_parameters(cls, params):
cls.add_relink_constraints_params(params)
params.optional_widget_type = bpy.props.StringProperty(
name = "Widget Type",
default = '',
description = "Choose the type of the widget to create"
name="Widget Type",
default='',
description="Choose the type of the widget to create"
)
@classmethod
def parameters_ui(self, layout, params):
def parameters_ui(cls, layout, params):
col = layout.column()
col.label(text='This rig type does not add the ORG prefix.')
col.label(text='Manually add ORG, MCH or DEF as needed.')
self.add_relink_constraints_ui(layout, params)
cls.add_relink_constraints_ui(layout, params)
pbone = bpy.context.active_pose_bone
@ -173,8 +181,8 @@ class Rig(BaseRig, RelinkConstraintsMixin):
layout_widget_dropdown(layout, params, "optional_widget_type")
#add_parameters = InstanceRig.add_parameters
#parameters_ui = InstanceRig.parameters_ui
# add_parameters = InstanceRig.add_parameters
# parameters_ui = InstanceRig.parameters_ui
def create_sample(obj):

View File

@ -15,21 +15,27 @@ class Rig(BaseRig, RelinkConstraintsMixin):
""" A "copy" rig. All it does is duplicate the original bone and
constrain it.
This is a control and deformation rig.
"""
def find_org_bones(self, pose_bone):
return pose_bone.name
bones: BaseRig.ToplevelBones[str, str, str, str]
org_name: str
make_control: bool
make_widget: bool
make_deform: bool
def find_org_bones(self, pose_bone) -> str:
return pose_bone.name
def initialize(self):
""" Gather and validate data about the rig.
"""
self.org_name = strip_org(self.bones.org)
self.org_name = strip_org(self.bones.org)
self.make_control = self.params.make_control
self.make_widget = self.params.make_widget
self.make_deform = self.params.make_deform
self.make_widget = self.params.make_widget
self.make_deform = self.params.make_deform
def generate_bones(self):
bones = self.bones
@ -42,7 +48,6 @@ class Rig(BaseRig, RelinkConstraintsMixin):
if self.make_deform:
bones.deform = self.copy_bone(bones.org, make_deformer_name(self.org_name), bbone=True)
def parent_bones(self):
bones = self.bones
@ -54,14 +59,12 @@ class Rig(BaseRig, RelinkConstraintsMixin):
if self.make_control and new_parent:
self.set_bone_parent(bones.ctrl, new_parent)
def configure_bones(self):
bones = self.bones
if self.make_control:
self.copy_bone_properties(bones.org, bones.ctrl)
def rig_bones(self):
bones = self.bones
@ -76,52 +79,50 @@ class Rig(BaseRig, RelinkConstraintsMixin):
if self.make_deform:
self.relink_move_constraints(bones.org, bones.deform, prefix='DEF:')
def generate_widgets(self):
bones = self.bones
if self.make_control:
# Create control widget
if self.make_widget:
create_registered_widget(self.obj, bones.ctrl, self.params.super_copy_widget_type or 'circle')
create_registered_widget(self.obj, bones.ctrl,
self.params.super_copy_widget_type or 'circle')
else:
create_bone_widget(self.obj, bones.ctrl)
@classmethod
def add_parameters(self, params):
def add_parameters(cls, params):
""" Add the parameters of this rig type to the
RigifyParameters PropertyGroup
"""
params.make_control = bpy.props.BoolProperty(
name = "Control",
default = True,
description = "Create a control bone for the copy"
name="Control",
default=True,
description="Create a control bone for the copy"
)
params.make_widget = bpy.props.BoolProperty(
name = "Widget",
default = True,
description = "Choose a widget for the bone control"
name="Widget",
default=True,
description="Choose a widget for the bone control"
)
params.super_copy_widget_type = bpy.props.StringProperty(
name = "Widget Type",
default = 'circle',
description = "Choose the type of the widget to create"
name="Widget Type",
default='circle',
description="Choose the type of the widget to create"
)
params.make_deform = bpy.props.BoolProperty(
name = "Deform",
default = True,
description = "Create a deform bone for the copy"
name="Deform",
default=True,
description="Create a deform bone for the copy"
)
self.add_relink_constraints_params(params)
cls.add_relink_constraints_params(params)
@classmethod
def parameters_ui(self, layout, params):
def parameters_ui(cls, layout, params):
""" Create the ui for the rig parameters.
"""
layout.prop(params, "make_control")
@ -136,7 +137,7 @@ class Rig(BaseRig, RelinkConstraintsMixin):
layout.prop(params, "make_deform")
self.add_relink_constraints_ui(layout, params)
cls.add_relink_constraints_ui(layout, params)
if params.relink_constraints and (params.make_control or params.make_deform):
col = layout.column()

View File

@ -1,11 +1,16 @@
# SPDX-License-Identifier: GPL-2.0-or-later
import bpy
from typing import Optional
from itertools import count
from bpy.types import PoseBone
from ..utils.rig import connected_children_names
from ..utils.naming import strip_org, make_derived_name
from ..utils.bones import put_bone, flip_bone, flip_bone_chain, is_same_position, is_connected_position
from ..utils.bones import (put_bone, flip_bone, flip_bone_chain, is_same_position,
is_connected_position)
from ..utils.bones import copy_bone_position, connect_bbone_chain_handles
from ..utils.widgets_basic import create_bone_widget, create_sphere_widget
from ..utils.misc import map_list
@ -15,32 +20,32 @@ from ..base_rig import BaseRig, stage
class SimpleChainRig(BaseRig):
"""A rig that consists of 3 connected chains of control, org and deform bones."""
def find_org_bones(self, bone):
def find_org_bones(self, bone: PoseBone):
return [bone.name] + connected_children_names(self.obj, bone.name)
min_chain_length = 2
bbone_segments = None
rig_parent_bone: str # Bone to be used as parent of the whole rig
def initialize(self):
if len(self.bones.org) < self.min_chain_length:
self.raise_error("Input to rig type must be a chain of {} or more bones.", self.min_chain_length)
self.raise_error(
"Input to rig type must be a chain of {} or more bones.", self.min_chain_length)
def parent_bones(self):
self.rig_parent_bone = self.get_bone_parent(self.bones.org[0])
bbone_segments = None
##############################
# BONES
#
# org[]:
# ORG bones
# ctrl:
# fk[]:
# FK control chain.
# deform[]:
# DEF bones
#
##############################
class CtrlBones(BaseRig.CtrlBones):
fk: list[str] # FK control chain
class MchBones(BaseRig.MchBones):
pass
bones: BaseRig.ToplevelBones[list[str], CtrlBones, MchBones, list[str]]
##############################
# Control chain
@ -49,7 +54,7 @@ class SimpleChainRig(BaseRig):
def make_control_chain(self):
self.bones.ctrl.fk = map_list(self.make_control_bone, count(0), self.bones.org)
def make_control_bone(self, i, org):
def make_control_bone(self, i: int, org: str):
return self.copy_bone(org, make_derived_name(org, 'ctrl'), parent=True)
@stage.parent_bones
@ -61,7 +66,7 @@ class SimpleChainRig(BaseRig):
for args in zip(count(0), self.bones.ctrl.fk, self.bones.org):
self.configure_control_bone(*args)
def configure_control_bone(self, i, ctrl, org):
def configure_control_bone(self, i: int, ctrl: str, org: str):
self.copy_bone_properties(org, ctrl)
@stage.generate_widgets
@ -69,7 +74,7 @@ class SimpleChainRig(BaseRig):
for args in zip(count(0), self.bones.ctrl.fk):
self.make_control_widget(*args)
def make_control_widget(self, i, ctrl):
def make_control_widget(self, i: int, ctrl: str):
create_bone_widget(self.obj, ctrl)
##############################
@ -84,7 +89,7 @@ class SimpleChainRig(BaseRig):
for args in zip(count(0), self.bones.org, self.bones.ctrl.fk):
self.rig_org_bone(*args)
def rig_org_bone(self, i, org, ctrl):
def rig_org_bone(self, i: int, org: str, ctrl: str):
self.make_constraint(org, 'COPY_TRANSFORMS', ctrl)
##############################
@ -94,7 +99,7 @@ class SimpleChainRig(BaseRig):
def make_deform_chain(self):
self.bones.deform = map_list(self.make_deform_bone, count(0), self.bones.org)
def make_deform_bone(self, i, org):
def make_deform_bone(self, i: int, org: str):
name = self.copy_bone(org, make_derived_name(org, 'def'), parent=True, bbone=True)
if self.bbone_segments:
self.get_bone(name).bbone_segments = self.bbone_segments
@ -109,7 +114,7 @@ class SimpleChainRig(BaseRig):
for args in zip(count(0), self.bones.deform, self.bones.org):
self.rig_deform_bone(*args)
def rig_deform_bone(self, i, deform, org):
def rig_deform_bone(self, i: int, deform: str, org: str):
self.make_constraint(deform, 'COPY_TRANSFORMS', org)
@ -118,18 +123,14 @@ class TweakChainRig(SimpleChainRig):
##############################
# BONES
#
# org[]:
# ORG bones
# ctrl:
# fk[]:
# FK control chain.
# tweak[]:
# Tweak control chain.
# deform[]:
# DEF bones
#
##############################
class CtrlBones(SimpleChainRig.CtrlBones):
tweak: list[str] # Tweak control chain
class MchBones(SimpleChainRig.MchBones):
pass
bones: BaseRig.ToplevelBones[list[str], CtrlBones, MchBones, list[str]]
##############################
# Tweak chain
@ -139,7 +140,7 @@ class TweakChainRig(SimpleChainRig):
orgs = self.bones.org
self.bones.ctrl.tweak = map_list(self.make_tweak_bone, count(0), orgs + orgs[-1:])
def make_tweak_bone(self, i, org):
def make_tweak_bone(self, i: int, org: str):
name = self.copy_bone(org, 'tweak_' + strip_org(org), parent=False, scale=0.5)
if i == len(self.bones.org):
@ -158,7 +159,7 @@ class TweakChainRig(SimpleChainRig):
for args in zip(count(0), self.bones.ctrl.tweak):
self.configure_tweak_bone(*args)
def configure_tweak_bone(self, i, tweak):
def configure_tweak_bone(self, i: int, tweak: str):
tweak_pb = self.get_bone(tweak)
tweak_pb.rotation_mode = 'ZXY'
@ -176,7 +177,7 @@ class TweakChainRig(SimpleChainRig):
for tweak in self.bones.ctrl.tweak:
self.make_tweak_widget(tweak)
def make_tweak_widget(self, tweak):
def make_tweak_widget(self, tweak: str):
create_sphere_widget(self.obj, tweak)
##############################
@ -188,7 +189,8 @@ class TweakChainRig(SimpleChainRig):
for args in zip(count(0), self.bones.org, tweaks, tweaks[1:]):
self.rig_org_bone(*args)
def rig_org_bone(self, i, org, tweak, next_tweak):
# noinspection PyMethodOverriding
def rig_org_bone(self, i: int, org: str, tweak: str, next_tweak: Optional[str]):
self.make_constraint(org, 'COPY_TRANSFORMS', tweak)
if next_tweak:
self.make_constraint(org, 'STRETCH_TO', next_tweak, keep_axis='SWING_Y')
@ -200,6 +202,9 @@ class ConnectingChainRig(TweakChainRig):
bbone_segments = 8
use_connect_reverse = None
use_connect_chain: bool
connected_tweak: Optional[str]
def initialize(self):
super().initialize()
@ -256,7 +261,7 @@ class ConnectingChainRig(TweakChainRig):
##############################
# Tweak chain
def check_connect_tweak(self, org):
def check_connect_tweak(self, org: str):
""" Check if it is possible to share the last parent tweak control. """
assert self.connected_tweak is None
@ -281,7 +286,7 @@ class ConnectingChainRig(TweakChainRig):
else:
return None
def make_tweak_bone(self, i, org):
def make_tweak_bone(self, i: int, org: str):
if i == 0 and self.check_connect_tweak(org):
return self.connected_tweak
else:
@ -294,7 +299,7 @@ class ConnectingChainRig(TweakChainRig):
if i > 0 or not (self.connected_tweak and self.use_connect_reverse):
self.set_bone_parent(tweak, main)
def configure_tweak_bone(self, i, tweak):
def configure_tweak_bone(self, i: int, tweak: str):
super().configure_tweak_bone(i, tweak)
if self.use_connect_chain and self.use_connect_reverse and i == len(self.bones.org):
@ -317,7 +322,7 @@ class ConnectingChainRig(TweakChainRig):
else:
self.set_bone_parent(self.bones.org[0], self.rig_parent_bone)
def rig_org_bone(self, i, org, tweak, next_tweak):
def rig_org_bone(self, i: int, org: str, tweak: str, next_tweak: Optional[str]):
if self.use_connect_chain and self.use_connect_reverse:
self.make_constraint(org, 'STRETCH_TO', tweak, keep_axis='SWING_Y')
else:
@ -326,7 +331,7 @@ class ConnectingChainRig(TweakChainRig):
##############################
# Deform chain
def make_deform_bone(self, i, org):
def make_deform_bone(self, i: int, org: str):
name = super().make_deform_bone(i, org)
if self.use_connect_chain and self.use_connect_reverse:
@ -345,7 +350,7 @@ class ConnectingChainRig(TweakChainRig):
self.set_bone_parent(deform[-1], self.bones.org[-1])
self.parent_bone_chain(reversed(deform), use_connect=True)
connect_bbone_chain_handles(self.obj, [ deform[0], parent_deform[0] ])
connect_bbone_chain_handles(self.obj, [deform[0], parent_deform[0]])
return
else:
@ -357,7 +362,7 @@ class ConnectingChainRig(TweakChainRig):
# Settings
@classmethod
def add_parameters(self, params):
def add_parameters(cls, params):
params.connect_chain = bpy.props.BoolProperty(
name='Connect chain',
default=False,
@ -365,6 +370,6 @@ class ConnectingChainRig(TweakChainRig):
)
@classmethod
def parameters_ui(self, layout, params):
def parameters_ui(cls, layout, params):
r = layout.row()
r.prop(params, "connect_chain")

View File

@ -3,6 +3,7 @@
import bpy
from itertools import count
from typing import Optional
from ...utils.bones import align_chain_x_axis
from ...utils.widgets_basic import create_circle_widget
@ -14,6 +15,8 @@ from ..chain_rigs import TweakChainRig
class Rig(TweakChainRig):
copy_rotation_axes: tuple[bool, bool, bool]
def initialize(self):
super().initialize()
@ -50,7 +53,7 @@ class Rig(TweakChainRig):
for args in zip(count(0), ctrls, [None] + ctrls):
self.rig_control_bone(*args)
def rig_control_bone(self, i, ctrl, prev_ctrl):
def rig_control_bone(self, _i: int, ctrl: str, prev_ctrl: Optional[str]):
if prev_ctrl:
self.make_constraint(
ctrl, 'COPY_ROTATION', prev_ctrl,
@ -59,12 +62,11 @@ class Rig(TweakChainRig):
)
# Widgets
def make_control_widget(self, i, ctrl):
def make_control_widget(self, i: int, ctrl: str):
create_circle_widget(self.obj, ctrl, radius=0.3, head_tail=0.5)
@classmethod
def add_parameters(self, params):
def add_parameters(cls, params):
""" Add the parameters of this rig type to the
RigifyParameters PropertyGroup
"""
@ -80,9 +82,8 @@ class Rig(TweakChainRig):
items = [('automatic', 'Automatic', ''), ('manual', 'Manual', '')]
params.roll_alignment = bpy.props.EnumProperty(items=items, name="Bone roll alignment", default='automatic')
@classmethod
def parameters_ui(self, layout, params):
def parameters_ui(cls, layout, params):
""" Create the ui for the rig parameters.
"""

View File

@ -3,8 +3,10 @@
import bpy
import json
from typing import Optional
from itertools import count
from ...rig_ui_template import PanelLayout
from ...utils.bones import put_bone, flip_bone, align_chain_x_axis, set_bone_widget_transform
from ...utils.naming import make_derived_name
from ...utils.widgets import create_widget
@ -21,6 +23,9 @@ from ..chain_rigs import SimpleChainRig
class Rig(SimpleChainRig):
"""A finger rig with master control."""
make_ik: bool
def initialize(self):
super().initialize()
@ -34,6 +39,19 @@ class Rig(SimpleChainRig):
def parent_bones(self):
self.rig_parent_bone = self.get_bone_parent(self.bones.org[0])
##############################
# BONES
class CtrlBones(SimpleChainRig.CtrlBones):
master: str # Master control
ik: str # IK control (@make_ik)
class MchBones(SimpleChainRig.MchBones):
stretch: list[str] # Stretch system
bend: list[str] # Bend system
bones: SimpleChainRig.ToplevelBones[list[str], CtrlBones, MchBones, list[str]]
##############################
# Master Control
@ -83,10 +101,10 @@ class Rig(SimpleChainRig):
self.bones.ctrl.fk = map_list(self.make_control_bone, count(0), orgs)
self.bones.ctrl.fk += [self.make_tip_control_bone(orgs[-1], orgs[0])]
def make_control_bone(self, i, org):
def make_control_bone(self, i: int, org: str):
return self.copy_bone(org, make_derived_name(org, 'ctrl'), inherit_scale=True)
def make_tip_control_bone(self, org, name_org):
def make_tip_control_bone(self, org: str, name_org: str):
name = self.copy_bone(org, make_derived_name(name_org, 'ctrl'), parent=False)
flip_bone(self.obj, name)
@ -102,12 +120,12 @@ class Rig(SimpleChainRig):
@stage.configure_bones
def configure_control_chain(self):
for args in zip(count(0), self.bones.ctrl.fk, self.bones.org + [None]):
for args in zip(count(0), self.bones.ctrl.fk, [*self.bones.org, None]):
self.configure_control_bone(*args)
ControlLayersOption.TWEAK.assign(self.params, self.obj, self.bones.ctrl.fk)
def configure_control_bone(self, i, ctrl, org):
def configure_control_bone(self, i: int, ctrl: str, org: Optional[str]):
if org:
self.copy_bone_properties(org, ctrl)
else:
@ -116,7 +134,7 @@ class Rig(SimpleChainRig):
bone.lock_rotation = (True, True, True)
bone.lock_scale = (True, True, True)
def make_control_widget(self, i, ctrl):
def make_control_widget(self, i: int, ctrl: str):
if ctrl == self.bones.ctrl.fk[-1]:
# Tip control
create_circle_widget(self.obj, ctrl, radius=0.3, head_tail=0.0)
@ -135,18 +153,18 @@ class Rig(SimpleChainRig):
self.build_ik_parent_switch(SwitchParentBuilder(self.generator))
def make_ik_control_bone(self, orgs):
def make_ik_control_bone(self, orgs: list[str]):
name = self.copy_bone(orgs[-1], make_derived_name(orgs[0], 'ctrl', '_ik'), scale=0.7)
put_bone(self.obj, name, self.get_bone(orgs[-1]).tail)
return name
def build_ik_parent_switch(self, pbuilder):
def build_ik_parent_switch(self, pbuilder: SwitchParentBuilder):
ctrl = self.bones.ctrl
pbuilder.build_child(
self, ctrl.ik, prop_bone=ctrl.ik,
select_tags=['held_object', 'limb_ik', {'child', 'limb_end'}], only_selected=True,
prop_id='IK_parent', prop_name='IK Parent', controls=[ ctrl.ik ],
prop_id='IK_parent', prop_name='IK Parent', controls=[ctrl.ik],
no_fix_rotation=True, no_fix_scale=True,
)
@ -194,10 +212,9 @@ class Rig(SimpleChainRig):
panel, output_bones=[ctrl.ik], input_bones=ctrl.fk[-1:],
input_ctrl_bones=[ctrl.master, *ctrl.fk],
label='IK->FK', rig_name=rig_name, tooltip='IK to FK',
compact=True, locks=(False,True,True),
compact=True, locks=(False, True, True),
)
@stage.generate_widgets
def make_ik_control_widget(self):
if self.make_ik:
@ -210,7 +227,7 @@ class Rig(SimpleChainRig):
def make_mch_bend_chain(self):
self.bones.mch.bend = map_list(self.make_mch_bend_bone, self.bones.org)
def make_mch_bend_bone(self, org):
def make_mch_bend_bone(self, org: str):
return self.copy_bone(org, make_derived_name(org, 'mch', '_drv'), inherit_scale=True, scale=0.3)
@stage.parent_bones
@ -242,7 +259,7 @@ class Rig(SimpleChainRig):
for args in zip(count(0), self.bones.mch.bend):
self.rig_mch_bend_bone(*args)
def rig_mch_bend_bone(self, i, mch):
def rig_mch_bend_bone(self, i: int, mch: str):
master = self.bones.ctrl.master
if i == 0:
self.make_constraint(mch, 'COPY_LOCATION', master)
@ -267,7 +284,7 @@ class Rig(SimpleChainRig):
def make_mch_stretch_chain(self):
self.bones.mch.stretch = map_list(self.make_mch_stretch_bone, self.bones.org)
def make_mch_stretch_bone(self, org):
def make_mch_stretch_bone(self, org: str):
return self.copy_bone(org, make_derived_name(org, 'mch'), parent=False)
@stage.parent_bones
@ -282,7 +299,7 @@ class Rig(SimpleChainRig):
for args in zip(count(0), self.bones.mch.stretch, ctrls, ctrls[1:]):
self.rig_mch_stretch_bone(*args)
def rig_mch_stretch_bone(self, i, mch, ctrl, ctrl_next):
def rig_mch_stretch_bone(self, i: int, mch: str, ctrl: str, ctrl_next: str):
if i == 0:
self.make_constraint(mch, 'COPY_LOCATION', ctrl)
self.make_constraint(mch, 'COPY_SCALE', ctrl)
@ -300,7 +317,7 @@ class Rig(SimpleChainRig):
if self.make_ik:
self.rig_org_ik(self.bones.org, self.bones.ctrl.ik)
def rig_org_ik(self, orgs, ik_ctrl):
def rig_org_ik(self, orgs: list[str], ik_ctrl: str):
axis = self.params.primary_rotation_axis
options = self.axis_options[axis]
@ -335,7 +352,8 @@ class Rig(SimpleChainRig):
panel = self.script.panel_with_selected_check(self, self.bones.ctrl.flatten())
panel.custom_prop(master, 'finger_curve', text="Curvature", slider=True)
def rig_deform_bone(self, i, deform, org):
# noinspection SpellCheckingInspection
def rig_deform_bone(self, i: int, deform: str, org: str):
master = self.bones.ctrl.master
bone = self.get_bone(deform)
@ -349,38 +367,43 @@ class Rig(SimpleChainRig):
# OPTIONS
@classmethod
def add_parameters(self, params):
def add_parameters(cls, params):
""" Add the parameters of this rig type to the
RigifyParameters PropertyGroup
"""
items = [('automatic', 'Automatic', ''), ('X', 'X manual', ''), ('Y', 'Y manual', ''), ('Z', 'Z manual', ''),
('-X', '-X manual', ''), ('-Y', '-Y manual', ''), ('-Z', '-Z manual', '')]
params.primary_rotation_axis = bpy.props.EnumProperty(items=items, name="Primary Rotation Axis", default='automatic')
items = [('automatic', 'Automatic', ''),
('X', 'X manual', ''), ('Y', 'Y manual', ''), ('Z', 'Z manual', ''),
('-X', '-X manual', ''), ('-Y', '-Y manual', ''), ('-Z', '-Z manual', '')]
params.primary_rotation_axis = bpy.props.EnumProperty(
items=items, name="Primary Rotation Axis", default='automatic')
params.bbones = bpy.props.IntProperty(
name = 'B-Bone Segments',
default = 10,
min = 1,
description = 'Number of B-Bone segments'
name='B-Bone Segments',
default=10,
min=1,
description='Number of B-Bone segments'
)
params.make_extra_ik_control = bpy.props.BoolProperty(
name = "Extra IK Control",
default = False,
description = "Create an optional IK control"
name="Extra IK Control",
default=False,
description="Create an optional IK control"
)
params.ik_local_location = bpy.props.BoolProperty(
name = 'IK Local Location',
default = True,
description = "Specifies the value of the Local Location option for IK controls, which decides if the location channels are aligned to the local control orientation or world",
name='IK Local Location',
default=True,
description="Specifies the value of the Local Location option for IK controls, "
"which decides if the location channels are aligned to the local control "
"orientation or world",
)
ControlLayersOption.TWEAK.add_parameters(params)
ControlLayersOption.EXTRA_IK.add_parameters(params)
@classmethod
def parameters_ui(self, layout, params):
def parameters_ui(cls, layout, params):
""" Create the ui for the rig parameters.
"""
r = layout.row()
@ -398,12 +421,14 @@ class Rig(SimpleChainRig):
if params.make_extra_ik_control:
ControlLayersOption.EXTRA_IK.parameters_ui(layout, params)
#############################
# Finger FK to IK operator ##
#############################
SCRIPT_REGISTER_OP_SNAP_FK_IK = ['POSE_OT_rigify_finger_fk2ik', 'POSE_OT_rigify_finger_fk2ik_bake']
# noinspection SpellCheckingInspection
SCRIPT_UTILITIES_OP_SNAP_FK_IK = ['''
########################
## Limb Snap IK to FK ##
@ -558,7 +583,14 @@ class POSE_OT_rigify_finger_fk2ik_bake(RigifyFingerFk2IkBase, RigifyBakeKeyframe
return self.bake_get_all_bone_curves(fk_bones, TRANSFORM_PROPS_ALL)
''']
def add_finger_snap_fk_to_ik(panel, *, master=None, fk_bones=[], ik_bones=[], ik_control=None, ik_constraint_bone=None, axis='+X', rig_name='', compact=None):
# noinspection PyDefaultArgument
def add_finger_snap_fk_to_ik(
panel: 'PanelLayout', *, master: Optional[str] = None,
fk_bones: list[str] = [], ik_bones: list[str] = [],
ik_control: Optional[str] = None,
ik_constraint_bone: Optional[str] = None,
axis='+X', rig_name='', compact: Optional[bool] = None):
panel.use_bake_settings()
panel.script.add_utilities(SCRIPT_UTILITIES_OP_SNAP_FK_IK)
panel.script.register_classes(SCRIPT_REGISTER_OP_SNAP_FK_IK)
@ -578,6 +610,7 @@ def add_finger_snap_fk_to_ik(panel, *, master=None, fk_bones=[], ik_bones=[], ik
clear_bones=[master, *fk_bones], compact=compact,
)
def create_sample(obj):
# generated by rigify.utils.write_metarig
bpy.ops.object.mode_set(mode='EDIT')
@ -629,7 +662,10 @@ def create_sample(obj):
pbone.lock_scale = (False, False, False)
pbone.rotation_mode = 'QUATERNION'
try:
pbone.rigify_parameters.extra_layers = [False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
pbone.rigify_parameters.extra_layers = [
False, False, False, False, False, True, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False]
except AttributeError:
pass
try:

View File

@ -8,7 +8,8 @@ from mathutils import Matrix
from ...utils.layers import ControlLayersOption
from ...utils.naming import strip_org, make_mechanism_name, make_derived_name
from ...utils.bones import BoneDict, put_bone, align_bone_to_axis, align_bone_orientation, set_bone_widget_transform
from ...utils.bones import (put_bone, align_bone_to_axis, align_bone_orientation,
set_bone_widget_transform, TypedBoneDict)
from ...utils.widgets import adjust_widget_transform_mesh
from ...utils.widgets_basic import create_circle_widget
from ...utils.misc import map_list
@ -22,6 +23,9 @@ class Rig(BaseSpineRig):
Spine rig with fixed pivot, hip/chest controls and tweaks.
"""
pivot_pos: int
use_fk: bool
def initialize(self):
super().initialize()
@ -34,34 +38,28 @@ class Rig(BaseSpineRig):
####################################################
# BONES
#
# org[]:
# ORG bones
# ctrl:
# master, hips, chest:
# Main controls.
# fk:
# chest[], hips[]:
# FK controls.
# tweak[]:
# Tweak control chain.
# mch:
# pivot:
# Pivot tweak parent.
# chain:
# chest[], hips[]:
# Tweak parents, distributing master deform.
# wgt_hips, wgt_chest:
# Widget position bones.
# deform[]:
# DEF bones
#
####################################################
class SplitChainBones(TypedBoneDict):
chest: list[str]
hips: list[str]
class CtrlBones(BaseSpineRig.CtrlBones):
hips: str # Hip control
chest: str # Chest control
fk: 'Rig.SplitChainBones' # FK controls
class MchBones(BaseSpineRig.MchBones):
pivot: str # Central pivot between sub-chains
chain: 'Rig.SplitChainBones' # Tweak parents, distributing master deform.
wgt_hips: str # Hip widget position bone.
wgt_chest: str # Chest widget position bone.
bones: BaseSpineRig.ToplevelBones[list[str], CtrlBones, MchBones, list[str]]
####################################################
# Master control bone
def get_master_control_pos(self, orgs):
def get_master_control_pos(self, orgs: list[str]):
base_bone = self.get_bone(orgs[0])
return (base_bone.head + base_bone.tail) / 2
@ -76,12 +74,12 @@ class Rig(BaseSpineRig):
self.bones.ctrl.hips = self.make_hips_control_bone(orgs[pivot-1], 'hips')
self.bones.ctrl.chest = self.make_chest_control_bone(orgs[pivot], 'chest')
def make_hips_control_bone(self, org, name):
def make_hips_control_bone(self, org: str, name: str):
name = self.copy_bone(org, name, parent=False)
align_bone_to_axis(self.obj, name, 'y', length=self.length / 4, flip=True)
return name
def make_chest_control_bone(self, org, name):
def make_chest_control_bone(self, org: str, name: str):
name = self.copy_bone(org, name, parent=False)
align_bone_to_axis(self.obj, name, 'y', length=self.length / 3)
return name
@ -100,7 +98,7 @@ class Rig(BaseSpineRig):
self.make_end_control_widget(ctrl.hips, mch.wgt_hips)
self.make_end_control_widget(ctrl.chest, mch.wgt_chest)
def make_end_control_widget(self, ctrl, wgt_mch):
def make_end_control_widget(self, ctrl: str, wgt_mch: str):
shape_bone = self.get_bone(wgt_mch)
is_horizontal = abs(shape_bone.z_axis.normalized().y) < 0.7
@ -117,22 +115,27 @@ class Rig(BaseSpineRig):
if is_horizontal:
# Tilt the widget toward the ground for horizontal (animal) spines
angle = math.copysign(28, shape_bone.x_axis.x)
rotmat = Matrix.Rotation(math.radians(angle), 4, 'X')
adjust_widget_transform_mesh(obj, rotmat, local=True)
rot_mat = Matrix.Rotation(math.radians(angle), 4, 'X')
adjust_widget_transform_mesh(obj, rot_mat, local=True)
####################################################
# FK control bones
fk_result: 'Rig.SplitChainBones' # ctrl.fk or mch.chain depending on use_fk
@stage.generate_bones
def make_control_chain(self):
if self.use_fk:
orgs = self.bones.org
self.bones.ctrl.fk = self.fk_result = BoneDict(
hips = map_list(self.make_control_bone, count(0), orgs[0:self.pivot_pos], repeat(True)),
chest = map_list(self.make_control_bone, count(self.pivot_pos), orgs[self.pivot_pos:], repeat(False)),
self.bones.ctrl.fk = self.fk_result = self.SplitChainBones(
hips=map_list(self.make_control_bone,
count(0), orgs[0:self.pivot_pos], repeat(True)),
chest=map_list(self.make_control_bone,
count(self.pivot_pos), orgs[self.pivot_pos:], repeat(False)),
)
def make_control_bone(self, i, org, is_hip):
# noinspection PyMethodOverriding
def make_control_bone(self, i: int, org: str, is_hip: bool):
name = self.copy_bone(org, make_derived_name(org, 'ctrl', '_fk'), parent=False)
if is_hip:
put_bone(self.obj, name, self.get_bone(name).tail)
@ -166,7 +169,7 @@ class Rig(BaseSpineRig):
for ctrl in fk.chest:
self.make_control_widget(ctrl, False)
def make_control_widget(self, ctrl, is_hip):
def make_control_widget(self, ctrl: str, is_hip: bool):
obj = create_circle_widget(self.obj, ctrl, radius=1.0, head_tail=0.5)
if is_hip:
adjust_widget_transform_mesh(obj, Matrix.Diagonal((1, -1, 1, 1)), local=True)
@ -183,12 +186,12 @@ class Rig(BaseSpineRig):
mch.wgt_hips = self.make_mch_widget_bone(orgs[0], 'WGT-hips')
mch.wgt_chest = self.make_mch_widget_bone(orgs[-1], 'WGT-chest')
def make_mch_pivot_bone(self, org, name):
def make_mch_pivot_bone(self, org: str, name: str):
name = self.copy_bone(org, make_mechanism_name(name), parent=False)
align_bone_to_axis(self.obj, name, 'y', length=self.length * 0.6 / 4)
return name
def make_mch_widget_bone(self, org, name):
def make_mch_widget_bone(self, org: str, name: str):
return self.copy_bone(org, make_mechanism_name(name), parent=False)
@stage.parent_bones
@ -211,14 +214,14 @@ class Rig(BaseSpineRig):
@stage.generate_bones
def make_mch_chain(self):
orgs = self.bones.org
self.bones.mch.chain = BoneDict(
hips = map_list(self.make_mch_bone, orgs[0:self.pivot_pos], repeat(True)),
chest = map_list(self.make_mch_bone, orgs[self.pivot_pos:], repeat(False)),
self.bones.mch.chain = self.SplitChainBones(
hips=map_list(self.make_mch_bone, orgs[0:self.pivot_pos], repeat(True)),
chest=map_list(self.make_mch_bone, orgs[self.pivot_pos:], repeat(False)),
)
if not self.use_fk:
self.fk_result = self.bones.mch.chain
def make_mch_bone(self, org, is_hip):
def make_mch_bone(self, org: str, is_hip: bool):
name = self.copy_bone(org, make_mechanism_name(strip_org(org)), parent=False)
align_bone_to_axis(self.obj, name, 'y', length=self.length / 10, flip=is_hip)
return name
@ -242,8 +245,9 @@ class Rig(BaseSpineRig):
for mch in chain.chest:
self.rig_mch_bone(mch, ctrl.chest, len(chain.chest))
def rig_mch_bone(self, mch, control, count):
self.make_constraint(mch, 'COPY_TRANSFORMS', control, space='LOCAL', influence=1/count)
def rig_mch_bone(self, mch: str, control: str, chain_len: int):
self.make_constraint(mch, 'COPY_TRANSFORMS', control,
space='LOCAL', influence=1 / chain_len)
####################################################
# Tweak bones
@ -260,7 +264,7 @@ class Rig(BaseSpineRig):
# SETTINGS
@classmethod
def add_parameters(self, params):
def add_parameters(cls, params):
params.pivot_pos = bpy.props.IntProperty(
name='pivot_position',
default=2,
@ -278,7 +282,7 @@ class Rig(BaseSpineRig):
ControlLayersOption.FK.add_parameters(params)
@classmethod
def parameters_ui(self, layout, params):
def parameters_ui(cls, layout, params):
r = layout.row()
r.prop(params, "pivot_pos")
@ -328,7 +332,6 @@ def create_sample(obj):
bone.parent = arm.edit_bones[bones['spine.002']]
bones['spine.003'] = bone.name
bpy.ops.object.mode_set(mode='OBJECT')
pbone = obj.pose.bones[bones['spine']]
pbone.rigify_type = 'spines.basic_spine'
@ -339,7 +342,10 @@ def create_sample(obj):
pbone.rotation_mode = 'QUATERNION'
try:
pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
pbone.rigify_parameters.tweak_layers = [
False, False, False, False, True, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False]
except AttributeError:
pass
pbone = obj.pose.bones[bones['spine.001']]

View File

@ -17,6 +17,8 @@ from .spine_rigs import BaseHeadTailRig
class Rig(BaseHeadTailRig):
copy_rotation_axes: tuple[bool, bool, bool]
def initialize(self):
super().initialize()
@ -66,7 +68,7 @@ class Rig(BaseHeadTailRig):
for args in zip(count(0), ctrls, [self.bones.ctrl.master] + ctrls):
self.rig_control_bone(*args)
def rig_control_bone(self, i, ctrl, prev_ctrl):
def rig_control_bone(self, _i: int, ctrl: str, prev_ctrl: str):
self.make_constraint(
ctrl, 'COPY_ROTATION', prev_ctrl,
use_xyz=self.copy_rotation_axes,
@ -74,7 +76,7 @@ class Rig(BaseHeadTailRig):
)
# Widgets
def make_control_widget(self, i, ctrl):
def make_control_widget(self, i: int, ctrl: str):
create_circle_widget(self.obj, ctrl, radius=0.5, head_tail=0.75)
####################################################
@ -96,7 +98,7 @@ class Rig(BaseHeadTailRig):
orgs = self.bones.org
self.bones.ctrl.tweak = map_list(self.make_tweak_bone, count(0), orgs[0:1] + orgs)
def make_tweak_bone(self, i, org):
def make_tweak_bone(self, i: int, org: str):
if i == 0:
if self.check_connect_tweak(org):
return self.connected_tweak
@ -113,6 +115,7 @@ class Rig(BaseHeadTailRig):
####################################################
# Deform chain
# noinspection SpellCheckingInspection
@stage.configure_bones
def configure_deform_chain(self):
if self.use_connect_chain and self.use_connect_reverse:
@ -121,12 +124,11 @@ class Rig(BaseHeadTailRig):
else:
self.get_bone(self.bones.deform[-1]).bone.bbone_easeout = 0.0
####################################################
# SETTINGS
@classmethod
def add_parameters(self, params):
def add_parameters(cls, params):
""" Add the parameters of this rig type to the
RigifyParameters PropertyGroup
"""
@ -139,9 +141,8 @@ class Rig(BaseHeadTailRig):
default=tuple([i == 0 for i in range(0, 3)])
)
@classmethod
def parameters_ui(self, layout, params):
def parameters_ui(cls, layout, params):
""" Create the ui for the rig parameters.
"""
@ -195,7 +196,10 @@ def create_sample(obj, *, parent=None):
except AttributeError:
pass
try:
pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
pbone.rigify_parameters.tweak_layers = [
False, False, False, False, True, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False]
except AttributeError:
pass
pbone = obj.pose.bones[bones['tail.001']]

View File

@ -2,6 +2,7 @@
import bpy
from typing import Optional, NamedTuple
from itertools import count
from ...utils.layers import ControlLayersOption
@ -24,6 +25,9 @@ class BaseSpineRig(TweakChainRig):
bbone_segments = 8
min_chain_length = 3
use_torso_pivot: bool # Generate the custom pivot control
length: float # Total length of the chain bones
def initialize(self):
super().initialize()
@ -32,21 +36,21 @@ class BaseSpineRig(TweakChainRig):
####################################################
# BONES
#
# ctrl:
# master
# Main control.
# master_pivot
# Custom pivot under the master control.
# mch:
# master_pivot
# Final output of the custom pivot.
#
####################################################
class CtrlBones(TweakChainRig.CtrlBones):
master: str # Master control
master_pivot: str # Custom pivot under the master control (conditional)
class MchBones(TweakChainRig.MchBones):
master_pivot: str # Final output of the custom pivot (conditional)
bones: TweakChainRig.ToplevelBones[list[str], CtrlBones, MchBones, list[str]]
####################################################
# Master control bone
component_torso_pivot: Optional[CustomPivotControl]
@stage.generate_bones
def make_master_control(self):
self.bones.ctrl.master = name = self.make_master_control_bone(self.bones.org)
@ -54,16 +58,16 @@ class BaseSpineRig(TweakChainRig):
self.component_torso_pivot = self.build_master_pivot(name)
self.build_parent_switch(name)
def get_master_control_pos(self, orgs):
def get_master_control_pos(self, orgs: list[str]):
return self.get_bone(orgs[0]).head
def make_master_control_bone(self, orgs):
def make_master_control_bone(self, orgs: list[str]):
name = self.copy_bone(orgs[0], 'torso')
put_bone(self.obj, name, self.get_master_control_pos(orgs))
align_bone_to_axis(self.obj, name, 'y', length=self.length * 0.6)
return name
def build_master_pivot(self, master_name, **args):
def build_master_pivot(self, master_name: str, **args):
if self.use_torso_pivot:
return CustomPivotControl(
self, 'master_pivot', master_name, parent=master_name, **args
@ -75,7 +79,7 @@ class BaseSpineRig(TweakChainRig):
else:
return self.bones.ctrl.master
def build_parent_switch(self, master_name):
def build_parent_switch(self, master_name: str):
pbuilder = SwitchParentBuilder(self.generator)
org_parent = self.get_bone_parent(self.bones.org[0])
@ -92,7 +96,7 @@ class BaseSpineRig(TweakChainRig):
self.register_parent_bones(pbuilder)
def register_parent_bones(self, pbuilder):
def register_parent_bones(self, pbuilder: SwitchParentBuilder):
pbuilder.register_parent(self, self.bones.org[0], name='Hips', exclude_self=True, tags={'hips'})
pbuilder.register_parent(self, self.bones.org[-1], name='Chest', exclude_self=True, tags={'chest'})
@ -121,7 +125,7 @@ class BaseSpineRig(TweakChainRig):
self.set_bone_parent(org, tweak)
def rig_org_bone(self, i, org, tweak, next_tweak):
# For spine rigs, these constraints go on the deform bones. See T74483#902192.
# For spine rigs, these constraints go on the deformation bones. See T74483#902192.
pass
####################################################
@ -142,31 +146,33 @@ class BaseSpineRig(TweakChainRig):
for args in zip(count(0), self.bones.deform, tweaks, tweaks[1:]):
self.rig_deform_bone(*args)
def rig_deform_bone(self, i, deform, tweak, next_tweak):
# noinspection PyMethodOverriding
def rig_deform_bone(self, i: int, deform: str, tweak: str, next_tweak: Optional[str]):
self.make_constraint(deform, 'COPY_TRANSFORMS', tweak)
if next_tweak:
self.make_constraint(deform, 'STRETCH_TO', next_tweak, keep_axis='SWING_Y')
@stage.configure_bones
def configure_bbone_chain(self):
# noinspection SpellCheckingInspection
self.get_bone(self.bones.deform[0]).bone.bbone_easein = 0.0
####################################################
# SETTINGS
@classmethod
def add_parameters(self, params):
def add_parameters(cls, params):
params.make_custom_pivot = bpy.props.BoolProperty(
name = "Custom Pivot Control",
default = False,
description = "Create a rotation pivot control that can be repositioned arbitrarily"
name="Custom Pivot Control",
default=False,
description="Create a rotation pivot control that can be repositioned arbitrarily"
)
# Setting up extra layers for the FK and tweak
ControlLayersOption.TWEAK.add_parameters(params)
@classmethod
def parameters_ui(self, layout, params):
def parameters_ui(cls, layout, params):
layout.prop(params, 'make_custom_pivot')
ControlLayersOption.TWEAK.parameters_ui(layout, params)
@ -175,6 +181,19 @@ class BaseSpineRig(TweakChainRig):
class BaseHeadTailRig(ConnectingChainRig):
""" Base for head and tail rigs. """
class RotationBone(NamedTuple):
org: str
name: str
bone: str
def_val: float # Default value of the follow slider
copy_scale: bool
rotation_bones: list[RotationBone]
follow_bone: str
default_prop_bone: str
prop_bone: str
def initialize(self):
super().initialize()
@ -183,7 +202,7 @@ class BaseHeadTailRig(ConnectingChainRig):
####################################################
# Utilities
def get_parent_master(self, default_bone):
def get_parent_master(self, default_bone: str) -> str:
""" Return the parent's master control bone if connecting and found. """
if self.use_connect_chain and 'master' in self.rigify_parent.bones.ctrl:
@ -191,7 +210,7 @@ class BaseHeadTailRig(ConnectingChainRig):
else:
return default_bone
def get_parent_master_panel(self, default_bone):
def get_parent_master_panel(self, default_bone: str):
""" Return the parent's master control bone if connecting and found, and script panel. """
controls = self.bones.ctrl.flatten()
@ -208,37 +227,38 @@ class BaseHeadTailRig(ConnectingChainRig):
####################################################
# Rotation follow
def make_mch_follow_bone(self, org, name, defval, *, copy_scale=False):
def make_mch_follow_bone(self, org: str, name: str, def_val: float, *, copy_scale=False):
bone = self.copy_bone(org, make_derived_name('ROT-'+name, 'mch'), parent=True)
self.rotation_bones.append((org, name, bone, defval, copy_scale))
self.rotation_bones.append(self.RotationBone(org, name, bone, def_val, copy_scale))
return bone
@stage.parent_bones
def align_mch_follow_bones(self):
self.follow_bone = self.get_parent_master('root')
for org, name, bone, defval, copy_scale in self.rotation_bones:
for org, name, bone, def_val, copy_scale in self.rotation_bones:
align_bone_orientation(self.obj, bone, self.follow_bone)
@stage.configure_bones
def configure_mch_follow_bones(self):
self.prop_bone, panel = self.get_parent_master_panel(self.default_prop_bone)
for org, name, bone, defval, copy_scale in self.rotation_bones:
textname = name.replace('_',' ').title() + ' Follow'
for org, name, bone, def_val, copy_scale in self.rotation_bones:
text_name = name.replace('_', ' ').title() + ' Follow'
self.make_property(self.prop_bone, name+'_follow', default=float(defval))
panel.custom_prop(self.prop_bone, name+'_follow', text=textname, slider=True)
self.make_property(self.prop_bone, name+'_follow', default=float(def_val))
panel.custom_prop(self.prop_bone, name+'_follow', text=text_name, slider=True)
@stage.rig_bones
def rig_mch_follow_bones(self):
for org, name, bone, defval, copy_scale in self.rotation_bones:
for org, name, bone, def_val, copy_scale in self.rotation_bones:
self.rig_mch_rotation_bone(bone, name+'_follow', copy_scale)
def rig_mch_rotation_bone(self, mch, prop_name, copy_scale):
def rig_mch_rotation_bone(self, mch: str, prop_name: str, copy_scale: bool):
con = self.make_constraint(mch, 'COPY_ROTATION', self.follow_bone)
self.make_driver(con, 'influence', variables=[(self.prop_bone, prop_name)], polynomial=[1,-1])
self.make_driver(con, 'influence',
variables=[(self.prop_bone, prop_name)], polynomial=[1, -1])
if copy_scale:
self.make_constraint(mch, 'COPY_SCALE', self.follow_bone)
@ -256,14 +276,14 @@ class BaseHeadTailRig(ConnectingChainRig):
# Settings
@classmethod
def add_parameters(self, params):
def add_parameters(cls, params):
super().add_parameters(params)
# Setting up extra layers for the FK and tweak
ControlLayersOption.TWEAK.add_parameters(params)
@classmethod
def parameters_ui(self, layout, params):
def parameters_ui(cls, layout, params):
super().parameters_ui(layout, params)
ControlLayersOption.TWEAK.parameters_ui(layout, params)

View File

@ -24,6 +24,9 @@ class Rig(BaseHeadTailRig):
use_connect_reverse = False
min_chain_length = 1
long_neck: bool
has_neck: bool
def initialize(self):
super().initialize()
@ -32,27 +35,20 @@ class Rig(BaseHeadTailRig):
####################################################
# BONES
#
# org[]:
# ORG bones
# ctrl:
# neck, head, neck_bend:
# Main controls.
# tweak[]:
# Tweak control chain.
# mch:
# rot_neck, rot_head:
# Main control parents, implement FK follow.
# stretch
# Long neck stretch behavior.
# ik[]
# Long neck IK behavior.
# chain[]
# Tweak parents.
# deform[]:
# DEF bones
#
####################################################
class CtrlBones(BaseHeadTailRig.CtrlBones):
neck: str # Main neck control
head: str # Main head control
neck_bend: str # Extra neck bend control for long neck
class MchBones(BaseHeadTailRig.MchBones):
rot_neck: str # Main neck control parent for FK follow
rot_head: str # Main head control parent for FK follow
stretch: str # Long neck stretch helper
ik: list[str] # Long neck IK system
chain: list[str] # Tweak parents
bones: BaseHeadTailRig.ToplevelBones[list[str], CtrlBones, MchBones, list[str]]
####################################################
# Main control bones
@ -72,7 +68,7 @@ class Rig(BaseHeadTailRig):
self.default_prop_bone = ctrl.head
def make_neck_control_bone(self, org, name, org_head):
def make_neck_control_bone(self, org: str, name: str, org_head: str):
name = self.copy_bone(org, name, parent=False)
# Neck spans all neck bones (except head)
@ -80,7 +76,7 @@ class Rig(BaseHeadTailRig):
return name
def make_neck_bend_control_bone(self, org, name, neck):
def make_neck_bend_control_bone(self, org: str, name: str, neck: str):
name = self.copy_bone(org, name, parent=False)
neck_bend_eb = self.get_bone(name)
@ -98,7 +94,7 @@ class Rig(BaseHeadTailRig):
return name
def make_head_control_bone(self, org, name):
def make_head_control_bone(self, org: str, name: str):
return self.copy_bone(org, name, parent=False)
@stage.parent_bones
@ -119,7 +115,7 @@ class Rig(BaseHeadTailRig):
if self.long_neck:
self.configure_neck_bend_bone(self.bones.ctrl.neck_bend, self.bones.org[0])
def configure_neck_bend_bone(self, ctrl, org):
def configure_neck_bend_bone(self, ctrl: str, _org: str):
bone = self.get_bone(ctrl)
bone.lock_rotation = (True, True, True)
bone.lock_rotation_w = True
@ -134,7 +130,7 @@ class Rig(BaseHeadTailRig):
if self.long_neck:
self.make_neck_bend_widget(ctrl.neck_bend)
def make_neck_widget(self, ctrl):
def make_neck_widget(self, ctrl: str):
radius = 1/max(1, len(self.bones.mch.chain))
create_circle_widget(
@ -143,7 +139,7 @@ class Rig(BaseHeadTailRig):
head_tail=0.5,
)
def make_neck_bend_widget(self, ctrl):
def make_neck_bend_widget(self, ctrl: str):
radius = 1/max(1, len(self.bones.mch.chain))
create_neck_bend_widget(
@ -152,7 +148,7 @@ class Rig(BaseHeadTailRig):
head_tail=0.0,
)
def make_head_widget(self, ctrl):
def make_head_widget(self, ctrl: str):
# place wgt @ middle of head bone for long necks
if self.long_neck:
head_tail = 0.5
@ -161,9 +157,9 @@ class Rig(BaseHeadTailRig):
create_circle_widget(
self.obj, ctrl,
radius = 0.5,
head_tail = head_tail,
with_line = False,
radius=0.5,
head_tail=head_tail,
with_line=False,
)
####################################################
@ -179,7 +175,7 @@ class Rig(BaseHeadTailRig):
mch.stretch = self.make_mch_stretch_bone(orgs[0], 'STR-neck', orgs[-1])
mch.rot_head = self.make_mch_follow_bone(orgs[-1], 'head', 0.0, copy_scale=True)
def make_mch_stretch_bone(self, org, name, org_head):
def make_mch_stretch_bone(self, org: str, name: str, org_head: str):
name = self.copy_bone(org, make_derived_name(name, 'mch'), parent=False)
self.get_bone(name).tail = self.get_bone(org_head).head
return name
@ -198,7 +194,7 @@ class Rig(BaseHeadTailRig):
if self.has_neck:
self.rig_mch_stretch_bone(self.bones.mch.stretch, self.bones.ctrl.head)
def rig_mch_stretch_bone(self, mch, head):
def rig_mch_stretch_bone(self, mch: str, head: str):
self.make_constraint(mch, 'STRETCH_TO', head, keep_axis='SWING_Y')
####################################################
@ -210,7 +206,7 @@ class Rig(BaseHeadTailRig):
if self.long_neck:
self.bones.mch.ik = map_list(self.make_mch_ik_bone, orgs[0:-1])
def make_mch_ik_bone(self, org):
def make_mch_ik_bone(self, org: str):
return self.copy_bone(org, make_derived_name(org, 'mch', '_ik'), parent=False)
@stage.parent_bones
@ -228,7 +224,7 @@ class Rig(BaseHeadTailRig):
for args in zip(count(0), ik):
self.rig_mch_ik_bone(*args, len(ik), head)
def rig_mch_ik_bone(self, i, mch, ik_len, head):
def rig_mch_ik_bone(self, i: int, mch: str, ik_len: int, head: str):
if i == ik_len - 1:
self.make_constraint(mch, 'IK', head, chain_count=ik_len)
@ -242,7 +238,7 @@ class Rig(BaseHeadTailRig):
orgs = self.bones.org
self.bones.mch.chain = map_list(self.make_mch_bone, orgs[1:-1])
def make_mch_bone(self, org):
def make_mch_bone(self, org: str):
return self.copy_bone(org, make_derived_name(org, 'mch'), parent=False, scale=1/4)
@stage.parent_bones
@ -267,14 +263,14 @@ class Rig(BaseHeadTailRig):
for args in zip(count(0), chain):
self.rig_mch_bone(*args, len(chain))
def rig_mch_bone_long(self, i, mch, ik, len_mch):
def rig_mch_bone_long(self, i: int, mch: str, ik: str, len_mch: int):
ctrl = self.bones.ctrl
self.make_constraint(mch, 'COPY_LOCATION', ik)
step = 2/(len_mch+1)
xval = (i+1)*step
influence = 2*xval - xval**2 #parabolic influence of pivot
x_val = (i+1)*step
influence = 2*x_val - x_val**2 # parabolic influence of pivot
self.make_constraint(
mch, 'COPY_LOCATION', ctrl.neck_bend,
@ -286,10 +282,10 @@ class Rig(BaseHeadTailRig):
def rig_mch_bone(self, i, mch, len_mch):
ctrl = self.bones.ctrl
nfactor = float((i + 1) / (len_mch + 1))
n_factor = float((i + 1) / (len_mch + 1))
self.make_constraint(
mch, 'COPY_ROTATION', ctrl.head,
influence=nfactor, space='LOCAL'
influence=n_factor, space='LOCAL'
)
self.make_constraint(mch, 'COPY_SCALE', ctrl.neck)
@ -345,7 +341,7 @@ class Rig(BaseHeadTailRig):
else:
tweaks = [self.connected_tweak or self.bones.ctrl.head]
for args in zip(count(0), self.bones.org, tweaks, tweaks[1:] + [None]):
for args in zip(count(0), self.bones.org, tweaks, [*tweaks[1:], None]):
self.rig_org_bone(*args)
@ -392,7 +388,10 @@ def create_sample(obj, *, parent=None):
except AttributeError:
pass
try:
pbone.rigify_parameters.tweak_layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
pbone.rigify_parameters.tweak_layers = [
False, False, False, False, True, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False]
except AttributeError:
pass
pbone = obj.pose.bones[bones['neck.001']]

View File

@ -32,8 +32,8 @@ class Rig(SubstitutionRig, BoneUtilityMixin):
if neck_pos >= len(orgs):
self.raise_error("Neck is too short.")
spine_orgs = orgs[0 : neck_pos-1]
head_orgs = orgs[neck_pos-1 : ]
spine_orgs = orgs[0: neck_pos-1]
head_orgs = orgs[neck_pos-1:]
if self.params.use_tail:
tail_pos = self.params.tail_pos
@ -42,8 +42,8 @@ class Rig(SubstitutionRig, BoneUtilityMixin):
if tail_pos >= pivot_pos:
self.raise_error("Tail cannot be above or the same as pivot.")
tail_orgs = list(reversed(spine_orgs[0 : tail_pos]))
spine_orgs = spine_orgs[tail_pos : ]
tail_orgs = list(reversed(spine_orgs[0: tail_pos]))
spine_orgs = spine_orgs[tail_pos:]
pivot_pos -= tail_pos
# Split the bone chain and flip the tail
@ -65,17 +65,17 @@ class Rig(SubstitutionRig, BoneUtilityMixin):
# Create the parts
self.assign_params(spine_orgs[0], params_copy, pivot_pos=pivot_pos, make_fk_controls=False)
result = [ self.instantiate_rig(basic_spine.Rig, spine_orgs[0]) ]
result = [self.instantiate_rig(basic_spine.Rig, spine_orgs[0])]
if tail_orgs:
self.assign_params(tail_orgs[0], params_copy, connect_chain=True)
result += [ self.instantiate_rig(basic_tail.Rig, tail_orgs[0]) ]
result += [self.instantiate_rig(basic_tail.Rig, tail_orgs[0])]
if head_orgs:
self.assign_params(head_orgs[0], params_copy, connect_chain=True)
result += [ self.instantiate_rig(super_head.Rig, head_orgs[0]) ]
result += [self.instantiate_rig(super_head.Rig, head_orgs[0])]
return result
@ -86,10 +86,10 @@ def add_parameters(params):
super_head.Rig.add_parameters(params)
params.neck_pos = bpy.props.IntProperty(
name = 'neck_position',
default = 6,
min = 0,
description = 'Neck start position'
name='neck_position',
default=6,
min=0,
description='Neck start position'
)
params.tail_pos = bpy.props.IntProperty(

View File

@ -15,7 +15,7 @@ def get_future_names_arm(bones):
farm = strip_mch(strip_org(bones[1].name))
hand = strip_mch(strip_org(bones[2].name))
suffix=''
suffix = ''
if uarm[-2:] == '.L' or uarm[-2:] == '.R':
suffix = uarm[-2:]
uarm = uarm.rstrip(suffix)
@ -33,7 +33,7 @@ def get_future_names_arm(bones):
# pole = 'upper_arm_ik_target.L'
names['controls'] = [uarm + '_ik', uarm + '_fk', farm + '_fk', hand + '_fk', hand + '_ik',
make_mechanism_name(hand + '_fk'), uarm + '_parent']
make_mechanism_name(hand + '_fk'), uarm + '_parent']
names['ik_ctrl'] = [hand + '_ik', make_mechanism_name(uarm) + '_ik', make_mechanism_name(uarm) + '_ik_target']
names['fk_ctrl'] = uarm + '_fk' + suffix
names['parent'] = uarm + '_parent' + suffix
@ -80,7 +80,7 @@ def get_future_names_leg(bones):
# pole = 'thigh_ik_target.R'
names['controls'] = [thigh + '_ik', thigh + '_fk', shin + '_fk', foot + '_fk', toe, foot + '_heel_ik',
foot + '_ik', make_mechanism_name(foot + '_fk'), thigh + '_parent']
foot + '_ik', make_mechanism_name(foot + '_fk'), thigh + '_parent']
names['ik_ctrl'] = [foot + '_ik', make_mechanism_name(thigh) + '_ik', make_mechanism_name(thigh) + '_ik_target']
names['fk_ctrl'] = thigh + '_fk' + suffix
names['parent'] = thigh + '_parent' + suffix
@ -128,7 +128,7 @@ def get_future_names_paw(bones):
# pole = 'thigh_ik_target.R'
names['controls'] = [thigh + '_ik', thigh + '_fk', shin + '_fk', foot + '_fk', toe, foot + '_heel_ik',
foot + '_ik', make_mechanism_name(foot + '_fk'), thigh + '_parent']
foot + '_ik', make_mechanism_name(foot + '_fk'), thigh + '_parent']
names['ik_ctrl'] = [foot + '_ik', make_mechanism_name(thigh) + '_ik', make_mechanism_name(thigh) + '_ik_target']
names['fk_ctrl'] = thigh + '_fk' + suffix
names['parent'] = thigh + '_parent' + suffix
@ -157,17 +157,17 @@ def get_future_names(bones):
def get_limb_generated_names(rig):
pbones = rig.pose.bones
pose_bones = rig.pose.bones
names = dict()
for b in pbones:
for b in pose_bones:
super_limb_orgs = []
if re.match('^ORG', b.name) and b.rigify_type == 'limbs.super_limb':
super_limb_orgs.append(b)
children = connected_children_names(rig, b.name)
for child in children:
if re.match('^ORG', child) or re.match('^MCH', child):
super_limb_orgs.append(pbones[child])
super_limb_orgs.append(pose_bones[child])
names[b.name] = get_future_names(super_limb_orgs)
return names

View File

@ -9,8 +9,33 @@ MODULE_NAME = "super_widgets" # Windows/Mac blender is weird, so __package__ do
def create_eye_widget(rig, bone_name, size=1.0, bone_transform_name=None):
obj = create_widget(rig, bone_name, bone_transform_name)
if obj is not None:
verts = [(1.1920928955078125e-07*size, 0.5000000596046448*size, 0.0*size), (-0.12940943241119385*size, 0.482962965965271*size, 0.0*size), (-0.24999988079071045*size, 0.4330127537250519*size, 0.0*size), (-0.35355329513549805*size, 0.35355344414711*size, 0.0*size), (-0.43301260471343994*size, 0.2500000596046448*size, 0.0*size), (-0.4829627275466919*size, 0.12940959632396698*size, 0.0*size), (-0.49999988079071045*size, 1.0094120739267964e-07*size, 0.0*size), (-0.482962965965271*size, -0.12940940260887146*size, 0.0*size), (-0.43301260471343994*size, -0.24999986588954926*size, 0.0*size), (-0.3535534143447876*size, -0.35355323553085327*size, 0.0*size), (-0.25*size, -0.43301257491111755*size, 0.0*size), (-0.1294095516204834*size, -0.48296281695365906*size, 0.0*size), (-1.1920928955078125e-07*size, -0.4999999403953552*size, 0.0*size), (0.12940943241119385*size, -0.4829629063606262*size, 0.0*size), (0.24999988079071045*size, -0.4330127537250519*size, 0.0*size), (0.35355329513549805*size, -0.35355353355407715*size, 0.0*size), (0.4330127239227295*size, -0.25000008940696716*size, 0.0*size), (0.482962965965271*size, -0.12940965592861176*size, 0.0*size), (0.5000001192092896*size, -1.6926388468618825e-07*size, 0.0*size), (0.48296308517456055*size, 0.1294093281030655*size, 0.0*size), (0.4330129623413086*size, 0.24999980628490448*size, 0.0*size), (0.35355377197265625*size, 0.35355323553085327*size, 0.0*size), (0.25000035762786865*size, 0.43301260471343994*size, 0.0*size), (0.1294100284576416*size, 0.48296287655830383*size, 0.0*size), ]
edges = [(1, 0), (2, 1), (3, 2), (4, 3), (5, 4), (6, 5), (7, 6), (8, 7), (9, 8), (10, 9), (11, 10), (12, 11), (13, 12), (14, 13), (15, 14), (16, 15), (17, 16), (18, 17), (19, 18), (20, 19), (21, 20), (22, 21), (23, 22), (0, 23), ]
verts = [(1.1920928955078125e-07*size, 0.5000000596046448*size, 0.0*size),
(-0.12940943241119385*size, 0.482962965965271*size, 0.0*size),
(-0.24999988079071045*size, 0.4330127537250519*size, 0.0*size),
(-0.35355329513549805*size, 0.35355344414711*size, 0.0*size),
(-0.43301260471343994*size, 0.2500000596046448*size, 0.0*size),
(-0.4829627275466919*size, 0.12940959632396698*size, 0.0*size),
(-0.49999988079071045*size, 1.0094120739267964e-07*size, 0.0*size),
(-0.482962965965271*size, -0.12940940260887146*size, 0.0*size),
(-0.43301260471343994*size, -0.24999986588954926*size, 0.0*size),
(-0.3535534143447876*size, -0.35355323553085327*size, 0.0*size),
(-0.25*size, -0.43301257491111755*size, 0.0*size),
(-0.1294095516204834*size, -0.48296281695365906*size, 0.0*size),
(-1.1920928955078125e-07*size, -0.4999999403953552*size, 0.0*size),
(0.12940943241119385*size, -0.4829629063606262*size, 0.0*size),
(0.24999988079071045*size, -0.4330127537250519*size, 0.0*size),
(0.35355329513549805*size, -0.35355353355407715*size, 0.0*size),
(0.4330127239227295*size, -0.25000008940696716*size, 0.0*size),
(0.482962965965271*size, -0.12940965592861176*size, 0.0*size),
(0.5000001192092896*size, -1.6926388468618825e-07*size, 0.0*size),
(0.48296308517456055*size, 0.1294093281030655*size, 0.0*size),
(0.4330129623413086*size, 0.24999980628490448*size, 0.0*size),
(0.35355377197265625*size, 0.35355323553085327*size, 0.0*size),
(0.25000035762786865*size, 0.43301260471343994*size, 0.0*size),
(0.1294100284576416*size, 0.48296287655830383*size, 0.0*size), ]
edges = [(1, 0), (2, 1), (3, 2), (4, 3), (5, 4), (6, 5), (7, 6), (8, 7), (9, 8), (10, 9),
(11, 10), (12, 11), (13, 12), (14, 13), (15, 14), (16, 15), (17, 16), (18, 17),
(19, 18), (20, 19), (21, 20), (22, 21), (23, 22), (0, 23), ]
faces = []
mesh = obj.data
@ -24,8 +49,92 @@ def create_eye_widget(rig, bone_name, size=1.0, bone_transform_name=None):
def create_eyes_widget(rig, bone_name, size=1.0, bone_transform_name=None):
obj = create_widget(rig, bone_name, bone_transform_name)
if obj is not None:
verts = [(0.8928930759429932*size, -0.7071065902709961*size, 0.0*size), (0.8928932547569275*size, 0.7071067690849304*size, 0.0*size), (-1.8588197231292725*size, -0.9659252762794495*size, 0.0*size), (-2.100001096725464*size, -0.8660248517990112*size, 0.0*size), (-2.3071072101593018*size, -0.7071059942245483*size, 0.0*size), (-2.4660258293151855*size, -0.49999913573265076*size, 0.0*size), (-2.5659260749816895*size, -0.258818119764328*size, 0.0*size), (-2.5999999046325684*size, 8.575012770961621e-07*size, 0.0*size), (-2.5659255981445312*size, 0.2588198482990265*size, 0.0*size), (-2.4660253524780273*size, 0.5000006556510925*size, 0.0*size), (-2.3071064949035645*size, 0.7071075439453125*size, 0.0*size), (-2.099999189376831*size, 0.866025984287262*size, 0.0*size), (-1.8588184118270874*size, 0.9659261703491211*size, 0.0*size), (-1.5999996662139893*size, 1.000000238418579*size, 0.0*size), (-1.341180443763733*size, 0.9659258723258972*size, 0.0*size), (-1.0999995470046997*size, 0.8660253882408142*size, 0.0*size), (-0.8928929567337036*size, 0.7071067094802856*size, 0.0*size), (-0.892893373966217*size, -0.7071066498756409*size, 0.0*size), (-1.100000262260437*size, -0.8660252690315247*size, 0.0*size), (-1.3411810398101807*size, -0.9659255743026733*size, 0.0*size), (1.600000023841858*size, 1.0*size, 0.0*size), (1.3411810398101807*size, 0.9659258127212524*size, 0.0*size), (1.100000023841858*size, 0.8660253882408142*size, 0.0*size), (-1.600000262260437*size, -0.9999997615814209*size, 0.0*size), (1.0999997854232788*size, -0.8660252690315247*size, 0.0*size), (1.341180682182312*size, -0.9659257531166077*size, 0.0*size), (1.5999996662139893*size, -1.0*size, 0.0*size), (1.8588186502456665*size, -0.965925931930542*size, 0.0*size), (2.0999996662139893*size, -0.8660256266593933*size, 0.0*size), (2.3071064949035645*size, -0.7071071863174438*size, 0.0*size), (2.4660253524780273*size, -0.5000002980232239*size, 0.0*size), (2.5659255981445312*size, -0.25881943106651306*size, 0.0*size), (2.5999999046325684*size, -4.649122899991198e-07*size, 0.0*size), (2.5659260749816895*size, 0.25881853699684143*size, 0.0*size), (2.4660258293151855*size, 0.4999994933605194*size, 0.0*size), (2.3071072101593018*size, 0.707106351852417*size, 0.0*size), (2.1000006198883057*size, 0.8660250902175903*size, 0.0*size), (1.8588197231292725*size, 0.9659256339073181*size, 0.0*size), (-1.8070557117462158*size, -0.7727401852607727*size, 0.0*size), (-2.0000009536743164*size, -0.6928198337554932*size, 0.0*size), (-2.1656856536865234*size, -0.5656847357749939*size, 0.0*size), (-2.292820692062378*size, -0.3999992609024048*size, 0.0*size), (-2.3727407455444336*size, -0.20705445110797882*size, 0.0*size), (-2.3999998569488525*size, 7.336847716032935e-07*size, 0.0*size), (-2.3727405071258545*size, 0.207055926322937*size, 0.0*size), (-2.2928202152252197*size, 0.40000057220458984*size, 0.0*size), (-2.1656851768493652*size, 0.5656861066818237*size, 0.0*size), (-1.9999992847442627*size, 0.6928208470344543*size, 0.0*size), (-1.8070547580718994*size, 0.7727410197257996*size, 0.0*size), (-1.5999996662139893*size, 0.8000002503395081*size, 0.0*size), (-1.3929443359375*size, 0.7727407813072205*size, 0.0*size), (-1.1999995708465576*size, 0.6928203701972961*size, 0.0*size), (-1.0343143939971924*size, 0.5656854510307312*size, 0.0*size), (-1.0343146324157715*size, -0.5656852722167969*size, 0.0*size), (-1.2000001668930054*size, -0.6928201913833618*size, 0.0*size), (-1.3929448127746582*size, -0.7727404236793518*size, 0.0*size), (-1.6000001430511475*size, -0.7999997735023499*size, 0.0*size), (1.8070557117462158*size, 0.772739827632904*size, 0.0*size), (2.0000009536743164*size, 0.6928195953369141*size, 0.0*size), (2.1656856536865234*size, 0.5656843781471252*size, 0.0*size), (2.292820692062378*size, 0.39999890327453613*size, 0.0*size), (2.3727407455444336*size, 0.20705409348011017*size, 0.0*size), (2.3999998569488525*size, -1.0960745839838637e-06*size, 0.0*size), (2.3727405071258545*size, -0.20705628395080566*size, 0.0*size), (2.2928202152252197*size, -0.4000009298324585*size, 0.0*size), (2.1656851768493652*size, -0.5656863451004028*size, 0.0*size), (1.9999992847442627*size, -0.692821204662323*size, 0.0*size), (1.8070547580718994*size, -0.7727413773536682*size, 0.0*size), (1.5999996662139893*size, -0.8000004887580872*size, 0.0*size), (1.3929443359375*size, -0.7727410197257996*size, 0.0*size), (1.1999995708465576*size, -0.6928204894065857*size, 0.0*size), (1.0343143939971924*size, -0.5656855702400208*size, 0.0*size), (1.0343146324157715*size, 0.5656850337982178*size, 0.0*size), (1.2000004053115845*size, 0.6928199529647827*size, 0.0*size), (1.3929448127746582*size, 0.7727401852607727*size, 0.0*size), (1.6000001430511475*size, 0.7999995350837708*size, 0.0*size), ]
edges = [(24, 0), (1, 22), (16, 1), (17, 0), (23, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9), (9, 10), (10, 11), (11, 12), (12, 13), (21, 20), (22, 21), (13, 14), (14, 15), (15, 16), (17, 18), (18, 19), (19, 23), (25, 24), (26, 25), (27, 26), (28, 27), (29, 28), (30, 29), (31, 30), (32, 31), (33, 32), (34, 33), (35, 34), (36, 35), (37, 36), (20, 37), (56, 38), (38, 39), (39, 40), (40, 41), (41, 42), (42, 43), (43, 44), (44, 45), (45, 46), (46, 47), (47, 48), (48, 49), (49, 50), (50, 51), (51, 52), (53, 54), (54, 55), (55, 56), (75, 57), (57, 58), (58, 59), (59, 60), (60, 61), (61, 62), (62, 63), (63, 64), (64, 65), (65, 66), (66, 67), (67, 68), (68, 69), (69, 70), (70, 71), (72, 73), (73, 74), (74, 75), (52, 72), (53, 71), ]
verts = [(0.8928930759429932*size, -0.7071065902709961*size, 0.0*size),
(0.8928932547569275*size, 0.7071067690849304*size, 0.0*size),
(-1.8588197231292725*size, -0.9659252762794495*size, 0.0*size),
(-2.100001096725464*size, -0.8660248517990112*size, 0.0*size),
(-2.3071072101593018*size, -0.7071059942245483*size, 0.0*size),
(-2.4660258293151855*size, -0.49999913573265076*size, 0.0*size),
(-2.5659260749816895*size, -0.258818119764328*size, 0.0*size),
(-2.5999999046325684*size, 8.575012770961621e-07*size, 0.0*size),
(-2.5659255981445312*size, 0.2588198482990265*size, 0.0*size),
(-2.4660253524780273*size, 0.5000006556510925*size, 0.0*size),
(-2.3071064949035645*size, 0.7071075439453125*size, 0.0*size),
(-2.099999189376831*size, 0.866025984287262*size, 0.0*size),
(-1.8588184118270874*size, 0.9659261703491211*size, 0.0*size),
(-1.5999996662139893*size, 1.000000238418579*size, 0.0*size),
(-1.341180443763733*size, 0.9659258723258972*size, 0.0*size),
(-1.0999995470046997*size, 0.8660253882408142*size, 0.0*size),
(-0.8928929567337036*size, 0.7071067094802856*size, 0.0*size),
(-0.892893373966217*size, -0.7071066498756409*size, 0.0*size),
(-1.100000262260437*size, -0.8660252690315247*size, 0.0*size),
(-1.3411810398101807*size, -0.9659255743026733*size, 0.0*size),
(1.600000023841858*size, 1.0*size, 0.0*size),
(1.3411810398101807*size, 0.9659258127212524*size, 0.0*size),
(1.100000023841858*size, 0.8660253882408142*size, 0.0*size),
(-1.600000262260437*size, -0.9999997615814209*size, 0.0*size),
(1.0999997854232788*size, -0.8660252690315247*size, 0.0*size),
(1.341180682182312*size, -0.9659257531166077*size, 0.0*size),
(1.5999996662139893*size, -1.0*size, 0.0*size),
(1.8588186502456665*size, -0.965925931930542*size, 0.0*size),
(2.0999996662139893*size, -0.8660256266593933*size, 0.0*size),
(2.3071064949035645*size, -0.7071071863174438*size, 0.0*size),
(2.4660253524780273*size, -0.5000002980232239*size, 0.0*size),
(2.5659255981445312*size, -0.25881943106651306*size, 0.0*size),
(2.5999999046325684*size, -4.649122899991198e-07*size, 0.0*size),
(2.5659260749816895*size, 0.25881853699684143*size, 0.0*size),
(2.4660258293151855*size, 0.4999994933605194*size, 0.0*size),
(2.3071072101593018*size, 0.707106351852417*size, 0.0*size),
(2.1000006198883057*size, 0.8660250902175903*size, 0.0*size),
(1.8588197231292725*size, 0.9659256339073181*size, 0.0*size),
(-1.8070557117462158*size, -0.7727401852607727*size, 0.0*size),
(-2.0000009536743164*size, -0.6928198337554932*size, 0.0*size),
(-2.1656856536865234*size, -0.5656847357749939*size, 0.0*size),
(-2.292820692062378*size, -0.3999992609024048*size, 0.0*size),
(-2.3727407455444336*size, -0.20705445110797882*size, 0.0*size),
(-2.3999998569488525*size, 7.336847716032935e-07*size, 0.0*size),
(-2.3727405071258545*size, 0.207055926322937*size, 0.0*size),
(-2.2928202152252197*size, 0.40000057220458984*size, 0.0*size),
(-2.1656851768493652*size, 0.5656861066818237*size, 0.0*size),
(-1.9999992847442627*size, 0.6928208470344543*size, 0.0*size),
(-1.8070547580718994*size, 0.7727410197257996*size, 0.0*size),
(-1.5999996662139893*size, 0.8000002503395081*size, 0.0*size),
(-1.3929443359375*size, 0.7727407813072205*size, 0.0*size),
(-1.1999995708465576*size, 0.6928203701972961*size, 0.0*size),
(-1.0343143939971924*size, 0.5656854510307312*size, 0.0*size),
(-1.0343146324157715*size, -0.5656852722167969*size, 0.0*size),
(-1.2000001668930054*size, -0.6928201913833618*size, 0.0*size),
(-1.3929448127746582*size, -0.7727404236793518*size, 0.0*size),
(-1.6000001430511475*size, -0.7999997735023499*size, 0.0*size),
(1.8070557117462158*size, 0.772739827632904*size, 0.0*size),
(2.0000009536743164*size, 0.6928195953369141*size, 0.0*size),
(2.1656856536865234*size, 0.5656843781471252*size, 0.0*size),
(2.292820692062378*size, 0.39999890327453613*size, 0.0*size),
(2.3727407455444336*size, 0.20705409348011017*size, 0.0*size),
(2.3999998569488525*size, -1.0960745839838637e-06*size, 0.0*size),
(2.3727405071258545*size, -0.20705628395080566*size, 0.0*size),
(2.2928202152252197*size, -0.4000009298324585*size, 0.0*size),
(2.1656851768493652*size, -0.5656863451004028*size, 0.0*size),
(1.9999992847442627*size, -0.692821204662323*size, 0.0*size),
(1.8070547580718994*size, -0.7727413773536682*size, 0.0*size),
(1.5999996662139893*size, -0.8000004887580872*size, 0.0*size),
(1.3929443359375*size, -0.7727410197257996*size, 0.0*size),
(1.1999995708465576*size, -0.6928204894065857*size, 0.0*size),
(1.0343143939971924*size, -0.5656855702400208*size, 0.0*size),
(1.0343146324157715*size, 0.5656850337982178*size, 0.0*size),
(1.2000004053115845*size, 0.6928199529647827*size, 0.0*size),
(1.3929448127746582*size, 0.7727401852607727*size, 0.0*size),
(1.6000001430511475*size, 0.7999995350837708*size, 0.0*size), ]
edges = [(24, 0), (1, 22), (16, 1), (17, 0), (23, 2), (2, 3), (3, 4), (4, 5), (5, 6),
(6, 7), (7, 8), (8, 9), (9, 10), (10, 11), (11, 12), (12, 13), (21, 20), (22, 21),
(13, 14), (14, 15), (15, 16), (17, 18), (18, 19), (19, 23), (25, 24), (26, 25),
(27, 26), (28, 27), (29, 28), (30, 29), (31, 30), (32, 31), (33, 32), (34, 33),
(35, 34), (36, 35), (37, 36), (20, 37), (56, 38), (38, 39), (39, 40), (40, 41),
(41, 42), (42, 43), (43, 44), (44, 45), (45, 46), (46, 47), (47, 48), (48, 49),
(49, 50), (50, 51), (51, 52), (53, 54), (54, 55), (55, 56), (75, 57), (57, 58),
(58, 59), (59, 60), (60, 61), (61, 62), (62, 63), (63, 64), (64, 65), (65, 66),
(66, 67), (67, 68), (68, 69), (69, 70), (70, 71), (72, 73), (73, 74), (74, 75),
(52, 72), (53, 71), ]
faces = []
mesh = obj.data
@ -39,8 +148,33 @@ def create_eyes_widget(rig, bone_name, size=1.0, bone_transform_name=None):
def create_ear_widget(rig, bone_name, size=1.0, bone_transform_name=None):
obj = create_widget(rig, bone_name, bone_transform_name)
if obj is not None:
verts = [(-2.4903741291382175e-09*size, 1.0*size, -3.123863123732917e-08*size), (-7.450580596923828e-09*size, 0.9829629063606262*size, 0.0776456817984581*size), (-1.4901161193847656e-08*size, 0.9330127239227295*size, 0.1499999761581421*size), (-2.9802322387695312e-08*size, 0.8535534143447876*size, 0.2121320217847824*size), (-2.9802322387695312e-08*size, 0.75*size, 0.25980761647224426*size), (-2.9802322387695312e-08*size, 0.6294095516204834*size, 0.2897777259349823*size), (-2.9802322387695312e-08*size, 0.5000000596046448*size, 0.29999998211860657*size), (-5.960464477539063e-08*size, 0.37059056758880615*size, 0.2897777855396271*size), (-5.960464477539063e-08*size, 0.25000008940696716*size, 0.25980767607688904*size), (-4.470348358154297e-08*size, 0.14644670486450195*size, 0.21213211119174957*size), (-4.470348358154297e-08*size, 0.06698736548423767*size, 0.15000009536743164*size), (-4.470348358154297e-08*size, 0.017037123441696167*size, 0.07764581590890884*size), (-3.6718930118695425e-08*size, 0.0*size, 1.1981423142515268e-07*size), (-2.9802322387695312e-08*size, 0.017037034034729004*size, -0.07764559239149094*size), (-2.9802322387695312e-08*size, 0.06698718667030334*size, -0.14999987185001373*size), (-1.4901161193847656e-08*size, 0.14644640684127808*size, -0.21213191747665405*size), (0.0*size, 0.24999985098838806*size, -0.25980761647224426*size), (0.0*size, 0.3705902695655823*size, -0.2897777259349823*size), (0.0*size, 0.4999997615814209*size, -0.30000004172325134*size), (0.0*size, 0.6294092535972595*size, -0.2897777855396271*size), (0.0*size, 0.7499997615814209*size, -0.2598077356815338*size), (1.4901161193847656e-08*size, 0.8535531759262085*size, -0.21213220059871674*size), (0.0*size, 0.9330125451087952*size, -0.15000019967556*size), (0.0*size, 0.9829628467559814*size, -0.07764596492052078*size), ]
edges = [(1, 0), (2, 1), (3, 2), (4, 3), (5, 4), (6, 5), (7, 6), (8, 7), (9, 8), (10, 9), (11, 10), (12, 11), (13, 12), (14, 13), (15, 14), (16, 15), (17, 16), (18, 17), (19, 18), (20, 19), (21, 20), (22, 21), (23, 22), (0, 23), ]
verts = [(-2.4903741291382175e-09*size, 1.0*size, -3.123863123732917e-08*size),
(-7.450580596923828e-09*size, 0.9829629063606262*size, 0.0776456817984581*size),
(-1.4901161193847656e-08*size, 0.9330127239227295*size, 0.1499999761581421*size),
(-2.9802322387695312e-08*size, 0.8535534143447876*size, 0.2121320217847824*size),
(-2.9802322387695312e-08*size, 0.75*size, 0.25980761647224426*size),
(-2.9802322387695312e-08*size, 0.6294095516204834*size, 0.2897777259349823*size),
(-2.9802322387695312e-08*size, 0.5000000596046448*size, 0.29999998211860657*size),
(-5.960464477539063e-08*size, 0.37059056758880615*size, 0.2897777855396271*size),
(-5.960464477539063e-08*size, 0.25000008940696716*size, 0.25980767607688904*size),
(-4.470348358154297e-08*size, 0.14644670486450195*size, 0.21213211119174957*size),
(-4.470348358154297e-08*size, 0.06698736548423767*size, 0.15000009536743164*size),
(-4.470348358154297e-08*size, 0.017037123441696167*size, 0.07764581590890884*size),
(-3.6718930118695425e-08*size, 0.0*size, 1.1981423142515268e-07*size),
(-2.9802322387695312e-08*size, 0.017037034034729004*size, -0.07764559239149094*size),
(-2.9802322387695312e-08*size, 0.06698718667030334*size, -0.14999987185001373*size),
(-1.4901161193847656e-08*size, 0.14644640684127808*size, -0.21213191747665405*size),
(0.0*size, 0.24999985098838806*size, -0.25980761647224426*size),
(0.0*size, 0.3705902695655823*size, -0.2897777259349823*size),
(0.0*size, 0.4999997615814209*size, -0.30000004172325134*size),
(0.0*size, 0.6294092535972595*size, -0.2897777855396271*size),
(0.0*size, 0.7499997615814209*size, -0.2598077356815338*size),
(1.4901161193847656e-08*size, 0.8535531759262085*size, -0.21213220059871674*size),
(0.0*size, 0.9330125451087952*size, -0.15000019967556*size),
(0.0*size, 0.9829628467559814*size, -0.07764596492052078*size), ]
edges = [(1, 0), (2, 1), (3, 2), (4, 3), (5, 4), (6, 5), (7, 6), (8, 7), (9, 8), (10, 9),
(11, 10), (12, 11), (13, 12), (14, 13), (15, 14), (16, 15), (17, 16), (18, 17),
(19, 18), (20, 19), (21, 20), (22, 21), (23, 22), (0, 23), ]
faces = []
mesh = obj.data
@ -53,21 +187,78 @@ def create_ear_widget(rig, bone_name, size=1.0, bone_transform_name=None):
@widget_generator(register="jaw")
def create_jaw_widget(geom, size=1.0):
geom.verts = [(0.606898307800293*size, 0.6533132195472717*size, 0.09324522316455841*size), (0.5728408694267273*size, 0.7130533456802368*size, 0.04735109210014343*size), (0.478340744972229*size, 0.856249213218689*size, 0.0167550016194582*size), (0.3405401408672333*size, 1.0092359781265259*size, 0.003642391413450241*size), (0.1764744222164154*size, 1.1159402132034302*size, 0.0003642391529865563*size), (0.5728408694267273*size, 0.7130533456802368*size, 0.1391393542289734*size), (0.478340744972229*size, 0.856249213218689*size, 0.16973544657230377*size), (0.3405401408672333*size, 1.0092359781265259*size, 0.18284805119037628*size), (0.1764744222164154*size, 1.1159402132034302*size, 0.1861262023448944*size), (0.0*size, 1.153113603591919*size, 0.0*size), (-0.606898307800293*size, 0.6533132195472717*size, 0.09324522316455841*size), (-0.5728408694267273*size, 0.7130533456802368*size, 0.04735109210014343*size), (-0.478340744972229*size, 0.856249213218689*size, 0.0167550016194582*size), (-0.3405401408672333*size, 1.0092359781265259*size, 0.003642391413450241*size), (-0.1764744222164154*size, 1.1159402132034302*size, 0.0003642391529865563*size), (0.0*size, 1.153113603591919*size, 0.18649044632911682*size), (-0.5728408694267273*size, 0.7130533456802368*size, 0.1391393542289734*size), (-0.478340744972229*size, 0.856249213218689*size, 0.16973544657230377*size), (-0.3405401408672333*size, 1.0092359781265259*size, 0.18284805119037628*size), (-0.1764744222164154*size, 1.1159402132034302*size, 0.1861262023448944*size)]
geom.edges = [(1, 0), (2, 1), (3, 2), (4, 3), (9, 4), (6, 5), (7, 6), (8, 7), (15, 8), (5, 0), (11, 10), (12, 11), (13, 12), (14, 13), (9, 14), (17, 16), (18, 17), (19, 18), (15, 19), (16, 10)]
geom.verts = [(0.606898307800293*size, 0.6533132195472717*size, 0.09324522316455841*size),
(0.5728408694267273*size, 0.7130533456802368*size, 0.04735109210014343*size),
(0.478340744972229*size, 0.856249213218689*size, 0.0167550016194582*size),
(0.3405401408672333*size, 1.0092359781265259*size, 0.003642391413450241*size),
(0.1764744222164154*size, 1.1159402132034302*size, 0.0003642391529865563*size),
(0.5728408694267273*size, 0.7130533456802368*size, 0.1391393542289734*size),
(0.478340744972229*size, 0.856249213218689*size, 0.16973544657230377*size),
(0.3405401408672333*size, 1.0092359781265259*size, 0.18284805119037628*size),
(0.1764744222164154*size, 1.1159402132034302*size, 0.1861262023448944*size),
(0.0*size, 1.153113603591919*size, 0.0*size),
(-0.606898307800293*size, 0.6533132195472717*size, 0.09324522316455841*size),
(-0.5728408694267273*size, 0.7130533456802368*size, 0.04735109210014343*size),
(-0.478340744972229*size, 0.856249213218689*size, 0.0167550016194582*size),
(-0.3405401408672333*size, 1.0092359781265259*size, 0.003642391413450241*size),
(-0.1764744222164154*size, 1.1159402132034302*size, 0.0003642391529865563*size),
(0.0*size, 1.153113603591919*size, 0.18649044632911682*size),
(-0.5728408694267273*size, 0.7130533456802368*size, 0.1391393542289734*size),
(-0.478340744972229*size, 0.856249213218689*size, 0.16973544657230377*size),
(-0.3405401408672333*size, 1.0092359781265259*size, 0.18284805119037628*size),
(-0.1764744222164154*size, 1.1159402132034302*size, 0.1861262023448944*size)]
geom.edges = [(1, 0), (2, 1), (3, 2), (4, 3), (9, 4), (6, 5), (7, 6), (8, 7), (15, 8), (5, 0),
(11, 10), (12, 11), (13, 12), (14, 13), (9, 14), (17, 16), (18, 17), (19, 18),
(15, 19), (16, 10)]
@widget_generator(register="teeth")
def create_teeth_widget(geom, *, size=1.0):
geom.verts = [(0.6314387321472168*size, 0.4999997019767761*size, 0.09999999403953552*size), (0.5394065976142883*size, 0.29289281368255615*size, 0.09999999403953552*size), (0.3887903690338135*size, 0.1339743733406067*size, 0.09999999403953552*size), (0.19801488518714905*size, 0.03407406806945801*size, 0.09999999403953552*size), (-3.4034394502668874e-07*size, 0.0*size, 0.09999999403953552*size), (-0.19801555573940277*size, 0.034074246883392334*size, 0.09999999403953552*size), (-0.7000000476837158*size, 1.0000001192092896*size, -0.10000000894069672*size), (-0.6778771877288818*size, 0.7411810755729675*size, -0.10000000894069672*size), (-0.6314389705657959*size, 0.5000001192092896*size, -0.10000000894069672*size), (-0.5394070148468018*size, 0.2928934097290039*size, -0.10000000894069672*size), (-0.38879096508026123*size, 0.13397473096847534*size, -0.10000000894069672*size), (-0.19801555573940277*size, 0.034074246883392334*size, -0.10000000894069672*size), (-3.4034394502668874e-07*size, 0.0*size, -0.10000000894069672*size), (0.19801488518714905*size, 0.03407406806945801*size, -0.10000000894069672*size), (0.3887903690338135*size, 0.1339743733406067*size, -0.10000000894069672*size), (0.5394065976142883*size, 0.29289281368255615*size, -0.10000000894069672*size), (0.6314387321472168*size, 0.4999997019767761*size, -0.10000000894069672*size), (0.6778769493103027*size, 0.7411805391311646*size, -0.10000000894069672*size), (0.6999999284744263*size, 0.9999995231628418*size, -0.10000000894069672*size), (-0.38879096508026123*size, 0.13397473096847534*size, 0.09999999403953552*size), (-0.5394070148468018*size, 0.2928934097290039*size, 0.09999999403953552*size), (-0.6314389705657959*size, 0.5000001192092896*size, 0.09999999403953552*size), (-0.6778771877288818*size, 0.7411810755729675*size, 0.09999999403953552*size), (-0.7000000476837158*size, 1.0000001192092896*size, 0.09999999403953552*size), (0.6778769493103027*size, 0.7411805391311646*size, 0.09999999403953552*size), (0.6999999284744263*size, 0.9999995231628418*size, 0.09999999403953552*size)]
geom.edges = [(25, 24), (24, 0), (0, 1), (1, 2), (2, 3), (3, 4), (7, 6), (8, 7), (9, 8), (10, 9), (11, 10), (12, 11), (13, 12), (14, 13), (15, 14), (16, 15), (17, 16), (18, 17), (4, 5), (5, 19), (19, 20), (20, 21), (21, 22), (22, 23), (18, 25), (6, 23)]
geom.verts = [(0.6314387321472168*size, 0.4999997019767761*size, 0.09999999403953552*size),
(0.5394065976142883*size, 0.29289281368255615*size, 0.09999999403953552*size),
(0.3887903690338135*size, 0.1339743733406067*size, 0.09999999403953552*size),
(0.19801488518714905*size, 0.03407406806945801*size, 0.09999999403953552*size),
(-3.4034394502668874e-07*size, 0.0*size, 0.09999999403953552*size),
(-0.19801555573940277*size, 0.034074246883392334*size, 0.09999999403953552*size),
(-0.7000000476837158*size, 1.0000001192092896*size, -0.10000000894069672*size),
(-0.6778771877288818*size, 0.7411810755729675*size, -0.10000000894069672*size),
(-0.6314389705657959*size, 0.5000001192092896*size, -0.10000000894069672*size),
(-0.5394070148468018*size, 0.2928934097290039*size, -0.10000000894069672*size),
(-0.38879096508026123*size, 0.13397473096847534*size, -0.10000000894069672*size),
(-0.19801555573940277*size, 0.034074246883392334*size, -0.10000000894069672*size),
(-3.4034394502668874e-07*size, 0.0*size, -0.10000000894069672*size),
(0.19801488518714905*size, 0.03407406806945801*size, -0.10000000894069672*size),
(0.3887903690338135*size, 0.1339743733406067*size, -0.10000000894069672*size),
(0.5394065976142883*size, 0.29289281368255615*size, -0.10000000894069672*size),
(0.6314387321472168*size, 0.4999997019767761*size, -0.10000000894069672*size),
(0.6778769493103027*size, 0.7411805391311646*size, -0.10000000894069672*size),
(0.6999999284744263*size, 0.9999995231628418*size, -0.10000000894069672*size),
(-0.38879096508026123*size, 0.13397473096847534*size, 0.09999999403953552*size),
(-0.5394070148468018*size, 0.2928934097290039*size, 0.09999999403953552*size),
(-0.6314389705657959*size, 0.5000001192092896*size, 0.09999999403953552*size),
(-0.6778771877288818*size, 0.7411810755729675*size, 0.09999999403953552*size),
(-0.7000000476837158*size, 1.0000001192092896*size, 0.09999999403953552*size),
(0.6778769493103027*size, 0.7411805391311646*size, 0.09999999403953552*size),
(0.6999999284744263*size, 0.9999995231628418*size, 0.09999999403953552*size)]
geom.edges = [(25, 24), (24, 0), (0, 1), (1, 2), (2, 3), (3, 4), (7, 6), (8, 7), (9, 8),
(10, 9), (11, 10), (12, 11), (13, 12), (14, 13), (15, 14), (16, 15), (17, 16),
(18, 17), (4, 5), (5, 19), (19, 20), (20, 21), (21, 22), (22, 23), (18, 25),
(6, 23)]
def create_face_widget(rig, bone_name, size=1.0, bone_transform_name=None):
obj = create_widget(rig, bone_name, bone_transform_name)
if obj is not None:
verts = [(-0.25*size, -0.25*size, 0.07499998807907104*size), (-0.25*size, 0.25*size, 0.07499998807907104*size), (0.25*size, 0.25*size, 0.07499998807907104*size), (0.25*size, -0.25*size, 0.07499998807907104*size), (-0.25*size, -0.25*size, -0.07499998807907104*size), (-0.25*size, 0.25*size, -0.07499998807907104*size), (0.25*size, 0.25*size, -0.07499998807907104*size), (0.25*size, -0.25*size, -0.07499998807907104*size), ]
edges = [(4, 5), (5, 1), (1, 0), (0, 4), (5, 6), (6, 2), (2, 1), (6, 7), (7, 3), (3, 2), (7, 4), (0, 3), ]
verts = [(-0.25*size, -0.25*size, 0.07499998807907104*size),
(-0.25*size, 0.25*size, 0.07499998807907104*size),
(0.25*size, 0.25*size, 0.07499998807907104*size),
(0.25*size, -0.25*size, 0.07499998807907104*size),
(-0.25*size, -0.25*size, -0.07499998807907104*size),
(-0.25*size, 0.25*size, -0.07499998807907104*size),
(0.25*size, 0.25*size, -0.07499998807907104*size),
(0.25*size, -0.25*size, -0.07499998807907104*size), ]
edges = [(4, 5), (5, 1), (1, 0), (0, 4), (5, 6), (6, 2), (2, 1), (6, 7), (7, 3),
(3, 2), (7, 4), (0, 3), ]
faces = []
mesh = obj.data
@ -78,11 +269,26 @@ def create_face_widget(rig, bone_name, size=1.0, bone_transform_name=None):
return None
# noinspection SpellCheckingInspection
def create_ikarrow_widget(rig, bone_name, size=1.0, bone_transform_name=None, roll=0):
obj = create_widget(rig, bone_name, bone_transform_name)
if obj is not None:
verts = [(0.10000000149011612*size, 0.0*size, -0.30000001192092896*size), (0.10000000149011612*size, 0.699999988079071*size, -0.30000001192092896*size), (-0.10000000149011612*size, 0.0*size, -0.30000001192092896*size), (-0.10000000149011612*size, 0.699999988079071*size, -0.30000001192092896*size), (0.20000000298023224*size, 0.699999988079071*size, -0.30000001192092896*size), (0.0*size, 1.0*size, -0.30000001192092896*size), (-0.20000000298023224*size, 0.699999988079071*size, -0.30000001192092896*size), (0.10000000149011612*size, 0.0*size, 0.30000001192092896*size), (0.10000000149011612*size, 0.699999988079071*size, 0.30000001192092896*size), (-0.10000000149011612*size, 0.0*size, 0.30000001192092896*size), (-0.10000000149011612*size, 0.699999988079071*size, 0.30000001192092896*size), (0.20000000298023224*size, 0.699999988079071*size, 0.30000001192092896*size), (0.0*size, 1.0*size, 0.30000001192092896*size), (-0.20000000298023224*size, 0.699999988079071*size, 0.30000001192092896*size), ]
edges = [(0, 1), (2, 3), (1, 4), (4, 5), (3, 6), (5, 6), (0, 2), (7, 8), (9, 10), (8, 11), (11, 12), (10, 13), (12, 13), (7, 9), ]
verts = [(0.10000000149011612*size, 0.0*size, -0.30000001192092896*size),
(0.10000000149011612*size, 0.699999988079071*size, -0.30000001192092896*size),
(-0.10000000149011612*size, 0.0*size, -0.30000001192092896*size),
(-0.10000000149011612*size, 0.699999988079071*size, -0.30000001192092896*size),
(0.20000000298023224*size, 0.699999988079071*size, -0.30000001192092896*size),
(0.0*size, 1.0*size, -0.30000001192092896*size),
(-0.20000000298023224*size, 0.699999988079071*size, -0.30000001192092896*size),
(0.10000000149011612*size, 0.0*size, 0.30000001192092896*size),
(0.10000000149011612*size, 0.699999988079071*size, 0.30000001192092896*size),
(-0.10000000149011612*size, 0.0*size, 0.30000001192092896*size),
(-0.10000000149011612*size, 0.699999988079071*size, 0.30000001192092896*size),
(0.20000000298023224*size, 0.699999988079071*size, 0.30000001192092896*size),
(0.0*size, 1.0*size, 0.30000001192092896*size),
(-0.20000000298023224*size, 0.699999988079071*size, 0.30000001192092896*size), ]
edges = [(0, 1), (2, 3), (1, 4), (4, 5), (3, 6), (5, 6), (0, 2), (7, 8), (9, 10),
(8, 11), (11, 12), (10, 13), (12, 13), (7, 9), ]
faces = []
mesh = obj.data
@ -101,7 +307,14 @@ def create_hand_widget(rig, bone_name, size=1.0, bone_transform_name=None):
# Create hand widget
obj = create_widget(rig, bone_name, bone_transform_name, subsurf=2)
if obj is not None:
verts = [(0.0*size, 1.5*size, -0.7000000476837158*size), (1.1920928955078125e-07*size, -0.25*size, -0.6999999284744263*size), (0.0*size, -0.25*size, 0.7000000476837158*size), (-1.1920928955078125e-07*size, 1.5*size, 0.6999999284744263*size), (5.960464477539063e-08*size, 0.7229999899864197*size, -0.699999988079071*size), (-5.960464477539063e-08*size, 0.7229999899864197*size, 0.699999988079071*size), (1.1920928955078125e-07*size, -2.9802322387695312e-08*size, -0.699999988079071*size), (0.0*size, 2.9802322387695312e-08*size, 0.699999988079071*size), ]
verts = [(0.0*size, 1.5*size, -0.7000000476837158*size),
(1.1920928955078125e-07*size, -0.25*size, -0.6999999284744263*size),
(0.0*size, -0.25*size, 0.7000000476837158*size),
(-1.1920928955078125e-07*size, 1.5*size, 0.6999999284744263*size),
(5.960464477539063e-08*size, 0.7229999899864197*size, -0.699999988079071*size),
(-5.960464477539063e-08*size, 0.7229999899864197*size, 0.699999988079071*size),
(1.1920928955078125e-07*size, -2.9802322387695312e-08*size, -0.699999988079071*size),
(0.0*size, 2.9802322387695312e-08*size, 0.699999988079071*size), ]
edges = [(1, 2), (0, 3), (0, 4), (3, 5), (4, 6), (1, 6), (5, 7), (2, 7)]
faces = []
@ -118,7 +331,14 @@ def create_foot_widget(rig, bone_name, size=1.0, bone_transform_name=None):
# Create hand widget
obj = create_widget(rig, bone_name, bone_transform_name, subsurf=2)
if obj is not None:
verts = [(-0.6999998688697815*size, -0.5242648720741272*size, 0.0*size), (-0.7000001072883606*size, 1.2257349491119385*size, 0.0*size), (0.6999998688697815*size, 1.2257351875305176*size, 0.0*size), (0.7000001072883606*size, -0.5242648720741272*size, 0.0*size), (-0.6999998688697815*size, 0.2527350187301636*size, 0.0*size), (0.7000001072883606*size, 0.2527352571487427*size, 0.0*size), (-0.7000001072883606*size, 0.975735068321228*size, 0.0*size), (0.6999998688697815*size, 0.9757352471351624*size, 0.0*size), ]
verts = [(-0.6999998688697815*size, -0.5242648720741272*size, 0.0*size),
(-0.7000001072883606*size, 1.2257349491119385*size, 0.0*size),
(0.6999998688697815*size, 1.2257351875305176*size, 0.0*size),
(0.7000001072883606*size, -0.5242648720741272*size, 0.0*size),
(-0.6999998688697815*size, 0.2527350187301636*size, 0.0*size),
(0.7000001072883606*size, 0.2527352571487427*size, 0.0*size),
(-0.7000001072883606*size, 0.975735068321228*size, 0.0*size),
(0.6999998688697815*size, 0.9757352471351624*size, 0.0*size), ]
edges = [(1, 2), (0, 3), (0, 4), (3, 5), (4, 6), (1, 6), (5, 7), (2, 7), ]
faces = []
@ -131,11 +351,69 @@ def create_foot_widget(rig, bone_name, size=1.0, bone_transform_name=None):
return None
# noinspection SpellCheckingInspection
def create_ballsocket_widget(rig, bone_name, size=1.0, bone_transform_name=None):
obj = create_widget(rig, bone_name, bone_transform_name)
if obj is not None:
verts = [(-0.050000108778476715*size, 0.779460072517395*size, -0.2224801927804947*size), (0.049999915063381195*size, 0.779460072517395*size, -0.22248023748397827*size), (0.09999985247850418*size, 0.6790841817855835*size, -0.3658318817615509*size), (-2.3089636158601934e-07*size, 0.5930476188659668*size, -0.488704651594162*size), (-0.10000013560056686*size, 0.6790841817855835*size, -0.3658317029476166*size), (0.04999981075525284*size, 0.6790841817855835*size, -0.36583182215690613*size), (-0.050000183284282684*size, 0.6790841817855835*size, -0.3658318519592285*size), (-0.3658319115638733*size, 0.6790841221809387*size, 0.05000019446015358*size), (-0.3658318817615509*size, 0.6790841221809387*size, -0.04999979957938194*size), (-0.36583176255226135*size, 0.6790841221809387*size, 0.10000018030405045*size), (-0.48870471119880676*size, 0.5930476188659668*size, 2.4472291215715813e-07*size), (-0.3658319413661957*size, 0.679084062576294*size, -0.0999998077750206*size), (-0.22248037159442902*size, 0.7794600129127502*size, -0.04999985918402672*size), (-0.22248034179210663*size, 0.7794600129127502*size, 0.05000016465783119*size), (0.3658319115638733*size, 0.6790841221809387*size, -0.05000000819563866*size), (0.3658319115638733*size, 0.6790841221809387*size, 0.05000000074505806*size), (0.36583179235458374*size, 0.6790841221809387*size, -0.09999998658895493*size), (0.4887046813964844*size, 0.5930476188659668*size, -3.8399143420519977e-08*size), (0.3658319413661957*size, 0.679084062576294*size, 0.10000000149011612*size), (0.050000034272670746*size, 0.7794599533081055*size, 0.2224804311990738*size), (-0.04999997466802597*size, 0.7794599533081055*size, 0.2224804311990738*size), (-0.09999992698431015*size, 0.679084062576294*size, 0.36583200097084045*size), (1.267315070663244e-07*size, 0.5930474996566772*size, 0.48870477080345154*size), (0.1000000610947609*size, 0.679084062576294*size, 0.3658318519592285*size), (-0.049999915063381195*size, 0.679084062576294*size, 0.3658319413661957*size), (0.05000007897615433*size, 0.679084062576294*size, 0.36583197116851807*size), (0.22248029708862305*size, 0.7794600129127502*size, 0.05000004544854164*size), (0.22248028218746185*size, 0.7794600129127502*size, -0.04999994859099388*size), (-4.752442350763886e-08*size, 0.8284152746200562*size, -0.1499999612569809*size), (-0.03882290795445442*size, 0.8284152746200562*size, -0.14488883316516876*size), (-0.07500004768371582*size, 0.8284152746200562*size, -0.12990377843379974*size), (-0.10606606304645538*size, 0.8284152746200562*size, -0.10606598109006882*size), (-0.1299038827419281*size, 0.8284152746200562*size, -0.07499996572732925*size), (-0.14488893747329712*size, 0.8284152746200562*size, -0.038822825998067856*size), (-0.15000006556510925*size, 0.8284152746200562*size, 2.4781975582754967e-08*size), (-0.1448889672756195*size, 0.8284152746200562*size, 0.038822878152132034*size), (-0.1299038827419281*size, 0.8284152746200562*size, 0.07500001043081284*size), (-0.10606609284877777*size, 0.8284152746200562*size, 0.1060660257935524*size), (-0.0750000923871994*size, 0.8284152746200562*size, 0.12990383803844452*size), (-0.038822952657938004*size, 0.8284152746200562*size, 0.14488889276981354*size), (-1.0593657862045802e-07*size, 0.8284152746200562*size, 0.15000005066394806*size), (0.03882275149226189*size, 0.8284152746200562*size, 0.14488892257213593*size), (0.07499989867210388*size, 0.8284152746200562*size, 0.1299038976430893*size), (0.10606591403484344*size, 0.8284152746200562*size, 0.10606611520051956*size), (0.12990373373031616*size, 0.8284152746200562*size, 0.0750000849366188*size), (0.14488881826400757*size, 0.8284152746200562*size, 0.038822952657938004*size), (0.1499999463558197*size, 0.8284152746200562*size, 1.0584351883835552e-07*size), (0.14488881826400757*size, 0.8284152746200562*size, -0.03882275149226189*size), (0.12990379333496094*size, 0.8284152746200562*size, -0.07499989122152328*size), (0.10606604814529419*size, 0.8284152746200562*size, -0.10606592148542404*size), (0.07500004768371582*size, 0.8284152746200562*size, -0.12990371882915497*size), (0.03882291540503502*size, 0.8284152746200562*size, -0.14488880336284637*size), ]
edges = [(1, 0), (3, 2), (5, 2), (4, 3), (6, 4), (1, 5), (0, 6), (13, 7), (12, 8), (7, 9), (9, 10), (8, 11), (27, 14), (26, 15), (14, 16), (16, 17), (15, 18), (17, 18), (10, 11), (12, 13), (20, 19), (22, 21), (24, 21), (23, 22), (29, 28), (30, 29), (31, 30), (32, 31), (33, 32), (34, 33), (35, 34), (36, 35), (37, 36), (38, 37), (39, 38), (40, 39), (41, 40), (42, 41), (43, 42), (44, 43), (45, 44), (46, 45), (47, 46), (48, 47), (49, 48), (50, 49), (51, 50), (28, 51), (26, 27), (25, 23), (20, 24), (19, 25), ]
verts = [(-0.050000108778476715*size, 0.779460072517395*size, -0.2224801927804947*size),
(0.049999915063381195*size, 0.779460072517395*size, -0.22248023748397827*size),
(0.09999985247850418*size, 0.6790841817855835*size, -0.3658318817615509*size),
(-2.3089636158601934e-07*size, 0.5930476188659668*size, -0.488704651594162*size),
(-0.10000013560056686*size, 0.6790841817855835*size, -0.3658317029476166*size),
(0.04999981075525284*size, 0.6790841817855835*size, -0.36583182215690613*size),
(-0.050000183284282684*size, 0.6790841817855835*size, -0.3658318519592285*size),
(-0.3658319115638733*size, 0.6790841221809387*size, 0.05000019446015358*size),
(-0.3658318817615509*size, 0.6790841221809387*size, -0.04999979957938194*size),
(-0.36583176255226135*size, 0.6790841221809387*size, 0.10000018030405045*size),
(-0.48870471119880676*size, 0.5930476188659668*size, 2.4472291215715813e-07*size),
(-0.3658319413661957*size, 0.679084062576294*size, -0.0999998077750206*size),
(-0.22248037159442902*size, 0.7794600129127502*size, -0.04999985918402672*size),
(-0.22248034179210663*size, 0.7794600129127502*size, 0.05000016465783119*size),
(0.3658319115638733*size, 0.6790841221809387*size, -0.05000000819563866*size),
(0.3658319115638733*size, 0.6790841221809387*size, 0.05000000074505806*size),
(0.36583179235458374*size, 0.6790841221809387*size, -0.09999998658895493*size),
(0.4887046813964844*size, 0.5930476188659668*size, -3.8399143420519977e-08*size),
(0.3658319413661957*size, 0.679084062576294*size, 0.10000000149011612*size),
(0.050000034272670746*size, 0.7794599533081055*size, 0.2224804311990738*size),
(-0.04999997466802597*size, 0.7794599533081055*size, 0.2224804311990738*size),
(-0.09999992698431015*size, 0.679084062576294*size, 0.36583200097084045*size),
(1.267315070663244e-07*size, 0.5930474996566772*size, 0.48870477080345154*size),
(0.1000000610947609*size, 0.679084062576294*size, 0.3658318519592285*size),
(-0.049999915063381195*size, 0.679084062576294*size, 0.3658319413661957*size),
(0.05000007897615433*size, 0.679084062576294*size, 0.36583197116851807*size),
(0.22248029708862305*size, 0.7794600129127502*size, 0.05000004544854164*size),
(0.22248028218746185*size, 0.7794600129127502*size, -0.04999994859099388*size),
(-4.752442350763886e-08*size, 0.8284152746200562*size, -0.1499999612569809*size),
(-0.03882290795445442*size, 0.8284152746200562*size, -0.14488883316516876*size),
(-0.07500004768371582*size, 0.8284152746200562*size, -0.12990377843379974*size),
(-0.10606606304645538*size, 0.8284152746200562*size, -0.10606598109006882*size),
(-0.1299038827419281*size, 0.8284152746200562*size, -0.07499996572732925*size),
(-0.14488893747329712*size, 0.8284152746200562*size, -0.038822825998067856*size),
(-0.15000006556510925*size, 0.8284152746200562*size, 2.4781975582754967e-08*size),
(-0.1448889672756195*size, 0.8284152746200562*size, 0.038822878152132034*size),
(-0.1299038827419281*size, 0.8284152746200562*size, 0.07500001043081284*size),
(-0.10606609284877777*size, 0.8284152746200562*size, 0.1060660257935524*size),
(-0.0750000923871994*size, 0.8284152746200562*size, 0.12990383803844452*size),
(-0.038822952657938004*size, 0.8284152746200562*size, 0.14488889276981354*size),
(-1.0593657862045802e-07*size, 0.8284152746200562*size, 0.15000005066394806*size),
(0.03882275149226189*size, 0.8284152746200562*size, 0.14488892257213593*size),
(0.07499989867210388*size, 0.8284152746200562*size, 0.1299038976430893*size),
(0.10606591403484344*size, 0.8284152746200562*size, 0.10606611520051956*size),
(0.12990373373031616*size, 0.8284152746200562*size, 0.0750000849366188*size),
(0.14488881826400757*size, 0.8284152746200562*size, 0.038822952657938004*size),
(0.1499999463558197*size, 0.8284152746200562*size, 1.0584351883835552e-07*size),
(0.14488881826400757*size, 0.8284152746200562*size, -0.03882275149226189*size),
(0.12990379333496094*size, 0.8284152746200562*size, -0.07499989122152328*size),
(0.10606604814529419*size, 0.8284152746200562*size, -0.10606592148542404*size),
(0.07500004768371582*size, 0.8284152746200562*size, -0.12990371882915497*size),
(0.03882291540503502*size, 0.8284152746200562*size, -0.14488880336284637*size), ]
edges = [(1, 0), (3, 2), (5, 2), (4, 3), (6, 4), (1, 5), (0, 6), (13, 7), (12, 8), (7, 9),
(9, 10), (8, 11), (27, 14), (26, 15), (14, 16), (16, 17), (15, 18), (17, 18),
(10, 11), (12, 13), (20, 19), (22, 21), (24, 21), (23, 22), (29, 28), (30, 29),
(31, 30), (32, 31), (33, 32), (34, 33), (35, 34), (36, 35), (37, 36), (38, 37),
(39, 38), (40, 39), (41, 40), (42, 41), (43, 42), (44, 43), (45, 44), (46, 45),
(47, 46), (48, 47), (49, 48), (50, 49), (51, 50), (28, 51), (26, 27), (25, 23),
(20, 24), (19, 25), ]
faces = []
mesh = obj.data
@ -149,5 +427,57 @@ def create_ballsocket_widget(rig, bone_name, size=1.0, bone_transform_name=None)
@widget_generator(register="gear")
def create_gear_widget(geom, *, radius=0.5):
size = radius * 10
geom.verts = [(0.11251477152109146*size, -8.06030631128607e-10*size, 0.01843983121216297*size), (0.018439611420035362*size, -4.918176976786981e-09*size, 0.11251477152109146*size), (0.09270283579826355*size, -8.06030631128607e-10*size, 0.01843983121216297*size), (0.08732416480779648*size, -1.5810827092010982e-09*size, 0.03617095574736595*size), (0.07858962565660477*size, -2.295374557093055e-09*size, 0.05251204967498779*size), (0.052511852234601974*size, -3.4352671818282943e-09*size, 0.07858975231647491*size), (0.03617073595523834*size, -3.8170644423018985e-09*size, 0.08732425421476364*size), (0.018439611420035362*size, -4.0521714872454595e-09*size, 0.09270287305116653*size), (0.09402976930141449*size, -2.937612375575327e-09*size, 0.06720473617315292*size), (0.08150213211774826*size, -3.513068946858766e-09*size, 0.08036965131759644*size), (0.06872907280921936*size, -4.0997978345558295e-09*size, 0.09379243850708008*size), (-0.1125146746635437*size, -8.06030631128607e-10*size, 0.01843983121216297*size), (-0.01843959279358387*size, -4.918176976786981e-09*size, 0.11251477152109146*size), (1.078764189088588e-08*size, -4.918176976786981e-09*size, 0.11251477152109146*size), (-0.09270282834768295*size, -8.06030631128607e-10*size, 0.01843983121216297*size), (-0.0873241126537323*size, -1.5810827092010982e-09*size, 0.03617095574736595*size), (-0.07858961820602417*size, -2.295374557093055e-09*size, 0.05251204967498779*size), (-0.05251181498169899*size, -3.4352671818282943e-09*size, 0.07858975231647491*size), (-0.036170728504657745*size, -3.8170644423018985e-09*size, 0.08732425421476364*size), (-0.01843959279358387*size, -4.0521714872454595e-09*size, 0.09270287305116653*size), (-0.09402971714735031*size, -2.937612375575327e-09*size, 0.06720473617315292*size), (-0.08150212466716766*size, -3.513068946858766e-09*size, 0.08036965131759644*size), (-0.06872902065515518*size, -4.0997978345558295e-09*size, 0.09379243850708008*size), (0.11251477152109146*size, 8.06031352773573e-10*size, -0.018439847975969315*size), (0.11251477152109146*size, 3.801315519479033e-16*size, -8.696396491814085e-09*size), (0.018439611420035362*size, 4.918176532697771e-09*size, -0.11251476407051086*size), (0.09270283579826355*size, 8.06031352773573e-10*size, -0.018439847975969315*size), (0.08732416480779648*size, 1.5810828202234006e-09*size, -0.03617095947265625*size), (0.07858962565660477*size, 2.29537477913766e-09*size, -0.05251205340027809*size), (0.052511852234601974*size, 3.435267403872899e-09*size, -0.07858975976705551*size), (0.03617073595523834*size, 3.8170644423018985e-09*size, -0.08732425421476364*size), (0.018439611420035362*size, 4.0521714872454595e-09*size, -0.09270287305116653*size), (0.09402976930141449*size, 2.937614596021376e-09*size, -0.0672047883272171*size), (0.08150213211774826*size, 3.513068946858766e-09*size, -0.08036965131759644*size), (0.06872907280921936*size, 4.099800055001879e-09*size, -0.09379249066114426*size), (-0.1125146746635437*size, 8.06031352773573e-10*size, -0.018439847975969315*size), (-0.1125146746635437*size, 3.801315519479033e-16*size, -8.696396491814085e-09*size), (-0.01843959279358387*size, 4.918176532697771e-09*size, -0.11251476407051086*size), (1.078764189088588e-08*size, 4.918176532697771e-09*size, -0.11251476407051086*size), (-0.09270282834768295*size, 8.06031352773573e-10*size, -0.018439847975969315*size), (-0.0873241126537323*size, 1.5810828202234006e-09*size, -0.03617095947265625*size), (-0.07858961820602417*size, 2.29537477913766e-09*size, -0.05251205340027809*size), (-0.05251181498169899*size, 3.435267403872899e-09*size, -0.07858975976705551*size), (-0.036170728504657745*size, 3.8170644423018985e-09*size, -0.08732425421476364*size), (-0.01843959279358387*size, 4.0521714872454595e-09*size, -0.09270287305116653*size), (-0.09402971714735031*size, 2.937614596021376e-09*size, -0.0672047883272171*size), (-0.08150212466716766*size, 3.513068946858766e-09*size, -0.08036965131759644*size), (-0.06872902065515518*size, 4.099800055001879e-09*size, -0.09379249066114426*size), ]
geom.edges = [(0, 2), (0, 24), (7, 1), (13, 1), (3, 2), (4, 3), (6, 5), (7, 6), (9, 8), (10, 9), (10, 5), (4, 8), (11, 14), (11, 36), (19, 12), (13, 12), (15, 14), (16, 15), (18, 17), (19, 18), (21, 20), (22, 21), (22, 17), (16, 20), (23, 26), (23, 24), (31, 25), (38, 25), (27, 26), (28, 27), (30, 29), (31, 30), (33, 32), (34, 33), (34, 29), (28, 32), (35, 39), (35, 36), (44, 37), (38, 37), (40, 39), (41, 40), (43, 42), (44, 43), (46, 45), (47, 46), (47, 42), (41, 45), ]
geom.verts = [(0.11251477152109146*size, -8.06030631128607e-10*size, 0.01843983121216297*size),
(0.018439611420035362*size, -4.918176976786981e-09*size, 0.11251477152109146*size),
(0.09270283579826355*size, -8.06030631128607e-10*size, 0.01843983121216297*size),
(0.08732416480779648*size, -1.5810827092010982e-09*size, 0.03617095574736595*size),
(0.07858962565660477*size, -2.295374557093055e-09*size, 0.05251204967498779*size),
(0.052511852234601974*size, -3.4352671818282943e-09*size, 0.07858975231647491*size),
(0.03617073595523834*size, -3.8170644423018985e-09*size, 0.08732425421476364*size),
(0.018439611420035362*size, -4.0521714872454595e-09*size, 0.09270287305116653*size),
(0.09402976930141449*size, -2.937612375575327e-09*size, 0.06720473617315292*size),
(0.08150213211774826*size, -3.513068946858766e-09*size, 0.08036965131759644*size),
(0.06872907280921936*size, -4.0997978345558295e-09*size, 0.09379243850708008*size),
(-0.1125146746635437*size, -8.06030631128607e-10*size, 0.01843983121216297*size),
(-0.01843959279358387*size, -4.918176976786981e-09*size, 0.11251477152109146*size),
(1.078764189088588e-08*size, -4.918176976786981e-09*size, 0.11251477152109146*size),
(-0.09270282834768295*size, -8.06030631128607e-10*size, 0.01843983121216297*size),
(-0.0873241126537323*size, -1.5810827092010982e-09*size, 0.03617095574736595*size),
(-0.07858961820602417*size, -2.295374557093055e-09*size, 0.05251204967498779*size),
(-0.05251181498169899*size, -3.4352671818282943e-09*size, 0.07858975231647491*size),
(-0.036170728504657745*size, -3.8170644423018985e-09*size, 0.08732425421476364*size),
(-0.01843959279358387*size, -4.0521714872454595e-09*size, 0.09270287305116653*size),
(-0.09402971714735031*size, -2.937612375575327e-09*size, 0.06720473617315292*size),
(-0.08150212466716766*size, -3.513068946858766e-09*size, 0.08036965131759644*size),
(-0.06872902065515518*size, -4.0997978345558295e-09*size, 0.09379243850708008*size),
(0.11251477152109146*size, 8.06031352773573e-10*size, -0.018439847975969315*size),
(0.11251477152109146*size, 3.801315519479033e-16*size, -8.696396491814085e-09*size),
(0.018439611420035362*size, 4.918176532697771e-09*size, -0.11251476407051086*size),
(0.09270283579826355*size, 8.06031352773573e-10*size, -0.018439847975969315*size),
(0.08732416480779648*size, 1.5810828202234006e-09*size, -0.03617095947265625*size),
(0.07858962565660477*size, 2.29537477913766e-09*size, -0.05251205340027809*size),
(0.052511852234601974*size, 3.435267403872899e-09*size, -0.07858975976705551*size),
(0.03617073595523834*size, 3.8170644423018985e-09*size, -0.08732425421476364*size),
(0.018439611420035362*size, 4.0521714872454595e-09*size, -0.09270287305116653*size),
(0.09402976930141449*size, 2.937614596021376e-09*size, -0.0672047883272171*size),
(0.08150213211774826*size, 3.513068946858766e-09*size, -0.08036965131759644*size),
(0.06872907280921936*size, 4.099800055001879e-09*size, -0.09379249066114426*size),
(-0.1125146746635437*size, 8.06031352773573e-10*size, -0.018439847975969315*size),
(-0.1125146746635437*size, 3.801315519479033e-16*size, -8.696396491814085e-09*size),
(-0.01843959279358387*size, 4.918176532697771e-09*size, -0.11251476407051086*size),
(1.078764189088588e-08*size, 4.918176532697771e-09*size, -0.11251476407051086*size),
(-0.09270282834768295*size, 8.06031352773573e-10*size, -0.018439847975969315*size),
(-0.0873241126537323*size, 1.5810828202234006e-09*size, -0.03617095947265625*size),
(-0.07858961820602417*size, 2.29537477913766e-09*size, -0.05251205340027809*size),
(-0.05251181498169899*size, 3.435267403872899e-09*size, -0.07858975976705551*size),
(-0.036170728504657745*size, 3.8170644423018985e-09*size, -0.08732425421476364*size),
(-0.01843959279358387*size, 4.0521714872454595e-09*size, -0.09270287305116653*size),
(-0.09402971714735031*size, 2.937614596021376e-09*size, -0.0672047883272171*size),
(-0.08150212466716766*size, 3.513068946858766e-09*size, -0.08036965131759644*size),
(-0.06872902065515518*size, 4.099800055001879e-09*size, -0.09379249066114426*size), ]
geom.edges = [(0, 2), (0, 24), (7, 1), (13, 1), (3, 2), (4, 3), (6, 5), (7, 6), (9, 8),
(10, 9), (10, 5), (4, 8), (11, 14), (11, 36), (19, 12), (13, 12), (15, 14),
(16, 15), (18, 17), (19, 18), (21, 20), (22, 21), (22, 17), (16, 20), (23, 26),
(23, 24), (31, 25), (38, 25), (27, 26), (28, 27), (30, 29), (31, 30), (33, 32),
(34, 33), (34, 29), (28, 32), (35, 39), (35, 36), (44, 37), (38, 37), (40, 39),
(41, 40), (43, 42), (44, 43), (46, 45), (47, 46), (47, 42), (41, 45), ]

View File

@ -7,11 +7,15 @@ import math
# noinspection PyUnresolvedReferences
from mathutils import Matrix, Vector
from typing import Callable, Any, Collection, Iterator
from typing import TYPE_CHECKING, Callable, Any, Collection, Iterator, Optional, Sequence
from bpy.types import Action, bpy_struct, FCurve
import json
if TYPE_CHECKING:
from ..rig_ui_template import PanelLayout
rig_id = None
@ -849,7 +853,7 @@ class POSE_OT_rigify_clear_keyframes(bpy.types.Operator):
# noinspection PyDefaultArgument,PyUnusedLocal
def add_clear_keyframes_button(panel, *, bones=[], label='', text=''):
def add_clear_keyframes_button(panel: 'PanelLayout', *, bones: list[str] = [], label='', text=''):
panel.use_bake_settings()
panel.script.add_utilities(SCRIPT_UTILITIES_OP_CLEAR_KEYS)
panel.script.register_classes(SCRIPT_REGISTER_OP_CLEAR_KEYS)
@ -921,8 +925,10 @@ class POSE_OT_rigify_generic_snap_bake(RigifyGenericSnapBase, RigifyBakeKeyframe
''']
def add_fk_ik_snap_buttons(panel, op_single, op_bake, *, label=None, rig_name='', properties=None,
clear_bones=None, compact=None):
def add_fk_ik_snap_buttons(panel: 'PanelLayout', op_single: str, op_bake: str, *,
label, rig_name='', properties: dict[str, Any],
clear_bones: Optional[list[str]] = None,
compact: Optional[bool] = None):
assert label and properties
if rig_name:
@ -944,8 +950,12 @@ def add_fk_ik_snap_buttons(panel, op_single, op_bake, *, label=None, rig_name=''
# noinspection PyDefaultArgument
def add_generic_snap(panel, *, output_bones=[], input_bones=[], input_ctrl_bones=[], label='Snap',
rig_name='', undo_copy_scale=False, compact=None, clear=True, locks=None, tooltip=None):
def add_generic_snap(panel: 'PanelLayout', *,
output_bones: list[str] = [], input_bones: list[str] = [],
input_ctrl_bones: list[str] = [], label='Snap',
rig_name='', undo_copy_scale=False, compact: Optional[bool] = None,
clear=True, locks: Optional[Sequence[bool]] = None,
tooltip: Optional[str] = None):
panel.use_bake_settings()
panel.script.add_utilities(SCRIPT_UTILITIES_OP_SNAP)
panel.script.register_classes(SCRIPT_REGISTER_OP_SNAP)
@ -972,8 +982,11 @@ def add_generic_snap(panel, *, output_bones=[], input_bones=[], input_ctrl_bones
# noinspection PyDefaultArgument
def add_generic_snap_fk_to_ik(panel, *, fk_bones=[], ik_bones=[], ik_ctrl_bones=[], label='FK->IK',
rig_name='', undo_copy_scale=False, compact=None, clear=True):
def add_generic_snap_fk_to_ik(panel: 'PanelLayout', *,
fk_bones: list[str] = [], ik_bones: list[str] = [],
ik_ctrl_bones: list[str] = [], label='FK->IK',
rig_name='', undo_copy_scale=False,
compact: Optional[bool] = None, clear=True):
add_generic_snap(
panel, output_bones=fk_bones, input_bones=ik_bones, input_ctrl_bones=ik_ctrl_bones,
label=label, rig_name=rig_name, undo_copy_scale=undo_copy_scale, compact=compact, clear=clear

View File

@ -4,7 +4,7 @@ import bpy
import math
from mathutils import Vector, Matrix
from typing import Optional, Callable
from typing import Optional, Callable, Iterable
from .errors import MetarigError
from .naming import get_name, make_derived_name, is_control_bone
@ -15,7 +15,69 @@ from .misc import pairwise, ArmatureObject
# Bone collection
########################
class BoneDict(dict):
class BaseBoneDict(dict):
"""
Special dictionary for holding bone names in a structured way.
Allows access to contained items as attributes, and only
accepts certain types of values.
"""
@staticmethod
def __sanitize_attr(key, value):
if hasattr(BaseBoneDict, key):
raise KeyError(f"Invalid BoneDict key: {key}")
if value is None or isinstance(value, (str, list, BaseBoneDict)):
return value
if isinstance(value, dict):
return BaseBoneDict(value)
raise ValueError(f"Invalid BoneDict value: {repr(value)}")
def __init__(self, *args, **kwargs):
super().__init__()
for key, value in dict(*args, **kwargs).items():
dict.__setitem__(self, key, BaseBoneDict.__sanitize_attr(key, value))
self.__dict__ = self
def __repr__(self):
return "BoneDict(%s)" % (dict.__repr__(self))
def __setitem__(self, key, value):
dict.__setitem__(self, key, BaseBoneDict.__sanitize_attr(key, value))
def update(self, *args, **kwargs):
for key, value in dict(*args, **kwargs).items():
dict.__setitem__(self, key, BaseBoneDict.__sanitize_attr(key, value))
def flatten(self, key: Optional[str] = None):
"""Return all contained bones or a single key as a list."""
items = [self[key]] if key is not None else self.values()
all_bones = []
for item in items:
if isinstance(item, BaseBoneDict):
all_bones.extend(item.flatten())
elif isinstance(item, list):
all_bones.extend(item)
elif item is not None:
all_bones.append(item)
return all_bones
class TypedBoneDict(BaseBoneDict):
# Omit DynamicAttrs to ensure usages of undeclared attributes are highlighted
pass
class BoneDict(BaseBoneDict):
"""
Special dictionary for holding bone names in a structured way.
@ -25,54 +87,6 @@ class BoneDict(dict):
@DynamicAttrs
"""
@staticmethod
def __sanitize_attr(key, value):
if hasattr(BoneDict, key):
raise KeyError(f"Invalid BoneDict key: {key}")
if value is None or isinstance(value, (str, list, BoneDict)):
return value
if isinstance(value, dict):
return BoneDict(value)
raise ValueError(f"Invalid BoneDict value: {repr(value)}")
def __init__(self, *args, **kwargs):
super().__init__()
for key, value in dict(*args, **kwargs).items():
dict.__setitem__(self, key, BoneDict.__sanitize_attr(key, value))
self.__dict__ = self
def __repr__(self):
return "BoneDict(%s)" % (dict.__repr__(self))
def __setitem__(self, key, value):
dict.__setitem__(self, key, BoneDict.__sanitize_attr(key, value))
def update(self, *args, **kwargs):
for key, value in dict(*args, **kwargs).items():
dict.__setitem__(self, key, BoneDict.__sanitize_attr(key, value))
def flatten(self, key=None):
"""Return all contained bones or a single key as a list."""
items = [self[key]] if key is not None else self.values()
all_bones = []
for item in items:
if isinstance(item, BoneDict):
all_bones.extend(item.flatten())
elif isinstance(item, list):
all_bones.extend(item)
elif item is not None:
all_bones.append(item)
return all_bones
########################
# Bone manipulation
@ -220,7 +234,7 @@ def flip_bone(obj: ArmatureObject, bone_name: str):
raise MetarigError("Cannot flip bones outside of edit mode")
def flip_bone_chain(obj: ArmatureObject, bone_names: list[str]):
def flip_bone_chain(obj: ArmatureObject, bone_names: Iterable[str]):
"""Flips a connected bone chain."""
assert obj.mode == 'EDIT'
@ -282,7 +296,7 @@ def put_bone(obj: ArmatureObject, bone_name: str, pos: Optional[Vector], *,
raise MetarigError("Cannot 'put' bones outside of edit mode")
def disable_bbones(obj: ArmatureObject, bone_names: list[str]):
def disable_bbones(obj: ArmatureObject, bone_names: Iterable[str]):
"""Disables B-Bone segments on the specified bones."""
assert(obj.mode != 'EDIT')
for bone in bone_names:
@ -440,7 +454,7 @@ class BoneUtilityMixin(object):
bone.inherit_scale = inherit_scale
bone.parent = (eb[parent_name] if parent_name else None)
def parent_bone_chain(self, bone_names: list[str],
def parent_bone_chain(self, bone_names: Iterable[str],
use_connect: Optional[bool] = None,
inherit_scale: Optional[str] = None):
"""Link bones into a chain with parenting. First bone may be None."""
@ -453,7 +467,7 @@ class BoneUtilityMixin(object):
# B-Bones
##############################################
def connect_bbone_chain_handles(obj: ArmatureObject, bone_names: list[str]):
def connect_bbone_chain_handles(obj: ArmatureObject, bone_names: Iterable[str]):
assert obj.mode == 'EDIT'
for prev_name, next_name in pairwise(bone_names):

View File

@ -151,6 +151,15 @@ class ControlLayersOption:
layout_layer_buttons(box, params, self.layers_option, active_layers)
# Declarations for auto-completion
FK: 'ControlLayersOption'
TWEAK: 'ControlLayersOption'
EXTRA_IK: 'ControlLayersOption'
FACE_PRIMARY: 'ControlLayersOption'
FACE_SECONDARY: 'ControlLayersOption'
SKIN_PRIMARY: 'ControlLayersOption'
SKIN_SECONDARY: 'ControlLayersOption'
ControlLayersOption.FK = ControlLayersOption(
'fk', description="Layers for the FK controls to be on")

View File

@ -6,7 +6,7 @@ import importlib.util
import re
from itertools import count
from typing import TYPE_CHECKING, Any, Optional, Sequence, Mapping
from typing import TYPE_CHECKING, Any, Optional, Sequence
from bpy.types import bpy_struct, Constraint, Object, PoseBone, Bone, Armature
# noinspection PyUnresolvedReferences