1
$\begingroup$

I would like to start by expressing my gratitude to this community for providing solutions to programming problems related to BPY. I usually find answers here without submitting my question, but this time I am a bit stumped, the solutions to similar problems didn't yield result I was hoping for.

I am trying to piece together a small blender 2.79 addon for handling Bezier curves. It would draw the curve I need, small piece at a time, based on the origin point, distance and angle I provide. On start-up, addon creates the first curve segment by invoking the operator. Then the user can fine tune settings in the tool panel, when satisfied with current segment, user can add next segment with a button press, that yields next segment, taking previous endPoint as new origin for new segment.

The problem seems to be, that the first segment is created, is linked to the scene, it shows on the screen, but as soon as I try to manipulate it, it doesn't show up in context.scene.objects list.

Here is the code:

bl_info = {
    "name": "Bezier Piecewise Segments",
    "author": "i",
    "version": (1, 0),
    "blender": (2, 79, 0),
    "location": "View3D > Add > Curve > Piecewise",
    "description": "Adds functionaly adjustable bezier segments",
    "warning": "",
    "wiki_url": "",
    "category": "Testing"
}

import bpy, math, mathutils
from mathutils import Vector

pointCloud = [
    [Vector((0, 0, 0)), Vector((-0.0707, -0.0707, 0)), Vector((0.0707, 0.0707, 0)), 'FREE', 'FREE'],
    [Vector((0.3536, 0.3536, 0)), Vector((0.2828, 0.2828, 0)), Vector((0.4243, 0.4243, 0.0000)), 'FREE', 'FREE']
    ]



def getEndPoint(origin, radius, angle):
    return Vector((
        origin.x + radius * math.cos(math.radians(angle)),
        origin.y + radius * math.sin(math.radians(angle)),
        0
        ))

def get_curve_object(objectName):
    bpy.ops.object.select_all(action='DESELECT')
    ob = bpy.data.objects.get(objectName)
    if (ob.type != 'CURVE'):
        return
    bpy.context.scene.objects.active = ob
    bpy.ops.object.select_pattern(pattern=objectName)

class AddSegment(bpy.types.Operator):
    bl_label="Adds segment"
    bl_idname="curve.add_piecewise_segment"
    bl_options={'REGISTER', 'UNDO'}
    
    startPoint = bpy.props.FloatVectorProperty(name="", subtype='TRANSLATION')
    length = bpy.props.FloatProperty(name='', default=0.1, step=250, precision=2)
    angle = bpy.props.FloatProperty(name='', default=45, step=500, precision=1)
    
    @classmethod
    def poll(self, context):
        return context.scene
    
    def execute(self, context):
        objname = 'NumChuck'
        #get_curve_object(objname)
        objectdata = bpy.data.objects.get(objname, None)
        if (objectdata == None):
            curvedata = bpy.data.curves.new(name=objname, type='CURVE')  
            curvedata.dimensions = '3D'
            objectdata = bpy.data.objects.new(objname, curvedata)  
            objectdata.location = (0,0,0) #object origin  
            bpy.context.scene.objects.link(objectdata)
            control_points = curvedata.splines.new('BEZIER')
            control_points.bezier_points.add(2)
            scene = bpy.context.scene
            #scene.objects.link(objectdata)
            scene.update()
            bpy.context.scene.objects.active = bpy.data.objects['NumChuck']
            
        objectdata = bpy.data.objects.get(objname, None)
        curve = bpy.data.curves[objname].splines[0]
        control_points = curve.bezier_points
        for num in range(len(pointCloud)):
            control_points[num].co = pointCloud[num][0]
            control_points[num].handle_left = pointCloud[num][1]
            control_points[num].handle_right = pointCloud[num][2]
            control_points[num].handle_left_type = pointCloud[num][3]
            control_points[num].handle_right_type = pointCloud[num][4]
        objectdata = bpy.data.objects.get(objname, None)
        bpy.data.objects[objname].select = True
        bpy.context.scene.objects.active = bpy.data.objects[objname]
        scene = bpy.context.scene
        #scene.objects.link(objectdata)
        scene.update()

        return {'FINISHED'}


