1

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()
DGRL
  • 162
  • 9
  • 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. – Robert Gützkow Dec 23 '19 at 18:24
  • Yes i know the issue here is that i dont want to add 2 meshes but only 1 – DGRL Dec 23 '19 at 18:29
  • Please test the script and see what happens – DGRL Dec 23 '19 at 18:30
  • @DRGL with the approach you're using, there's no need for the object_data_add since you've already created and linked the object with its mesh data. – Robert Gützkow Dec 23 '19 at 18:38
  • How can i get the ALO menu in my script to work with the mesh i created? The ALO menu pops up but does not work at all – DGRL Dec 23 '19 at 18:43
  • You need an operator that has properties which can be adjusted. Currently you're adding the object at a fixed location with fixed vertex positions. – Robert Gützkow Dec 23 '19 at 18:50
  • 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) – DGRL Dec 23 '19 at 18:53
  • 1
    Didn't we already solve that 2 weeks ago: https://blender.stackexchange.com/a/160952/31447 ? – brockmann Dec 23 '19 at 19:04
  • @brockmann No that was something different In that question the script was made using bpy.ops Ive been told to use bmesh instead of bpy.ops and create new meshes seems to be fun learning bmesh bit its a whole different thing

    Thanks for you help back then. learned a lot from it

    – DGRL Dec 23 '19 at 19:06
  • 1
    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") – batFINGER Dec 23 '19 at 20:12

2 Answers2

2

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)
Robert Gützkow
  • 25,622
  • 3
  • 47
  • 78
  • This is what i meant @Robert Thanks again for your lessons and help

    Appriciate it guys

    – DGRL Dec 23 '19 at 19:09
2

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()
batFINGER
  • 84,216
  • 10
  • 108
  • 233