Code Template for a Pop-up Menu?

Hi,

Is there a code template for creating a pop-up menu?
Much the same when I press Ctrl+Shift+C and the rigging menu pops up.

I want to make the same pop-up plugin but with my own custom commands.

Here is the behavior that I am after:

Regards,
Ben

Yeah it should be UI Menu or UI Menu Simple, under the Templates>>Python dropdown in the Text Editor window.

These might also help for getting it up and running:

1 Like

Hi @bluepython

Thanks for the response. Yes, it seems like the UI Menu or UI Menu Simple is the way to go, but how do I lay-out them in a “columnar” manner like the Ctrl+Shift+C above?

You can use the draw function to mess with the layout, adding columns or adding line items to the same rows, etc. So you define the draw function in your class and reference your different elements inside it. This might help a bit:

1 Like

@bluepython

Thanks again for the response but for some reason the draw function doesn’t work on the UI Template.
I tried adding the layout.prop but it does not work. It also doesn’t error out.

Here is the code so far:

import bpy


class SimpleCustomMenu(bpy.types.Menu):
    bl_label = "Simple Custom Menu"
    bl_idname = "OBJECT_MT_simple_custom_menu"
    
    text = bpy.props.StringProperty(name="Enter Text", default="")
    scale = bpy.props.FloatProperty(name="Scale", default=1)
    rotation = bpy.props.BoolProperty(name="Z Up", default=False)
    center = bpy.props.BoolProperty(name="Center Origin", default=False)
    extrude = bpy.props.BoolProperty(name="Extrude", default=False)
    extrude_amount = bpy.props.FloatProperty(name="Extrude Amount", default=0.06)

    def draw(self, context):
        layout = self.layout

        layout.label(text="Sample Text")
        layout.prop(self, "text")
        layout.prop(self, "scale")
        layout.prop(self, "rotation")
        layout.prop(self, "center")
        layout.prop(self, "extrude")
        layout.prop(self, "extrude_amount")

        
        #layout.operator("wm.open_mainfile")
        #layout.operator("wm.save_as_mainfile")


def register():
    bpy.utils.register_class(SimpleCustomMenu)


def unregister():
    bpy.utils.unregister_class(SimpleCustomMenu)


if __name__ == "__main__":
    register()

    # The menu can also be called from scripts
    bpy.ops.wm.call_menu(name=SimpleCustomMenu.bl_idname)

Hi, you can’t declare props there, if your using custom props you’ll need to register them first, you’ll want to register in a property group https://docs.blender.org/api/master/bpy.props.html#propertygroup-example and then in register() use something like;

bpy.types.Scene.my_props = bpy.props.PointerProperty(type=YOUR PROPERTY GROUP)
Also remember to register the property group class.

Each property should be an annotation;
text : bpy.props.StringProperty(name=“Enter Text”, default="")

In draw you can lay it out using:
my_props = context.scene.my_props
layout.prop(my_props, ’ text’)
however it looks like you want layout.column_flow() https://docs.blender.org/api/master/bpy.types.UILayout.html?highlight=column_flow#bpy.types.UILayout.UILayout.column_flow

1 Like

btw you can call your menu using bpy.ops.wm.call_menu(name=“OBJECT_MT_simple_custom_menu” )

If all the functions are coming from a single operator you can declare you properties within the operator class variables and use an invoke pop up method https://docs.blender.org/api/master/bpy.types.WindowManager.html?highlight=invoke_props_dialog#bpy.types.WindowManager.WindowManager.invoke_props_dialog

1 Like

@PTCreative

Thanks for the response.

I tried registering it but it still does not work. Here is the code so far:

import bpy


class MaterialSettings(bpy.types.PropertyGroup):
    text : bpy.props.StringProperty(name="Enter Text", default="")
    scale : bpy.props.FloatProperty(name="Scale", default=1)
    rotation : bpy.props.BoolProperty(name="Z Up", default=False)
    center : bpy.props.BoolProperty(name="Center Origin", default=False)
    extrude : bpy.props.BoolProperty(name="Extrude", default=False)
    extrude_amount : bpy.props.FloatProperty(name="Extrude Amount", default=0.06)

bpy.utils.register_class(MaterialSettings)

bpy.types.Material.my_settings = bpy.props.PointerProperty(type=MaterialSettings)


