3
$\begingroup$

I am trying to convert all the curves in a blendfile to meshes - like this, as explained here:

import bpy

for obj in [ obj for obj in bpy.data.objects  ]:
    if obj.type == "CURVE":
        print(obj, obj.type, obj.parent.type)
        print([ o.type for o in getChildren(obj.parent) ])

        dg  = bpy.context.evaluated_depsgraph_get()
        obj = dg.objects.get(obj.name)
        
        me = obj.to_mesh()
        print(len(me.vertices))
        try:
            o = bpy.data.objects.new(obj.name + "Mesh", me)
        except Exception as e:     
            print(e)

However it throws an error:

 Error: Can not create object in main database with an evaluated data data-block

I've also tried using:

 obj = obj.evaluated_get(dg) 

like explained here but this fails too.

What am I doing wrong?

$\endgroup$
1
  • $\begingroup$ I don't understand why you're trying to use the depsgraph, but you have a Python issue: You are using obj both as the loop variable and as a variable within the loop. Try changing the internal name to something else. $\endgroup$ Jun 1, 2022 at 15:20

3 Answers 3

4
$\begingroup$

The docs of bpy.types.Object.to_mesh state :

The result is temporary and can not be used by objects from the main database

Which means you can't use this evaluated mesh as data for an actual object in the scene. It will be thrown to the garbage collector once the scope it was created in completes.

As the other answer suggest, you may want to use the bpy.ops.object.convert operator to do it. I would add the optional keep_original argument since your code seems to hint that you want to keep the original curves.

As I discovered in my endeavour to document all operator overrides, this operator can't be overriden. So you'll have to select objects by code.

import bpy


bpy.ops.object.select_all(action='DESELECT')


for obj in bpy.data.objects:
    if obj.type == 'CURVE':
        obj.select_set(True)
bpy.ops.object.convert(target='MESH', keep_original=True)

You can also use lower-level functions :

import bpy


for obj in bpy.data.objects:
    if obj.type == "CURVE":
        mesh = bpy.data.meshes.new_from_object(obj)
        new_obj = bpy.data.objects.new(obj.name, mesh)
        new_obj.matrix_world = obj.matrix_world
        bpy.context.collection.objects.link(new_obj)

Credit https://blender.stackexchange.com/a/277424/86891 and https://docs.blender.org/api/current/bpy.types.BlendDataMeshes.html#bpy.types.BlendDataMeshes.new_from_object

$\endgroup$
1
$\begingroup$

Turns out there is an even simpler solution, if you copy the evaluated mesh, it will create a mesh datablock you can use for real.

import bpy

for obj in bpy.data.objects[:]:
    if obj.type == "CURVE":
        me = obj.to_mesh()
        o = bpy.data.objects.new(obj.name + "Mesh", me.copy())
        o.matrix_world = obj.matrix_world
        bpy.context.collection.objects.link(o)
$\endgroup$
0
$\begingroup$

AFAIK to convert a curve to an object you have to select it. So I guess you can do something like this:

obj.select_set(True)
bpy.ops.object.convert(target='MESH')
$\endgroup$

You must log in to answer this question.

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