Auria
(Auria)
June 10, 2011, 6:56pm
1
Hi,
this sounds unbelievably simple, and maybe I’ve missed something; but I can’t figure how to make a dynamic dropdown menu/combo.
I know how to make a dropdown using “bpy.props.EnumProperty”. But it appears that you need to set the possible values when creating the property. What if the possible values change over time? (I tried overwriting the EnumProperty with new values but this just results in blender crashing).
So is anyone aware of a strategy to achieve this seemingly simple task?
Thanks
Jambay
(Jambay)
June 10, 2011, 7:50pm
2
There are several ways - but the simplest, and non-Blender related, is:
Create a list with more than you expect to use. Only show those that you are using…
Very common strategy when creating structures to allow for modification in future releases. Make space for options that you haven’t implemented yet and the read/write ops won’t change just the details of how the structure is handled.
HTH/makes sense.
Can anyone tell me “what is dynamic popups?”
Auria
(Auria)
June 11, 2011, 11:44am
4
A popup menu in which the elements are different over time (determined dynamically). At this time I only know how to make a popup with static contents (contents doesn’t change)
@Jambay :
this is somewhat interesting, but in my case I don’t think this is a feasible approach; I need to build the list of items from the scene created by the user, so I can’t know the possibilities in advance
you could use a menu list which can be upated dynamically and put in your dynamic pop up window!
salutations
Auria
(Auria)
June 12, 2011, 7:50am
6
RickyBlender, maybe you can be a little more specific? The closest I have managed to obtain so far is :
import bpy
l = []
for curr in bpy.data.objects:
l.append( (curr.name, curr.name, curr.name) )
class ObjectPickerCombo(bpy.types.Operator):
bl_idname = "screen.stk_object_picker"
bl_label = ("SuperTuxKart object picker")
m_property_id = id
m_obj = ""
m_props = []
value = bpy.props.EnumProperty(attr="value", name="value", default=l[0][0],
items=l)
def invoke(self, context, event):
print("Outer invoke")
l = []
for curr in bpy.data.objects:
l.append( (curr.name, curr.name + " (updated)", curr.name + " (updated)") )
ObjectPickerCombo.value = bpy.props.EnumProperty(attr="value", name="value", default=l[0][0],
items=l)
context.region.tag_redraw()
upper = self
class ObjectPickerDialog(bpy.types.Operator):
bl_idname = "screen.stk_object_picker_dialog"
bl_label = ("SuperTuxKart select object")
m_upper = upper
the_list = l
def execute(self, context):
print("Exec inner")
context.region.tag_redraw()
context.window_manager.invoke_props_dialog(self)
context.region.tag_redraw()
return {'FINISHED'}
def draw(self, context):
self.m_props = []
layout = self.layout
for curr in self.the_list:
layout.prop_enum(self.m_upper, "value", curr[0])
self.l = l
#context.window_manager.invoke_props_dialog(self)
bpy.utils.register_class(ObjectPickerDialog)
context.region.tag_redraw()
bpy.ops.screen.stk_object_picker_dialog()
context.region.tag_redraw()
return {'RUNNING_MODAL'}
def execute(self, context):
context.region.tag_redraw()
print("Exec")
return {'FINISHED'}
bpy.utils.register_class(ObjectPickerCombo)
class HelloWorldPanel(bpy.types.Panel):
bl_idname = "OBJECT_PT_hello_world"
bl_label = "Hello World"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "object"
def draw(self, context):
self.layout.label(text="Hello World")
self.layout.operator("screen.stk_object_picker", text="", icon="TRIA_DOWN")
bpy.utils.register_class(HelloWorldPanel)
Apart from being surprisingly complicated, this little snippet also crashes blender. Maybe you can see what I’m doing wrong?
Auria
(Auria)
June 12, 2011, 8:54am
7
OK thanks a lot for pointing me this link
By modifying the example in the link, I finally obtained this, which is exactly what I wanted :
import bpy
class SelectObjectOperator(bpy.types.Operator):
bl_idname = "scene.select_object"
bl_label = "Select Object Operator"
name = bpy.props.StringProperty()
def execute(self, context):
context.scene["selection"] = self.name
print("Executing", self.name)
return {'FINISHED'}
bpy.utils.register_class(SelectObjectOperator)
class BranchMenu(bpy.types.Menu):
bl_idname = "mocapmadness.branchmenu"
bl_label = "Branch to Action"
def draw(self, context):
objects = context.scene.objects
layout = self.layout
for object in objects:
if object.type != "MESH": continue
text = object.name
layout.operator("scene.select_object", text=text).name=text
class OBJECT_PT_hello(bpy.types.Panel):
bl_label = "Hello World Panel"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "object"
def draw(self, context):
layout = self.layout
obj = context.object
row = layout.row()
row.prop(context.scene, '["selection"]')
row.menu("mocapmadness.branchmenu",text="", icon="TRIA_DOWN")
def register():
bpy.utils.register_class(BranchMenu)
bpy.utils.register_class(OBJECT_PT_hello)
def unregister():
bpy.utils.unregister_class(OBJECT_PT_hello)
if __name__ == "__main__":
register()
Thanks!
so your talking about a menu button not a pop up window !
now this add only a panel in object panel propertie on the right
i mean if you select several objects then i can see the dynamic menu with only an arrow
but would be nicer if this was like a menu button ?
glad i could help
happy 2.5
rarebit
(rarebit)
June 14, 2011, 7:24am
9
Nice… I’d call this a drop down combo (even though it didn’t drop down in my case)