def draw(self, context): layout = self.layout src = context.src mp = context.mp mpath = src.motion_path layout.prop(mp, 'show_frame_numbers') # , text="Frame Numbers") layout.prop(mp, 'show_keyframe_highlight') # , text="Keyframes") if mp.show_keyframe_highlight: if Is.posebone(src): layout.prop(mp, 'show_keyframe_action_all', text="+ Non-Grouped Keyframes") layout.prop(mp, 'show_keyframe_numbers', text="Keyframe Numbers") layout.separator() if Is.posebone(src): layout.label(text=src.name, icon='BONE_DATA') else: layout.label(text=src.name, icon='OBJECT_DATA') if mpath: layout.prop(mpath, 'lines') # , text="Lines") layout.prop(mpath, 'use_custom_color') # , text="Custom Color") else: op = 'zpy.update_motion_paths' layout.label(text="Add Motion Paths") layout.operator(op, text="At Heads").use_tails = False layout.operator(op, text="At Tails").use_tails = True layout.separator() mot = utils.prefs(__package__).motion layout.prop(mot, 'frame_before') layout.prop(mot, 'frame_after')
def mesh(self, context): layout = self.layout obj = context.active_object if not (Is.mesh(obj) and Is.armature(obj.parent)): return False scn = context.scene if hasattr(scn, 'DazShowRigging'): layout.prop(scn, 'DazMannequinGroup', text="") idname = 'daz.add_mannequin_macro' # op = layout.operator(idname, text="Full Macro") layout.operator_menu_hold(idname, menu='MACRO_MT_add_mannequin_full', text="Add Mannequin (Full Macro)" + mannequin.head).macro = True layout.operator_menu_hold(idname, menu='MACRO_MT_add_mannequin_only', text="Add Mannequin" + mannequin.head) # op.head = 'SOLID' # op.macro = True # layout.operator(idname, text="Solid").head = 'SOLID' # layout.operator(idname, text="Jaw").head = 'JAW' # layout.operator(idname, text="Full").head = 'FULL' layout.operator('object.data_transfer_mannequin_preset', icon='OUTLINER_DATA_MESH') layout.operator('object.data_transfer_materials', icon='MATERIAL') return True
def bone_group(rig, name='Group', color=None): "" if Is.posebone(rig): rig = rig.id_data group = rig.pose.bone_groups.new(name=name) if Is.string(color): group.color_set = color # DEFAULT = regular bone color (not unique) # THEME01 - THEME15 = Builtin color palettes # THEME16 - THEME20 = Black for user assigned templates # CUSTOM = manually set elif color is False: group.color_set = 'DEFAULT' elif color is True: from random import randrange as random rand = f"{random(1, 15):02}" group.color_set = f'THEME{rand}' elif color: group.color_set = 'CUSTOM' gc = group.colors if not Is.iterable(color): if Is.digit(color): color = [[color] * 3] * 3 else: color = [color] * 3 (gc.normal, gc.select, gc.active) = color return group
def sorted_bones(selected): "Scan through selected bones to find order of bones in a a tree" selected = [ b for b in selected if (Is.posebone(b) or Is.bone(b) or Is.editbone(b)) ] bones = list() while selected: for bone in list(selected): if (bone not in selected): # a previous bone was one of this bone's parents continue for parent in bone.parent_recursive: if parent in selected: break else: bones.append(bone) selected.remove(bone) # Loop over children, which "may" result in less looping for child in bone.children_recursive: if child in selected: bones.append(child) selected.remove(child) return bones
def execute(self, context): do_all = (self.mode == {'loc', 'rot', 'scale'}) selected = Get.selected(context, mirror=True) for src in selected: base = get_base(src) if 'loc' in self.mode: src.location = base.location if 'rot' in self.mode: if src.rotation_mode == 'QUATERNION': src.rotation_quaternion = base.rotation_quaternion elif src.rotation_mode == 'AXIS_ANGLE': src.rotation_axis_angle = base.rotation_axis_angle else: src.rotation_euler = base.rotation_euler if Is.posebone(src): src.bbone_curveinx = src.bbone_curveoutx = src.bbone_curveiny = src.bbone_curveouty = src.bbone_rollin = src.bbone_rollout = 0 if 'scale' in self.mode: src.scale = base.scale if Is.posebone(src): src.bbone_scaleinx = src.bbone_scaleinx = src.bbone_scaleiny = src.bbone_scaleoutx = src.bbone_scaleouty = 1 src.bbone_easein = src.bbone_easeout = 0 utils.clean_custom(src) keyframe.keyingset(context, selected=selected) return {'FINISHED'}
def blend(current, target): if (Is.digit(current) and Is.digit(target)) and not \ (Is.string(current) or Is.string(target)): return (current * (1.0 - factor) + target * factor) elif (factor): return target else: return current
def visible_armature_layers(bone, arm): """List of layer indexes that is visible and the Bone is on""" if Is.posebone(bone): bone = bone.bone if Is.armature(arm): arm = arm.data return [i for i, j in zip(bone.layers, arm.layers) if i and j]
def mirror_bone(bone): name = utils.flip_name(bone.name) if name == bone.name: return if Is.posebone(bone): return bone.id_data.pose.bones.get(name) elif Is.editbone(bone): return bone.id_data.edit_bones.get(name) elif Is.bone(bone): return bone.id_data.bones.get(name)
def keyingset(context, default=True, **kargs): """ Use bpy.ops to insert keyframe. default means to only use the keying set if the keying set button is enabled """ insert_key = kargs.get('insert_key') if not keyframe.poll_insert(context, insert_key): return ks = context.scene.keying_sets_all.active if (default and not keyframe.use_keyingset(context)) or \ ks is None: ks = 'LocRotScale' else: ks = ks.bl_idname bones = kargs.get('bones', list()) objects = kargs.get('objects', list()) selected = kargs.get('selected', list()) # if bones is None: bones = Get.selected_pose_bones(context) # if objects is None: objects = Get.selected_objects(context) for src in selected: if Is.posebone(src): bones.append(src) elif Is.object(src): objects.append(src) else: assert None, ("This is not a bone or object", src) if kargs.get('skip_bones', False): # This step removes bones from badBonePrefixes for src in bones.copy(): if not keyframe.poll_insert(context, insert_key, src=src): bones.remove(src) # if keyframe.use_keyingset(): # bpy.ops.anim.keyframe_insert(type=ks, confirm_success=False) # # else: # for src in KSI.iter(): # keyframe.all(src) if (bones or objects): try: return bpy.ops.anim.keyframe_insert(dict(selected_pose_bones=bones, selected_objects=objects), type=ks, confirm_success=False) except Exception as ex: pass else: "Nothing to keyframe"
def execute(self, context): active = obj = context.object transfer = bpy.ops.object.data_transfer if (not Is.mesh(obj)) or getattr(obj, 'DazMannequin', False): # redesignate obj obj = None for o in context.selected_objects: if Is.mesh(o) and (not getattr(o, 'DazMannequin', False)): obj = o Set.active(context, o) break if not all(( obj, obj.data.polygons, transfer.poll(context.copy()), )): self.report({'INFO'}, "Only Mannequins Selected") return {'CANCELLED'} mesh = obj.data if mesh.polygons[0].use_smooth: # only check one face, rather than all bpy.ops.object.shade_smooth() if mesh.use_auto_smooth: transfer(data_type='CUSTOM_NORMAL') for o in context.selected_objects: if Is.mesh(o): o.data.use_auto_smooth = True if obj.vertex_groups: # Vertex groups add to file size, so don't keep them for everything transfer(data_type='VGROUP_WEIGHTS', layers_select_src='ALL', layers_select_dst='NAME') if mesh.vertex_colors: transfer(data_type='VCOL', layers_select_src='ALL', layers_select_dst='NAME') if mesh.uv_layers: transfer(data_type='UV', layers_select_src='ALL', layers_select_dst='NAME') Set.active(context, active) return {'FINISHED'}
def selected_edit_bones(context, src=None): "Always return edit bones as list, never as None" if src: bones = src.data.edit_bones selected = [ b for b in bones if Is.selected(b) and Is.visible(context, b) ] else: selected = Get.as_list(context, 'selected_editable_bones') return selected
def in_scene(context, object, value=True): # TODO: set this function to be able to remove an object from scene # currently it ONLY uses the value for set at True if value: if Is.collection(object): scn = context.scene if not Get.collection_from_scene(object, scn.collection): scn.collection.children.link(object) elif not (Is.in_scene(context, object) and Is.in_view(context, object)): Get.objects(context, link=True).link(object)
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 matrix(src, local=False, basis=False, tail=False, copy=True): # editbone. matrix # bone. matrix, matrix_local # posebone. matrix, matrix_basis, matrix_channel # object. matrix_world, matrix_basis, matrix_local, matrix_parent_inverse if Is.posebone(src): if copy: matrix = utils.multiply_matrix(src.id_data.matrix_world, src.matrix) else: matrix = src.matrix if basis: matrix_local = src.matrix_basis else: matrix_local = src.bone.matrix_local elif Is.bone(src): matrix = src.matrix matrix_local = src.matrix_basis elif Is.editbone(src): matrix = matrix_local = src.matrix else: matrix = src.matrix_world if basis: matrix_local = src.matrix_basis else: matrix_local = src.matrix_local if copy: matrix = matrix.copy() matrix_local = matrix_local.copy() # scaled = False # if len(set(matrix.to_scale())) == 1: # matrix *= matrix.to_scale()[0] # scaled = True if (tail and hasattr(src, 'tail')): # matrix.translation += (src.tail - src.head) matrix.translation = matrix.Translation(src.tail).translation matrix_local.translation = \ matrix_local.Translation(src.tail).translation # for (i, t) in enumerate(matrix.translation): # v = (src.tail[i] - src.head[i]) * ( # 1 if scaled else matrix.to_scale()[i]) # matrix.translation[i] += v if (basis or local): return matrix_local else: return matrix
def tail(context, bone): # ------ Bones if any((Is.posebone(bone), Is.bone(bone), Is.editbone(bone))): if (Is.posebone(bone)): obj = bone.id_data else: obj = Get.rig(context, bone) if obj is None: return else: mat = Get.matrix(obj) return utils.multiply_matrix(mat, bone.tail)
def execute(self, context): mannequin.head = f" ({self.head.title()})" objects = list() for obj in context.selected_objects: if Is.mesh(obj) and Is.armature(obj.parent): inst = self.convert(context, obj) objects.append(inst) for obj in reversed(objects): Set.active_select(context, obj, isolate=False) return {'FINISHED'}
def armature_display_type(armature, display_type='RANDOM', random_src=None): """ Set the default bone display for rig objects\\ display_type is enum in with the following odds: 'OCTAHEDRAL' * 6, 'STICK' * 6, 'WIRE' * 2, 'BBONE' * 4, 'ENVELOPE' * 1, random_src is the source armature to avoid when randomly selecting type """ import random display_types = [ *['OCTAHEDRAL'] * 6, *['STICK'] * 6, *['WIRE'] * 2, *['BBONE'] * 4, *['ENVELOPE'] * 1, ] # armature.show_in_front = True if Is.armature(armature): armature = armature.data if Is.armature(random_src): random_src = random_src.data def set_type(arm, type): if hasattr(arm, 'draw_type'): # 2.7 arm.draw_type = type elif hasattr(arm, 'display_type'): # 2.8 arm.display_type = type def get_type(arm): if hasattr(arm, 'draw_type'): # 2.7 return arm.draw_type elif hasattr(arm, 'display_type'): # 2.8 return arm.display_type if display_type == 'RANDOM': display_type = display_types.pop(random.randrange(len(display_types))) while random_src and display_types and \ display_type == get_type(random_src): # Remove items from the display types until it's different display_type = display_types.pop( random.randrange(len(display_types))) set_type(armature, display_type) return display_type
def poll(cls, context): ob = context.object if Is.armature(ob) and ob.mode in ('POSE', 'EDIT'): return Get.selected(context, ob) if not bpy.ops.paint.weight_from_bones.poll(context.copy()): return if Is.mesh(ob) and (ob.mode == 'WEIGHT_PAINT'): for mod in ob.modifiers: if (mod.type == 'ARMATURE') and (mod.object in Get.objects(context)[:]): if mod.object.mode == 'POSE': return True
def icon_from_type(src): "return an Icon id for the specified item's type" if Is.object(src): if src.type == 'LIGHT_PROBE': icon = 'LIGHTPROBE_' + src.data.type else: icon = src.type + '_DATA' elif Is.bone(src) or Is.editbone(src) or Is.posebone(src): icon = 'BONE_DATA' else: icon = 'ERROR' utils.debug("Can't find icon type for ", src, type(src)) return icon
def scale_range(OldValue, OldMin, OldMax, NewMin, NewMax): """Convert a number in a range, relatively to a different range""" if Is.iterable(OldValue): NewValues = list() for (index, OldValue) in enumerate(OldValue): OldRange = (OldMax[index] - OldMin[index]) NewRange = (NewMax[index] - NewMin[index]) if (OldRange == 0): NewValue = NewMin[index] else: NewValue = (((OldValue - OldMin[index]) * NewRange) / OldRange) + NewMin[index] NewValues.append(NewValue) return NewValues OldRange = (OldMax - OldMin) NewRange = (NewMax - NewMin) if (OldRange == 0): NewValue = NewMin else: NewValue = (((OldValue - OldMin) * NewRange) / OldRange) + NewMin return NewValue
def valid_op(*ops): """Validate whether or not an operator is in bpy.ops; if True, return operator""" valid = list() for op in ops: if not Is.string(op): if hasattr(op, 'bl_idname'): op = op.bl_idname else: continue try: exec(f'bpy.ops.{op}.get_rna_type()') valid.append(op) except: continue if len(ops) > 1: return valid elif valid: return valid[0] else: return None
def bone(context, armature, name="", edit=None, pose=None, overwrite=False): "Insert a bone into an armature object" if getattr(armature, 'type', None) != 'ARMATURE': return # active = Get.active(context) # Set.active(context, armature) # Set.select(armature, True) # Set.visible(context, armature, True) # mode = armature.mode.replace('EDIT_ARMATURE', 'EDIT') Set.in_scene(context, armature) is_visible = Is.visible(context, armature) Set.visible(context, armature, True) mode = armature.mode # mode = context.mode.replace('EDIT_ARMATURE', 'EDIT') # Go into Edit mode and create a new bone ebones = armature.data.edit_bones if armature.mode != 'EDIT': Set.mode(context, 'EDIT', armature) mirror = armature.data.use_mirror_x armature.data.use_mirror_x = False children = list() if overwrite and name in ebones: for child in ebones[name].children: children.append((child, child.use_connect)) child.use_connect = False ebones.remove(ebones[name]) bone = ebones.new(name) for child, child_connect in children: child.parent = bone child.use_connect = child_connect bone.tail = ((0, 0, 1)) # If the bone's head AND tail stay at 0, # it gets deleted when leaving edit mode name = bone.name if edit: edit(bone) armature.data.use_mirror_x = mirror pbones = armature.pose.bones if pose: Set.mode(context, 'POSE', armature) bone = pbones[name] pose(bone) # Revert mode change if mode != armature.mode: # Set.active(active) Set.mode(context, mode, armature) Set.visible(context, armature, is_visible) if armature.mode == 'EDIT': bone = ebones[name] else: bone = pbones[name] return bone
def execute(self, context): # active = Get.active(context) mode = context.mode # pose = list() for rig in context.selected_objects: if (not Is.armature(rig)) or (rig.data.get('rig_id') is None): continue meta = New.object(context, name="metarig", data=rig.data.copy()) meta.data.animation_data_clear() metafy_rigify(context, meta) # pose.append(meta, rig) else: if context.mode != mode: bpy.ops.object.mode_set(mode=mode) # if mode == 'POSE': # Set.mode(context, 'OBJECT') # for (meta, rig) in pose: # Set.select(rig, True) # Set.select(meta, False) # if meta == active: # Set.active(context, rig) # if mode == 'POSE': # Set.mode(context, 'POSE') return {'FINISHED'}
def get_obj_from_path(path, obj=None): if path.startswith('bpy.data.'): obj2 = eval(path.split('"]', 1)[0] + '"]') if Is.object(obj2): obj = obj2 return obj
def selected_pose_bones(context, src=None, force: "not needed, todelete" = False): "Always return pose bones as list, never as None" if src: selected = [ b for b in src.pose.bones if Is.selected(b) and Is.visible(context, b) ] # elif not force and context.mode not in ('POSE', 'PAINT_WEIGHT'): # selected = [] else: selected = Get.as_list(context, 'selected_pose_bones') return selected
def execute(self, context): mute = None for obj in bpy.data.objects: if (not Is.mesh(obj)) or (obj.data.shape_keys is None): continue muted = bool('mute_shapekeys' in obj) if mute is None: mute = not muted if mute and not muted: # Storing shapekey settings obj['mute_shapekeys'] = (obj.active_shape_key_index, obj.show_only_shape_key) (obj.active_shape_key_index, obj.show_only_shape_key) = (0, True) elif not mute and muted: # Resetting shapekey settings (obj.active_shape_key_index, obj.show_only_shape_key) = obj['mute_shapekeys'] del (obj['mute_shapekeys']) if mute is True: self.report({'INFO'}, "Locked all mesh shapekeys") elif mute is False: self.report({'INFO'}, "Unlocked all mesh shapekeys") return {'FINISHED'}
def proportional(dist, mode: "string or context" = None, rng: "Random Seed" = None): """Convert a number (from 0-1) to its proportional equivalent""" from math import sqrt from random import random if not (0 <= dist <= 1): return dist if not Is.string(mode) and mode is not None: mode = mode.scene.tool_settings.proportional_edit_falloff if mode == 'SHARP': return dist * dist elif mode == 'SMOOTH': return 3.0 * dist * dist - 2.0 * dist * dist * dist elif mode == 'ROOT': return sqrt(dist) elif mode == 'LINEAR': return dist elif mode == 'CONSTANT': return 1.0 elif mode == 'SPHERE': return sqrt(2 * dist - dist * dist) elif mode == 'RANDOM': if (rng is None): rng = random() return rng * dist elif mode == 'INVERSE_SQUARE': return dist * (2.0 - dist) else: # default equivalent to constant return 1
def frame_from_strip(context, anim_or_strip, frame=None, absolute=False): "Convert the keyframe.co inside scaled nla strip to timeline frame" if frame is None: frame = context.scene.frame_current_final anim = anim_or_strip.id_data.animation_data strip = anim_or_strip tweak = anim.use_tweak_mode is_strip = Is.nla_strip(strip) if (tweak or is_strip): if (tweak and is_strip and strip.active) and hasattr( anim, 'nla_tweak_strip_time_to_scene'): value = anim.nla_tweak_strip_time_to_scene(frame, invert=False) else: if not is_strip: strip = Get.active_strip(anim) value = Get.strip_co_frame(strip, co=frame) else: value = frame if absolute: return value else: return (round(value, 6))
def frame_to_strip(context, anim_or_strip, frame=None, absolute=False): "Convert the keyframe.co/frame to correct frame inside nla strip" if frame is None: frame = context.scene.frame_current_final anim = anim_or_strip.id_data.animation_data strip = anim_or_strip tweak = anim.use_tweak_mode is_strip = Is.nla_strip(strip) if (tweak or is_strip): if is_strip and strip.active and hasattr( anim, 'nla_tweak_strip_time_to_scene'): value = anim.nla_tweak_strip_time_to_scene(frame, invert=True) else: if not is_strip: strip = Get.active_strip(anim) value = Get.strip_co_frame(strip, frame=frame) else: # Null call, so just return scene frame value = frame if absolute: return value else: return (round(value, 6))
def reload_proxies(scn): for rig in bpy.data.objects: if not (Is.armature(rig) and not rig.library and rig.data.library): continue for src in bpy.data.objects: if (src.data == rig.data) and (src.library == rig.data.library): break else: # Can't find the original linked rig continue copy_custom(src, rig) copy_groups(src.pose.bone_groups, rig.pose.bone_groups) for pbone in rig.pose.bones: sbone = src.pose.bones.get(pbone.name) if not sbone: # Rig is proxy that was made local, incorrectly/incompletely continue elif (True, True) in zip(rig.data.layers_protected, pbone.bone.layers): # Bone is in a protected layer, so properties are locked and auto-reset continue if sbone.bone_group: try: pbone.bone_group = Get.bone_group(rig, name=sbone.bone_group.name) except: print(pbone, sbone) copy_constraints(sbone, pbone) copy_custom(sbone, pbone) copy_drivers(src, rig)