I'm writing a simple script that will help me use Blender better. One script sets everything up that's needed for retopology. The second just makes a hexagon and fan fills its face.

Individually, I can get these scripts to function correctly, but when I add them both together, or when I add them as separate scripts, the one that executes first will be the operation that both buttons will be caused to execute.

bl_info = {
    "name": "Dope Tools",
    "author": "Digital Dope",
    "version": (1, 0),
    "blender": (2, 79, 0),
    "location": "View3D > Add > Mesh > New Object",
    "description": "Adds several features to blender that I need",
    "warning": "",
    "wiki_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

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

    def execute(self, context):
        bpy.ops.mesh.primitive_plane_add(radius=1, view_align=False, enter_editmode=False, location=(0, 0, 0), layers=(True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False))
        bpy.ops.transform.rotate(value=1.5708, axis=(1, 0, 0), constraint_axis=(True, False, False), constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1)
        bpy.ops.transform.resize(value=(0.1, 0.1, 0.1), constraint_axis=(False, False, False), constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1)
        bpy.ops.object.modifier_add(type='MIRROR')
        bpy.ops.object.modifier_add(type='SHRINKWRAP')
        bpy.ops.object.modifier_add(type='SUBSURF')
        bpy.context.object.modifiers["Mirror"].use_clip = True
        bpy.context.object.modifiers["Mirror"].show_on_cage = True
        bpy.context.object.modifiers["Subsurf"].show_on_cage = True
        bpy.ops.object.editmode_toggle()
        bpy.ops.transform.translate(value=(-0.100995, 0, 0), constraint_axis=(True, False, False), constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1, release_confirm=True, use_accurate=False)
        bpy.context.scene.tool_settings.use_snap = True
        bpy.context.scene.tool_settings.snap_element = 'VERTEX'
        bpy.context.scene.tool_settings.use_snap_align_rotation = True
        bpy.context.object.show_all_edges = True
        return {'FINISHED'}

def add_object_button(self, context):
    self.layout.operator(
        AddRetopoSU.bl_idname,
        text="Add Retopo",
        icon='MOD_SHRINKWRAP')

class AddHex(Operator, AddObjectHelper):
    bl_idname = "mesh.add_object"
    bl_label = "Add Hexagon"
    bl_options = {'REGISTER', 'UNDO'}

    def execute(self, context):
        bpy.ops.mesh.primitive_circle_add(vertices=5, radius=1, fill_type='TRIFAN', view_align=False, enter_editmode=False, location=(0, 0, 0))
        return {'FINISHED'}

def add_Hex_button(self, context):
    self.layout.operator(
        AddHex.bl_idname,
        text="Add Hexagon",
        icon='MESH_ICOSPHERE')

def register():
    bpy.utils.register_class(AddHex)
    bpy.types.INFO_MT_mesh_add.prepend(add_Hex_button)
    bpy.utils.register_class(AddRetopoSU)
    bpy.types.INFO_MT_mesh_add.prepend(add_object_button)

def unregister():
    bpy.utils.unregister_class(AddHex)
    bpy.types.INFO_MT_mesh_add.remove(add_Hex_button)
    bpy.utils.unregister_class(AddRetopoSU)
    bpy.types.INFO_MT_mesh_add.remove(add_object_button)


if __name__ == "__main__":
    register()
up vote 4 down vote accepted

Give it a unique bl_idname

Both operators have the same bl_idname = "mesh.add_object". When you register you are effectively overriding the first with the second.

Give it a name like

bl_idname = "mesh.add_retopo"

and call it in code with

bpy.ops.mesh.add_retopo()

or use its, now unique id in the UI layout.

layout.operator("mesh.add_retopo")

Links.

Why does operators bl_idname have to contain 1 dot?

  • THat worked! Thank you! But now I have to find a way to make the name and icon unique. as it stands they now have the same label and icon because the "text" and "icon" variables cannot be changed. Could I use text.hex= and text.retopo= (a dot to make them unique?) – Internet Warriors Jun 14 at 14:25
  • Not quite sure what you are asking. Blender uses xxxx.yyyy to name its operators. xxxx is object for object operators by convention, but can use any lower case name dot name. When the operator is registered it becomes bpy.ops.xxxx.yyyy() and can be added to layout by its id "xxxx.yyyy". If another is registered with same id it overwrites the previously defined (prob in q) On the menu, There is no need for the text argument as it already uses bl_label by default. Could add icon = 'SOME_ICON' as a class variable, and use layout.operator(AddHex.bl_idname, icon = AddHex.icon )` ? – batFINGER Jun 14 at 14:46
  • You have answered my question. I'm sorry if I wasn't clear. I'm a few days old to this.... Thank you so much for you time and consideration! I appreciate it. – Internet Warriors Jun 14 at 19:14

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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