Set all curve points to Bezier via script

Hi There!

I am working on a script, which imports curves and converts them to a mesh automatically.
It works fine so far, but I am stuck with converting the curve to be of BEZIER typem which is needed to get better UVs.

My code so far:

import bpy

from bpy.props import (StringProperty,
                       BoolProperty,
                       IntProperty,
                       FloatProperty,
                       FloatVectorProperty,
                       EnumProperty,
                       PointerProperty,
                       )
from bpy.types import (Panel,
                       Menu,
                       Operator,
                       PropertyGroup,
                       )


# ------------------------------------------------------------------------
#    Scene Properties
# ------------------------------------------------------------------------

class MyProperties(PropertyGroup):

    svgSourcePath: StringProperty(
        name = "Directory",
        description="Choose a directory:",
        default="",
        maxlen=1024,
        subtype='FILE_PATH'
        )
        
    fbxExportPath: StringProperty(
        name = "Directory",
        description="Choose a directory:",
        default="",
        maxlen=1024,
        subtype='DIR_PATH'
        )
        
    pictoName: StringProperty(
        name = "Pictogramm Name",
        description="Choose a directory:",
        default="",
        maxlen=1024,
        #subtype='DIR_PATH'
        )


# ------------------------------------------------------------------------
#    Operators
# ------------------------------------------------------------------------

class WM_OT_pictomesher(Operator):
    bl_label = "~ ~ ~ Mesh it! ~ ~ ~"
    bl_idname = "wm.pictomesher"

    def execute(self, context):
        scene = context.scene
        # The following line is pure magic to me, but works?!?
        mytool = scene.my_tool
        svgfilepath = mytool.svgSourcePath
        bpy.ops.import_curve.svg(filepath=svgfilepath)


        # Create a Material for Checking/Debugging in Blender
        if bpy.data.materials.get('SplineTestMaterial') is None:
            testMaterial = bpy.data.materials.new(name="SplineTestMaterial")
            testMaterial.use_nodes = True
            nodes = testMaterial.node_tree.nodes
            tree = testMaterial.node_tree

            emission = nodes.new('ShaderNodeEmission')
            emission.location = (-200,100)
            gradient = nodes.new('ShaderNodeTexGradient')
            gradient.location = (-400, 100)
            mapping = nodes.new('ShaderNodeMapping')
            mapping.location = (-800, 100)
            mapping.scale[0] = 100
            mapping.translation[0] = -50
            coord = nodes.new('ShaderNodeTexCoord')
            coord.location = (-1000, 100)

            tree.links.new(emission.outputs[0],nodes["Material Output"].inputs[0])
            tree.links.new(gradient.outputs[0], emission.inputs[0])
            tree.links.new(mapping.outputs[0], gradient.inputs[0])
            tree.links.new(coord.outputs[2], mapping.inputs[0])
        else:
            testMaterial = bpy.data.materials.get('SplineTestMaterial')

        curves = []
        for obj in bpy.data.objects:
            obj.select_set(obj.type == "CURVE")
        curves = bpy.context.selected_objects 


        # Normalize input Curves
        dimensionValues = []
        for curve in curves:
            scale = curve.scale    
            minx = curve.bound_box[0][0] * scale.x
            maxx = curve.bound_box[4][0] * scale.x
            miny = curve.bound_box[0][1] * scale.y
            maxy = curve.bound_box[2][1] * scale.y
            dx = maxx - minx
            dy = maxy - miny
            dimensionValues.append(dx)
            dimensionValues.append(dy)

        highestDimensionValue = 0
        for value in dimensionValues:
            if value > highestDimensionValue:
                highestDimensionValue = value
                
        bpy.ops.transform.resize(value=(1/highestDimensionValue, 1/highestDimensionValue, 1/highestDimensionValue))


        # Creating Nurbs Curve for sweeping if None exists
        if bpy.data.objects.get('NurbsCircle') is None:
            nurbs_circle = 0
            nurbs_circle_size = 0.00025
            nurbs_circle = bpy.ops.curve.primitive_nurbs_circle_add(radius=nurbs_circle_size, enter_editmode=False, location=(0, 0, 0))
            print(nurbs_circle)
            
        myNurbs = bpy.data.objects.get('NurbsCircle')
        myNurbs.data.resolution_u = 2
            
           
        # Sweep Curve    
        for curve in curves:
            bpy.context.view_layer.objects.active = curve
            bpy.context.object.data.bevel_object = bpy.data.objects["NurbsCircle"]
            bpy.context.object.data.resolution_u = 16
            bpy.context.object.data.use_uv_as_generated = True
            bpy.context.object.data.materials.append(testMaterial)
            bpy.context.object.data.dimensions = '2D'
            #bpy.context.object.data.type='BEZIER'
            
            
        # Set HandleType
        for curve in curves:
            #curve.spline_type_set(type='BEZIER')
            #Find the Blender object of interest 
            crv_obj = curve
            #Get access to the curve object data
            crv_data = crv_obj.data
            #active spline
            spline = crv_data.splines.active
            #Find the active bezier control point bcp
            selected_points = [bcp for bcp in spline.bezier_points if bcp.select_control_point]

            for bez_point in selected_points:
                #Set Free
                bez_point.handle_right_type = 'FREE'
                bez_point.handle_left_type = 'FREE'

        
        
        # Convert Curves to Meshes
        for curve in curves:
            deg = context.evaluated_depsgraph_get()
            me = bpy.data.meshes.new_from_object(curve.evaluated_get(deg), depsgraph=deg)
            new_obj = bpy.data.objects.new(curve.name + "_mesh", me)
            bpy.context.collection.objects.link(new_obj)
            for o in context.selected_objects:
                o.select_set(False)

            new_obj.matrix_world = curve.matrix_world
            new_obj.select_set(True)
            context.view_layer.objects.active = new_obj
            
        # Export
        exportpath = mytool.fbxExportPath
        bpy.ops.export_scene.fbx(filepath=exportpath + mytool.pictoName + ".fbx", check_existing=True,global_scale=1, bake_space_transform=True, use_selection=False,object_types={'EMPTY', 'MESH'}, axis_up='Y')
        
            
        cont = bpy.context.area.type
        print(str(cont))
        
        return {'FINISHED'}

