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
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$ – Seyed Morteza Kamali Aug 21 '20 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 '20 at 14:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.