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 description(cls, context, properties): if not Locks: return elif Get.selected_pose_bones(context, force=True): return "Toggle locked weights to the selected bones" else: return "Reset locked weights to normal"
def scan_strips(context, sub, selected): frames = list() for obj in Get.objects_nla(context): data = getattr(obj, 'data', None) shapes = getattr(data, 'shape_keys', None) # Poll object if pose(context): if not pose(obj): continue elif selected: if not Get.selected_pose_bones(context, src=obj): continue else: if (selected and obj not in selected): continue for src in (obj, data, shapes): frames_fcurve = list() frames_strip = list() for item in Get.strip_tracks(src, selected=False): strip = item.strip if strip.mute and not strip.select: continue for fc in strip.fcurves: if fc.hide: continue scan_fcurve(context, sub, fc, frames_fcurve) if frames_fcurve: # Don't scan strip boxes if have animation keyframes continue (fs, fe) = (strip.frame_start, strip.frame_end) if not sub: (fs, fe) = (smooth(fs), smooth(fe)) frames_strip.append(fs) frames_strip.append(fe) # Get loop ends if (strip.action) and (strip.repeat != 1.0): afe = strip.action_frame_end fel = fer = Get.frame_from_strip(context, strip, afe) while fel < strip.frame_end: frames_strip.append([smooth(fel), fel][sub]) fel += (fer - strip.frame_start) if frames_fcurve: frames.extend(frames_fcurve) else: frames.extend(frames_strip) return sorted(set(frames))
def execute(self, context): # editWidget(context, context.active_pose_bone) bones = Get.selected_pose_bones(context) # bpy.ops.object.mode_set(mode='OBJECT') for bone in bones: if (bone.custom_shape) and (not bone.id_data.proxy): editWidget(context, bone) return {'FINISHED'}
def execute(self, context): global Auto_normalize, Locks ts = context.scene.tool_settings pbones = Get.selected_pose_bones(context, force=True) mode = self.mode obj = context.object # 2.8 doesn't do multi-object weight paint if Auto_normalize is None: # first run Auto_normalize = ts.use_auto_normalize # Without auto normalize, locks essentially do nothing if self.mode in ['None', 'DEFAULT']: # In case op called without invoke # Allow op to be called to only run in one mode regardless as to selection self.mode = 'None' mode = ('RESET', 'SET')[bool(pbones)] if mode == 'SET': bones = [b.name for b in pbones] toggled = 0 for vg in obj.vertex_groups: if (obj.name, vg.name) not in Locks: # store initial value Locks[obj.name, vg.name] = vg.lock_weight if vg.name in bones: vg.lock_weight = False toggled += 1 else: vg.lock_weight = True report = f"{toggled}/{len(obj.vertex_groups)} " \ "Bone Weight Groups Locked" ts.use_auto_normalize = True else: for vg in obj.vertex_groups: vg.lock_weight = Locks.get((obj.name, vg.name), vg.lock_weight) report = f"Reset {len(Locks)} Vertex Group Locks" # reset first run value ts.use_auto_normalize = Auto_normalize Auto_normalize = None Locks = {} self.report({'INFO'}, report) return {'FINISHED'}
def execute(self, context): objs = self.get_objs(context) active_bone = context.active_pose_bone selected_bones = [ b for b in Get.selected_pose_bones(context) if b != active_bone ] for ob in objs: for b in selected_bones: if self.target == 'selected': utils.subtract_vertex_groups(ob, active_bone.name, b.name) elif self.target == 'active': utils.subtract_vertex_groups(ob, b.name, active_bone.name) return {'FINISHED'}
def execute(self, context): # editWidget(context, context.active_pose_bone) bones = Get.selected_pose_bones(context) # bpy.ops.object.mode_set(mode='OBJECT') for bone in bones: wgt = bone.custom_shape if wgt and (not bone.id_data.proxy): bone.custom_shape = None if wgt.users < 2: # only used by widget collection now, so delete it bpy.data.objects.remove(wgt) return {'FINISHED'}
def execute(self, context): objects = [] if context.mode == "POSE": for bone in Get.selected_pose_bones(context): objects.append(bone.custom_shape) else: for ob in Get.selected_objects(context): if ob.type == 'MESH': objects.append(ob) if not objects: self.report({'INFO'}, 'Select Meshes or Pose_bones') addRemoveWidgets(context, "add", bpy.types.Scene.widget_list[1]['items'], objects) return {'FINISHED'}
def execute(self, context): if context.mode == "POSE": for bone in Get.selected_pose_bones(context): if bone.custom_shape_transform and bone.custom_shape: boneMatrix(bone.custom_shape, bone.custom_shape_transform) elif bone.custom_shape: boneMatrix(bone.custom_shape, bone) else: for ob in Get.selected_objects(context): if ob.type == 'MESH': matchBone = fromWidgetFindBone(ob) if matchBone: if matchBone.custom_shape_transform: boneMatrix(ob, matchBone.custom_shape_transform) else: boneMatrix(ob, matchBone) return {'FINISHED'}
def draw_menu(self, context): w_menu = getattr(self, 'bl_idname', None) == 'VIEW3D_MT_pose_context_menu' # self.bl_label == 'Pose Context Menu' if w_menu and context.mode != 'PAINT_WEIGHT': return if not Locks: name = "Lock by Selected Bones" elif Get.selected_pose_bones(context, force=True): name = "Toggle Locks to Selected Bones" else: name = "Reset Weight Locks" layout = self.layout layout.operator('object.vertex_group_isolate_bones', text=name, icon='PINNED') if w_menu: layout.separator()
def active_select(context, target, isolate=True): # , isolate_mode=False): """ Set target as active scene object or bone, and select it\\ # isolate_mode would set all other selected objects to Object mode """ # def deselect(src): # if isolate_mode and src.id_data.mode != 'OBJECT': # Set.mode(context, 'OBJECT', src) # Set.select(src, False) if isolate: objects = Get.selected_objects(context) bones = Get.selected_pose_bones(context) for src in [*objects, *bones]: # deselect(src) Set.select(src, False) Set.visible(context, target, True) Set.active(context, target) Set.select(target, True) if Is.posebone(target): Set.mode(context, 'POSE', target)
def scan_actions(context, sub, selected): scn = context.scene fc = (int(scn.frame_current_final), scn.frame_current_final)[sub] frames = list() for obj in selected: if Is.gpencil(obj): for layer in obj.data.layers: for frame in layer.frames: frames.append(frame.frame_number) for obj in Get.objects_nla(context): # Poll object if pose(context): if not pose(obj): continue elif selected: bones = [ f'pose.bones[\"{b.name}\"]' for b in Get.selected_pose_bones(context, src=obj) ] if not bones: continue else: bones = list() else: if (selected and obj not in selected): continue else: bones = list() for anim in Get.animation_datas(obj): if (not anim.action): continue if anim.use_tweak_mode: for s in Get.strips(anim.id_data): if s.action == anim.action: strip = s if s.active: break # Get loop ends cycle = list() afe = strip.action_frame_end fel = fer = Get.frame_from_strip(context, strip, afe) while fel < strip.frame_end: offset = (fer - strip.frame_start) cycle.append(offset) fel += abs(offset) # If offset becomes negative, it "should" create an infinite loop # abs() forces positive, which "should" prevent loop else: strip = None for fcurve in anim.action.fcurves: path = fcurve.data_path if bones: # Bones are selected, so verify this fcurve if for one of them for bpath in bones: if path.startswith(bpath): break else: continue elif path.startswith('pose.bones[\"'): try: eval(repr(obj) + '.' + path) # Validate path bpath = path.split('\"]', 1)[0] + '\"]' bone = eval(repr(obj) + '.' + bpath) if not Is.visible(context, bone): continue except: # curve points to a removed bone or something continue scan_fcurve(context, sub, fcurve, frames, strip=strip) return sorted(set(frames))
def poll(cls, context): if context.mode not in ('POSE', 'PAINT_WEIGHT'): return return len(Get.selected_pose_bones(context)) > 1
def poll(cls, context): if context.mode == 'PAINT_WEIGHT': return for bone in Get.selected_pose_bones(context): if bone.parent and bone.parent.parent: return True
def get_keys(self, context): scn_frame = context.scene.frame_current_final fcurves = dict() quats = dict() updates = dict() break_sync = False if hasattr(context.scene, 'sync'): break_sync = context.scene.sync.sync_3d and context.scene.sync.sync_between_3d if context.mode == 'POSE': # objects = [o for o in Get.objects(context) if o.mode == 'POSE'] objects = list() for ob in Get.objects(context): if ob.mode != 'POSE': continue bones = tuple([f"pose.bones[\"{b.name}\"]" for b in Get.selected_pose_bones(context, ob)]) if bones: objects.append((ob, bones)) if not objects: for ob in Get.objects(context): if ob.mode != 'POSE': continue bones = tuple([f"pose.bones[\"{b.name}\"]" for b in ob.pose.bones if Is.visible(context, b)]) if bones: objects.append((ob, bones)) else: objects = [(o, list()) for o in Get.selected_objects(context)] for (ob, bones) in objects: for anim in Get.animation_datas(ob): action = anim.action if not action: continue if anim.use_tweak_mode: frame = Get.frame_to_strip(context, anim, scn_frame) for s in Get.strips(anim.id_data): if s.action == action: strip = s if s.active: break blend = strip.blend_type else: frame = scn_frame blend = anim.action_blend_type offset = abs(frame - scn_frame) if (scn_frame < frame): offset *= -1 for fc in anim.action.fcurves: path = fc.data_path index = fc.array_index if len(fc.keyframe_points) < 2: continue if bones: src = None for bone in bones: if path.startswith(bone): try: eval(repr(ob) + '.' + path) # Validate path src = eval(repr(ob) + '.' + bone) attr = path.replace(bone, '', 1) if attr.startswith('.'): attr = attr.replace('.', '', 1) is_custom = False else: is_custom = True except: # curve points to a removed bone or something src = None break else: # Pose mode but bone not selected continue if src is None: # Missing bone continue else: attr = path src = ob if attr in transforms: is_custom = False elif attr.startswith('["'): is_custom = True else: # if attr.startswith(('pose.bones', 'bones')): continue # Find the property to be able to manipulate, and its current value if is_custom: prop = src split = attr.rsplit('"]["', 1) if len(split) == 2: prop = eval(repr(src) + split[0] + '"]') attr = '["' + split[1] prop_value = getattr(prop, attr) elif hasattr(src, attr): prop = getattr(src, attr) if Is.iterable(prop): # elif attr in transforms: # prop = src.path_resolve(attr) prop_value = prop[index] else: prop = src prop_value = getattr(prop, attr) else: # maybe a constraint: # pose.bones[bone.name].constraints[con.name].influence continue # Function to apply values to the bone/object, later if Is.iterable(prop): def apply(self, val): "Function to apply values to (array) in bone/object, later" self.prop[self.index] = val prop = src.path_resolve(attr) prop_value = prop[index] is_array = True else: def apply(self, val): setattr(self.prop, self.attr, val) is_array = False cache = dict( attr=attr, apply=apply, index=index, is_array=is_array, key=None, quat=None, prop=prop, src=src, value=fc.evaluate(frame), ) left = type('', (), cache) current = type('', (), cache) current.found = False right = type('', (), cache) pre_key = None # Find the current keyframe, and keys left and right if break_sync: # types = context.scene.keyframe_navigation_types types = ('KEYFRAME', 'MOVING_HOLD') for key in fc.keyframe_points: if key.co.x < frame: if (left.key is None) or (key.type in types): left.key = key left.value = key.co.y right.key = key right.value = key.co.y elif key.co.x == frame: if left.key is None: left.key = key left.value = key.co.y current.key = key current.found = True right.key = key right.value = key.co.y elif key.co.x > frame: if left.key is None: left.key = key left.value = key.co.y if (key.type in types) or key == fc.keyframe_points[-1]: right.key = key right.value = key.co.y break if not (left.key and right.key): for key in fc.keyframe_points: if key.co.x < frame: left.key = key left.value = key.co.y right.key = key right.value = key.co.y elif key.co.x == frame: if left.key is None: left.key = key left.value = key.co.y current.key = key current.found = True right.key = key right.value = key.co.y elif key.co.x > frame: if left.key is None: left.key = key left.value = key.co.y right.key = key right.value = key.co.y break if not (left.key and right.key): # Nothing to tween continue # Get info for current keyframe's defaults sVal = left.key.co.x + offset eVal = right.key.co.x + offset current.w1 = frame - sVal current.w2 = eVal - frame left.frame = left.key.co.x current.frame = frame right.frame = right.key.co.x current.in_range = False if frame < left.frame: left.value = prop_value elif right.frame < frame: right.value = prop_value else: current.in_range = True if blend == 'REPLACE': current.value = prop_value else: if not self.has_additive: self.has_additive = True if current.key: value = current.key.co.y else: value = fc.evaluate(frame) left.value = prop_value + (left.value - value) current.value = prop_value # + (value - value) right.value = prop_value + (right.value - value) if tween.update: if sVal not in updates: updates[sVal] = list() if eVal not in updates: updates[eVal] = list() updates[sVal].append(left) updates[eVal].append(right) # Add classes to memory fcurves[fc] = [left, current, right] if attr == 'rotation_quaternion': # Do math for quaternions if (action, path) not in quats: quats[(action, path)] = dict() if (src.lock_rotations_4d or not src.lock_rotation_w) \ and True not in src.lock_rotation[:]: quats[(action, path)][index] = (left, current, right) if updates: for frame in updates: context.scene.frame_set(frame) for (cls) in updates[frame]: if Is.iterable(prop): cls.value = cls.prop[cls.index] else: cls.value = getattr(cls.prop, cls.attr) context.scene.frame_set(scn_frame) for (action, path) in quats: if len(quats[action, path]) < 4: continue (w_left, w_current, w_right) = quats[action, path][0] (x_left, x_current, x_right) = quats[action, path][1] (y_left, y_current, y_right) = quats[action, path][2] (z_left, z_current, z_right) = quats[action, path][3] left_quat = [x.value for x in (w_left, x_left, y_left, z_left)] current_quat = [x.value for x in (w_current, x_current, y_current, z_current)] right_quat = [x.value for x in (w_right, x_right, y_right, z_right)] cpp.normalize_qt(left_quat) cpp.normalize_qt(current_quat) cpp.normalize_qt(right_quat) for x in (w_left, x_left, y_left, z_left): x.quat = left_quat for x in (w_current, x_current, y_current, z_current): x.quat = current_quat for x in (w_right, x_right, y_right, z_right): x.quat = right_quat return fcurves
def poll(self, context): if context.mode == 'POSE': return Get.selected_pose_bones(context) if context.mode == 'OBJECT': return Get.selected_objects(context)
def execute(self, context): from zpy_constraints import Constraint wgt = utils.find_op('bonewidget.create_widget') # if wgt is None: # def wgt(*nil, **null): # return for bone in Get.selected_pose_bones(context): if not (bone.parent and bone.parent.parent): continue rig = bone.id_data bone_name = bone.name # Get and create bones for edit mode Set.mode(context, 'EDIT', rig) editbone = rig.data.edit_bones[bone_name] class fk: head = editbone.parent.parent tail = editbone.parent bone = editbone class ik: head = New.bone(context, rig, name="IK-" + fk.head.name) tail = New.bone(context, rig, name="IK-" + fk.tail.name) bone = New.bone(context, rig, name="IK-" + fk.bone.name) class stretch: head = New.bone(context, rig, name="IK-Stretch-" + fk.head.name) tail = New.bone(context, rig, name="IK-Stretch-" + fk.tail.name) bone = New.bone(context, rig, name="IK-Stretch-" + fk.bone.name) fk_names = [b.name for b in cls(fk)] ik_names = [b.name for b in cls(ik)] stretch_names = [b.name for b in cls(stretch)] # Set transforms for edit bones for k in (ik, stretch): for (b, f) in zip(cls(k), cls(fk)): copy(b, f, 'bbone_x') copy(b, f, 'bbone_z') copy(b, f, 'matrix') copy(b, f, 'tail') for b in cls(stretch): b.inherit_scale = 'NONE' b.length /= 3 stretch.tail.head = fk.head.tail stretch.bone.head = fk.tail.tail ik.tail.tail = ik.bone.head # Set parenting ik.head.parent = fk.head.parent ik.tail.parent = ik.head # ik.bone.parent = fk.head.parent for (b, i) in zip(cls(stretch), cls(ik)): b.parent = i # Switch bones back to pose mode Set.mode(context, 'POSE', rig) bones = rig.pose.bones class fk: head = bones[fk_names[0]] tail = bones[fk_names[1]] bone = bones[fk_names[2]] class ik: head = bones[ik_names[0]] tail = bones[ik_names[1]] bone = bones[ik_names[2]] class stretch: head = bones[stretch_names[0]] tail = bones[stretch_names[1]] bone = bones[stretch_names[2]] # for k in ('fk', 'ik', 'stretch'): # for h in ('head', 'tail', 'bone'): # exec(f"{k}.{h} = bones[{k}.{h}.name]") # # fk.head = bones[fk.head.name] ik.head.ik_stretch = 0.10 ik.tail.ik_stretch = 0.10 # for (b, i) in zip(cls(ik), cls(fk)): # Set.matrix(b, Get.matrix(i)) # Insert constraints cc = Constraint.new(context, add_relations=False, add_drivers=False) cc.type = 'IK' cc.add_constraint(context, ik.tail, ik.bone).chain_count = 2 cc.type = 'COPY_TRANSFORMS' cc.add_constraint(context, fk.head, stretch.head) cc.add_constraint(context, fk.tail, stretch.tail) cc.add_constraint(context, fk.bone, stretch.bone) cc.type = 'STRETCH_TO' cc.add_constraint(context, fk.head, stretch.tail) cc.add_constraint(context, fk.tail, stretch.bone) fk.bone.bone.select = False ik.bone.bone.select = True if fk.bone.bone == rig.data.bones.active: rig.data.bones.active = ik.bone.bone # Hide bones fk.head.bone.hide = True ik.tail.bone.hide = True fk.tail.bone.hide = True fk.bone.bone.hide = True if not wgt: continue # wgt(cc, widget='Rigify - Arrows', slide=(0, 0, 0), rotate=(0, 0, 0), relative_size=True, global_size=1, scale=(1, 1, 1)) cc = dict(selected_pose_bones=[ik.head]) # wgt(cc, scale=(1.25, 1.50, 1), widget='Rigify - Arrows') wgt(cc, scale=(1, 1, 1), widget='Blenrig - IK Limb') cc = dict(selected_pose_bones=cls(stretch)) wgt(cc, scale=(3, ) * 3, widget='Sphere') cc = dict(selected_pose_bones=[ik.bone]) if 'hand' in ik.bone.name.lower(): wgt(cc, scale=(1, 1, 1), widget='Blenrig - Hand') elif 'foot' in ik.bone.name.lower(): wgt(cc, scale=(1, 1, 1), widget='Blenrig - Foot') else: wgt(cc, scale=(1, 1, 1), widget='Cube') return {'FINISHED'}
def poll(cls, context): # if not all((context.object and context.object.type == 'ARMATURE' and context.object.pose)): # if bpy.ops.object.editmode_toggle.poll(context.copy()): for b in Get.selected_pose_bones(context): if b.custom_shape and not b.id_data.proxy: return True
def poll(self, context): if context.mode == 'PAINT_WEIGHT': return return Get.selected_pose_bones(context)
def poll(self, context): if (context.mode == 'POSE'): return len(Get.selected_pose_bones(context)) > 1 elif (context.mode == 'EDIT_ARMATURE'): return len([b for b in Get.selected_bones(context) if b.select]) > 1