7
$\begingroup$

Is there a way to add search functionality to EnumProperty in my add-on, similar to material search?
Or maybe there is another property with search functionality that I could use?

enter image description here

$\endgroup$
2
  • $\begingroup$ blender.stackexchange.com/a/8814/5113 $\endgroup$
    – Chebhou
    Commented Jan 17, 2016 at 12:44
  • $\begingroup$ @Chebhou Thanks, but template_list is not what I am looking for, it's too big and has a different and more complicated purpose than a simple dropdown list. $\endgroup$ Commented Jan 17, 2016 at 15:26

2 Answers 2

6
$\begingroup$

As of Blender 2.79+ you can use a PointerProperty:

Demo based on @batFINGERs answer to Object selection box with eyedropper

import bpy
from bpy.props import PointerProperty


class TEST_PT_layout_panel(bpy.types.Panel):
    bl_label = "Prop Panels"
    bl_category = "Test Panel"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "scene"

    def draw(self, context):
        scene = context.scene
        layout = self.layout
        
        col = layout.column()
        col.prop_search(scene, "prop_obj", context.scene, "objects")
        #or 
        col.prop(scene, "prop_obj")
        col.prop(scene, "prop_mat")


def register():
    bpy.types.Scene.prop_obj = PointerProperty(type=bpy.types.Object)
    bpy.types.Scene.prop_mat = PointerProperty(type=bpy.types.Material)
    bpy.utils.register_class(TEST_PT_layout_panel)


def unregister():
    bpy.utils.unregister_class(TEST_PT_layout_panel)
    del bpy.types.Scene.prop_obj
    del bpy.types.Scene.prop_mat
    
if __name__ == "__main__":
    register()
    bpy.ops.wm.call_panel(name="TEST_PT_layout_panel")

Alternatively you can use a Search Popup. The following operator example lists all objects in the scene and returns the selected object name:

enter image description here

Blender 2.8+

bl_info = {
    "name": "Search Popup",
    "version": (0, 0, 1),
    "blender": (2, 80, 0),
    "category": "Development"
}

import bpy

from bpy.props import EnumProperty
from bpy.types import Operator


# ------------------------------------------------------------------------
#   Operator
# ------------------------------------------------------------------------

def my_callback(scene, context):
    objs = ([o.name for o in bpy.context.scene.objects])
    return [(y.upper(), y, "", x) for x, y in enumerate(objs)]


class MYCAT_OT_searchPopup(Operator):
    """Tooltip"""
    bl_idname = "object.search_popup"
    bl_label = "Search Popup"
    bl_property = "my_enum"

    my_enum: EnumProperty(name="Objects", description="", items=my_callback)

    def execute(self, context):
        self.report({'INFO'}, "You've selected: %s" % self.my_enum)
        return {'FINISHED'}

    def invoke(self, context, event):
        wm = context.window_manager
        wm.invoke_search_popup(self)
        return {'FINISHED'}


# ------------------------------------------------------------------------
#   Register
# ------------------------------------------------------------------------

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

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

if __name__ == "__main__":
    register()

    # test call
    bpy.ops.object.search_popup('INVOKE_DEFAULT')

Blender 2.7x

bl_info = {
    "name": "Search Popup",
    "version": (0, 0, 1),
    "blender": (2, 75, 0),
    "category": "Test"
}

import bpy

from bpy.props import (EnumProperty,
                       PointerProperty,
                       )
from bpy.types import (Operator,
                       AddonPreferences,
                       PropertyGroup,
                       )


# ------------------------------------------------------------------------
#    store properties in the active scene
# ------------------------------------------------------------------------

def my_callback(scene, context):
    objs = ([o.name for o in bpy.context.scene.objects])
    return [(y.upper(), y, "", x) for x, y in enumerate(objs)]


class MySettings(PropertyGroup):

    objs = EnumProperty(
        name="Objects",
        description="",
        items=my_callback
        )

# ------------------------------------------------------------------------
#    operator
# ------------------------------------------------------------------------

class MyOperator(Operator):
    """Tooltip"""
    bl_idname = "object.search_popup"
    bl_label = "Search Popup"
    bl_property = "my_enum"
    
    my_enum = MySettings.objs
    
    def execute(self, context):
        self.report({'INFO'}, "You've selected: %s" % self.my_enum)
        return {'FINISHED'}

    def invoke(self, context, event):
        wm = context.window_manager
        wm.invoke_search_popup(self)
        return {'FINISHED'}
    
# ------------------------------------------------------------------------
# register and unregister functions
# ------------------------------------------------------------------------

def register():
    bpy.utils.register_module(__name__)
    bpy.types.Scene.my_tool = PointerProperty(type=MySettings)

def unregister():
    bpy.utils.unregister_module(__name__)
    del bpy.types.Scene.my_tool

if __name__ == "__main__":
    register()
    
    # test call
    bpy.ops.object.search_popup('INVOKE_DEFAULT')

Related:

$\endgroup$
4
  • $\begingroup$ Sure, here is the add-on. $\endgroup$ Commented Jan 19, 2016 at 11:15
  • $\begingroup$ @MikhailRachinskiy Looking great :) Thanks for sharing! $\endgroup$
    – p2or
    Commented Jan 19, 2016 at 12:08
  • $\begingroup$ I'm new to python. Question is it also possible to list scene collections like the objects and materials in the example? Working in Blender 3.6.x $\endgroup$ Commented Oct 31, 2023 at 16:44
  • 1
    $\begingroup$ Yeah, it should work the same way @ChristophWerner $\endgroup$
    – p2or
    Commented Jan 2 at 8:00
1
$\begingroup$

One can use bpy.types.UILayout.template_ID to get this UI element, but it works only with datablocks, enums won't work with it.

$\endgroup$
5
  • $\begingroup$ just out of curiosity did you look into the py script that calls such a template? $\endgroup$ Commented Jan 16, 2016 at 19:03
  • $\begingroup$ @ClaasKuhnen Sure, just press RMB on "Add new material" button and select "Edit Source" from drop down menu. $\endgroup$ Commented Jan 17, 2016 at 5:44
  • $\begingroup$ U missunderstood me me. As far as I know the templates point to other Py files where they define the layout for just UI elements. Maybe in those py files is the answer to your question. $\endgroup$ Commented Jan 17, 2016 at 17:01
  • 1
    $\begingroup$ @ClaasKuhnen As far as I know all UI elements written in C, just to check I looked in Blender's /scripts/modules folder and discovered nothing that might describe UI elements. $\endgroup$ Commented Jan 17, 2016 at 19:17
  • $\begingroup$ I am sorry - just thought this might be an option. $\endgroup$ Commented Jan 17, 2016 at 20:32

You must log in to answer this question.

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