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 '21 at 6:19
  • $\begingroup$ Oh is that a template? Good catch, thanks! Il check that out $\endgroup$
    – Rug
    Sep 24 '21 at 17:33
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$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.