Add New Folder inside "Add Mesh"

Hi Reader,

i’m a complete Blender newby
found there are addons/plugin templates to create new meshes
working on a set of mesh plugins, all Platonic solids, so i would like to group them inside the “Add Mesh” when possible.

i think it has to be done here somehow, but i do not know how.
bpy.types.VIEW3D_MT_mesh_add.append(add_object_button)

any advise/help is absolutely welcome.
thank you

You have to define a draw function for your new items and then append it to VIEW3D_MT_mesh_add
This example will add a new button at the bottom of the add menu that calls object.delete:

import bpy

def draw(self, context):
    self.layout.operator("object.delete", icon="INFO")

def register():
   bpy.types.VIEW3D_MT_mesh_add.append(draw)

def unregister():
    bpy.types.VIEW3D_MT_mesh_add.remove(draw)

if __name__ == "__main__":
    register()
2 Likes

thankyou…
you do create a new button, i like to build a menu there

as you see i can add a separator there, and then i like to have some sort of submenu where i can add all my new buttons into that submenu

do have build a file with 5 addons, each have an own button, and these buttons i like to add in a submenu so my screenspace is neat and less messy

def draw(self, context):
self.layout.separator()
#self.layout.menu()
#self.layout.operator(“object.delete”, icon=“INFO”)

yes, all of that is possible. It’s well documented in the api docs, most of your questions will be answered there.

1 Like

The API Docs is not so clear for me, dont know how to read it in a proper way.
i am only a Newby in Blender…
thank you for your time, a syou see this forum thingy is also not working very well, how to get this text properly formatted is also one of my questions…:wink:

this is the solution

import bpy
class MyCustomMenu(bpy.types.Menu):
bl_label = “My Menu”
bl_idname = “OBJECT_MT_my_custom_menu”

def draw(self, context):
    layout = self.layout							 
    layout.operator("mesh.primitive_cube_add", icon='MESH_CUBE')
    layout.operator("mesh.primitive_cone_add", icon='MESH_CONE')
    layout.operator("mesh.primitive_plane_add", icon='MESH_PLANE')  		   

def MyCustomMenuAdd(self, context):
self.layout.menu(MyCustomMenu.bl_idname)

def register():
bpy.utils.register_class(MyCustomMenu)
bpy.types.VIEW3D_MT_mesh_add.append(MyCustomMenuAdd)

def unregister():
bpy.utils.unregister_class(MyCustomMenu)
bpy.types.VIEW3D_MT_mesh_add.remove(MyCustomMenuAdd)

if name == “main”:
register()

use three backticks to start and end code blocks (devtalk uses Markdown syntax). alternatively you can just select all of your code and hit the ‘preformatted text’ button, though it won’t have python syntax highlighting that way.

this("example")

vs

this("example")

1 Like

thank you, the menu i found works in the script editor, but when i load it as a plugin it does not… dont see an error why it does not load it…

maybe a systemboot will help

Perfect, thank you for your help/support, got it working and here is the awesome result…
Maybe you like som platonic Solids as well into your reportoire… :wink:

bl_info = {
    "name": "Platonic Solids",
    "author": ":. ieoie .:",
    "version": (1, 0),
    "blender": (2, 80, 0),
    "location": "View3D > Add > Mesh > New Platonic Solid",
    "description": "Adds a new Mesh Object",
    "category": "Add Mesh",
}


import bpy
import math
from bpy.types import Operator
from bpy.props import FloatVectorProperty
from bpy_extras.object_utils import AddObjectHelper, object_data_add
from mathutils import Vector

