1
$\begingroup$

Does anyone know how to clone an existing panel? Down below there is a partial solution from Jakemoyo ( thanks!), using a popover. But I don't want a popover, I want the original layout, just cloned. Any ideas?

Original question:

I have a problem that is driving me mad: I try to duplicate an existing panel for convenience (in my case the vertex group panel) and I simply can't find a way to do it.

What I tried: found the source, which in my case is the following:

class DATA_PT_vertex_groups(MeshButtonsPanel, Panel):

    bl_label = "Vertex Groups"
    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}

    @classmethod
    def poll(cls, context):
        engine = context.engine
        obj = context.object
        return (obj and obj.type in {'MESH', 'LATTICE'} and (engine in cls.COMPAT_ENGINES))

    def draw(self, context):
        layout = self.layout

        ob = context.object
        group = ob.vertex_groups.active

        rows = 3
        if group:
            rows = 5

        row = layout.row()
        row.template_list("MESH_UL_vgroups", "", ob, "vertex_groups", ob.vertex_groups, "active_index", rows=rows)

        col = row.column(align=True)

        col.operator("object.vertex_group_add", icon='ADD', text="")
        props = col.operator("object.vertex_group_remove", icon='REMOVE', text="")
        props.all_unlocked = props.all = False

        col.separator()

        col.menu("MESH_MT_vertex_group_context_menu", icon='DOWNARROW_HLT', text="")

        if group:
            col.separator()
            col.operator("object.vertex_group_move", icon='TRIA_UP', text="").direction = 'UP'
            col.operator("object.vertex_group_move", icon='TRIA_DOWN', text="").direction = 'DOWN'

        if (
                ob.vertex_groups and
                (ob.mode == 'EDIT' or
                 (ob.mode == 'WEIGHT_PAINT' and ob.type == 'MESH' and ob.data.use_paint_mask_vertex))
        ):
            row = layout.row()

            sub = row.row(align=True)
            sub.operator("object.vertex_group_assign", text="Assign")
            sub.operator("object.vertex_group_remove_from", text="Remove")

            sub = row.row(align=True)
            sub.operator("object.vertex_group_select", text="Select")
            sub.operator("object.vertex_group_deselect", text="Deselect")

            layout.prop(context.tool_settings, "vertex_group_weight", text="Weight")

I could copy paste the whole code generating this panel in my own code, but that seems overkill. Is there a better way to reference from the existing code? I mean, in case of an operator it's easy (pseudo code):

row.operator("my_addon.my_custom_operator_from_bpy.ops.blabla", text="do whatever")

I am aware of:

Copy existing property from e.g. Properties window to a custom panel

Is there a way to get custom properties panel in a custom t panel?

How to draw Blender's default panel in Operator draw function?

But those solutions are for some custom props, which are not the issue. I need the whole panel.

Thank you for your help!

$\endgroup$

2 Answers 2

2
+50
$\begingroup$

If your copy-class has all needed properties available and the same poll tests, just as the original class, then you could simply call the original's draw() call.. Here's small example with a new Panel..

import bpy

class CopyDrawPanel(bpy.types.Panel):
    """Duplicate draw"""
    bl_label = "Copy Draw Panel"
    bl_idname = "OBJECT_PT_copydraw"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "object"

    @classmethod
    def poll(cls, context):
        bpy.types.DATA_PT_vertex_groups.poll(cls, context)

    def draw(self, context):
        bpy.types.DATA_PT_vertex_groups.draw(self, context)

def register():
    bpy.utils.register_class(CopyDrawPanel)


def unregister():
    bpy.utils.unregister_class(CopyDrawPanel)
    
if __name__ == "__main__":
    register()  
$\endgroup$
4
  • $\begingroup$ Hi,thank you for your answer, I just tried, but it doesn't work. Maybe I misunderstood something. but the new class cannot have the same properties as the old one, bl_space_type, bL_region_type and bl_category have to be different, the idea being cloning the panel in a different region. Also, bpy.types.Copy__DATA_PT_vertex_groups.draw(self, context) gives a TypeError, as it accepts only one argument. $\endgroup$
    – radoo
    Commented Jul 25, 2022 at 8:13
  • $\begingroup$ Not the bl_* properties.. but if the original class uses some variable that is then referenced in the draw call, then you'll need to have that variable in your own copyclass.. Also, bpy.types.Copy__DATA_PT_vertex_groups is an illegal name... you should call bpy.types.DATA_PT_vertex_groups.draw(self, context) in your copy's draw() $\endgroup$
    – Secrop
    Commented Jul 25, 2022 at 8:53
  • $\begingroup$ I'm changing the code example, to reflect a bit better the one you show. $\endgroup$
    – Secrop
    Commented Jul 25, 2022 at 9:02
  • $\begingroup$ Ok, my bad, thanks a bunch! That solved it! $\endgroup$
    – radoo
    Commented Jul 25, 2022 at 9:46
1
$\begingroup$

You would do something like this, using a UILayout.popover:


# just using the UI_panel_simple.py as an example
import bpy


class HelloWorldPanel(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_label = "Hello World Panel"
    bl_idname = "OBJECT_PT_hello"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "object"

    def draw(self, context):
        layout = self.layout

        obj = context.object

        row = layout.row()
        row.label(text="Hello world!", icon='WORLD_DATA')

        row = layout.row()
        row.label(text="Active object is: " + obj.name)
        row = layout.row()
        row.prop(obj, "name")

        row = layout.row()
        row.operator("mesh.primitive_cube_add")
        row = layout.row()
       # this puts the same menu into a popover menu item in whatever menu 
       #you're working on.
        # try messing with the different options as well, I just used popover cause 
        # it seemed the most expedient.
        row.popover("DATA_PT_vertex_groups")


def register():
    bpy.utils.register_class(HelloWorldPanel)


def unregister():
    bpy.utils.unregister_class(HelloWorldPanel)
    


if __name__ == "__main__":
    register()

Which gives you this result:

enter image description here

enter image description here

You can probably mess with some of the other UILayout attributes, but I think this will get you in the ballpark.

$\endgroup$
1
  • $\begingroup$ Thank you. It works, but I can only make it work as popover. It seems that only the popover can wrap a whole panel. docs.blender.org/api/current/bpy.types.UILayout.html If you know a way to get the proper panel, I would be greatly appreciate it! $\endgroup$
    – radoo
    Commented Jul 18, 2022 at 6:03

You must log in to answer this question.

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