# ------------------------------------------------------------------------
#    Panel in Object Mode
# ------------------------------------------------------------------------

class LayoutDemoPanel(bpy.types.Panel):
    """Creates a Panel in the scene context of the properties editor"""
    bl_label = "PictoMesher"
    bl_idname = "SCENE_PT_layout3"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'

    def draw(self, context):
        layout = self.layout

        scene = context.scene
        
        mytool = scene.my_tool
        layout.label(text="SVG Datei:")
        layout.prop(mytool, "svgSourcePath")
        layout.label(text="Export Ordner:")  
        layout.prop(mytool, "fbxExportPath")
        layout.label(text="Pictogramm Name - muss gesetzt sein!!!")  
        layout.prop(mytool, "pictoName")
        
        
        # Big render button
        layout.label(text="Big Button:")
        row = layout.row()
        row.scale_y = 3.0
        row.operator("wm.pictomesher")
        

# ------------------------------------------------------------------------
#    Registration
# ------------------------------------------------------------------------
classes = (
    MyProperties,
    WM_OT_pictomesher,
    LayoutDemoPanel
)

def register():
    from bpy.utils import register_class
    for cls in classes:
        register_class(cls)

    bpy.types.Scene.my_tool = PointerProperty(type=MyProperties)

def unregister():
    from bpy.utils import unregister_class
    for cls in reversed(classes):
        unregister_class(cls)
    del bpy.types.Scene.my_tool


if __name__ == "__main__":
    register()

So I found a way to do this via ops:

            bpy.ops.object.editmode_toggle()
            bpy.ops.curve.select_all(action='DESELECT')
            bpy.ops.curve.select_all(action='SELECT')
            bpy.ops.curve.spline_type_set(type='BEZIER')
            bpy.ops.curve.handle_type_set(type='FREE_ALIGN')
            #bpy.context.object.data.type='BEZIER'
            bpy.ops.object.editmode_toggle()

But ops are not reallz a preferred way to do it, right? Any ideas how to do it via data?

1 Like