class PlatonicsMenu(bpy.types.Menu): 	 
    bl_label = "Platonic Solids"	   
    bl_idname = "OBJECT_MT_my_custom_menu"
        
    def draw(self, context):
        layout = self.layout							 
        layout.operator(OBJECT_OT_add_tetrapos.bl_idname,
                        text="Tetrahedron Positive", 
                        icon='PLUGIN')
        layout.operator(OBJECT_OT_add_tetraneg.bl_idname,
                        text="Tetrahedron Negative", 
                        icon='PLUGIN')
        layout.operator(OBJECT_OT_add_tetrastar.bl_idname,
                        text="Tetrahedron Star", 
                        icon='PLUGIN') 
        layout.operator(OBJECT_OT_add_octa.bl_idname,
                        text="Octahedron", 
                        icon='PLUGIN')
        layout.operator(OBJECT_OT_add_cube.bl_idname,
                        text="Cube", 
                        icon='PLUGIN')
        layout.operator(OBJECT_OT_add_dodeca.bl_idname,
                        text="Dodecahedron", 
                        icon='PLUGIN')
        layout.operator(OBJECT_OT_add_icosa.bl_idname,
                        text="Icosahedron", 
                        icon='PLUGIN')
        
def PlatonicsMenuAdd(self, context):
    self.layout.menu(PlatonicsMenu.bl_idname)


def add_tetrapos(self, context):
    scale_x = self.scale.x
    scale_y = self.scale.y
    scale_z = self.scale.z

    verts = [
        Vector((1 * scale_x, 1 * scale_y, 1 * scale_z)),
        Vector((-1 * scale_x, 1 * scale_y, -1 * scale_z)),
        Vector((-1 * scale_x, -1 * scale_y, 1 * scale_z)),
        Vector((1 * scale_x, -1 * scale_y, -1 * scale_z)),
    ]

    edges = []
    faces = [[0, 1, 2], [0, 2, 3], [0, 3, 1], [2, 1, 3]]

    mesh = bpy.data.meshes.new(name="obj_TetraPos")
    mesh.from_pydata(verts, edges, faces)
    # useful for development when the mesh may be invalid.
    # mesh.validate(verbose=True)
    object_data_add(context, mesh, operator=self)
    
def add_tetraneg(self, context):
    scale_x = self.scale.x
    scale_y = self.scale.y
    scale_z = self.scale.z

    verts = [
        Vector((1 * scale_x, 1 * scale_y, -1 * scale_z)),
        Vector((-1 * scale_x, 1 * scale_y, 1 * scale_z)),
        Vector((1 * scale_x, -1 * scale_y, 1 * scale_z)),
        Vector((-1 * scale_x, -1 * scale_y, -1 * scale_z)),
    ]

    edges = []
    faces = [[0, 1, 2], [0, 2, 3], [0, 3, 1], [2, 1, 3]]

    mesh = bpy.data.meshes.new(name="obj_TetraNeg")
    mesh.from_pydata(verts, edges, faces)
    # useful for development when the mesh may be invalid.
    # mesh.validate(verbose=True)
    object_data_add(context, mesh, operator=self)

def add_tetrastar(self, context):
    scale_x = self.scale.x
    scale_y = self.scale.y
    scale_z = self.scale.z
    
    verts = [
        Vector((1 * scale_x, 1 * scale_y, 1 * scale_z)),
        Vector((-1 * scale_x, 1 * scale_y, -1 * scale_z)),
        Vector((-1 * scale_x, -1 * scale_y, 1 * scale_z)),
        Vector((1 * scale_x, -1 * scale_y, -1 * scale_z)),
    
        Vector((1 * scale_x, 1 * scale_y, -1 * scale_z)),
        Vector((-1 * scale_x, 1 * scale_y, 1 * scale_z)),
        Vector((1 * scale_x, -1 * scale_y, 1 * scale_z)),
        Vector((-1 * scale_x, -1 * scale_y, -1 * scale_z))
    ]

    edges = []
    faces = [[0, 1, 2], [0, 2, 3], [0, 3, 1], [2, 1, 3],
            [4, 5, 6], [4, 6, 7], [4, 7, 5], [6, 5, 7]]

    mesh = bpy.data.meshes.new(name="obj_TetraStar")
    mesh.from_pydata(verts, edges, faces)
    # useful for development when the mesh may be invalid.
    # mesh.validate(verbose=True)
    object_data_add(context, mesh, operator=self)

