def _input_check(name, mode): assert mode in (None, 'all') assert isinstance(name, (str, list)) or name is None assert not (mode == 'all' and name is None) regex_flag = False regex = re.compile('[.^$*+}{|)(]') if isinstance(name, str): if regex.search(name) is not None: # not a normal string name = env.Props().search(name) regex_flag = True if isinstance(name, list): # if name is a list of regular expressions checked_name = [] for this_name in name: if regex.search(this_name) is not None: checked_name += env.Props().search(this_name) regex_flag = True else: checked_name += [this_name] name = list(np.unique(checked_name)) name = [n for n in name if '/' not in n] if len(name) == 1: name = name[0] return name, mode, regex_flag
def readattr(names, frames=1, attrs='location', fname=False, sheet_name='animation', columns=('object', 'keyframe', 'attribute', 'value')): """ Get location and rotation information of mesh objects from the current blender scene. Created to save weight in and weight out nutational positions of bones. Generalizes to saving location and rotation information for any mesh objects. Inputs: names: list of names in the blender file, ['Foot_R', 'Leg_R', 'Spine'] each 'name' can be a blender collection, a parent object (empty), or the name of an object itself frames: keyframe numbers in the blender scene to grab location and rotation information from attrs: list of attributes ['location', 'rotation_euler', 'scale'] fname: target file name 'somefile.xlsx' Returns: p: a pandas dataframe containing the name of the mesh, keyframe, location and rotation vectors To save contents to an excel file, supply strings to fname, and sheet_name variables Example: (load skeletalSystem.blend in blender) fname = 'D:\\Workspace\\blenderPython\\apps\\anatomy\\nutations.xlsx' p2 = bpn.io.readattr('Skeletal_Sys', [1, 100], ['location', 'rotation_euler'], fname) """ if isinstance(names, str): names = [names] # convert to list if a string is passed if isinstance(frames, int): frames = [frames] if isinstance(attrs, str): attrs = [attrs] # make sure names has only valid things in it names = [i for i in names if env.Props()(i)] p = [] for frame in frames: bpy.context.scene.frame_set(frame) for name in names: thisProp = env.Props().get(name)[0] if isinstance(thisProp, bpy.types.Collection): all_objects = bpy.data.collections[name].all_objects elif isinstance(thisProp, bpy.types.Object): all_objects = env.Props().get_children(name) all_objects = [o for o in all_objects if o.type == 'MESH'] for obj in all_objects: for attr in attrs: p.append([obj.name, frame, attr, list(getattr(obj, attr))]) p = pd.DataFrame(p, columns=list(columns)) if isinstance(fname, str): p.to_excel(fname, index=False, sheet_name=sheet_name) return p
def get_obj_list(obj_name): prop_list = env.Props().get(obj_name) if len(prop_list) > 1: # multiple props detected, only keep objects prop_list = [ o for o in prop_list if isinstance(o, bpy.types.Object) ] return prop_list
def __init__(self, rig_name='CircularRig', size=0.20): assert not env.Props().get(rig_name) super().__init__(rig_name) self.rig_name = rig_name self.size = size self.targ = empty('target', 'SPHERE', size=self.size, coll_name=self.rig_name) self.targ.scl = size cam = core.Thing('Camera', 'Camera') self.camera = ObjectOnCircle(cam, self.rig_name, 2, self.size, self.targ) self.camera.scl = size key_light = core.Thing('Key', 'Light', 'SUN', energy=2.5, angle=0.2, color=(1., 1., 1.)) self.key_light = ObjectOnCircle(key_light, self.rig_name, 2.5, self.size, self.targ) fill_light = core.Thing('Fill', 'Light', 'SUN', energy=0.2, angle=0.2, color=(1., 1., 1.)) self.fill_light = ObjectOnCircle(fill_light, self.rig_name, 3, self.size, self.targ) back_light = core.Thing('Back', 'Light', 'SPOT', energy=15, spot_size=np.pi/6, spot_blend=0.15, shadow_soft_size=0.1, color=(1., 1., 1.)) self.back_light = ObjectOnCircle(back_light, self.rig_name, 5, self.size, self.targ) self.key_light.theta = self.camera.theta - np.pi/4 self.fill_light.theta = self.camera.theta + np.pi/3 self.back_light.theta = self.camera.theta + 5*np.pi/6 self.key_light.center = (0, 0, 0.15) self.fill_light.center = (0, 0, 0.15) self.back_light.center = (0, 0, 1)
def _get_one_with_name(name): """Returns one dispatched object.""" all_items = env.Props().get(name) if all_items: # at least one item found all_obj_items = [ item for item in all_items if type(item).__name__ == priority ] if all_obj_items: # one of the items was object item return enhance(all_obj_items[0]) return enhance(all_items[0]) print('No prop found with name: ' + name) return []
The coordinate frame in which articulation center is specified (specifies the frame in world coordinates) :param articulation angle: (radians) how much to articulate that joint """ for tkf in range(1, n_keyframes): articulation_center = trf.PointCloud( articulation_center_rel, articulation_center_frames[tkf]).in_world().co[0, :] progress = (tkf / n_keyframes)**1 q = trf.Quat([1, 0, 0], articulation_angle * progress, trf.CoordFrame(origin=articulation_center)) for b in bones: all_frames[b.name][tkf] = q * all_frames[b.name][tkf] # get all leg bones from the right leg leg_bones = env.Props().get_children('Leg_Bones_R') leg_bones = [utils.enhance(b) for b in leg_bones] # Initialize coordinate frames for every keyframe for every bone all_frames = {} for bone in leg_bones: all_frames[bone.name] = {} for kf in range(n_keyframes): all_frames[bone.name][kf] = bone.frame # original frame # apply transformation around the hip joint exc_list = ['Ilium_R'] bone_list = [b for b in leg_bones if b.name not in exc_list] _transform_bones(bone_list, hip_articulation_center_rel_ilium, all_frames['Ilium_R'], hip_articulation_angle)
def get(name=None, mode=None, priority='Object'): """ Dispatcher for the bpn module. Takes as input the name of a prop in the blender environment. Returns a 'wrapped' version of the object. MESH bpy.types.Object - core.MeshObject Other bpy.types.Object - core.Object Prop in bpy.data.* - core.Thing bpn.obj('sphere') :param obj_name: (str) name of the object in blender's environment :param mode: (None, 'all') if 'all', returns all things with the name (priority given to objects) If there are objects and curves with the same name, then use utils.get(['x_label', 'y_label'], priority='Curve') to get the curves utils.get(['x_label', 'y_label']) to get the objects utils.get(['x_label', 'y_label'], 'all') to get both objects and curves Regular expressions: (With regular expression input, generic 'Thing' objects are filtered out.) utils.get('abe.*') to get all objects that contain 'abe' utils.get('abe.*', 'all') to get all items that contain 'abe' utils.get('^z') to get things starting with 'z' utils.get('^z') to get things ending with '_R' utils.get(['^my', '_R$']) to get things starting with my OR ending with '_R$' Return all objects of a certain type: utils.get('collections') """ def _input_check(name, mode): assert mode in (None, 'all') assert isinstance(name, (str, list)) or name is None assert not (mode == 'all' and name is None) regex_flag = False regex = re.compile('[.^$*+}{|)(]') if isinstance(name, str): if regex.search(name) is not None: # not a normal string name = env.Props().search(name) regex_flag = True if isinstance(name, list): # if name is a list of regular expressions checked_name = [] for this_name in name: if regex.search(this_name) is not None: checked_name += env.Props().search(this_name) regex_flag = True else: checked_name += [this_name] name = list(np.unique(checked_name)) name = [n for n in name if '/' not in n] if len(name) == 1: name = name[0] return name, mode, regex_flag def _get_one_with_name(name): """Returns one dispatched object.""" all_items = env.Props().get(name) if all_items: # at least one item found all_obj_items = [ item for item in all_items if type(item).__name__ == priority ] if all_obj_items: # one of the items was object item return enhance(all_obj_items[0]) return enhance(all_items[0]) print('No prop found with name: ' + name) return [] def _get_all_with_name(name): """Returns a list of dispatched objects (even if there is only one).""" assert isinstance(name, str) return [ enhance(item) for item in env.Props().get(name) if enhance(item) ] def _dispatcher(name, mode): if mode is None and name is None: # no inputs given, return the last object return _get_one_with_name([o.name for o in bpy.data.objects][-1]) if mode is None and isinstance(name, str): # return one object return _get_one_with_name(name) if mode is None and isinstance(name, list): return [_get_one_with_name(this_name) for this_name in name] if mode == 'all' and isinstance(name, str): return _get_all_with_name(name) if mode == 'all' and isinstance( name, list): # here for completeness, don't recommend using it ret_list = [] for this_name in name: ret_list += _get_all_with_name(this_name) return ret_list return [] # In theory, this statement should never be reached if isinstance( name, str ) and name in env.PROP_FIELDS: # special case: return all items of a given type return [enhance(t) for t in env.Props()(return_empty=True)[name]] name, mode, regex_flag = _input_check(name, mode) ret_list = _dispatcher(name, mode) if regex_flag and isinstance(ret_list, list): ret_list = [o for o in ret_list if o.__class__.__name__ != 'Thing'] if len(ret_list) == 1: # after filtering, there was only one element ret_list = ret_list[0] return ret_list
def _get_all_with_name(name): """Returns a list of dispatched objects (even if there is only one).""" assert isinstance(name, str) return [ enhance(item) for item in env.Props().get(name) if enhance(item) ]