I've been trying to make a button to reset all the stretch-tos in my custom armature as per this question, but my previous menu work has all been in a new menu section in the sidebar of the 3D view.
As per this reply, I now have a button that appears at the correct time, thank you very much for that, but now I'm having trouble calling the function itself.
import bpy
from mathutils import Matrix
from bpy.types import (Panel,
Menu,
Operator,
PropertyGroup,
Struct,
)
from bpy.props import (StringProperty,
BoolProperty,
IntProperty,
FloatProperty,
FloatVectorProperty,
EnumProperty,
PointerProperty,
)
# Yes I will trim down the import section once I know what it actually needs.
class WM_OT_Stretchto(Operator):
bl_label = "Reset Stretch-Tos"
bl_idname = "wm.stretchto"
bl_options = {'REGISTER', 'INTERNAL'}
@classmethod
def poll(cls, context):
return True
def execute(self, context):
override = context.copy()
context = bpy.context
for b in context.selected_pose_bones_from_active_object:
b.matrix_basis = Matrix()
bpy.ops.screen.frame_jump()
for b in bpy.context.selected_pose_bones:
for c in b.constraints:
if c.type == "STRETCH_TO":
bpy.ops.constraint.stretchto_reset()
# this is what the X next to the field in the constraint menu says it does,
# but in this script, it does nothing, and I can't figure out why.
bpy.ops.screen.frame_jump()
return {'FINISHED'}
def invoke(self, context, event):
return context.window_manager.invoke_props_dialog(self)
# operator
class WM_OT_Stretch(bpy.types.Operator):
bl_label = "Reset Stretch-Tos"
bl_idname = "wm.stretch"
bl_options = {'REGISTER', 'INTERNAL'}
def execute(self, context):
print("op called")
return {'FINISHED'}
# custom draw function
def draw_stretch(self, context):
layout = self.layout
# show if rest
if context.object.data.pose_position == 'REST':
layout.operator("wm.stretchto", text= 'Reset Stretch-Tos')
# else show nothing
else:
pass
# register
classes = (
WM_OT_Stretch,
WM_OT_Stretchto # operator
)
def register():
from bpy.utils import register_class
for cls in classes:
register_class(cls)
# avoid multi entries
cls = getattr(bpy.types, "DATA_PT_pose") # get class
if hasattr(cls.draw, "_draw_funcs"): # check if any draw function appended
if not [f for f in cls.draw._draw_funcs if f.__name__ == 'draw_stretch']: # check if custom draw in panel draw_funcs
cls.append(draw_stretch) # append
else:
cls.append(draw_stretch) # append
if __name__ == "__main__":
register()
UPDATE: I'm now getting an error from line 31 that says AttributeError: 'Context' object has no attribute 'grease_pencil'
It shouldn't even be calling for grease pencil so IDK what that's about.
Further Update:
I've tried this in 4.1 now and it gives meTypeError: 'Armature' object is not iterable