diff options
author | Alexander Gavrilov <angavrilov@gmail.com> | 2019-02-16 13:57:57 +0300 |
---|---|---|
committer | Alexander Gavrilov <angavrilov@gmail.com> | 2019-03-14 14:39:16 +0300 |
commit | 36e8d00aec705b06008a0bc334fe266448b4f2c2 (patch) | |
tree | 02bf0290ec6423c611e3cd4ad49c69cb77acb67e /rigify/utils/layers.py | |
parent | eabb5cddf79e5fae3ca429242cf2c6f5a272920e (diff) |
Rigify: add support for user-defined rig packages and related utilities.
As suggested by @icappielo, and after discussion with @meta-androcto,
I start a public request to commit third-party contributions already
accepted to https://github.com/eigen-value/rigify/tree/rigify_0.6_beta
Specifically, this includes:
* User-defined rig package (feature set) support by @pioverfour.
This allows users to install pre-packaged rig sets via zip
files, which become accessible together with built-in rigs,
as discussed in T52758.
https://github.com/eigen-value/rigify/pull/1
* Modularization of python script generation, allowing rigs to
add their own utility functions and operators to the generated
script. This is critical to make custom rig support really
useful.
https://github.com/eigen-value/rigify/pull/5
* The utils.py file is split into multiple modules with a backward
compatibility proxy for old functions.
* Automatic verification that different rigs don't try to create
different rig settings with the same name to alleviate increased
risk of namespace conflicts with custom rigs.
https://github.com/eigen-value/rigify/pull/7
* New utility class that implements bone layer selection UI.
https://github.com/eigen-value/rigify/pull/6
* New utilities to replace copy & pasted boilerplate code for
creating custom properties, constraints and drivers.
https://github.com/eigen-value/rigify/pull/11
Some other random changes by MAD have likely slipped through.
These changes have already been extensively discussed and accepted
into the branch by @luciorossi, so I see no reason not to commit
them to the official repository to be tested during 2.8 beta.
Reviewers: icappiello
Differential Revision: https://developer.blender.org/D4364
Diffstat (limited to 'rigify/utils/layers.py')
-rw-r--r-- | rigify/utils/layers.py | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/rigify/utils/layers.py b/rigify/utils/layers.py new file mode 100644 index 00000000..1045e493 --- /dev/null +++ b/rigify/utils/layers.py @@ -0,0 +1,140 @@ +#====================== BEGIN GPL LICENSE BLOCK ====================== +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +#======================= END GPL LICENSE BLOCK ======================== + +# <pep8 compliant> + +import bpy + + +def get_layers(layers): + """ Does its best to extract a set of layers from any data thrown at it. + """ + if type(layers) == int: + return [x == layers for x in range(0, 32)] + elif type(layers) == str: + s = layers.split(",") + l = [] + for i in s: + try: + l += [int(float(i))] + except ValueError: + pass + return [x in l for x in range(0, 32)] + elif type(layers) == tuple or type(layers) == list: + return [x in layers for x in range(0, 32)] + else: + try: + list(layers) + except TypeError: + pass + else: + return [x in layers for x in range(0, 32)] + + +#============================================= +# UI utilities +#============================================= + +class ControlLayersOption: + def __init__(self, name, toggle_name=None, toggle_default=True, description="Set of control layers"): + self.name = name + self.toggle_default = toggle_default + self.description = description + + self.toggle_option = self.name+'_layers_extra' + self.layers_option = self.name+'_layers' + self.toggle_name = toggle_name if toggle_name else self.toggle_option + + def get(self, params): + if getattr(params, self.toggle_option): + return list(getattr(params, self.layers_option)) + else: + return None + + def assign(self, params, bone_set, bone_list): + layers = self.get(params) + + if layers: + for name in bone_list: + bone = bone_set[name] + if isinstance(bone, bpy.types.PoseBone): + bone = bone.bone + + bone.layers = layers + + def add_parameters(self, params): + prop_toggle = bpy.props.BoolProperty( + name=self.toggle_name, + default=self.toggle_default, + description="" + ) + + setattr(params, self.toggle_option, prop_toggle) + + prop_layers = bpy.props.BoolVectorProperty( + size=32, + description=self.description, + default=tuple([i == 1 for i in range(0, 32)]) + ) + + setattr(params, self.layers_option, prop_layers) + + def parameters_ui(self, layout, params): + r = layout.row() + r.prop(params, self.toggle_option) + r.active = getattr(params, self.toggle_option) + + col = r.column(align=True) + row = col.row(align=True) + + bone_layers = bpy.context.active_pose_bone.bone.layers[:] + + for i in range(8): # Layers 0-7 + icon = "NONE" + if bone_layers[i]: + icon = "LAYER_ACTIVE" + row.prop(params, self.layers_option, index=i, toggle=True, text="", icon=icon) + + row = col.row(align=True) + + for i in range(16, 24): # Layers 16-23 + icon = "NONE" + if bone_layers[i]: + icon = "LAYER_ACTIVE" + row.prop(params, self.layers_option, index=i, toggle=True, text="", icon=icon) + + col = r.column(align=True) + row = col.row(align=True) + + for i in range(8, 16): # Layers 8-15 + icon = "NONE" + if bone_layers[i]: + icon = "LAYER_ACTIVE" + row.prop(params, self.layers_option, index=i, toggle=True, text="", icon=icon) + + row = col.row(align=True) + + for i in range(24, 32): # Layers 24-31 + icon = "NONE" + if bone_layers[i]: + icon = "LAYER_ACTIVE" + row.prop(params, self.layers_option, index=i, toggle=True, text="", icon=icon) + + +ControlLayersOption.FK = ControlLayersOption('fk', description="Layers for the FK controls to be on") +ControlLayersOption.TWEAK = ControlLayersOption('tweak', description="Layers for the tweak controls to be on") |