def execute(self, context): if self.bones: bones = eval(self.bones) else: bones = Get.selected_pose_bones(context) if not bones: return {'CANCELLED'} wgts = readWidgets() if self.widget: widget = wgts[self.widget] else: widget = wgts[context.scene.widget_list] for bone in bones: if bone.id_data.proxy: continue slide = list(self.slide) rotate = list(self.rotate) if self.mirror: mirror = findMirrorObject(bone) if mirror and mirror in bones and bone.name.endswith( ('L', 'l')): slide[0] *= -1 rotate[1] *= -1 rotate[2] *= -1 createWidget( context, bone, widget, self.relative_size, self.global_size, [*self.scale], slide, rotate, get_collection(context), ) utils.update(context) pr = utils.prefs(__addon__).bone_widgets # pr = prefs.prefs().bone_widgets if pr.keep_settings: pr.slide = self.slide pr.rotate = self.rotate pr.relative_size = self.relative_size pr.global_size = self.global_size pr.scale = self.scale pr.mirror = self.mirror # Create new object then delete it. # When creating multiple widgets, if the last one tries to enter edit # mode before a particular update occurs, Blender will crash. # If the last object created (I.E. this empty) is not the widget, # Blender can enter edit mode without crash Get.objects(context, link=True).unlink(New.object(context)) return {'FINISHED'}
def invoke(self, context, event): # Get current pose selected = Get.selected(context, mirror=True) for src in selected: pose.base[repr(src)] = Get.matrix(src, basis=True) # Disable animation and get pose from lower layers base_anim = dict() for src in selected: obj = src.id_data anim = obj.animation_data if (anim) and (obj not in base_anim): tracks = list() if anim.use_tweak_mode: # Find the strip to disable for track in reversed(anim.nla_tracks): for _strip in track.strips: if _strip.active: strip = _strip break elif _strip.action == anim.action: # backup in case strip isn't "active" strip = _strip else: tracks.append((track, track.mute)) # track.mute = True continue break base_anim[obj] = [strip, strip.mute, tracks] strip.mute = True # anim.use_tweak_mode = False else: base_anim[obj] = [None, anim.action_influence, tracks] anim.action_influence = 0 utils.update(context) pose.reset[repr(src)] = Get.matrix(src, basis=True) # Re-enable animation for obj in base_anim: anim = obj.animation_data (strip, value, tracks) = base_anim[obj] if strip: # for (track, track_mute) in tracks: # track.mute = track_mute strip.mute = value # anim.use_tweak_mode = True else: anim.action_influence = value utils.update(context) # context.window_manager.modal_handler_add(self) # return {'RUNNING_MODAL'} return self.execute(context)
def update_constraint_matrix(mats): from zpy import utils # Set the matrix for con in constraints: if hasattr(con, 'use_offset') and con.use_offset: utils.update(context) # utils.update(context) for src in srcs: new_mat = Get.matrix_constraints(context, src, mats[src], constraints) mats[src] = new_mat
def rigify_to_meta(rigify, metarig): """Retarget Rigify meshes to Metarig""" pose = (metarig.data.pose_position, rigify.data.pose_position) (metarig.data.pose_position, rigify.data.pose_position) = ('REST', 'REST') utils.update(bpy.context) for obj in bpy.data.objects: if Is.curve(obj) and obj.name.startswith(rigify.name + '-MCH-'): # Splines from angavrilov's spline rig continue for mod in obj.modifiers: if hasattr(mod, 'object') and mod.object == rigify: mod.object = metarig metafy_vgroups(rigify, obj, metarig) if (obj.parent == rigify): rigify_bone = obj.parent_bone if rigify_bone: if rigify_bone.startswith('DEF-'): meta_bone = rigify_bone[4:] else: meta_bone = rigify_bone if meta_bone in metarig.data.bones: mat = Get.matrix(obj) # pmat = obj.matrix_parent_inverse.copy() obj.parent = metarig obj.parent_bone = meta_bone # obj.matrix_parent_inverse = pmat Set.matrix(obj, mat) else: obj.parent = metarig if Is.mesh(obj): meshes = {obj.data} if hasattr(obj, 'variants'): # The LoDs store the mesh datas and drivers without an object for layer in obj.variants.layers: if layer.mesh: meshes.add(layer.mesh) for lod in layer.lods: meshes.add(lod.mesh) for mesh in meshes: if mesh: rigify_drivers(rigify, metarig, mesh.shape_keys) for mat in bpy.data.materials: rigify_drivers(rigify, metarig, mat) rigify_drivers(rigify, metarig, mat.node_tree) (metarig.data.pose_position, rigify.data.pose_position) = pose
def meta_to_rigify(metarig, rigify): """Retarget Metarig meshes to Rigify rig""" pose = (metarig.data.pose_position, rigify.data.pose_position) (metarig.data.pose_position, rigify.data.pose_position) = ('REST', 'REST') utils.update(bpy.context) for obj in bpy.data.objects: for mod in obj.modifiers: if hasattr(mod, 'object') and mod.object == metarig: mod.object = rigify rigify_vgroups(metarig, rigify, obj) if obj.parent == metarig: if obj.parent_bone: rigify_bone = vg_names.get(obj.parent_bone, False) if rigify_bone is False: rigify_bone = 'DEF-' + obj.parent_bone if rigify_bone and rigify_bone in rigify.data.bones: mat = Get.matrix(obj) # pmat = obj.matrix_parent_inverse.copy() obj.parent = rigify obj.parent_bone = rigify_bone # obj.matrix_parent_inverse = pmat Set.matrix(obj, mat) else: obj.parent = rigify if Is.mesh(obj): meshes = {obj.data} if hasattr(obj, 'variants'): # The LoDs store the mesh datas and drivers without an object for layer in obj.variants.layers: if layer.mesh: meshes.add(layer.mesh) for lod in layer.lods: meshes.add(lod.mesh) for mesh in meshes: if mesh: rigify_drivers(metarig, rigify, mesh.shape_keys) for mat in bpy.data.materials: rigify_drivers(metarig, rigify, mat) rigify_drivers(metarig, rigify, mat.node_tree) (metarig.data.pose_position, rigify.data.pose_position) = pose
def get_pole(pole, line): from math import radians from mathutils import Matrix bone["pole_vector"] = 0 pole = get(pole) line = get(line) # lock rotation/scale, since bone only suppose to be moved pole.rotation_mode = 'XYZ' pole.lock_rotation_w = True pole.lock_rotation = (True, True, True) pole.lock_scale = (True, True, True) utils.update(bpy.context) mat = getmat(pole, line) @ Matrix.Rotation(radians(180), 4, 'X') rotcopy(pole, mat) utils.update(bpy.context) poles[pole.name] = Get.matrix(pole) rotcopy(pole, Matrix()) pole.location = (0, 0, 0)
def execute(self, context): # TODO: Redo / Cleanup code class props: keep_matrix = True connect = False connect_child = False stretch = False if self.type == 'BONE': pass elif self.type == 'BONE_CONNECT': connect = True elif self.type == 'STRETCH': stretch = True elif self.type == 'STRETCH_CONNECT': stretch = True connect = True elif self.type == 'CHILD_CONNECT': connect_child = True ap = context.active_pose_bone bones = dict() matrices = {b: b.matrix.copy() for b in context.selected_pose_bones} for rig in context.selected_objects: if rig.mode != 'POSE': continue Set.mode(context, 'EDIT', rig) mirror = rig.data.use_mirror_x rig.data.use_mirror_x = False ab = context.active_bone edit_bones = Get.selected_edit_bones(context, rig) if ab and ab.parent in edit_bones: for eb in [*ab.parent_recursive, None]: if eb in edit_bones: # bones.append((rig, eb.name)) continue ab.use_connect = False ab.parent = eb bones[ab.name] = rig break for eb in edit_bones: if props.connect_child: for bb in eb.children: if bb in edit_bones: eb.tail = bb.head bb.use_connect = True else: if eb == ab: # or it'll delete itself continue eb.use_connect = False if props.stretch: eb.head = ab.tail eb.parent = ab bones[eb.name] = rig if props.connect: head = ab.tail - eb.head tail = ab.tail - eb.tail connects = [] for ebc in [*eb.children_recursive, eb]: connects.append([ebc, ebc.use_connect]) ebc.use_connect = False for ebc, c in connects: ebc.translate(ab.tail - eb.head) for ebc, c in connects: ebc.use_connect = c eb.use_connect = True rig.data.use_mirror_x = mirror Set.mode(context, 'POSE', rig) if props.keep_matrix: # ap.matrix = matrices[ap] # update() for b in bones: rig = bones[b] bone = rig.pose.bones.get(b) if bone is None: print(f"{rig.name} can't find {b}", *rig.pose.bones, sep='\n\t') continue if bone == ap: # Skip changing the active bone continue if bone not in matrices: print("Skip matrix,", bone.name) continue Set.matrix(bone, matrices[bone]) utils.update(context) return {'FINISHED'}
def fix_poles(): def op(**args): eval('bpy.ops.pose.rigify_limb_toggle_pole_' + rig.data["rig_id"])( dict(active_object=rig), 'INVOKE_DEFAULT', **args) poles = dict() def getmat(bone, active): """Helper function for visual transform copy, gets the active transform in bone space """ obj_bone = bone.id_data obj_active = active.id_data data_bone = obj_bone.data.bones[bone.name] # all matrices are in armature space unless commented otherwise active_to_selected = obj_bone.matrix_world.inverted( ) @ obj_active.matrix_world active_matrix = active_to_selected @ active.matrix otherloc = active_matrix # final 4x4 mat of target, location. bonemat_local = data_bone.matrix_local.copy() # self rest matrix if data_bone.parent: parentposemat = obj_bone.pose.bones[ data_bone.parent.name].matrix.copy() parentbonemat = data_bone.parent.matrix_local.copy() else: parentposemat = parentbonemat = Matrix() if parentbonemat == parentposemat or not data_bone.use_inherit_rotation: newmat = bonemat_local.inverted() @ otherloc else: bonemat = parentbonemat.inverted() @ bonemat_local newmat = bonemat.inverted() @ parentposemat.inverted( ) @ otherloc return newmat def rotcopy(item, mat): """Copy rotation to item from matrix mat depending on item.rotation_mode""" if item.rotation_mode == 'QUATERNION': item.rotation_quaternion = mat.to_3x3().to_quaternion() elif item.rotation_mode == 'AXIS_ANGLE': rot = mat.to_3x3().to_quaternion().to_axis_angle( ) # returns (Vector((x, y, z)), w) axis_angle = rot[1], rot[0][0], rot[0][1], rot[0][ 2] # convert to w, x, y, z item.rotation_axis_angle = axis_angle else: item.rotation_euler = mat.to_3x3().to_euler(item.rotation_mode) def get_pole(pole, line): from math import radians from mathutils import Matrix bone["pole_vector"] = 0 pole = get(pole) line = get(line) # lock rotation/scale, since bone only suppose to be moved pole.rotation_mode = 'XYZ' pole.lock_rotation_w = True pole.lock_rotation = (True, True, True) pole.lock_scale = (True, True, True) utils.update(bpy.context) mat = getmat(pole, line) @ Matrix.Rotation(radians(180), 4, 'X') rotcopy(pole, mat) utils.update(bpy.context) poles[pole.name] = Get.matrix(pole) rotcopy(pole, Matrix()) pole.location = (0, 0, 0) if get('thigh_parent.L'): op(prop_bone="thigh_parent.L", ik_bones= "[\"thigh_ik.L\", \"MCH-shin_ik.L\", \"MCH-thigh_ik_target.L\"]", ctrl_bones= "[\"thigh_ik.L\", \"foot_ik.L\", \"thigh_ik_target.L\"]", extra_ctrls= "[\"foot_ik_pivot.L\", \"foot_heel_ik.L\", \"foot_spin_ik.L\"]") get_pole('thigh_ik_target.L', 'VIS_thigh_ik_pole.L') if get('thigh_parent.R'): op(prop_bone="thigh_parent.R", ik_bones= "[\"thigh_ik.R\", \"MCH-shin_ik.R\", \"MCH-thigh_ik_target.R\"]", ctrl_bones= "[\"thigh_ik.R\", \"foot_ik.R\", \"thigh_ik_target.R\"]", extra_ctrls= "[\"foot_ik_pivot.R\", \"foot_heel_ik.R\", \"foot_spin_ik.R\"]") get_pole('thigh_ik_target.R', 'VIS_thigh_ik_pole.R') if get('upper_arm_parent.L'): op(prop_bone="upper_arm_parent.L", ik_bones= "[\"upper_arm_ik.L\", \"MCH-forearm_ik.L\", \"MCH-upper_arm_ik_target.L\"]", ctrl_bones= "[\"upper_arm_ik.L\", \"hand_ik.L\", \"upper_arm_ik_target.L\"]", extra_ctrls="[\"hand_ik_pivot.L\", \"hand_ik_wrist.L\"]") get_pole('upper_arm_ik_target.L', 'VIS_upper_arm_ik_pole.L') if get('upper_arm_parent.R'): op(prop_bone="upper_arm_parent.R", ik_bones= "[\"upper_arm_ik.R\", \"MCH-forearm_ik.R\", \"MCH-upper_arm_ik_target.R\"]", ctrl_bones= "[\"upper_arm_ik.R\", \"hand_ik.R\", \"upper_arm_ik_target.R\"]", extra_ctrls="[\"hand_ik_pivot.R\", \"hand_ik_wrist.R\"]") get_pole('upper_arm_ik_target.R', 'VIS_upper_arm_ik_pole.R') if poles: utils.update(bpy.context) mode = Get.mode(rig) Set.mode(bpy.context, 'EDIT', rig) for (name, mat) in poles.items(): edit_bone = rig.data.edit_bones[name] Set.matrix(edit_bone, mat) Set.mode(bpy.context, mode, rig)
def generate(self, context, ob, rig, coll): scn = context.scene faceverts, vertfaces = self.getVertFaces(ob) majors = {} skip = [] for vgrp in ob.vertex_groups: if vgrp.name in rig.data.bones: majors[vgrp.index] = [] else: skip.append(vgrp.index) for v in ob.data.vertices: wmax = 1e-3 vbest = None for g in v.groups: if g.weight > wmax and g.group not in skip: wmax = g.weight vbest = v gbest = g.group if vbest is not None: majors[gbest].append(vbest) roots = [bone for bone in rig.data.bones if bone.parent is None] for bone in roots: self.remapBones(bone, ob.vertex_groups, majors, None) face_mats = dict() if ob.data.materials: for f in ob.data.polygons: face_mats[( f.area, *f.center, *f.normal)] = ob.material_slots[f.material_index].material nobs = [] for vgrp in ob.vertex_groups: if (vgrp.name not in rig.pose.bones.keys() or vgrp.index not in majors.keys()): continue fnums = [] for v in majors[vgrp.index]: for fn in vertfaces[v.index]: fnums.append(fn) fnums = list(set(fnums)) nverts = [] nfaces = [] for fn in fnums: f = ob.data.polygons[fn] nverts += f.vertices nfaces.append(f.vertices) if not nfaces: continue nverts = list(set(nverts)) nverts.sort() bone = rig.pose.bones[vgrp.name] head = bone.bone.head_local # verts = [ob.data.vertices[vn].co - head for vn in nverts] verts = [ob.data.vertices[vn].co for vn in nverts] assoc = dict([(vn, n) for n, vn in enumerate(nverts)]) faces = [] for fverts in nfaces: faces.append([assoc[vn] for vn in fverts]) name = ob.name[0:3] + "_" + vgrp.name me = bpy.data.meshes.new(name) me.from_pydata(verts, [], faces) nob = bpy.data.objects.new(name, me) coll.objects.link(nob) nob.DazMannequin = True # nob.location = head # nob.lock_location = nob.lock_rotation = nob.lock_scale = (True,True,True) nobs.append((nob, bone)) if ob.data.materials: for b in me.polygons: mat_i = face_mats.get((b.area, *b.center, *b.normal)) if mat_i is None: # Add an empty material if mat is None: from random import random mat = bpy.data.materials.new(ob.name + 'Mannequin') mat.diffuse_color[0:3] = (random(), random(), random()) # for omat in ob.data.materials: # mat.diffuse_color = omat.diffuse_color if mat.name not in me.materials: me.materials.append(mat) continue if mat_i.name not in me.materials: me.materials.append(mat_i) for (i, mat_c) in enumerate(nob.material_slots): if mat_c.material == mat_i: b.material_index = i break else: if mat is None: from random import random mat = bpy.data.materials.new(ob.name + 'Mannequin') mat.diffuse_color[0:3] = (random(), random(), random()) # for omat in ob.data.materials: # mat.diffuse_color = omat.diffuse_color if mat.name not in me.materials: me.materials.append(mat) utils.update(context) for (nob, bone) in nobs: mat = Get.matrix(nob) # pmat = nob.matrix_parent_inverse.copy() nob.parent = rig nob.parent_bone = bone.name nob.parent_type = 'BONE' # nob.matrix_parent_inverse = pmat Set.matrix(nob, mat)
def update_pose(self, context): # for region in context.area.regions: # if region.type == 'WINDOW': # break # else: # return self.cancel(context) region = context.region rv3d = context.space_data.region_3d gp = context.annotation_data stroke = gp.layers.active.frames[0].strokes[0] for chain in Get.sorted_chains(context.selected_pose_bones): bone_chain = list() for bone in reversed(chain): bone_chain.insert(0, bone) if bone == chain[0]: # Do location pass # continue # or break; should do the same else: pass while bone.parent not in chain: # Do unselected in betweens bone = bone.parent if not Is.visible(context, bone): # Don't rotate hidden bones continue bone_chain.insert(0, bone) bcount = len(bone_chain) - 1 gcount = len(stroke.points) - 1 # if bcount: # while gcount > bcount * 3: # # Split point count in half # index = 0 # while index < len(stroke.points) - 1: # stroke.points.pop(index=index + 1) # index += 1 # print(bcount, gcount, '\t', index, len(stroke.points)) # gcount = len(stroke.points) - 1 bone_mats = list() con_tmp = list() index = 0 for bone in bone_chain: if index > bcount: index = bcount point_index = utils.scale_range(index, 0, bcount, 0, gcount) point = stroke.points[int(point_index)] if index == 0: if not (bone.parent): bone = bone_chain[0] point = stroke.points[0] to_2d = location_3d_to_region_2d( region, rv3d, point.co) # get 2d space of stroke if to_2d: to_3d = region_2d_to_location_3d( region, rv3d, to_2d, bone.head) # keep depth of bone empty = New.object(context, bone.name) empty.empty_display_size = 0.25 empty.location = to_3d con = bone.constraints.new('COPY_LOCATION') con.target = empty con_tmp.append((bone, con, empty)) if bcount == 0: point = stroke.points[-1] else: # index += 1 point_index = utils.scale_range( 0.5, 0, bcount, 0, gcount) point = stroke.points[int(point_index)] to_2d = location_3d_to_region_2d( region, rv3d, point.co) # get 2d space of stroke if to_2d: to_3d = region_2d_to_location_3d( region, rv3d, to_2d, bone.tail) # keep depth of bone empty = New.object(context, bone.name) empty.empty_display_size = 0.1 empty.location = to_3d con = bone.constraints.new('DAMPED_TRACK') con.target = empty con_tmp.append((bone, con, empty)) index += 1 utils.update(context) for (bone, con, empty) in reversed(con_tmp): mat = Get.matrix_constraints(context, bone) # mat = Get.matrix(bone) bone_mats.append((bone, mat)) bone.constraints.remove(con) Get.objects(context, link=True).unlink(empty) for (bone, mat) in bone_mats: Set.matrix(bone, mat) keyframe.keyingset(context, selected=[bone], skip_bones=True) self.remove_annotation(context) return {'FINISHED'}