If you want to display an enum from an operator, use:
col.operator_enum("wm.template_operator", "preset_enum")
If you want to display an enum from an operator, use:
col.operator_enum("wm.template_operator", "preset_enum")
And to display operator as menu, I have to use operator_menu_enum
, right?
col.operator_menu_enum("wm.template_operator", "preset_enum")
As a drop-down, yes.
Iām sorry, but I have another bunch of questions.
BONE_PT_relations
for example) into custom operator?
import bpy
from bpy.types import Menu, Operator
class CUSTOM_MT_menu(Menu):
bl_label = "Main Menu"
bl_idname = "CUSTOM_MT_menu"
def draw(self, context):
layout = self.layout
pie = layout.menu_pie()
pie.operator("object.custom_operator", text='Operator')
class CUSTOM_OT_operator(Operator):
bl_idname = "object.custom_operator"
bl_label = "Operator"
def execute(self, context):
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self, width=70)
def draw(self, context):
layout = self.layout
layout.operator("mesh.primitive_cube_add", text = "Cube", icon = "MESH_CUBE")
layout.operator("mesh.primitive_cube_add", text = "Cube", icon = "MESH_CUBE")
layout.operator("mesh.primitive_cube_add", text = "Cube", icon = "MESH_CUBE")
classes = (
CUSTOM_MT_menu,
CUSTOM_OT_operator
)
register, unregister = bpy.utils.register_classes_factory(classes)
if __name__ == "__main__":
register()
bpy.ops.wm.call_menu_pie(name="CUSTOM_MT_menu")
pie.popover
doesnāt work with armature panels (btw same situation in PME). I assume itās because ofIs it bug? How to deal with it?
Thanks in advance.
Did you try it yourself? If yes but nothing happens, the what does the system console say?
You can use wm.call_panel
or write your own operator that displays itself as a button, which when clicked opens a specific panel.
Not really a bug. Some context members arenāt meant to exist outside certain areas. You can use the context override I showed earlier to manually assign these members.
Something like:
class Context(dict):
def __init__(self, context=None, **kwargs):
super().__init__()
self.__dict__ = self
if context is not None:
self.update(context.copy())
self.update(**kwargs)
arm = context.object if context.object.type == 'ARMATURE' else None
context_ = Context(context,
bone=context.active_bone,
armature=arm)
bpy.types.BONE_PT_relations.draw(self, context_)
To be fairā¦Initially I had no idea But after re-reading your first answer in this thread, I managed to do it, thank you.
The question is how to add collapse/expand button and label on top, and get rid of āOKā button then Iām calling operator from pie menuā¦(like in PME, third screenshot in my previous message).
import bpy
from bpy.types import Menu, Operator
class CUSTOM_MT_menu(Menu):
bl_label = "Main Menu"
bl_idname = "CUSTOM_MT_menu"
def draw(self, context):
layout = self.layout
pie = layout.menu_pie()
pie.operator("object.custom_operator", text='Test Operator')
pie.popover("DATA_PT_display", text="Relations")
pie.popover("OBJECT_PT_display", text="Display")
class CUSTOM_OT_operator(Operator):
bl_idname = "object.custom_operator"
bl_label = "Test Operator"
def execute(self, context):
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self)
def draw(self, context):
layout = self.layout
box = layout.box()
col = box.column()
override = Layout(col)
bpy.types.OBJECT_PT_display.draw(override, context)
if context.object.type == 'ARMATURE':
context_ = Context(context, armature=context.object.data)
box = layout.box()
col = box.column()
override = Layout(col)
bpy.types.DATA_PT_display.draw(override, context_)
class Context(dict):
def __init__(self, context=None, **kwargs):
super().__init__()
self.__dict__ = self
if context is not None:
self.update(context.copy())
self.update(**kwargs)
class Layout:
def __init__(self, layout):
self.layout = layout
classes = (
CUSTOM_MT_menu,
CUSTOM_OT_operator,
)
register, unregister = bpy.utils.register_classes_factory(classes)
if __name__ == "__main__":
register()
bpy.ops.wm.call_menu_pie(name="CUSTOM_MT_menu")
Wellā¦But itās not pie.popover. Or I donāt quite understandā¦nevermind.
For some reason I forget to insert
pie.popover("DATA_PT_display", text="Relations")
pie.popover("OBJECT_PT_display", text="Display")
into my code last time.
Ah. And I know nothing about wm.call_panel
. There is not to much information about it. How to use it?
You can create an enum in your custom operator and use layout.operator_enum()
. To call the draw function without an āOKā button, use context.window_manager.invoke_popup()
.
import bpy
from bpy.types import Menu, Operator
class CUSTOM_MT_menu(Menu):
bl_label = "Main Menu"
bl_idname = "CUSTOM_MT_menu"
def draw(self, context):
layout = self.layout
pie = layout.menu_pie()
pie.operator_enum("object.custom_operator", "enum")
# pie.popover("DATA_PT_display", text="Relations")
# pie.popover("OBJECT_PT_display", text="Display")
class CUSTOM_OT_operator(Operator):
bl_idname = "object.custom_operator"
bl_label = "Test Operator"
enum: bpy.props.EnumProperty(items=(
("RELATIONS", "Relations", ""),
("DISPLAY", "Display", ""),
))
def execute(self, context):
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_popup(self)
def draw(self, context):
layout = self.layout
if self.enum == 'DISPLAY':
layout.label(text="Display")
box = layout.box()
col = box.column()
override = Layout(col)
bpy.types.OBJECT_PT_display.draw(override, context)
elif self.enum == 'RELATIONS':
if context.object.type == 'ARMATURE':
layout.label(text="Relations")
context_ = Context(context, armature=context.object.data)
box = layout.box()
col = box.column()
override = Layout(col)
bpy.types.DATA_PT_display.draw(override, context_)
class Context(dict):
def __init__(self, context=None, **kwargs):
super().__init__()
self.__dict__ = self
if context is not None:
self.update(context.copy())
self.update(**kwargs)
class Layout:
def __init__(self, layout):
self.layout = layout
classes = (
CUSTOM_MT_menu,
CUSTOM_OT_operator,
)
register, unregister = bpy.utils.register_classes_factory(classes)
if __name__ == "__main__":
register()
bpy.ops.wm.call_menu_pie(name="CUSTOM_MT_menu")
Note that you wonāt get control over where each button is placed in the pie. You can get around this by creating an EnumProperty()
with one element in each.
Thank you!
Is it possible to add those triangle collapse/expand buttons to panels?
To draw the expand/collapse arrows you would need to write the toggle logic in the operator. That means an expand
BoolProperty for each panel you want to draw, and drawing it at the top of the panel. To do this programmatically is possible, but it requires a bigger framework. Suggest you take a look at how PME does it.
import bpy
from bpy.types import Menu, Operator
class CUSTOM_MT_menu(Menu):
bl_label = "Main Menu"
bl_idname = "CUSTOM_MT_menu"
def draw(self, context):
layout = self.layout
pie = layout.menu_pie()
pie.operator("object.custom_operator")
class CUSTOM_OT_operator(Operator):
bl_idname = "object.custom_operator"
bl_label = "Test Operator"
relations_expand: bpy.props.BoolProperty(default=True)
display_expand: bpy.props.BoolProperty(default=True)
def execute(self, context):
return {'FINISHED'}
def draw(self, context):
layout = self.layout
box = layout.box()
row = box.row()
row.alignment = 'LEFT'
row.emboss = 'NONE'
expand = self.display_expand
icon = "TRIA_DOWN" if expand else "TRIA_RIGHT"
row.prop(self, "display_expand", text="Display", icon=icon)
if expand:
override = Layout(box)
bpy.types.OBJECT_PT_display.draw(override, context)
type(context).armature = context.object.data
box = layout.box()
row = box.row()
row.alignment = 'LEFT'
row.emboss = 'NONE'
expand = self.relations_expand
icon = "TRIA_DOWN" if expand else "TRIA_RIGHT"
row.prop(self, "relations_expand", text="Relations", icon=icon)
if expand:
override = Layout(box)
bpy.types.DATA_PT_display.draw(override, context)
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_popup(self)
class Context(dict):
def __init__(self, context=None, **kwargs):
super().__init__()
self.__dict__ = self
if context is not None:
self.update(context.copy())
self.update(**kwargs)
class Layout:
def __init__(self, layout):
self.layout = layout
classes = (
CUSTOM_MT_menu,
CUSTOM_OT_operator,
)
register, unregister = bpy.utils.register_classes_factory(classes)
if __name__ == "__main__":
register()
bpy.ops.wm.call_menu_pie(name="CUSTOM_MT_menu")
Thank you so much!