0
$\begingroup$

Say I want to add a list of the UVLayers on a selected object in my UI Panel. Noted that PointerProperty only supports types with an ID or PropertyGroup subclass.

I tried instead passing the list of UV Layers as an EnumProperty in this way:

class PropGroup(PropertyGroup):
    def get_uvs(self):
        uvs = []
        for uvMap in self.seed_object.data.uv_layers:
            uvs.append(uvMap)
        return uvs

    seed_object: PointerProperty(
        name="Base Object",
        description="Object to duplicate",
        type=bpy.types.Object
    )

    seed_object_uvs: EnumProperty(
        name="Uvs",
        items=get_uvs()
    )
    ...

But I am getting an error that get_uvs is missing the parameter 'self'. When I pass 'self' literally in the line items=getuvs(self) it assumes this is a named argument. Declaring the function outside the class fixes the above issue of needing 'self', but throws an error where the seed_object parameter isn't defined. I understand this is because seed_object is being referenced before it is actually assigned, but still leaves me without a solution.

The clear workaround is to not declare the UVs as a property, and in the necessary operator(s) use something like object.uv_layers.active(), or whatever to get the layer. In general though, I'd like to know if there is a way to store this sort of object data in a Property Group or at least through the UI.

$\endgroup$
2
  • 2
    $\begingroup$ Goal is to replicate the regular UV layer list on a custom panel? If so, have a look into properties_data_mesh.py, there is a DATA_PT_uv_texture class calling: col.template_list("MESH_UL_uvmaps", "uvmaps", me, "uv_layers", me.uv_layers, "active_index", rows=2) to display the layers in a list. $\endgroup$
    – brockmann
    Sep 24, 2021 at 6:19
  • $\begingroup$ Oh is that a template? Good catch, thanks! Il check that out $\endgroup$
    – Rug
    Sep 24, 2021 at 17:33

1 Answer 1

2
$\begingroup$

Have a look into the UI source code (RMB on the UV layers > Edit Source). There is a DATA_PT_uv_texture class in properties_data_mesh.py calling UILayout.template_list() to display the UV layers (line 438).

In order to display the same list on a custom panel, just pass the actual mesh data C.object.data as me variable:

col.template_list("MESH_UL_uvmaps", "uvmaps", me, "uv_layers", me.uv_layers, "active_index", rows=2)

Demo based on the layout code from How to create a custom UI?

bl_info = {
    "name": "Add-on Template",
    "description": "",
    "author": "p2or",
    "version": (0, 0, 3),
    "blender": (2, 80, 0),
    "location": "3D View > Tools",
    "warning": "", # used for warning icon and text in addons panel
    "wiki_url": "",
    "tracker_url": "",
    "category": "Development"
}


import bpy
from bpy.types import Panel, Operator

# ------------------------------------------------------------------------
#    Operators
# ------------------------------------------------------------------------

class WM_OT_HelloWorld(Operator):
    bl_label = "Print Values Operator"
    bl_idname = "wm.hello_world"

    def execute(self, context):
        print (context.object.data.uv_layers.active)
        return {'FINISHED'}

# ------------------------------------------------------------------------
#    Panel in Object Mode
# ------------------------------------------------------------------------

class OBJECT_PT_CustomPanel(Panel):
    bl_label = "My Panel"
    bl_idname = "OBJECT_PT_custom_panel"
    bl_space_type = "VIEW_3D"   
    bl_region_type = "UI"
    bl_category = "Tools"
    #bl_context = "objectmode" 

    @classmethod
    def poll(self,context):
        return context.object is not None and context.object.type == 'MESH'

    def draw(self, context):
        layout = self.layout
        scene = context.scene
        me = context.object.data
        
        row = layout.row()
        row.template_list("MESH_UL_uvmaps", "uvmaps", me, "uv_layers", me.uv_layers, "active_index", rows=2)
        
        layout.operator(WM_OT_HelloWorld.bl_idname)
        layout.separator()

# ------------------------------------------------------------------------
#    Registration
# ------------------------------------------------------------------------

classes = (
    WM_OT_HelloWorld,
    OBJECT_PT_CustomPanel
)

def register():
    from bpy.utils import register_class
    for cls in classes:
        register_class(cls)

def unregister():
    from bpy.utils import unregister_class
    for cls in reversed(classes):
        unregister_class(cls)

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

You must log in to answer this question.

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