1
$\begingroup$

I just want to add custom addon to this path Edit Mode > Mesh > Sort Elements

enter image description here

I tried to use all bpytypes but it seems there is no access to this menu!

bl_info = {
    "name": "New Object",
    "author": "Your Name Here",
    "version": (1, 0),
    "blender": (2, 80, 0),
    "location": "Edit Mode > Mesh > Sort Elements",
    "description": "Adds a new Mesh Object",
    "warning": "",
    "doc_url": "",
    "category": "Add Mesh",
}


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


def add_object(self, context):
    scale_x = self.scale.x
    scale_y = self.scale.y

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

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

    mesh = bpy.data.meshes.new(name="New Object Mesh")
    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_object(Operator, AddObjectHelper):
    """Create a new Mesh Object"""
    bl_idname = "mesh.add_object"
    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_object(self, context)

        return {'FINISHED'}


# Registration

def add_object_button(self, context):
    self.layout.operator(
        OBJECT_OT_add_object.bl_idname,
        text="Add Object",
        icon='PLUGIN')


# This allows you to right click on a button and link to documentation
def add_object_manual_map():
    url_manual_prefix = "https://docs.blender.org/manual/en/latest/"
    url_manual_mapping = (
        ("bpy.ops.mesh.add_object", "scene_layout/object/types.html"),
    )
    return url_manual_prefix, url_manual_mapping


def register():
    bpy.utils.register_class(OBJECT_OT_add_object)
    bpy.utils.register_manual_map(add_object_manual_map)
    
    
    # all edit_mesh types
    bpy.types.VIEW3D_MT_edit_mesh.append(add_object_button)
    bpy.types.VIEW3D_MT_edit_mesh_clean.append(add_object_button)
    bpy.types.VIEW3D_MT_edit_mesh_context_menu.append(add_object_button)
    bpy.types.VIEW3D_MT_edit_mesh_delete.append(add_object_button)
    bpy.types.VIEW3D_MT_edit_mesh_edges.append(add_object_button)
    bpy.types.VIEW3D_MT_edit_mesh_edges_data.append(add_object_button)
    bpy.types.VIEW3D_MT_edit_mesh_extrude.append(add_object_button)
    bpy.types.VIEW3D_MT_edit_mesh_faces.append(add_object_button)
    bpy.types.VIEW3D_MT_edit_mesh_faces.append(add_object_button)
    bpy.types.VIEW3D_MT_edit_mesh_merge.append(add_object_button)
    bpy.types.VIEW3D_MT_edit_mesh_normals.append(add_object_button)
    bpy.types.VIEW3D_MT_edit_mesh_normals_average.append(add_object_button)
    bpy.types.VIEW3D_MT_edit_mesh_normals_select_strength.append(add_object_button)
    bpy.types.VIEW3D_MT_edit_mesh_normals_set_strength.append(add_object_button)
    bpy.types.VIEW3D_MT_edit_mesh_select_by_trait.append(add_object_button)
    bpy.types.VIEW3D_MT_edit_mesh_select_linked.append(add_object_button)
    bpy.types.VIEW3D_MT_edit_mesh_select_loops.append(add_object_button)
    bpy.types.VIEW3D_MT_edit_mesh_select_mode.append(add_object_button)
    bpy.types.VIEW3D_MT_edit_mesh_select_more_less.append(add_object_button)
    bpy.types.VIEW3D_MT_edit_mesh_select_similar.append(add_object_button)
    bpy.types.VIEW3D_MT_edit_mesh_shading.append(add_object_button)
    bpy.types.VIEW3D_MT_edit_mesh_showhide.append(add_object_button)
    bpy.types.VIEW3D_MT_edit_mesh_split.append(add_object_button)
    bpy.types.VIEW3D_MT_edit_mesh_vertices.append(add_object_button)
    bpy.types.VIEW3D_MT_edit_mesh_weights.append(add_object_button)


def unregister():
    bpy.utils.unregister_class(OBJECT_OT_add_object)
    bpy.utils.unregister_manual_map(add_object_manual_map)
    bpy.types.VIEW3D_MT_edit_mesh_context_menu.remove(add_object_button)
    #bpy.ops.mesh.sort_elements(type='RANDOMIZE', elements={'VERT'})


if __name__ == "__main__":
    register()

there is no bpy.types as VIEW3D_MT_edit_mesh_SortElements

$\endgroup$
1

2 Answers 2

0
$\begingroup$

TL;DR: There is no such a menu. Append it into VIEW3D_MT_edit_mesh.


The sort element itself is an enumerated submenu, which are written in space_view3D.py at lines:: 3620 as following:

layout.operator_menu_enum("mesh.sort_elements", "type", text="Sort Elements...")

enter image description here

This will make a sub-menu to enumerate all possible type that "mesh.sort_elements" will contain, which is an EnumProperties. And since it is written in VIEW3D_MT_edit_mesh draw method, it's hard to inject any other menu into it. Especially it is a property from built-in operator.

You might need to directly deal with bpy.ops.mesh.sort_elements logic, or you will need to use the hacky method provided above to rewrite the enum submenu part of it. Both are not a good practice IMO and will make your addon looks dangerous.

$\endgroup$
0
$\begingroup$

this answer and this basic menu example helped me to add a custom sort to Sort Elements

import bpy
from bpy.props import EnumProperty
from mathutils import Vector, Matrix
import bmesh

def sequential_sort():
    ob = bpy.context.object
    assert ob.type == "MESH"
    me = ob.data

    bm = bmesh.from_edit_mesh(me)
    v0 = bm.select_history.active
    f = bmesh.ops.contextual_create(
            bm,
            geom=bm.verts[:] + bm.edges[:],
            )["faces"][0]

    fverts = f.verts[:]

    if f.normal.dot((0, 0, 1)) < 0:
        fverts.reverse()

    for i, v in enumerate(fverts):
        v.index = i
        if v is v0:
            iv0 = i

    for v in fverts:
        v.index = (v.index - iv0) % len(fverts) 
        
    bm.verts.sort()

    bm.faces.remove(f)

    bmesh.update_edit_mesh(me) 



class SimpleOperator(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "mesh.sort_elements"
    bl_label = "Simple Object Operator"

    def items():
        items = []
        rna = bpy.ops.object.origin_set.get_rna_type()
        for i in rna.properties['type'].enum_items:
            items.append((i.identifier, i.name, i.description))
        items.append(('SEQUENTIAL_SORT', "Sequential Sort", "Sort Elements Sequentially"))
        return items

    type : EnumProperty(items=items(), default='GEOMETRY_ORIGIN')

    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):
        sequential_sort()
        return {'FINISHED'}

def draw_menu(self, context):
    self.layout.operator_menu_enum("mesh.sort_elements", "type", text="Sort Elements...")

def register():
    #bpy.types.VIEW3D_MT_object.prepend(draw_menu)
    bpy.utils.register_class(SimpleOperator)


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


if __name__ == "__main__":
    register()
$\endgroup$
2
  • $\begingroup$ @batFINGER I could add custom sort to SortElements menu but I couldn't add default enums. I tried to use this method rna = bpy.ops.mesh.sort_elements.get_rna_type() but it didn't work $\endgroup$ Aug 21, 2020 at 11:36
  • $\begingroup$ It "didn't work" because it requires a default that is in the list. Not 'GEOMETRY_ORIGIN`, which is the default for set origin op. Have made change to other to use the default as set in original operator. As commented in other answer: Will need to code for other options. $\endgroup$
    – batFINGER
    Aug 22, 2020 at 14:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .