1
$\begingroup$

I made a little script that makes a plane with thickness when i add the mesh to my model it places 2 meshes instead of 1

For 1 of the 2 meshes the ALO menu works but for the second one not Can someone help me and tell me what i did wrong?

This is the code i use

    bl_info = {
    "name": "Test object",
    "author": "DGRL",
    "version": (1, 0),
    "blender": (2, 80, 1),
    "location": "View3D > Add > Mesh > DGRL",
    "description": "Adds a new Mesh Object",
    "warning": "",
    "wiki_url": "",
    "category": "Add Mesh",
}

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



def add_object(self, context):


    verts = [(1, 1, 0), (-1, 1, 0), (-1, 0.9, 0), (-0.25, 0.9, 0),] 


    mesh = bpy.data.meshes.new("mesh") 
    obj = bpy.data.objects.new("MyObject", mesh)

    scene = bpy.context.scene
    bpy.context.collection.objects.link(obj) 
    bpy.context.view_layer.objects.active = obj 
    bpy.context.active_object.select_set(state=True)

    mesh = bpy.context.object.data
    bm = bmesh.new()

    for v in verts:
        bm.verts.new(v) 

    bm.faces.new(bm.verts)
    bm.to_mesh(mesh)  
    bm.free()


    **object_data_add(context, mesh, operator=self)**  *<-- THIS LINE MAKES A SECOND BMESH BUT WITHOUT THERE IS NO ADJUST LAST OPERATION MENU!*



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'}


    def execute(self, context):

        add_object(self, context)

        return {'FINISHED'}

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

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)
    bpy.types.VIEW3D_MT_mesh_add.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_mesh_add.remove(add_object_button)


if __name__ == "__main__":
    register()
$\endgroup$
  • $\begingroup$ The Adjust Last Operation panel will only be for the last operation. If you're adding multiple objects it will only be for the most recent one. $\endgroup$ – Robert Gützkow Dec 23 '19 at 18:24
  • $\begingroup$ Yes i know the issue here is that i dont want to add 2 meshes but only 1 $\endgroup$ – DGRL Dec 23 '19 at 18:29
  • $\begingroup$ Please test the script and see what happens $\endgroup$ – DGRL Dec 23 '19 at 18:30
  • 1
    $\begingroup$ Didn't we already solve that 2 weeks ago: blender.stackexchange.com/a/160952/31447 ? $\endgroup$ – brockmann Dec 23 '19 at 19:04
  • 1
    $\begingroup$ I recommended creating and manipulating meshes using ` bmesh` over the use of bpy.ops.mesh... operators in edit mode in particular. Unfortunately since I only created the meshes, it gave the impression nothing was happening. Made edit Please take some time to digest the changes made in answer below and question above, eg mesh = bpy.context.object.data vs mesh = bpy.data.meshes.new("mesh") $\endgroup$ – batFINGER Dec 23 '19 at 20:12
2
$\begingroup$

Question COde:

  • Makes a new mesh.
  • Makes a new object that links to new empty mesh

  • Links object to collection makes it active and selected

  • Links the empty mesh to object again (new object is now context)

  • Makes the bmesh and loads into mesh

Makes the mesh ok and adds a new object linked to that mesh to scene collections Ok... but it is not being transformed / aligned at all.

I dont get it tbh When i use object_data_add the location and rotation and align is just working fine on the second mesh that is placed ( let me be clear i want only 1 mesh to be placed) Why is it not working on the mesh i created? Im not talking about scaling but the 3 basic properties (location , rotation and align)

Because that is being done for you by the imported

AddObjectHelper and object_data_add

The function object_data_add is designed for use in conjunction with the AddObjectHelper class. It creates a new object, linked to the context collection objects, linked to our new mesh, transformed via location, rotation and align properties of the operator.

That is why it is passed (context, mesh, operator=self) , eg if the new object is ob the code of object_data_add(...) could include

ob.data = mesh
ob.location = operator.location

to position the object. The code is available to peruse 2.8x/scripts/modules/bpy_extras/object_utils.py

Changes

  • Conformed to operator naming standard
  • Removed un-needed imports
  • Removed un-needed documentation links
  • Changed around the methodology somewhat. The function add_plane_mesh() takes no argument and returns a mesh, regardless of operator or context. This makes it very re-usable, for example if addon is in a folder named "test_addon" could

       from test_addon import add_plane_object
    

    to use elsewhere. Moved object_data_add(...) into the operator's execute method conveniently with self and context as arguments.

Amended question code.

bl_info = {
    "name": "Test object",
    "author": "DGRL",
    "version": (1, 0),
    "blender": (2, 80, 1),
    "location": "View3D > Add > Mesh > DGRL",
    "description": "Adds a new Mesh Object",
    "warning": "",
    "wiki_url": "",
    "category": "Add Mesh",
}

import bpy
import bmesh
from bpy.types import Operator
from bpy_extras.object_utils import AddObjectHelper, object_data_add


def add_plane_mesh():

    verts = [(1, 1, 0), (-1, 1, 0), (-1, 0.9, 0), (-0.25, 0.9, 0),] 

    mesh = bpy.data.meshes.new("mesh") 
    bm = bmesh.new()

    bm.faces.new(bm.verts.new(v) for v in verts)
    bm.to_mesh(mesh)  
    bm.free()
    return mesh

class MESH_OT_add_object(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):
        object_data_add(
                context, 
                add_plane_mesh(), 
                operator=self)

        return {'FINISHED'}

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


def register():
    bpy.utils.register_class(MESH_OT_add_object)        
    bpy.types.VIEW3D_MT_mesh_add.append(add_object_button)


def unregister():
    bpy.utils.unregister_class(MESH_OT_add_object)        
    bpy.types.VIEW3D_MT_mesh_add.remove(add_object_button)


if __name__ == "__main__":
    register()
$\endgroup$
2
$\begingroup$

This was a quick answer to the user's question, however batFINGER's answer provides more details on how to improve the add-on. It also addresses other issues such as the architecture/structure, imports and the naming convention.


If you want to use object_data_add() from bpy_extras.object_utils then remove the object creation and linking to the scene from add_object.

def add_object(self, context):

    verts = [(1, 1, 0), (-1, 1, 0), (-1, 0.9, 0), (-0.25, 0.9, 0),] 

    mesh = bpy.data.meshes.new("mesh") 

    bm = bmesh.new()

    for v in verts:
        bm.verts.new(v) 

    bm.faces.new(bm.verts)
    bm.to_mesh(mesh)  
    bm.free()

    object_data_add(context, mesh, operator=self)
$\endgroup$
  • $\begingroup$ This is what i meant @Robert Thanks again for your lessons and help Appriciate it guys $\endgroup$ – DGRL Dec 23 '19 at 19:09

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.