3
$\begingroup$

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

$\endgroup$
1
  • $\begingroup$ You should not change your question. Ask a new one instead. The people who answered the question do not get notified with your progressive inquiries. Read this: meta.stackoverflow.com/questions/365154/… $\endgroup$
    – unwave
    Commented Jun 17 at 9:14

2 Answers 2

3
+50
$\begingroup$

If I understand you correctly, you want to add a new entry in the Pose panel (Properties > Data > Pose). For this you need to extend the existing panel, not create a new one.

To add a new entry in the panel you need to append a custom draw function to Panel.draw

How to add a button to outliner header via python script?

Check if a draw function exists in a Menu before registering

Python: Extend "Select Similar" menu?

import bpy

# 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.stretch", text= 'Reset Stretch-Tos')

    # else show nothing
    else:          
        pass        

# register        
classes = (
    WM_OT_Stretch,  # 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()
$\endgroup$
1
  • $\begingroup$ Well that does certainly add the button, that's a huge step forward thanks. Now I need to figure out why my reset code doesn't work. If you have no objections, once I figure that out I'll edit this answer to include the whole code, for anyone else who wants to use it. $\endgroup$ Commented Apr 10 at 20:38
2
$\begingroup$

You can find the source code of the UI by using the Edit Source operator after right clicking on the UI element. It will open the file in the text editor and put the cursor at the place of interest. For some UI elements this is not available, some of them are written in C and could not be changed.

Developer Extras must be enabled to see Edit Source: https://docs.blender.org/manual/en/latest/editors/preferences/interface.html#bpy-types-preferencesview-show-developer-ui

enter image description here

$\endgroup$
1
  • $\begingroup$ Knowing that Developer Extras is a thing would have been handy years ago, thank you so much. $\endgroup$ Commented Apr 10 at 20:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .