i want to make a menu for some things in a list (no blender-objects).
i used bpy.types.menu but i have some problems there (see image)
i have the problem, that the menu/list-items go to the right side after the 20th item.
i also want to add a search-field for it.
(on the right side of the image you can see, how i want my menu)
import bpy
class CustomMenu(bpy.types.Menu):
bl_label = "RubberDuck's New Bad Ass Menu" #panel name displayed in header
bl_idname = "OBJECT_MT_custom_menu"
def draw(self, context):
layout = self.layout
class SimpleOperator(bpy.types.Operator):
"""Tooltip"""
bl_idname = "object.simple_operator"
bl_label = "Simple Object Operator"
bl_options = {'REGISTER', 'UNDO'}
bl_property = "enumprop"
def item_cb(self, context):
return [(mat.name, mat.name, '') for mat in self.mats]
mats = bpy.props.CollectionProperty(type=bpy.types.PropertyGroup)
enumprop = bpy.props.EnumProperty(items=item_cb)#(('1','One',''),('2','Two','')))
@classmethod
def poll(cls, context):
return (context.active_object is not None and
context.active_object.type == 'MESH')
def execute(self, context):
self.report({'INFO'}, self.enumprop)
return {'FINISHED'}
def invoke(self, context, event):
self.mats.clear()
for i in range(1, 40): #seaching between 1,40. Try switch between 1,5 and you understand the resualt
self.mats.add().name = "Badlamshade_says_change_this %i" % i #change this Badlamshade_says_change_this
context.window_manager.invoke_search_popup(self)
return {'FINISHED'}
def register():
bpy.utils.register_class(SimpleOperator)
def unregister():
bpy.utils.unregister_class(SimpleOperator)
if __name__ == "__main__":
register()
# test call
bpy.ops.object.simple_operator('INVOKE_DEFAULT')
def draw_item(self, context):
layout = self.layout
layout.menu(CustomMenu.bl_idname)
def register():
bpy.utils.register_class(CustomMenu)
# lets add ourselves to the main header
bpy.types.INFO_HT_header.append(draw_item)
def unregister():
bpy.utils.unregister_class(CustomMenu)
bpy.types.INFO_HT_header.remove(draw_item)
if __name__ == "__main__":
register()
# The menu can also be called from scripts
bpy.ops.wm.call_menu(name=CustomMenu.bl_idname)
I believe search popup is what you are looking for. This works as is when you hit run script; you’ll have to play around with it to your fancy.
That dropdown type is a template_ID() and only available for built-in ID types.
I suggest to use a prop_search() on a custom Collection. There’s also invoke_search_popup(), but it needs an operator (thus a button to start it in a panel).
import bpy
enum_items = (
('FOO', 'Foo', ''),
('BAR', 'Bar', '')
)
class SearchOp(bpy.types.Operator):
bl_idname = "wm.invoke_search_popup"
bl_label = "Invoke Search Popup"
bl_property = "enumprop"
enumprop = bpy.props.EnumProperty(items=enum_items)
def execute(self, context):
self.report({'INFO'}, self.enumprop)
context.scene.enum_string = self.enumprop
context.region.tag_redraw()
return {'FINISHED'}
def invoke(self, context, event):
context.window_manager.invoke_search_popup(self)
return {'FINISHED'}
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 = "object"
def draw(self, context):
layout = self.layout
obj = context.object
col = layout.column()
s = context.scene.enum_string
col.operator(SearchOp.bl_idname, s if s else SearchOp.bl_label)
col.prop_search(context.scene, "coll_string", context.scene, "coll")
def populate_coll(scene):
bpy.app.handlers.scene_update_pre.remove(populate_coll)
scene.coll.clear()
for identifier, name, description in enum_items:
scene.coll.add().name = name
def register():
bpy.utils.register_module(__name__)
bpy.types.Scene.enum = bpy.props.EnumProperty(items=enum_items)
bpy.types.Scene.coll = bpy.props.CollectionProperty(
type=bpy.types.PropertyGroup
)
bpy.types.Scene.enum_string = bpy.props.StringProperty()
bpy.types.Scene.coll_string = bpy.props.StringProperty()
bpy.app.handlers.scene_update_pre.append(populate_coll)
def unregister():
bpy.utils.unregister_module(__name__)
del bpy.types.Scene.enum
del bpy.types.Scene.coll
del bpy.types.Scene.string
if __name__ == "__main__":
register()
is there really no possibility?
when i start the script first in a blend file, nothing is selected in the menu.
isn’t it possible to reset this when clicking on the button?
i did not realize that i can search by typing something into the field :D.
there is only a small thing left.
i want to access the data of the list.
everytime i select something i want to print the selected(here from the example: the first value >> FOO and the second one Foo) into a label