def add_octahedron(self, context):
    scale_x = self.scale.x
    scale_y = self.scale.y
    scale_z = self.scale.z

    verts = [
        Vector((0, 0, 1 * scale_z)),
        Vector((1 * scale_x, 0, 0)),
        Vector((0, 1 * scale_y, 0)),
        Vector((-1 * scale_x, 0, 0)),
        Vector((0, -1 * scale_y, 0)),
        Vector((0, 0, -1 * scale_z)),
    ]

    edges = []
    faces = [[0, 1, 2], [0, 2, 3], [0, 3, 4], [0, 4, 1],
                [5, 2, 1], [5, 3, 2], [5, 4, 3], [5, 1, 4]]

    mesh = bpy.data.meshes.new(name="obj_Octahedron")
    mesh.from_pydata(verts, edges, faces)
    # useful for development when the mesh may be invalid.
    # mesh.validate(verbose=True)
    object_data_add(context, mesh, operator=self)

def add_cube(self, context):
    scale_x = self.scale.x
    scale_y = self.scale.y
    scale_z = self.scale.z
    
    verts = [
        Vector((1 * scale_x, 1 * scale_y, 1 * scale_z)),
        Vector((-1 * scale_x, 1 * scale_y, 1 * scale_z)),
        Vector((-1 * scale_x, -1 * scale_y, 1 * scale_z)),
        Vector((1 * scale_x, -1 * scale_y, 1 * scale_z)),
        
        Vector((1 * scale_x, 1 * scale_y, -1 * scale_z)),
        Vector((-1 * scale_x, 1 * scale_y, -1 * scale_z)),
        Vector((-1 * scale_x, -1 * scale_y, -1 * scale_z)),
        Vector((1 * scale_x, -1 * scale_y, -1 * scale_z)),
    ]

    edges = []
    faces = [[0, 1, 2, 3], [1, 0, 4, 5], [2, 1, 5, 6], [3, 2, 6, 7], [0, 3, 7, 4], [5, 4, 7, 6]]

    mesh = bpy.data.meshes.new(name="obj_Cube")
    mesh.from_pydata(verts, edges, faces)
    # useful for development when the mesh may be invalid.
    # mesh.validate(verbose=True)
    object_data_add(context, mesh, operator=self)

def add_dodeca(self, context):
    scale_x = self.scale.x
    scale_y = self.scale.y
    scale_z = self.scale.z
    
    sPhi = (math.sqrt(5) - 1.0) * 0.5
    lPhi = 1.0 + sPhi
    
    verts = [
        # Cube verts
        Vector((1 * scale_x, 1 * scale_y, 1 * scale_z)),
        Vector((-1 * scale_x, 1 * scale_y, -1 * scale_z)),
        Vector((-1 * scale_x, -1 * scale_y, 1 * scale_z)),
        Vector((1 * scale_x, -1 * scale_y, -1 * scale_z)),
    
        Vector((1 * scale_x, 1 * scale_y, -1 * scale_z)),
        Vector((-1 * scale_x, 1 * scale_y, 1 * scale_z)),
        Vector((1 * scale_x, -1 * scale_y, 1 * scale_z)),
        Vector((-1 * scale_x, -1 * scale_y, -1 * scale_z)),
        
        # Dodeca verts        
        Vector((0, lPhi * scale_y, sPhi * scale_z)),
        Vector((0, lPhi * scale_y, -sPhi * scale_z)),
        
        Vector((0, -lPhi * scale_y, sPhi * scale_z)),
        Vector((0, -lPhi * scale_y, -sPhi * scale_z)),
        
        Vector((sPhi * scale_x, 0, lPhi * scale_z)),
        Vector((-sPhi * scale_x, 0, lPhi * scale_z)),
        
        Vector((sPhi * scale_x, 0, -lPhi * scale_z)),
        Vector((-sPhi * scale_x, 0, -lPhi * scale_z)),
        
        Vector((lPhi * scale_x, sPhi * scale_y, 0)),
        Vector((lPhi * scale_x, -sPhi * scale_y, 0)),
        
        Vector((-lPhi * scale_x, sPhi * scale_y, 0)),
        Vector((-lPhi * scale_x, -sPhi * scale_y, 0)),
    ]

    edges = []
    faces = [[0, 16, 4, 9, 8], [0, 8, 5, 13, 12], [8, 9, 1, 18, 5], [4, 14, 15, 1, 9],
            [5, 18, 19, 2, 13], [1, 15, 7, 19, 18], [7, 15, 14, 3, 11], [2, 19, 7, 11, 10], 
            [3, 17, 6, 10, 11], [2, 10, 6, 12, 13], [6, 17, 16, 0, 12], [3, 14, 4, 16, 17]]

    mesh = bpy.data.meshes.new(name="obj_Dodeca")
    mesh.from_pydata(verts, edges, faces)
    # useful for development when the mesh may be invalid.
    # mesh.validate(verbose=True)
    object_data_add(context, mesh, operator=self)

