1 #====================== BEGIN GPL LICENSE BLOCK ======================
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 #======================= END GPL LICENSE BLOCK ========================
25 from .utils
.errors
import RaiseErrorMixin
26 from .utils
.bones
import BoneDict
, BoneUtilityMixin
27 from .utils
.mechanism
import MechanismUtilityMixin
28 from .utils
.metaclass
import BaseStagedClass
30 # Only export certain symbols via 'from base_rig import *'
31 __all__
= ['BaseRig', 'stage']
33 #=============================================
35 #=============================================
37 class GenerateCallbackHost(BaseStagedClass
, define_stages
=True):
39 Standard set of callback methods to redefine.
40 Shared between BaseRig and GeneratorPlugin.
42 These callbacks are called in this order; every one is
43 called for all rigs before proceeding to the next stage.
45 Switching modes is not allowed in rigs for performance
46 reasons. Place code in the appropriate callbacks to use
47 the mode set by the main engine.
49 After each callback, all other methods decorated with
50 @stage.<method_name> are called, for instance:
52 def generate_bones(self):
59 Will print 'first', then 'second'. Multiple methods in the
60 same stage are called in the order they are first defined;
61 in case of inheritance, the class bodies are scanned in
62 reverse MRO order. E.g.:
75 # Was first defined in Base so still first:
82 Multiple inheritance can make this ordering confusing, so it
85 When overriding such methods in a subclass the appropriate
86 decorator should be repeated for code clarity reasons;
87 a warning is printed if this is not done.
91 Initialize processing after all rig classes are constructed.
92 Called in Object mode. May not change the armature.
96 def prepare_bones(self
):
98 Prepare ORG bones for generation, e.g. align them.
99 Called in Edit mode. May not add bones.
103 def generate_bones(self
):
110 def parent_bones(self
):
112 Parent all bones and set other edit mode properties.
113 Called in Edit mode. May not add bones.
117 def configure_bones(self
):
119 Configure bone properties, e.g. transform locks, layers etc.
120 Called in Object mode. May not do Edit mode operations.
124 def apply_bones(self
):
126 Can be used to apply some constraints to rest pose, and for final parenting.
127 Called in Edit mode. May not add bones.
133 Create and configure all constraints, drivers etc.
134 Called in Object mode. May not do Edit mode operations.
138 def generate_widgets(self
):
140 Create all widget objects.
141 Called in Object mode. May not do Edit mode operations.
147 Finishing touches to the construction of the rig.
148 Called in Object mode. May not do Edit mode operations.
153 class BaseRig(GenerateCallbackHost
, RaiseErrorMixin
, BoneUtilityMixin
, MechanismUtilityMixin
):
155 Base class for all rigs.
157 The main weak areas in the legacy Rigify rig class structure
158 was that there were no provisions for intelligent interactions
159 between rigs, and all processing was done via one generate
160 method, necessitating frequent expensive mode switches.
162 This structure fixes those problems by providing a mandatory
163 base class that hold documented connections between rigs, bones,
164 and the common generator object. The generation process is also
165 split into multiple stages.
167 def __init__(self
, generator
, pose_bone
):
168 self
.generator
= generator
170 self
.obj
= generator
.obj
171 self
.script
= generator
.script
172 self
.base_bone
= pose_bone
.name
173 self
.params
= pose_bone
.rigify_parameters
175 # Collection of bone names for use in implementing the rig
176 self
.bones
= BoneDict(
178 org
= self
.find_org_bones(pose_bone
),
187 # Data useful for complex rig interaction:
188 # Parent-child links between rigs.
189 self
.rigify_parent
= None
190 self
.rigify_children
= []
191 # ORG bones directly owned by the rig.
192 self
.rigify_org_bones
= set(self
.bones
.flatten('org'))
193 # Children of bones owned by the rig.
194 self
.rigify_child_bones
= set()
195 # Bones created by the rig (mapped to original names)
196 self
.rigify_new_bones
= dict()
198 def register_new_bone(self
, new_name
, old_name
=None):
199 """Registers this rig as the owner of this new bone."""
200 self
.rigify_new_bones
[new_name
] = old_name
201 self
.generator
.bone_owners
[new_name
] = self
203 ###########################################################
206 def find_org_bones(self
, pose_bone
):
208 Select bones directly owned by the rig. Returning the
209 same bone from multiple rigs is an error.
211 May return a single name, a list, or a BoneDict.
213 Called in Object mode, may not change the armature.
215 return [pose_bone
.name
]
217 ###########################################################
221 def add_parameters(cls
, params
):
223 This method add more parameters to params
224 :param params: rigify_parameters of a pose_bone
230 def parameters_ui(cls
, layout
, params
):
232 This method draws the UI of the rigify_parameters defined on the pose_bone
237 layout
.label(text
="No options")
240 def on_parameter_update(cls
, context
, pose_bone
, params
, param_name
):
242 A callback invoked whenever a parameter value is changed by the user.
246 #=============================================
248 #=============================================
251 class RigUtility(BoneUtilityMixin
, MechanismUtilityMixin
):
252 """Base class for utility classes that generate part of a rig."""
253 def __init__(self
, owner
):
257 def register_new_bone(self
, new_name
, old_name
=None):
258 self
.owner
.register_new_bone(new_name
, old_name
)
261 class RigComponent(GenerateCallbackHost
, RigUtility
):
262 """Base class for utility classes that generate part of a rig using callbacks."""
263 def __init__(self
, owner
):
264 super().__init
__(owner
)
266 self
.owner
.rigify_sub_objects
= objects
= self
.owner
.rigify_sub_objects
or []
271 #=============================================
272 # Rig Stage Decorators
273 #=============================================
278 # Generate @stage.<...> decorators for all valid stages
279 for name
, decorator
in GenerateCallbackHost
.make_stage_decorators():
280 setattr(stage
, name
, decorator
)