#!BPY """ Name: 'Rig-a-ma-rule' Blender: 248 Group: 'Object' Tooltip: 'Applies bone rules defined via python rules.py to a rig' """ __author__ = "Bassam Kurdali" __url__ = ["freefac.org", "tube.freefac.org"] __version__ = "0.1" __bpydoc__ = """\ Rig-a-ma-rule Applies bone rules defined via python rules.py to a rig rules.py is a dummy, targetless pyconstraint that attaches idprops to bones marulez.py is a python file that contains all the rules """ # -------------------------------------------------------------------------- # ***** BEGIN GPL LICENSE BLOCK ***** # # Script copyright (C) Bassam Kurdali # # 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # ***** END GPL LICENCE BLOCK ***** # -------------------------------------------------------------------------- # copyright 2009 Bassam Kurdali # thanks to Martin Poirier for code reviews, fixes and advice import Blender from Blender import Armature from Blender.Mathutils import * import marulez reload(marulez) Lefts = [".LEFT",".Left",".left",".lft",".LFT",".Lft",".L",".l"] Rights = [".RIGHT",".Right",".right",".rgt",".RGT",".Rgt",".R",".r"] targetmap = ["target1","target2","target3"] rulemap= ["eval","method","mypart","target1","target2","target3","tarpart","Xval","Yval","Zval"] PYCON = Blender.Constraint.Type["PYTHON"] PYTYP = Blender.Constraint.Settings["SCRIPT"] PROPS = Blender.Constraint.Settings["PROPERTIES"] ID = Blender.Text.get("boneID.py") RULE = Blender.Text.get("rule.py") def apply_rules(arm_dat,arm_pose,bone_type) : ''' apply_rules applys the ruls to the bones with the right bone_type arm_dat is armature data arm_pose is armature posedata bone_type is a string, can be "georule.py" for geobones or "rule.py" for other bones. ''' global PYCON, PYTYP, PROPS, ID, RULE, targetmap, rulemap callMethod = {} for ook in [ook for ook in dir(marulez) if "RULE" in ook] : callMethod[ook.replace("RULE","")] = marulez.__dict__[ook] #build our lists of bones to evaluate/targets in pose mode rulebones={} for bone_name in arm_pose.bones.keys() : for fake_constraint in arm_pose.bones[bone_name].constraints : if fake_constraint.type == PYCON and bone_type in fake_constraint[PYTYP].name: rules={} for key in rulemap: rules[key] = fake_constraint[PROPS][key] if bone_name not in rulebones: blank=[] rulebones[bone_name] = blank rulebones[bone_name].append(rules) if bone_name in rulebones: #we should sort our little list. deco=[ (rule["eval"],i, rule) for i, rule in enumerate(rulebones[bone_name]) ] deco.sort() rulebones[bone_name] = [ rule for _, _, rule in deco ] print rulebones[bone_name] print "" print "" deco = [ (rules[0]["eval"],bone_name,rules) for bone_name, rules in rulebones.iteritems() ] deco.sort() rulelist = [ (bone_name,rules) for _, bone_name,rules in deco] #actually apply the rules in edit mode arm_dat.makeEditable() for bone_name, rules in rulelist : # print "bone: ",bone_name # print " rules: " bone = arm_dat.bones[bone_name] for ruledict in rules : targets = [] if ruledict["target1"]: targets.append(arm_dat.bones[ruledict["target1"]]) if ruledict["target2"]: targets.append(arm_dat.bones[ruledict["target2"]]) if ruledict["target3"]: targets.append(arm_dat.bones[ruledict["target3"]]) # print ruledict["method"] callMethod[ruledict["method"]](bone,ruledict["mypart"],targets,ruledict["tarpart"],Vector([ruledict["Xval"],ruledict["Yval"],ruledict["Zval"]])) # print "" arm_dat.update() return def demangle(arm_pose): global PYCON, PYTYP, PROPS, ID, RULE, targetmap SIDE = '&S' NO = '&N' for bone_name in arm_pose.bones.keys(): bone = arm_pose.bones[bone_name] map_names={} pycons = [ const for const in bone.constraints if const.type == PYCON] for const in pycons: if const[PYTYP] == ID : template_name = const[PROPS]['user_template'] uid = const[PROPS]['user_uid'] if uid != bone_name: #means there was some replacement #replace &s and &n with the right targets side_index = uid.find(SIDE) no_index = uid.find(NO) if side_index > 0: multi= uid.partition(SIDE) multiL=[] if no_index > 0: #do stuff for substr in multi: if substr.find(NO) > 0: multiL.extend(substr.partition(NO)) else: multiL.append(substr) special = bone_name[:] for substr in multiL : if substr != SIDE and substr != NO: special = special.replace(substr,"") side = special.strip('0123456789') no = special.replace(side,"") map_names[NO] = no map_names[SIDE] = side if map_names : for const in pycons: if const[PYTYP] == RULE: for key in targetmap: if const[PROPS][key] : const[PROPS][key] = const[PROPS][key].replace(SIDE,map_names[SIDE]) const[PROPS][key] = const[PROPS][key].replace(NO,map_names[NO]) arm_pose.update() return def sided(string): global Lefts,Rights for a in Lefts: if a in string: return (-1) for a in Rights: if a in string: return (+1) return(0) def flipside(string): global Lefts, Rights for index, side in enumerate(Lefts) : if side in string: return (string.replace(side,Rights[index])) for index, side in enumerate(Rights): if side in string: return (string.replace(side,Lefts[index])) return (string) def sidefx(arm_pose): global PYCON, PYTYP, PROPS, RULE, targetmap, Lefts, Rights for bone_name in arm_pose.bones.keys(): myside = sided(bone_name) if myside != 0: bone = arm_pose.bones[bone_name] pycons = [ const for const in bone.constraints if const.type == PYCON ] for const in pycons: if const[PYTYP] == RULE: for target in targetmap: targetside = sided(const[PROPS][target]) if targetside !=0 and targetside != myside : const[PROPS][target] = flipside (const[PROPS][target]) def main(): DEMANGLE = Blender.Draw.Create(0) SIDECHEK = Blender.Draw.Create(0) pup_block =[\ ('Etchafix', DEMANGLE, 'Press if you just used etchaton to retarget'), ('Fix L/R', SIDECHEK, 'Press if you just mirrored and need to fix rules') ] if not Blender.Draw.PupBlock('Retarget Rig:', pup_block): return DEMANGLE = DEMANGLE.val SIDECHEK = SIDECHEK.val scn = Blender.Scene.GetCurrent() arm_ob = scn.objects.active if arm_ob.type == "Armature": arm_dat = arm_ob.getData() arm_pose = arm_ob.getPose() if DEMANGLE: demangle(arm_pose) if SIDECHEK: sidefx(arm_pose) apply_rules(arm_dat,arm_pose,"rule.py") if __name__ == '__main__': main()