class SimpleCustomMenu(bpy.types.Menu):
    bl_label = "Simple Custom Menu"
    bl_idname = "OBJECT_MT_simple_custom_menu"
    
    text : bpy.props.StringProperty(name="Enter Text", default="")
    scale : bpy.props.FloatProperty(name="Scale", default=1)
    rotation : bpy.props.BoolProperty(name="Z Up", default=False)
    center : bpy.props.BoolProperty(name="Center Origin", default=False)
    extrude : bpy.props.BoolProperty(name="Extrude", default=False)
    extrude_amount : bpy.props.FloatProperty(name="Extrude Amount", default=0.06)

    def draw(self, context):
        layout = self.layout
        
        layout.label(text="Sample Text")
        layout.prop(self, "text")
        layout.prop(self, "scale")
        layout.prop(self, "rotation")
        layout.prop(self, "center")
        layout.prop(self, "extrude")
        layout.prop(self, "extrude_amount")
        




def register():
    bpy.utils.register_class(SimpleCustomMenu)


def unregister():
    bpy.utils.unregister_class(SimpleCustomMenu)


if __name__ == "__main__":
    register()

    # The menu can also be called from scripts
    bpy.ops.wm.call_menu(name=SimpleCustomMenu.bl_idname)

Hey,
this should work, note the register functions and material props are found at
context.active_object.active_material.my_settings

class MaterialSettings(bpy.types.PropertyGroup):
	text : bpy.props.StringProperty(name="Enter Text", default="")
	scale : bpy.props.FloatProperty(name="Scale", default=1)
	rotation : bpy.props.BoolProperty(name="Z Up", default=False)
	center : bpy.props.BoolProperty(name="Center Origin", default=False)
	extrude : bpy.props.BoolProperty(name="Extrude", default=False)
	extrude_amount : bpy.props.FloatProperty(name="Extrude Amount", default=0.06)


class SimpleCustomMenu(bpy.types.Menu):
	bl_label = "Simple Custom Menu"
	bl_idname = "OBJECT_MT_simple_custom_menu"
	
	def draw(self, context):
		layout = self.layout
		props = context.active_object.active_material.my_settings
		
		layout.label(text="Sample Text")
		layout.prop(props, "text")
		layout.prop(props, "scale")
		layout.prop(props, "rotation")
		layout.prop(props, "center")
		layout.prop(props, "extrude")
		layout.prop(props, "extrude_amount")
		

def register():
	bpy.utils.register_class(SimpleCustomMenu)
	bpy.utils.register_class(MaterialSettings)
	bpy.types.Material.my_settings = bpy.props.PointerProperty(type=MaterialSettings)


def unregister():
	bpy.utils.unregister_class(SimpleCustomMenu)
	bpy.utils.unregister_class(MaterialSettings)
	del bpy.types.Material.my_settings 


if __name__ == "__main__":
	register()

# The menu can also be called from scripts
bpy.ops.wm.call_menu(name=SimpleCustomMenu.bl_idname)
1 Like

@PTCreative

Thanks for the reply. I tried your code but the result is exaclty the same when I execute it within Blender. (i.e. No error but no additional menu added either). :frowning:

@PTCreative and @bluepython

Thanks for the response. Regarding on registering properties to add to the pop-up menu.
Please see revised code below. I’ll tag now the thread as complete. I’ll just create a separate thread on them.

Thanks again!

import bpy


class MaterialSettings(bpy.types.PropertyGroup):
    text : bpy.props.StringProperty(name="Enter Text", default="Enter Text")
    scale : bpy.props.FloatProperty(name="Scale", default=1)
    rotation : bpy.props.BoolProperty(name="Z Up", default=False)
    center : bpy.props.BoolProperty(name="Center Origin", default=False)
    extrude : bpy.props.BoolProperty(name="Extrude", default=False)
    extrude_amount : bpy.props.FloatProperty(name="Extrude Amount", default=0.06)


class SimpleCustomMenu(bpy.types.Menu):
    bl_label = "Simple Custom Menu"
    bl_idname = "OBJECT_MT_simple_custom_menu"
    

    def draw(self, context):
        layout = self.layout
        
        scene = context.scene
        mytool = scene.my_tool
        
        layout.prop(mytool, "scale")
        layout.prop(mytool, "rotation")
        layout.prop(mytool, "center")
        layout.prop(mytool, "extrude")
        layout.prop(mytool, "extrude_amount")
        

classes = [MaterialSettings, SimpleCustomMenu] 

def register():
    for cls in classes:         
        bpy.utils.register_class(cls)

        bpy.types.Scene.my_tool = bpy.props.PointerProperty(type=MaterialSettings)

def unregister():
    for cls in classes:         
        bpy.utils.register_class(cls)
        del bpy.types.Scene.my_tool



#register, unregister = 

if __name__ == "__main__":
    register()

    # The menu can also be called from scripts
    bpy.ops.wm.call_menu(name=SimpleCustomMenu.bl_idname)

Hi , yes the my code only works if you have an active object with an assigned material, this way the settings are ‘per material’, otherwise you can register to the scene class to make it accessible at any time in the scene, it really depends what you’re wanting to achieve. All the best.

1 Like