More on template_list()
, which is related to the specific problem:
To search in properties other than a PropertyGroup
's .name
, you can either write a custom filter function (see Ui List Template), or use a little hack: Concatenate all fields for search and use it as .name
, but not draw it:
bl_info = {
"name": "Collection Menu",
"author": "CoDEmanX",
"version": (1, 0),
"blender": (2, 65, 0),
"location": "",
"description": "",
"warning": "",
"wiki_url": "",
"category": ""}
import bpy
coll_data = (
("Option A", "The first option, can be found by searching '1' as well"),
("Option B", "You can find this by searching for 'roflmao'"),
("Some text", "Some more descriptive explanation"),
("Blabla", "Talking stuff...")
)
class COLL_UL_search(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
if self.layout_type in {'DEFAULT', 'COMPACT'}:
# You should always start your row layout by a label (icon + text), or a non-embossed text field,
# this will also make the row easily selectable in the list! The later also enables ctrl-click rename.
# We use icon_value of label, as our given icon is an integer value, not an enum ID.
# Note "data" names should never be translated!
split = layout.split(0.3)
split.label(item.label)
split.label(item.description)
elif self.layout_type in {'GRID'}:
pass
class MyColl(bpy.types.PropertyGroup):
#name = bpy.props.StringProperty()
label = bpy.props.StringProperty()
description = bpy.props.StringProperty()
class HelloWorldPanel(bpy.types.Panel):
"""Creates a Panel in the Object properties window"""
bl_label = "Hello World Panel"
bl_idname = "OBJECT_PT_hello"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "scene"
def draw(self, context):
layout = self.layout
col = context.scene.col
idx = context.scene.col_idx
if idx >= len(col):
#context.scene.col_idx = len(col) - 1
text = "(index error)"
else:
text = col[idx].name
layout.template_list("COLL_UL_search", "", context.scene, "col", context.scene, "col_idx")
def collhack(scene):
bpy.app.handlers.scene_update_pre.remove(collhack)
try:
scene.col.clear()
except:
pass
for i, (label, description) in enumerate(coll_data, 1):
item = scene.col.add()
item.label = label
item.description = description
item.name = " ".join((str(i), label, description))
def register():
bpy.utils.register_module(__name__)
bpy.types.Scene.col = bpy.props.CollectionProperty(type=MyColl)
bpy.types.Scene.col_idx = bpy.props.IntProperty(default=0)
bpy.app.handlers.scene_update_pre.append(collhack)
def unregister():
bpy.utils.unregister_module(__name__)
del bpy.types.Scene.col
del bpy.types.Scene.col_idx
if __name__ == "__main__":
register()
And here's a complex, editable UIList that searches numbers, labels and descriptions:
import bpy
class MESH_UL_mylist(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index, flt_flag):
self.use_filter_show = True
if self.layout_type in {'DEFAULT', 'COMPACT'}:
split = layout.split(0.1)
split.label("%i." % (index + 1))
split = split.split(0.3)
split.prop(item, "label", text="", emboss=False)
split.prop(item, "description", text="", emboss=False)
elif self.layout_type in {'GRID'}:
pass
# Called once to filter/reorder items.
def filter_items(self, context, data, propname):
col = getattr(data, propname)
filter_name = self.filter_name.lower()
flt_flags = [self.bitflag_filter_item if any(
filter_name in filter_set for filter_set in (
str(i), item.label.lower(), item.description.lower()
)
)
else 0 for i, item in enumerate(col, 1)
]
if self.use_filter_sort_alpha:
flt_neworder = [x[1] for x in sorted(
zip(
[x[0] for x in sorted(enumerate(col), key=lambda x: x[1].label)],
range(len(col))
)
)
]
else:
flt_neworder = []
return flt_flags, flt_neworder
class MyColl(bpy.types.PropertyGroup):
#name = bpy.props.StringProperty()
label = bpy.props.StringProperty()
description = bpy.props.StringProperty()
class HelloWorldPanel(bpy.types.Panel):
"""Creates a Panel in the Object properties window"""
bl_label = "Hello World Panel"
bl_idname = "OBJECT_PT_hello"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "scene"
def draw(self, context):
layout = self.layout
layout.template_list("MESH_UL_mylist", "", context.scene, "col", context.scene, "col_idx")
# Demo data
coll_data = (
("Option A", "The first option, can be found by searching '1' as well"),
("Option B", "You can find this by searching for 'roflmao'"),
("Some text", "Some more descriptive explanation"),
("Blabla", "Talking stuff...")
)
def register():
bpy.utils.register_module(__name__)
bpy.types.Scene.col = bpy.props.CollectionProperty(type=MyColl)
bpy.types.Scene.col_idx = bpy.props.IntProperty(default=0)
# Add demo data
scene = bpy.context.scene
#scene.col.clear()
if 1: #len(scene.col) < 1:
for label, description in coll_data:
item = scene.col.add()
item.label = label
item.description = description
def unregister():
bpy.utils.unregister_module(__name__)
del bpy.types.Scene.col
del bpy.types.Scene.col_idx
if __name__ == "__main__":
register()