bpy.types.PointerProperty fpr View Layer?

Hey folks,

I want a dropdown for scenes, objects and viewlayers. Therefore I used the Pointer Property.
This works well for all types exept ViewLayer.
Can someone tell me why this is a valid pointer to a scene

  bpy.types.Scene.job_scene = PointerProperty(
        name="Scene",
        type=bpy.types.Scene
    )

but this isnt a valid pointer to a view layer?

bpy.types.ViewLayer = PointerProperty(
        name="View Layer",
        type=bpy.types.ViewLayer
    )

CollectionProperty and PointerProperty can only contain types which inherit from bpy.types.ID, which Scene does, but ViewLayer does not. The whole property system is dated and in urgent need of some work, which it does not seem to get. You will need to hack your way around to get whatever it is you want.

is there any way to get a pointer to a view layer then? Do you know a hacky way?

I would recommend you tag this as python support instead of Released Scripts and Themes

Also what is your actual objective a pointer to a scene or a pointer to a layer collection within a scene?

I wanted a dropdown to select currently available view layers.

For anyone who stumbles upon this topic in the future, you can create a custom enum like this:

 vl: EnumProperty(
        name="View Layer",
        items=populate_enum
    )

then create a custom function which checks the current scene and returns a list of the current vlayers:

def populate_enum(scene, context):

    current_view_layers = []

    for view_layer in bpy.context.scene.view_layers.items():
        current_view_layers.append((view_layer[0],view_layer[0], ""),)
 
    return current_view_layers
1 Like

I would suggest replacing bpy.context with the passed context, they may not always point to the same thing.

Also you’d likely want to store your enum function result somewhere to avoid the infamous dynamic enum bug

There are also alternatives that will mimic a drop down list.

list coll names

Such as using a string with a search which would allow you to get different types of data.

# blender 3.4.1

import bpy


def coll_list(self, context, edit_text):
    # always list all collection names
	# coll_names = [coll.name for coll in context.scene.collection.children_recursive]
    # restrict list by typing
    coll_names = [coll.name for coll in context.scene.collection.children_recursive if coll.name.startswith(edit_text)]
    return coll_names

def recurLayerCollection(layerColl, collName):
    found = None
    if (layerColl.name == collName):
        return layerColl
    for layer in layerColl.children:
        found = recurLayerCollection(layer, collName)
        if found:
            return found

class TEST_PG_props(bpy.types.PropertyGroup):
    coll_name: bpy.props.StringProperty(
    search=coll_list)
    my_mode: bpy.props.EnumProperty(
        name="my_mode",
        items=(
            ("collection", "collection", "collection"),
            ("View_layer", "View_layer", "View_layer"),
        ),
        description="",
        default="collection",
    )


class TEST_PT_test_panel(bpy.types.Panel):
    bl_idname = "TEST_PT_test_panel"
    bl_label = "Test Panel"
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"
    bl_category = "Test Tab"
 
    def draw(self, context):
        my_props = context.window_manager.my_props
        layout = self.layout
        col = layout.column()
        row = col.row()
        row.prop(my_props, "my_mode", expand=True)
        col.prop(my_props, "coll_name", text="name")
        row = col.row()
        if not my_props.coll_name:
            return
        if my_props.my_mode == 'collection':
            tmp = bpy.data.collections.get(my_props.coll_name)
            row.prop(tmp, "hide_select")
            row.prop(tmp, "hide_viewport")
            row.prop(tmp, "hide_render")
        else:
            tmp = recurLayerCollection(context.view_layer.layer_collection, my_props.coll_name)
            row.prop(tmp, "exclude")
            row.prop(tmp, "hide_viewport")
            row.prop(tmp, "holdout")
            row.prop(tmp, "indirect_only")


classes = [
    TEST_PG_props,
    TEST_PT_test_panel,
    ]


def register():
    for cls in classes:
        bpy.utils.register_class(cls)
    bpy.types.WindowManager.my_props = bpy.props.PointerProperty(
            type=TEST_PG_props)


def unregister():
    for cls in classes:
        bpy.utils.unregister_class(cls)
    del bpy.types.WindowManager.my_props

if __name__ == "__main__":
    register()
2 Likes