def add_icosa(self, context):
    scale_x = self.scale.x
    scale_y = self.scale.y
    scale_z = self.scale.z
    
    sPhi = (math.sqrt(5) - 1.0) * 0.5
    lPhi = 1.0 + sPhi
    
    verts = [
        
        # Icosa verts        
        Vector((1 * scale_x, lPhi * scale_y, 0)),
        Vector((-1 * scale_x, lPhi * scale_y, 0)),
        Vector((1 * scale_x, -lPhi * scale_y, 0)),
        Vector((-1 * scale_x, -lPhi * scale_y, 0)),
        
        Vector((0, 1 * scale_y, lPhi * scale_z)),
        Vector((0, -1 * scale_y, lPhi * scale_z)),
        Vector((0, 1 * scale_y, -lPhi * scale_z)),
        Vector((0, -1 * scale_y, -lPhi * scale_z)),
        
        Vector((lPhi * scale_x, 0, 1 * scale_z)),
        Vector((lPhi * scale_x, 0, -1 * scale_z)),
        Vector((-lPhi * scale_x, 0, 1 * scale_z)),
        Vector((-lPhi * scale_x, 0, -1 * scale_z)),
    ]

    edges = []
    faces = [[0, 6, 1], [0, 1, 4], [4, 5, 8], [4, 10, 5], [2, 5, 3], [2, 3, 7], 
            [3, 10, 11], [1, 11, 10], [6, 7, 11], [7, 6, 9], [2, 9, 8], [0, 8, 9], 
            [3, 5, 10], [2, 8, 5], [0, 4, 8], [1, 10, 4], [3, 11, 7], [2, 7, 9], 
            [0, 9, 6], [1, 6, 11]]

    mesh = bpy.data.meshes.new(name="obj_Icosa")
    mesh.from_pydata(verts, edges, faces)
    # useful for development when the mesh may be invalid.
    # mesh.validate(verbose=True)
    object_data_add(context, mesh, operator=self)



class OBJECT_OT_add_tetrapos(Operator, AddObjectHelper):
    """Create a new Mesh Object"""
    bl_idname = "mesh.add_tetrapos"
    bl_label = "Add Mesh Object"
    bl_options = {'REGISTER', 'UNDO'}

    scale: FloatVectorProperty(
        name="scale",
        default=(1.0, 1.0, 1.0),
        subtype='TRANSLATION',
        description="scaling",
    )

    def execute(self, context):

        add_tetrapos(self, context)

        return {'FINISHED'}

class OBJECT_OT_add_tetraneg(Operator, AddObjectHelper):
    """Create a new Mesh Object"""
    bl_idname = "mesh.add_tetraneg"
    bl_label = "Add Mesh Object"
    bl_options = {'REGISTER', 'UNDO'}

    scale: FloatVectorProperty(
        name="scale",
        default=(1.0, 1.0, 1.0),
        subtype='TRANSLATION',
        description="scaling",
    )

    def execute(self, context):

        add_tetraneg(self, context)

        return {'FINISHED'}