class RemoveSegment(bpy.types.Operator):
    bl_label="Removes Segments"
    bl_idname="curve.remove_piecewise_segment"
    bl_options={'REGISTER'}

    def execute(self, context):

        return {'FINISHED'}

class BerzierSegment(bpy.types.Operator):
    bl_label="Complicated Bezier"
    bl_idname="curve.control_bezier"
    bl_options={'REGISTER', 'UNDO'}

    curve_segment = bpy.props.IntProperty(name='', default=0)
    origin = bpy.props.FloatVectorProperty(name="", subtype='TRANSLATION')
    magnitude = bpy.props.FloatProperty(name='', default=0.5, step=25, precision=2)
    direction = bpy.props.FloatProperty(name='', default=45, step=500, precision=1)
    segmentType = bpy.props.EnumProperty(
        name='', default="Straight",
        items=[('Straight', 'Straight', ''), ('Curved', 'Curved', '')])
    curveRadius = bpy.props.FloatProperty(name='', default=1, step=500, precision=2)
    endPoint = Vector((0,0,0))
    
    def draw(self, context):
        layout = self.layout
        row = layout.row(align=True)
        row.label("Origin")
        row = layout.row(align=True)
        row.prop(self, 'origin')

        row = layout.row()
        row.label("Magnitude")
        row.label("Angle")
        row = layout.row()
        row.prop(self, 'magnitude')
        row.prop(self, 'direction')

        row = layout.row()
        row.label('Curvature')
        row.prop(self, 'segmentType')
        if self.segmentType == 'Curved':
            row = layout.row()
            row.label("Radius")
            row.prop(self, curveRadius)

        row = layout.row()
        op = row.operator(AddSegment.bl_idname, text="ADD")
        op.startPoint = self.endPoint
        op.length = self.magnitude
        op.angle = self.direction
        op = row.operator(RemoveSegment.bl_idname, text="REMOVE")

    def invoke(self, context, event):
        return bpy.ops.curve.add_piecewise_segment()

    def execute(self, context):
        scene = context.scene
        objs = [ob for ob in scene.objects]
        #active = [ob for ob in objs if ob.active]
        print('objects: ', objs)
        #print('active: ', active)
        endpoint_idx = self.curve_segment + 1
        self.endPoint = getEndPoint(self.origin, self.magnitude, self.direction)
        handleLength = 0.1
        handleLeft = getEndPoint(self.endPoint, -handleLength, self.direction)
        handleRight = getEndPoint(self.endPoint, handleLength, self.direction)
        objname = 'NumChuck'
        objectdata = bpy.data.objects.get(objname, None)
        curve = bpy.data.curves[objname].splines[0]
        control_point = curve.bezier_points[endpoint_idx]
        control_point.co = self.endPoint
        control_point.handle_left = handleLeft
        control_point.handle_right = handleRight
        control_point.handle_left_type = 'FREE'
        control_point.handle_right_type = 'FREE'

        return {'FINISHED'}



def append_to_menu(self, context):
    self.layout.operator(
        BerzierSegment.bl_idname,
        text="Piecewise Bezier",
        icon='PLUGIN')

def register():
    bpy.utils.register_class(BerzierSegment)
    bpy.utils.register_class(AddSegment)
    bpy.utils.register_class(RemoveSegment)
    bpy.types.INFO_MT_curve_add.append(append_to_menu)


def unregister():
    bpy.utils.unregister_class(AddSegment)
    bpy.utils.unregister_class(RemoveSegment)
    bpy.types.INFO_MT_mesh_add.remove(append_to_menu)

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

0

You must log in to answer this question.

Browse other questions tagged .