def create_ik_targets(self, bones): # Bug with iTaSC! cf http://developer.blender.org/T37894 if bpymorse.version() < (2, 70, 0): if self._bpy_object.pose.ik_solver == 'ITASC': logger.warn("Due to a bug in Blender (T37894), only the standard " \ "IK solver can be used with IK targets. Switching " \ "from iTaSC to standard IK solver.") self._bpy_object.pose.ik_solver = 'LEGACY' for target in bones: posebone = self._get_posebone(target) bpymorse.add_morse_empty("ARROWS") empty = bpymorse.get_first_selected_object() empty.scale = [0.01, 0.01, 0.01] empty.matrix_local = posebone.bone.matrix_local empty.location = posebone.bone.tail_local existing_ik = [c for c in posebone.constraints if c.type == 'IK'] if len(existing_ik) == 1: ik_constraint = existing_ik[0] elif existing_ik: raise MorseBuilderError("Bone %s has several IK constraints." \ "MORSE supports only one IK constraint per bone. Please " \ "remove other ones.") else: ik_constraint = posebone.constraints.new("IK") ik_constraint.ik_type = "DISTANCE" ik_constraint.use_rotation = True ik_constraint.use_tail = True ik_constraint.target = empty self.ik_targets.append((empty, target))
def _get_posebone(self, bone_name): """ Returns a given PoseBone in the armature. If the joint does not exist, throw an exception. """ armature = self._bpy_object if bone_name not in [c.name for c in armature.pose.bones]: msg = "Joint <%s> does not exist in model %s." % (bone_name, armature.name) msg += " Did you add a skeleton to your model in MakeHuman?" raise MorseBuilderError(msg) return armature.pose.bones[bone_name]
def append(self, obj, child=None, level=1): """ Add a child to the current object Add the object given as an argument as a child of this object. The argument is an instance to another component. This method is generally used to add components to a robot. *e.g.*, : robot.append(sensor), will set the robot parent of the sensor. If child is not None, the object will be parented to the named child of self instead of the root of self. """ obj._bpy_object.matrix_parent_inverse.identity() if child: _child = self.get_child(child) if _child: obj._bpy_object.parent = _child else: raise MorseBuilderError("No such child %s" % child) else: obj._bpy_object.parent = self._bpy_object obj.parent = self self.children.append(obj) import inspect try: frame = inspect.currentframe() builderscript_frame = inspect.getouterframes(frame)[level][ 0] # parent frame cmpts = builderscript_frame.f_locals if "self" in cmpts: #some silly guy decided to write a class to describe a silly robot tmp = copy.copy(cmpts["self"].__dict__) tmp.update(cmpts) cmpts = tmp for name, component in cmpts.items(): if component == obj: if not component.basename: # do automatic renaming only if a name is not already manually set component.basename = name finally: del builderscript_frame del frame
def __init__(self, name=None, armature_name=None, model_name=None): """ Initialize an armature Either `armature_name` or `model_name` or both must be specified. :param armature_name: Armature object name :param model_name: Armature model name, if any """ if not armature_name and not model_name: raise MorseBuilderError("You need to specify either the name of " \ "an armature or a Blender model in order to create an " \ "armature actuator.") if model_name: ActuatorCreator.__init__(self, name, action=ComponentCreator.USE_BLEND, blendfile=model_name, blendobject=armature_name, make_morseable=True) else: ActuatorCreator.__init__( self, name, action=ComponentCreator.LINK_EXISTING_OBJECT, blendobject=armature_name, make_morseable=True) self.ik_targets = [] # the user may have created IK constraints on the armature, without # setting an IK target. In that case, we add such a target for bone in self._bpy_object.pose.bones: for c in bone.constraints: if c.type == 'IK' and c.ik_type == 'DISTANCE': if not c.target: self.create_ik_targets([bone.name])