2
$\begingroup$

I have the following code to construct a bezier curve, an armature, and then hook them together, unfortunately it does not accomplish my mission

import bpy


def create_armed_spline(scn, resolution):

    curve = bpy.data.curves.new("dingus", 'CURVE')
    spline = curve.splines.new('BEZIER')

    spline.bezier_points.add((resolution+1)*2)

    half_thick = 0.1
    for i in range(resolution+1):
        p1 = spline.bezier_points[i]
        x1 = i / (resolution)
        p1.co = [x1, half_thick, 0]
        p2 = spline.bezier_points[2 * resolution + 1 - i]
        p2.co = [x1, -half_thick, 0]

        if (i>0):
            x2 = (i - 1 / 3) / (resolution)
            p1.handle_left = [x2, half_thick, 0]
            p2.handle_right = [x2, -half_thick, 0]
        else:
            p1.handle_left = [x1, half_thick/3, 0]
            p2.handle_right = [x1, -half_thick/3, 0]
        if i<resolution:
            x3 = (i + 1 / 3) / resolution
            p1.handle_right = [x3, half_thick, 0]
            p2.handle_left = [x3, -half_thick, 0]
        else:
            p1.handle_right = [ x1, half_thick/3, 0]
            p2.handle_left = [ x1, -half_thick, 0 ]

    spline.use_cyclic_u=True


    co = bpy.data.objects.new("dingus", curve)

    #

    arm = bpy.data.armatures.new("dingus")
    ao = bpy.data.objects.new("dingus armature", arm)

    co.parent = ao

    scn.objects.link(ao)
    scn.objects.link(co)

    #

    if 'OBJECT'!=bpy.context.mode:
        bpy.ops.object.mode_set(mode='OBJECT')

    scn.objects.active = ao

    bpy.ops.object.mode_set(mode='EDIT')

    bone_size = 0.1

    for i in range(resolution+1):
        x1 = i/resolution

        add_bone_set(arm, "%d"%i, [x1, half_thick])

        if (i>0):
            x2 = (i - 1 / 3) / resolution
            #add_bone_set(arm, "lh%d"%i, [x2, half_thick])

        if (i<resolution):
            x3 = (i+1/3)/resolution
            #add_bone_set(arm, "rh%d"%i, [x3, half_thick])

    bpy.ops.object.mode_set(mode='OBJECT')

    for i in range(2):
        hook_spline_to_armature(scn, co, ao, i, [0,1,0], "left %d"%i)
        hook_spline_to_armature(scn, co, ao, 2*resolution+1-i, [0, 1, 0], "right %d"%i)

    #

    return co, ao


def hook_spline_to_armature(scn, curve, ao, idx, parts, bone_name):
    mod = curve.modifiers.new("hook %d %r%r%r"%(idx,parts[0], parts[1], parts[2]), 'HOOK')
    mod.object = ao
    mod.subtarget = bone_name
    mod.falloff_type='NONE'

    scn.objects.active = curve
    bpy.ops.object.mode_set(mode='EDIT')
    for k in range(len(curve.data.splines[0].bezier_points)):
        bp = curve.data.splines[0].bezier_points[k]

        bp.select_control_point = (k==idx) and parts[1] != 0
        bp.select_left_handle = (k==idx) and parts[0] != 0
        bp.select_right_handle = (k==idx) and parts[2] != 0

    bpy.ops.object.hook_assign(modifier=mod.name)

    bpy.ops.object.mode_set(mode='OBJECT')

def add_bone_set(arm, idx, co):
    bone_size = 0.1

    b0 = arm.edit_bones.new("center %s" % idx)
    b0.head = [co[0], 0, 0]
    b0.tail = [co[0], 0, bone_size]

    b1 = arm.edit_bones.new("right %s" % idx)
    b1.head = [co[0], -co[1], 0]
    b1.tail = [co[0], -co[1], bone_size]
    b1.parent = b0

    b2 = arm.edit_bones.new("left %s" % idx)
    b2.head = [co[0], co[1], 0]
    b2.tail = [co[0], co[1], bone_size]
    b2.parent = b0

    return b0, b1, b2


def maybe_purge(scn, name):
    obj = bpy.data.objects.get(name)
    if obj is None:
        return

    obj.name = "discard"
    try:
        scn.objects.unlink(obj)
    except:
        pass


def mission1(scn):

    if 'OBJECT'!=bpy.context.mode:
        bpy.ops.object.mode_set(mode='OBJECT')

    maybe_purge(scn, "dingus")
    maybe_purge(scn, "dingus armature")
    spline, arm = create_armed_spline(scn, 1)

#
mission1(bpy.context.scene)

What I do get is a deformed bezier curve which appears to have no mathematical relationship to the armature it is hooked to.

screenshot

How do I fix my python code so it properly hooks the bezier control points to the bones of the armature?

$\endgroup$
1

1 Answer 1

1
$\begingroup$

It appears that hook modifiers are not truly initialized when you create them. They need a bpy.ops.object.hook_reset(modifier=mod.name) to clear out some hidden state that might be leftover garbage from the heap.

$\endgroup$

You must log in to answer this question.

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