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?
2 Answers
$\begingroup$
$\endgroup$
4
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:
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:
-
-
$\begingroup$ @MikhailRachinskiy Looking great :) Thanks for sharing! $\endgroup$– p2orCommented 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$– p2orCommented Jan 2 at 8:00
$\begingroup$
$\endgroup$
5
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.
-
$\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
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$