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 ik = posebone.constraints.new("IK") ik.use_rotation = True ik.use_tail = True ik.target = empty self.ik_targets.append((empty, target))
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 append_scenes(self, component=None): component = component or self._blender_filename filepath = self._compute_filepath(component) scenes = bpymorse.get_scenes_in_blend(filepath) # Format the objects list to append sclist = [{"name": sc} for sc in scenes] bpymorse.deselect_all() # Append the objects to the scene, and (auto)select them if bpymorse.version() >= (2, 71, 6): bpymorse.append(directory=filepath + "/Scene/", autoselect=True, files=sclist) else: bpymorse.link_append(directory=filepath + "/Scene/", link=False, autoselect=True, files=sclist)
def append_meshes(self, objects=None, component=None, prefix=None): """ Append the objects to the scene The ``objects`` are located either in: MORSE_COMPONENTS/``self._category``/``component``.blend/Object/ or in: MORSE_RESOURCE_PATH/``component``/Object/ If `component` is not set (neither as argument of `append_meshes` nor through the :py:class:`AbstractComponent` constructor), a Blender `Empty` is created instead. :param objects: list of the objects names to append :param component: component in which the objects are located :param prefix: filter the objects names to append (used by PassiveObject) :return: list of the imported (selected) Blender objects """ component = component or self._blender_filename if not component: # no Blender resource: simply create an empty bpymorse.deselect_all() bpymorse.add_morse_empty() return [bpymorse.get_first_selected_object()] filepath = self._compute_filepath(component) if not objects: # append all objects from blend file objects = bpymorse.get_objects_in_blend(filepath) if prefix: # filter (used by PassiveObject) objects = [obj for obj in objects if obj.startswith(prefix)] # Format the objects list to append objlist = [{"name": obj} for obj in objects] bpymorse.deselect_all() # Append the objects to the scene, and (auto)select them if bpymorse.version() >= (2, 71, 6): bpymorse.append(directory=filepath + "/Object/", autoselect=True, files=objlist) else: bpymorse.link_append(directory=filepath + "/Object/", link=False, autoselect=True, files=objlist) return bpymorse.get_selected_objects()
def append_scenes(self, component=None): component = component or self._blender_filename filepath = self._compute_filepath(component) scenes = bpymorse.get_scenes_in_blend(filepath) # Format the objects list to append sclist = [{'name': sc} for sc in scenes] bpymorse.deselect_all() # Append the objects to the scene, and (auto)select them if bpymorse.version() >= (2, 71, 6): bpymorse.append(directory=filepath + '/Scene/', autoselect=True, files=sclist) else: bpymorse.link_append(directory=filepath + '/Scene/', link=False, autoselect=True, files=sclist)
def append_meshes(self, objects=None, component=None, prefix=None): """ Append the component's Blender objects to the scene The ``objects`` are located either in: MORSE_COMPONENTS/``self._category``/``component``.blend/Object/ or in: MORSE_RESOURCE_PATH/``component``/Object/ If `component` is not set (neither as argument of `append_meshes` nor through the :py:class:`AbstractComponent` constructor), a Blender `Empty` is created instead. .. note:: By default, all the objects present in the component's blend file are imported. If you need to exclude some (like lights you may have in your blend file), prefix the name of this objects with ``_`` so that MORSE ignores them. :param objects: list of the objects names to append :param component: component in which the objects are located :param prefix: filter the objects names to append (used by PassiveObject) :return: list of the imported (selected) Blender objects """ component = component or self._blender_filename if not component: # no Blender resource: simply create an empty bpymorse.deselect_all() bpymorse.add_morse_empty() return [ bpymorse.get_first_selected_object(), ] filepath = self._compute_filepath(component) if not objects: # append all objects from blend file objects = bpymorse.get_objects_in_blend(filepath) filtered_objects = objects # ignore objects starting with '_' filtered_objects = [obj for obj in objects if not obj.startswith('_')] if prefix: # filter (used by PassiveObject) filtered_objects = [ obj for obj in filtered_objects if obj.startswith(prefix) ] logger.info("Importing objects from %s: %s" % (filepath, str(objects))) excluded = set(objects) - set(filtered_objects) if excluded: logger.info("(excluding %s)" % str(list(excluded))) # Format the objects list to append objlist = [{'name': obj} for obj in filtered_objects] bpymorse.deselect_all() # Append the objects to the scene, and (auto)select them if bpymorse.version() >= (2, 71, 6): bpymorse.append(directory=filepath + '/Object/', autoselect=True, files=objlist) else: bpymorse.link_append(directory=filepath + '/Object/', link=False, autoselect=True, files=objlist) return bpymorse.get_selected_objects()
def _set_sensor_frequency(self, sensor, delay): if bpymorse.version() >= (2, 74, 5): sensor.tick_skip = delay else: sensor.frequency = delay
def append_meshes(self, objects=None, component=None, prefix=None): """ Append the objects to the scene The ``objects`` are located either in: MORSE_COMPONENTS/``self._category``/``component``.blend/Object/ or in: MORSE_RESOURCE_PATH/``component``/Object/ If `component` is not set (neither as argument of `append_meshes` nor through the :py:class:`AbstractComponent` constructor), a Blender `Empty` is created instead. :param objects: list of the objects names to append :param component: component in which the objects are located :param prefix: filter the objects names to append (used by PassiveObject) :return: list of the imported (selected) Blender objects """ component = component or self._blender_filename if not component: # no Blender resource: simply create an empty bpymorse.deselect_all() bpymorse.add_morse_empty() return [bpymorse.get_first_selected_object(),] if component.endswith('.blend'): filepath = os.path.abspath(component) # external blend file else: filepath = os.path.join(MORSE_COMPONENTS, self._category, component + '.blend') looked_dirs = [filepath] if not os.path.exists(filepath): # Search for some blend file in different paths filepath = None resource_path = MORSE_RESOURCE_PATH.split(os.pathsep) for path in resource_path: tmp = os.path.join(path, component) looked_dirs.append(tmp) if os.path.exists(tmp): filepath = tmp break # Check if we got a match if not filepath: logger.error("Error while trying to load '%s': model not found.\n" "I was looking for one of these files: \n%s\n" "Either provide an absolute path, or a path relative \n" "to MORSE assets directories ($MORSE_RESOURCE_PATH \n" "or default path, typically $PREFIX/share/morse/data)."% (component, looked_dirs)) raise FileNotFoundError("%s '%s' not found"%(self.__class__.__name__, component)) if not objects: # append all objects from blend file objects = bpymorse.get_objects_in_blend(filepath) if prefix: # filter (used by PassiveObject) objects = [obj for obj in objects if obj.startswith(prefix)] # Format the objects list to append objlist = [{'name':obj} for obj in objects] bpymorse.deselect_all() # Append the objects to the scene, and (auto)select them if bpymorse.version() >= (2, 71, 6): bpymorse.append(directory=filepath + '/Object/', autoselect=True, files=objlist) else: bpymorse.link_append(directory=filepath + '/Object/', link=False, autoselect=True, files=objlist) return bpymorse.get_selected_objects()
def append_meshes(self, objects=None, component=None, prefix=None): """ Append the component's Blender objects to the scene The ``objects`` are located either in: MORSE_COMPONENTS/``self._category``/``component``.blend/Object/ or in: MORSE_RESOURCE_PATH/``component``/Object/ If `component` is not set (neither as argument of `append_meshes` nor through the :py:class:`AbstractComponent` constructor), a Blender `Empty` is created instead. .. note:: By default, all the objects present in the component's blend file are imported. If you need to exclude some (like lights you may have in your blend file), prefix the name of this objects with ``_`` so that MORSE ignores them. :param objects: list of the objects names to append :param component: component in which the objects are located :param prefix: filter the objects names to append (used by PassiveObject) :return: list of the imported (selected) Blender objects """ component = component or self._blender_filename if not component: # no Blender resource: simply create an empty bpymorse.deselect_all() bpymorse.add_morse_empty() return [bpymorse.get_first_selected_object(),] filepath = self._compute_filepath(component) if not objects: # append all objects from blend file objects = bpymorse.get_objects_in_blend(filepath) filtered_objects = objects # ignore objects starting with '_' filtered_objects = [obj for obj in objects if not obj.startswith('_')] if prefix: # filter (used by PassiveObject) filtered_objects = [obj for obj in filtered_objects if obj.startswith(prefix)] logger.info("Importing objects from %s: %s" % (filepath, str(objects))) excluded = set(objects) - set(filtered_objects) if excluded: logger.info("(excluding %s)" % str(list(excluded))) # Format the objects list to append objlist = [{'name':obj} for obj in filtered_objects] bpymorse.deselect_all() # Append the objects to the scene, and (auto)select them if bpymorse.version() >= (2, 71, 6): bpymorse.append(directory=filepath + '/Object/', autoselect=True, files=objlist) else: bpymorse.link_append(directory=filepath + '/Object/', link=False, autoselect=True, files=objlist) return bpymorse.get_selected_objects()
def append_meshes(self, objects=None, component=None, prefix=None): """ Append the objects to the scene The ``objects`` are located either in: MORSE_COMPONENTS/``self._category``/``component``.blend/Object/ or in: MORSE_RESOURCE_PATH/``component``/Object/ If `component` is not set (neither as argument of `append_meshes` nor through the :py:class:`AbstractComponent` constructor), a Blender `Empty` is created instead. :param objects: list of the objects names to append :param component: component in which the objects are located :param prefix: filter the objects names to append (used by PassiveObject) :return: list of the imported (selected) Blender objects """ component = component or self._blender_filename if not component: # no Blender resource: simply create an empty bpymorse.deselect_all() bpymorse.add_morse_empty() return [ bpymorse.get_first_selected_object(), ] if component.endswith('.blend'): filepath = os.path.abspath(component) # external blend file else: filepath = os.path.join(MORSE_COMPONENTS, self._category, component + '.blend') looked_dirs = [filepath] if not os.path.exists(filepath): # Search for some blend file in different paths filepath = None resource_path = MORSE_RESOURCE_PATH.split(os.pathsep) for path in resource_path: tmp = os.path.join(path, component) looked_dirs.append(tmp) if os.path.exists(tmp): filepath = tmp break # Check if we got a match if not filepath: logger.error( "Error while trying to load '%s': model not found.\n" "I was looking for one of these files: \n%s\n" "Either provide an absolute path, or a path relative \n" "to MORSE assets directories ($MORSE_RESOURCE_PATH \n" "or default path, typically $PREFIX/share/morse/data)." % (component, looked_dirs)) raise FileNotFoundError("%s '%s' not found" % (self.__class__.__name__, component)) if not objects: # append all objects from blend file objects = bpymorse.get_objects_in_blend(filepath) if prefix: # filter (used by PassiveObject) objects = [obj for obj in objects if obj.startswith(prefix)] # Format the objects list to append objlist = [{'name': obj} for obj in objects] bpymorse.deselect_all() # Append the objects to the scene, and (auto)select them if bpymorse.version() >= (2, 71, 6): bpymorse.append(directory=filepath + '/Object/', autoselect=True, files=objlist) else: bpymorse.link_append(directory=filepath + '/Object/', link=False, autoselect=True, files=objlist) return bpymorse.get_selected_objects()