class OBJECT_OT_add_tetrastar(Operator, AddObjectHelper):
    """Create a new Mesh Object"""
    bl_idname = "mesh.add_tetrastar"
    bl_label = "Add Mesh Object"
    bl_options = {'REGISTER', 'UNDO'}

    scale: FloatVectorProperty(
        name="scale",
        default=(1.0, 1.0, 1.0),
        subtype='TRANSLATION',
        description="scaling",
    )

    def execute(self, context):

        add_tetrastar(self, context)

        return {'FINISHED'}

class OBJECT_OT_add_octa(Operator, AddObjectHelper):
    """Create a new Mesh Object"""
    bl_idname = "mesh.add_octahedron"
    bl_label = "Add Mesh Object"
    bl_options = {'REGISTER', 'UNDO'}

    scale: FloatVectorProperty(
        name="scale",
        default=(1.0, 1.0, 1.0),
        subtype='TRANSLATION',
        description="scaling",
    )

    def execute(self, context):

        add_octahedron(self, context)

        return {'FINISHED'}

class OBJECT_OT_add_cube(Operator, AddObjectHelper):
    """Create a new Mesh Object"""
    bl_idname = "mesh.add_cube"
    bl_label = "Add Mesh Object"
    bl_options = {'REGISTER', 'UNDO'}

    scale: FloatVectorProperty(
        name="scale",
        default=(1.0, 1.0, 1.0),
        subtype='TRANSLATION',
        description="scaling",
    )

    def execute(self, context):

        add_cube(self, context)

        return {'FINISHED'}

class OBJECT_OT_add_dodeca(Operator, AddObjectHelper):
    """Create a new Mesh Object"""
    bl_idname = "mesh.add_dodeca"
    bl_label = "Add Mesh Object"
    bl_options = {'REGISTER', 'UNDO'}

    scale: FloatVectorProperty(
        name="scale",
        default=(1.0, 1.0, 1.0),
        subtype='TRANSLATION',
        description="scaling",
    )

    def execute(self, context):

        add_dodeca(self, context)

        return {'FINISHED'}

class OBJECT_OT_add_icosa(Operator, AddObjectHelper):
    """Create a new Mesh Object"""
    bl_idname = "mesh.add_icosa"
    bl_label = "Add Mesh Object"
    bl_options = {'REGISTER', 'UNDO'}

    scale: FloatVectorProperty(
        name="scale",
        default=(1.0, 1.0, 1.0),
        subtype='TRANSLATION',
        description="scaling",
    )

    def execute(self, context):

        add_icosa(self, context)

        return {'FINISHED'}


# Registration
def register():
    bpy.utils.register_class(PlatonicsMenu)
    bpy.types.VIEW3D_MT_mesh_add.append(PlatonicsMenuAdd)

    bpy.utils.register_class(OBJECT_OT_add_tetrapos)
    bpy.utils.register_class(OBJECT_OT_add_tetraneg)
    bpy.utils.register_class(OBJECT_OT_add_tetrastar)
    bpy.utils.register_class(OBJECT_OT_add_octa)
    bpy.utils.register_class(OBJECT_OT_add_cube)
    bpy.utils.register_class(OBJECT_OT_add_dodeca)
    bpy.utils.register_class(OBJECT_OT_add_icosa)


def unregister():
    bpy.utils.unregister_class(PlatonicsMenu)
    bpy.types.VIEW3D_MT_mesh_add.remove(PlatonicsMenuAdd)

    bpy.utils.unregister_class(OBJECT_OT_add_tetrapos)
    bpy.utils.unregister_class(OBJECT_OT_add_tetraneg)
    bpy.utils.unregister_class(OBJECT_OT_add_tetrastar)
    bpy.utils.unregister_class(OBJECT_OT_add_octa)
    bpy.utils.unregister_class(OBJECT_OT_add_cube)
    bpy.utils.unregister_class(OBJECT_OT_add_dodeca)
    bpy.utils.unregister_class(OBJECT_OT_add_icosa)


if __name__ == "__main__":
    register()

1 Like

Thank you, this was exactly, what I was looking for. :grinning: