5
$\begingroup$

At the moment this addon makes a custom panel with only one button that prints "Active Panel IDName:", but how can I pass the class panel where this button was pressed? Is there a way to get the class name by the position of the mouse or the WM_OT_custom_operator itself?

import bpy

# Custom function to be called by the button
def custom_function():
    print("Active Panel IDName: ")


# Define the Panel class
class VIEW3D_PT_custom_panel(bpy.types.Panel):
    bl_label = "Custom Panel"
    bl_idname = "VIEW3D_PT_custom_panel"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = "Custom"

    # Draw the panel content
    def draw(self, context):
        layout = self.layout

        # Create a button and link it to the custom function
        layout.operator("wm.custom_operator", text="Call Custom Function")

# Define the Operator class
class WM_OT_custom_operator(bpy.types.Operator):
    bl_idname = "wm.custom_operator"
    bl_label = "Custom Operator"


    def execute(self, context):
        custom_function()
        return {'FINISHED'}

# Register the classes
def register():
    bpy.utils.register_class(VIEW3D_PT_custom_panel)
    bpy.utils.register_class(WM_OT_custom_operator)

# Unregister the classes
def unregister():
    bpy.utils.unregister_class(WM_OT_custom_operator)
    bpy.utils.unregister_class(VIEW3D_PT_custom_panel)


register()
$\endgroup$

2 Answers 2

4
$\begingroup$

You can declare a panel_idname variable within your operator class which you can initialize when you instantiate the button operator in the panel's draw function. Here's the working script:

import bpy

def custom_function(panel_idname):
    print("Active Panel IDName:", panel_idname)


class VIEW3D_PT_custom_panel(bpy.types.Panel):
    bl_label = "Custom Panel"
    bl_idname = "VIEW3D_PT_custom_panel"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = "Custom"

    def draw(self, context):
        layout = self.layout
        layout.operator("wm.custom_operator", text="Call Custom Function").panel_idname = self.bl_idname

class WM_OT_custom_operator(bpy.types.Operator):
    bl_idname = "wm.custom_operator"
    bl_label = "Custom Operator"

    panel_idname: bpy.props.StringProperty()

    def execute(self, context):
        custom_function(self.panel_idname)
        return {'FINISHED'}

def register():
    bpy.utils.register_class(VIEW3D_PT_custom_panel)
    bpy.utils.register_class(WM_OT_custom_operator)

def unregister():
    bpy.utils.unregister_class(WM_OT_custom_operator)
    bpy.utils.unregister_class(VIEW3D_PT_custom_panel)


if __name__ == "__main__":
    register()
$\endgroup$
4
$\begingroup$

You can also use the more obscure bpy.types.UILayout.context_pointer_set if you don't want to modify the operator signature. You add a custom attribute to the layout that's displaying the button.

import bpy

# Custom function to be called by the button
def custom_function(context):
    if hasattr(context, "my_panel"):
        print(context.my_panel.bl_idname)
        

class VIEW3D_PT_custom_panel(bpy.types.Panel):
    bl_label = "Custom Panel"
    bl_idname = "VIEW3D_PT_custom_panel"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = "Custom"

    def draw(self, context):
        layout = self.layout
        
        layout.context_pointer_set("my_panel", self)
        # Create a button and link it to the custom function
        layout.operator("wm.custom_operator", text="Call Custom Function")


class WM_OT_custom_operator(bpy.types.Operator):
    bl_idname = "wm.custom_operator"
    bl_label = "Custom Operator"

    def execute(self, context):
        custom_function(context)
        return {'FINISHED'}


def register():
    bpy.utils.register_class(VIEW3D_PT_custom_panel)
    bpy.utils.register_class(WM_OT_custom_operator)


if __name__ == "__main__":
    register()
$\endgroup$

You must log in to answer this question.

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