Changeset View
Changeset View
Standalone View
Standalone View
rigify/rigs/limbs/super_finger.py
| import bpy | #====================== BEGIN GPL LICENSE BLOCK ====================== | ||||
| from ...utils import copy_bone, flip_bone | # | ||||
| from ...utils import strip_org, make_deformer_name, connected_children_names, make_mechanism_name | # This program is free software; you can redistribute it and/or | ||||
| from ...utils import create_circle_widget, create_widget | # modify it under the terms of the GNU General Public License | ||||
| from ...utils import MetarigError, align_bone_x_axis | # as published by the Free Software Foundation; either version 2 | ||||
| from ...utils.mechanism import make_property | # of the License, or (at your option) any later version. | ||||
| # | |||||
| script = """ | # This program is distributed in the hope that it will be useful, | ||||
| controls = [%s] | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| master_name = '%s' | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| if is_selected(controls): | # GNU General Public License for more details. | ||||
| layout.prop(pose_bones[master_name], '["%s"]', text="Curvature", slider=True) | # | ||||
| """ | # 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> | |||||
| class Rig: | import bpy | ||||
| import re | |||||
| def __init__(self, obj, bone_name, params): | from itertools import count | ||||
| self.obj = obj | |||||
| self.org_bones = [bone_name] + connected_children_names(obj, bone_name) | |||||
| self.params = params | |||||
| if len(self.org_bones) <= 1: | from ...utils.errors import MetarigError | ||||
| raise MetarigError("RIGIFY ERROR: Bone '%s': listen bro, that finger rig jusaint put tugetha rite. A little hint, use more than one bone!!" % (strip_org(bone_name))) | from ...utils.bones import flip_bone, align_chain_x_axis | ||||
| from ...utils.naming import make_derived_name | |||||
| from ...utils.widgets import create_widget | |||||
| from ...utils.widgets_basic import create_circle_widget | |||||
| from ...utils.misc import map_list | |||||
| def orient_org_bones(self): | from ...base_rig import stage | ||||
| bpy.ops.object.mode_set(mode='EDIT') | from ..chain_rigs import SimpleChainRig | ||||
| eb = self.obj.data.edit_bones | |||||
| if self.params.primary_rotation_axis == 'automatic': | |||||
| first_bone = eb[self.org_bones[0]] | class Rig(SimpleChainRig): | ||||
| last_bone = eb[self.org_bones[-1]] | """A finger rig with master control.""" | ||||
| def initialize(self): | |||||
| super().initialize() | |||||
| # Orient uarm farm bones | self.bbone_segments = 8 | ||||
| chain_y_axis = last_bone.tail - first_bone.head | self.first_parent = self.get_bone_parent(self.bones.org[0]) | ||||
| chain_rot_axis = first_bone.y_axis.cross(chain_y_axis) # ik-plane normal axis (rotation) | |||||
| if chain_rot_axis.length < first_bone.length/100: | |||||
| chain_rot_axis = first_bone.x_axis.normalized() | |||||
| else: | |||||
| chain_rot_axis = chain_rot_axis.normalized() | |||||
| for bone in self.org_bones: | def prepare_bones(self): | ||||
| align_bone_x_axis(self.obj, bone, chain_rot_axis) | if self.params.primary_rotation_axis == 'automatic': | ||||
| align_chain_x_axis(self.obj, self.bones.org) | |||||
| def generate(self): | ############################## | ||||
| org_bones = self.org_bones | # Master Control | ||||
| bpy.ops.object.mode_set(mode='EDIT') | @stage.generate_bones | ||||
| eb = self.obj.data.edit_bones | def make_master_control(self): | ||||
| orgs = self.bones.org | |||||
| name = self.copy_bone(orgs[0], make_derived_name(orgs[0], 'ctrl', '_master'), parent=True) | |||||
| self.bones.ctrl.master = name | |||||
| first_bone = self.get_bone(orgs[0]) | |||||
| last_bone = self.get_bone(orgs[-1]) | |||||
| self.get_bone(name).tail += (last_bone.tail - first_bone.head) * 1.25 | |||||
| @stage.configure_bones | |||||
| def configure_master_control(self): | |||||
| master = self.bones.ctrl.master | |||||
| bone = self.get_bone(master) | |||||
| bone.lock_scale = True, False, True | |||||
| @stage.generate_widgets | |||||
| def make_master_control_widget(self): | |||||
| master_name = self.bones.ctrl.master | |||||
| self.orient_org_bones() | w = create_widget(self.obj, master_name) | ||||
| if w is not None: | |||||
| mesh = w.data | |||||
| verts = [(0, 0, 0), (0, 1, 0), (0.05, 1, 0), (0.05, 1.1, 0), (-0.05, 1.1, 0), (-0.05, 1, 0)] | |||||
| if 'Z' in self.params.primary_rotation_axis: | |||||
| # Flip x/z coordinates | |||||
| temp = [] | |||||
| for v in verts: | |||||
| temp += [(v[2], v[1], v[0])] | |||||
| verts = temp | |||||
| edges = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 1)] | |||||
| mesh.from_pydata(verts, edges, []) | |||||
| mesh.update() | |||||
| # Bone name lists | ############################## | ||||
| ctrl_chain = [] | # Control chain | ||||
| def_chain = [] | |||||
| mch_chain = [] | |||||
| mch_drv_chain = [] | |||||
| # Create ctrl master bone | |||||
| org_name = self.org_bones[0] | |||||
| temp_name = strip_org(self.org_bones[0]) | |||||
| if temp_name[-2:] == '.L' or temp_name[-2:] == '.R': | |||||
| suffix = temp_name[-2:] | |||||
| master_name = temp_name[:-2] + "_master" + suffix | |||||
| else: | |||||
| master_name = temp_name + "_master" | |||||
| master_name = copy_bone(self.obj, org_name, master_name) | |||||
| ctrl_bone_master = eb[master_name] | |||||
| # Parenting bug fix ?? | |||||
| ctrl_bone_master.use_connect = False | |||||
| ctrl_bone_master.parent = None | |||||
| ctrl_bone_master.tail += (eb[org_bones[-1]].tail - eb[org_name].head) * 1.25 | |||||
| for bone in org_bones: | |||||
| eb[bone].use_connect = False | |||||
| if org_bones.index(bone) != 0: | |||||
| eb[bone].parent = None | |||||
| # Creating the bone chains | |||||
| for i in range(len(self.org_bones)): | |||||
| name = self.org_bones[i] | |||||
| ctrl_name = strip_org(name) | |||||
| # Create control bones | |||||
| ctrl_bone = copy_bone(self.obj, name, ctrl_name) | |||||
| ctrl_bone_e = eb[ctrl_name] | |||||
| # Create deformation bones | |||||
| def_name = make_deformer_name(ctrl_name) | |||||
| def_bone = copy_bone(self.obj, name, def_name) | |||||
| # Create mechanism bones | |||||
| mch_name = make_mechanism_name(ctrl_name) | |||||
| mch_bone = copy_bone(self.obj, name, mch_name) | |||||
| # Create mechanism driver bones | |||||
| drv_name = make_mechanism_name(ctrl_name) + "_drv" | |||||
| mch_bone_drv = copy_bone(self.obj, name, drv_name) | |||||
| # Adding to lists | |||||
| ctrl_chain += [ctrl_bone] | |||||
| def_chain += [def_bone] | |||||
| mch_chain += [mch_bone] | |||||
| mch_drv_chain += [mch_bone_drv] | |||||
| # Restoring org chain parenting | |||||
| for bone in org_bones[1:]: | |||||
| eb[bone].parent = eb[org_bones[org_bones.index(bone) - 1]] | |||||
| # Parenting the master bone to the first org | |||||
| ctrl_bone_master = eb[master_name] | |||||
| ctrl_bone_master.parent = eb[org_bones[0]] | |||||
| # Parenting chain bones | |||||
| for i in range(len(self.org_bones)): | |||||
| # Edit bone references | |||||
| def_bone_e = eb[def_chain[i]] | |||||
| ctrl_bone_e = eb[ctrl_chain[i]] | |||||
| mch_bone_e = eb[mch_chain[i]] | |||||
| mch_bone_drv_e = eb[mch_drv_chain[i]] | |||||
| if i == 0: | @stage.generate_bones | ||||
| # First ctl bone | def make_control_chain(self): | ||||
| ctrl_bone_e.parent = mch_bone_drv_e | orgs = self.bones.org | ||||
| ctrl_bone_e.use_connect = False | self.bones.ctrl.fk = map_list(self.make_control_bone, count(0), orgs) | ||||
| # First def bone | self.bones.ctrl.fk += [self.make_tip_control_bone(orgs[-1], orgs[0])] | ||||
| def_bone_e.parent = eb[self.org_bones[i]].parent | |||||
| def_bone_e.use_connect = False | def make_control_bone(self, i, org): | ||||
| # First mch bone | return self.copy_bone(org, make_derived_name(org, 'ctrl'), parent=False) | ||||
| mch_bone_e.parent = eb[self.org_bones[i]].parent | |||||
| mch_bone_e.use_connect = False | def make_tip_control_bone(self, org, name_org): | ||||
| # First mch driver bone | name = self.copy_bone(org, make_derived_name(name_org, 'ctrl'), parent=False) | ||||
| mch_bone_drv_e.parent = eb[self.org_bones[i]].parent | |||||
| mch_bone_drv_e.use_connect = False | flip_bone(self.obj, name) | ||||
| self.get_bone(name).length /= 2 | |||||
| return name | |||||
| @stage.parent_bones | |||||
| def parent_control_chain(self): | |||||
| ctrls = self.bones.ctrl.fk | |||||
| for args in zip(ctrls, self.bones.mch.bend + ctrls[-2:]): | |||||
| self.set_bone_parent(*args) | |||||
| @stage.configure_bones | |||||
| def configure_control_chain(self): | |||||
| for args in zip(count(0), self.bones.ctrl.fk, self.bones.org + [None]): | |||||
| self.configure_control_bone(*args) | |||||
| def configure_control_bone(self, i, ctrl, org): | |||||
| if org: | |||||
| self.copy_bone_properties(org, ctrl) | |||||
| else: | else: | ||||
| # The rest | bone = self.get_bone(ctrl) | ||||
| ctrl_bone_e.parent = mch_bone_drv_e | bone.lock_rotation_w = True | ||||
| ctrl_bone_e.use_connect = False | bone.lock_rotation = (True, True, True) | ||||
| bone.lock_scale = (True, True, True) | |||||
| def_bone_e.parent = eb[def_chain[i-1]] | |||||
| def_bone_e.use_connect = True | def make_control_widget(self, ctrl): | ||||
| if ctrl == self.bones.ctrl.fk[-1]: | |||||
| mch_bone_drv_e.parent = eb[ctrl_chain[i-1]] | # Tip control | ||||
| mch_bone_drv_e.use_connect = False | create_circle_widget(self.obj, ctrl, radius=0.3, head_tail=0.0) | ||||
| else: | |||||
| # Parenting mch bone | create_circle_widget(self.obj, ctrl, radius=0.3, head_tail=0.5) | ||||
| mch_bone_e.parent = ctrl_bone_e | |||||
| mch_bone_e.use_connect = False | |||||
| # Creating tip control bone | |||||
| tip_name = copy_bone(self.obj, org_bones[-1], temp_name) | |||||
| ctrl_bone_tip = eb[tip_name] | |||||
| flip_bone(self.obj, tip_name) | |||||
| ctrl_bone_tip.length /= 2 | |||||
| ctrl_bone_tip.parent = eb[ctrl_chain[-1]] | |||||
| bpy.ops.object.mode_set(mode='OBJECT') | |||||
| pb = self.obj.pose.bones | ############################## | ||||
| # MCH bend chain | |||||
| # Setting pose bones locks | @stage.generate_bones | ||||
| pb_master = pb[master_name] | def make_mch_bend_chain(self): | ||||
| pb_master.lock_scale = True, False, True | self.bones.mch.bend = map_list(self.make_mch_bend_bone, self.bones.org) | ||||
| pb[tip_name].lock_scale = True, True, True | def make_mch_bend_bone(self, org): | ||||
| pb[tip_name].lock_rotation = True, True, True | return self.copy_bone(org, make_derived_name(org, 'mch', '_drv'), parent=False) | ||||
| pb[tip_name].lock_rotation_w = True | |||||
| @stage.parent_bones | |||||
| make_property(pb_master, 'finger_curve', 0.0, description="Rubber hose finger cartoon effect") | def parent_mch_bend_chain(self): | ||||
| ctrls = self.bones.ctrl.fk | |||||
| # Pose settings | for args in zip(self.bones.mch.bend, [self.first_parent] + ctrls): | ||||
| for org, ctrl, deform, mch, mch_drv in zip(self.org_bones, ctrl_chain, def_chain, mch_chain, mch_drv_chain): | self.set_bone_parent(*args) | ||||
| # Constraining the deform bones | |||||
| con = pb[deform].constraints.new('COPY_TRANSFORMS') | |||||
| con.target = self.obj | |||||
| con.subtarget = mch | |||||
| # Constraining the mch bones | |||||
| if mch_chain.index(mch) == 0: | |||||
| con = pb[mch].constraints.new('COPY_LOCATION') | |||||
| con.target = self.obj | |||||
| con.subtarget = ctrl | |||||
| con = pb[mch].constraints.new('COPY_SCALE') | |||||
| con.target = self.obj | |||||
| con.subtarget = ctrl | |||||
| con = pb[mch].constraints.new('DAMPED_TRACK') | |||||
| con.target = self.obj | |||||
| con.subtarget = ctrl_chain[ctrl_chain.index(ctrl)+1] | |||||
| con = pb[mch].constraints.new('STRETCH_TO') | |||||
| con.target = self.obj | |||||
| con.subtarget = ctrl_chain[ctrl_chain.index(ctrl)+1] | |||||
| con.volume = 'NO_VOLUME' | |||||
| elif mch_chain.index(mch) == len(mch_chain) - 1: | |||||
| con = pb[mch].constraints.new('DAMPED_TRACK') | |||||
| con.target = self.obj | |||||
| con.subtarget = tip_name | |||||
| con = pb[mch].constraints.new('STRETCH_TO') | |||||
| con.target = self.obj | |||||
| con.subtarget = tip_name | |||||
| con.volume = 'NO_VOLUME' | |||||
| else: | |||||
| con = pb[mch].constraints.new('DAMPED_TRACK') | |||||
| con.target = self.obj | |||||
| con.subtarget = ctrl_chain[ctrl_chain.index(ctrl)+1] | |||||
| con = pb[mch].constraints.new('STRETCH_TO') | |||||
| con.target = self.obj | |||||
| con.subtarget = ctrl_chain[ctrl_chain.index(ctrl)+1] | |||||
| con.volume = 'NO_VOLUME' | |||||
| # Constraining and driving mch driver bones | |||||
| pb[mch_drv].rotation_mode = 'YZX' | |||||
| if mch_drv_chain.index(mch_drv) == 0: | |||||
| # Constraining to master bone | |||||
| con = pb[mch_drv].constraints.new('COPY_LOCATION') | |||||
| con.target = self.obj | |||||
| con.subtarget = master_name | |||||
| con = pb[mch_drv].constraints.new('COPY_ROTATION') | |||||
| con.target = self.obj | |||||
| con.subtarget = master_name | |||||
| con.target_space = 'LOCAL' | |||||
| con.owner_space = 'LOCAL' | |||||
| else: | |||||
| # Match axis to expression | # Match axis to expression | ||||
| options = { | axis_options = { | ||||
| "automatic": {"axis": 0, | "automatic": {"axis": 0, | ||||
| "expr": '(1-sy)*pi'}, | "expr": '(1-sy)*pi'}, | ||||
| "X": {"axis": 0, | "X": {"axis": 0, | ||||
| "expr": '(1-sy)*pi'}, | "expr": '(1-sy)*pi'}, | ||||
| "-X": {"axis": 0, | "-X": {"axis": 0, | ||||
| "expr": '-((1-sy)*pi)'}, | "expr": '-((1-sy)*pi)'}, | ||||
| "Y": {"axis": 1, | "Y": {"axis": 1, | ||||
| "expr": '(1-sy)*pi'}, | "expr": '(1-sy)*pi'}, | ||||
| "-Y": {"axis": 1, | "-Y": {"axis": 1, | ||||
| "expr": '-((1-sy)*pi)'}, | "expr": '-((1-sy)*pi)'}, | ||||
| "Z": {"axis": 2, | "Z": {"axis": 2, | ||||
| "expr": '(1-sy)*pi'}, | "expr": '(1-sy)*pi'}, | ||||
| "-Z": {"axis": 2, | "-Z": {"axis": 2, | ||||
| "expr": '-((1-sy)*pi)'} | "expr": '-((1-sy)*pi)'} | ||||
| } | } | ||||
| @stage.rig_bones | |||||
| def rig_mch_bend_chain(self): | |||||
| for args in zip(count(0), self.bones.mch.bend): | |||||
| self.rig_mch_bend_bone(*args) | |||||
| def rig_mch_bend_bone(self, i, mch): | |||||
| master = self.bones.ctrl.master | |||||
| if i == 0: | |||||
| self.make_constraint(mch, 'COPY_LOCATION', master) | |||||
| self.make_constraint(mch, 'COPY_ROTATION', master, space='LOCAL') | |||||
| else: | |||||
| axis = self.params.primary_rotation_axis | axis = self.params.primary_rotation_axis | ||||
| options = self.axis_options[axis] | |||||
| # Drivers | bone = self.get_bone(mch) | ||||
| drv = pb[mch_drv].driver_add("rotation_euler", options[axis]["axis"]).driver | bone.rotation_mode = 'YZX' | ||||
| drv.type = 'SCRIPTED' | |||||
| drv.expression = options[axis]["expr"] | |||||
| drv_var = drv.variables.new() | |||||
| drv_var.name = 'sy' | |||||
| drv_var.type = "SINGLE_PROP" | |||||
| drv_var.targets[0].id = self.obj | |||||
| drv_var.targets[0].data_path = pb[master_name].path_from_id() + '.scale.y' | |||||
| # Setting bone curvature setting, custom property, and drivers | |||||
| def_bone = self.obj.data.bones[deform] | |||||
| def_bone.bbone_segments = 8 | |||||
| drv = def_bone.driver_add("bbone_easein").driver # Ease in | |||||
| drv.type='SUM' | |||||
| drv_var = drv.variables.new() | |||||
| drv_var.name = "curvature" | |||||
| drv_var.type = "SINGLE_PROP" | |||||
| drv_var.targets[0].id = self.obj | |||||
| drv_var.targets[0].data_path = pb_master.path_from_id() + '["finger_curve"]' | |||||
| drv = def_bone.driver_add("bbone_easeout").driver # Ease out | |||||
| drv.type='SUM' | |||||
| drv_var = drv.variables.new() | |||||
| drv_var.name = "curvature" | |||||
| drv_var.type = "SINGLE_PROP" | |||||
| drv_var.targets[0].id = self.obj | |||||
| drv_var.targets[0].data_path = pb_master.path_from_id() + '["finger_curve"]' | |||||
| # Assigning shapes to control bones | self.make_driver( | ||||
| create_circle_widget(self.obj, ctrl, radius=0.3, head_tail=0.5) | bone, 'rotation_euler', index=options['axis'], | ||||
| expression=options['expr'], | |||||
| variables={'sy': (master, '.scale.y')} | |||||
| ) | |||||
| ############################## | |||||
| # MCH stretch chain | |||||
| @stage.generate_bones | |||||
| 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): | |||||
| return self.copy_bone(org, make_derived_name(org, 'mch'), parent=False) | |||||
| @stage.parent_bones | |||||
| def parent_mch_stretch_chain(self): | |||||
| ctrls = self.bones.ctrl.fk | |||||
| for args in zip(self.bones.mch.stretch, [self.first_parent] + ctrls[1:]): | |||||
| self.set_bone_parent(*args) | |||||
| @stage.rig_bones | |||||
| def rig_mch_stretch_chain(self): | |||||
| ctrls = self.bones.ctrl.fk | |||||
| for args in zip(count(0), self.bones.mch.stretch, ctrls, ctrls[1:]): | |||||
| self.rig_mch_stretch_bone(*args) | |||||
| # Create ctrl master widget | def rig_mch_stretch_bone(self, i, mch, ctrl, ctrl_next): | ||||
| w = create_widget(self.obj, master_name) | if i == 0: | ||||
| if w is not None: | self.make_constraint(mch, 'COPY_LOCATION', ctrl) | ||||
| mesh = w.data | self.make_constraint(mch, 'COPY_SCALE', ctrl) | ||||
| verts = [(0, 0, 0), (0, 1, 0), (0.05, 1, 0), (0.05, 1.1, 0), (-0.05, 1.1, 0), (-0.05, 1, 0)] | |||||
| if 'Z' in self.params.primary_rotation_axis: | self.make_constraint(mch, 'DAMPED_TRACK', ctrl_next) | ||||
| # Flip x/z coordinates | self.make_constraint(mch, 'STRETCH_TO', ctrl_next, volume='NO_VOLUME') | ||||
| temp = [] | |||||
| for v in verts: | ############################## | ||||
| temp += [(v[2], v[1], v[0])] | # ORG chain | ||||
| verts = temp | |||||
| edges = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 1)] | |||||
| mesh.from_pydata(verts, edges, []) | |||||
| mesh.update() | |||||
| # Create tip control widget | @stage.rig_bones | ||||
| create_circle_widget(self.obj, tip_name, radius=0.3, head_tail=0.0) | def rig_org_chain(self): | ||||
| for args in zip(count(0), self.bones.org, self.bones.mch.stretch): | |||||
| self.rig_org_bone(*args) | |||||
| ############################## | |||||
| # Deform chain | |||||
| @stage.configure_bones | |||||
| def configure_master_properties(self): | |||||
| master = self.bones.ctrl.master | |||||
| self.make_property(master, 'finger_curve', 0.0, description="Rubber hose finger cartoon effect") | |||||
| # Create UI | # Create UI | ||||
| controls_string = ", ".join( | panel = self.script.panel_with_selected_check(self, self.bones.ctrl.flatten()) | ||||
| ["'" + x + "'" for x in ctrl_chain] | panel.custom_prop(master, 'finger_curve', text="Curvature", slider=True) | ||||
| ) + ", " + "'" + master_name + "'" | |||||
| return [script % (controls_string, master_name, 'finger_curve')] | def rig_deform_bone(self, i, deform, org): | ||||
| master = self.bones.ctrl.master | |||||
| bone = self.get_bone(deform) | |||||
| self.make_constraint(deform, 'COPY_TRANSFORMS', org) | |||||
| def add_parameters(params): | self.make_driver(bone.bone, 'bbone_easein', variables=[(master, 'finger_curve')]) | ||||
| self.make_driver(bone.bone, 'bbone_easeout', variables=[(master, 'finger_curve')]) | |||||
| ############### | |||||
| # OPTIONS | |||||
| @classmethod | |||||
| def add_parameters(self, params): | |||||
| """ Add the parameters of this rig type to the | """ Add the parameters of this rig type to the | ||||
| RigifyParameters PropertyGroup | RigifyParameters PropertyGroup | ||||
| """ | """ | ||||
| items = [('automatic', 'Automatic', ''), ('X', 'X manual', ''), ('Y', 'Y manual', ''), ('Z', 'Z manual', ''), | items = [('automatic', 'Automatic', ''), ('X', 'X manual', ''), ('Y', 'Y manual', ''), ('Z', 'Z manual', ''), | ||||
| ('-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.primary_rotation_axis = bpy.props.EnumProperty(items=items, name="Primary Rotation Axis", default='automatic') | ||||
| @classmethod | |||||
| def parameters_ui(layout, params): | def parameters_ui(self, layout, params): | ||||
| """ Create the ui for the rig parameters. | """ Create the ui for the rig parameters. | ||||
| """ | """ | ||||
| r = layout.row() | r = layout.row() | ||||
| r.label(text="Bend rotation axis:") | r.label(text="Bend rotation axis:") | ||||
| r.prop(params, "primary_rotation_axis", text="") | r.prop(params, "primary_rotation_axis", text="") | ||||
| def create_sample(obj): | def create_sample(obj): | ||||
| # generated by rigify.utils.write_metarig | # generated by rigify.utils.write_metarig | ||||
| bpy.ops.object.mode_set(mode='EDIT') | bpy.ops.object.mode_set(mode='EDIT') | ||||
| arm = obj.data | arm = obj.data | ||||
| bones = {} | bones = {} | ||||
| ▲ Show 20 Lines • Show All 82 Lines • Show Last 20 Lines | |||||