1
$\begingroup$

I have the following code in python:

import bpy
import random

#Define start and endpoints for the curve
start_point = (9, 9, 9)
end_point = (-9, -9, -9)

#Define the volume for the curve
x_min, x_max = -10, 10
y_min, y_max = -10, 10
z_min, z_max = -10, 10

#Create a new curve object
curve = bpy.data.curves.new('MyCurve', type='CURVE')
curve.dimensions = '3D'

#Create a new spline for the curve
spline = curve.splines.new('BEZIER')
spline.bezier_points.add(3)

#Set the start and endpoints for the spline
spline.bezier_points[0].co = start_point
spline.bezier_points[-1].co = end_point

#Randomly set the control points for the spline
for i, point in enumerate(spline.bezier_points[1:-1]):
    point.co = (random.uniform(x_min, x_max),
    random.uniform(y_min, y_max),
    random.uniform(z_min, z_max))
    point.handle_left_type = 'AUTO'
    point.handle_right_type = 'AUTO'

#Verify that the start and endpoints are within the specified volume
assert start_point[0] >= x_min and start_point[0] <= x_max, "Start point x-coordinate is outside of the defined volume"
assert start_point[1] >= y_min and start_point[1] <= y_max, "Start point y-coordinate is outside of the defined volume"
assert start_point[2] >= z_min and start_point[2] <= z_max, "Start point z-coordinate is outside of the defined volume"
assert end_point[0] >= x_min and end_point[0] <= x_max, "End point x-coordinate is outside of the defined volume"
assert end_point[1] >= y_min and end_point[1] <= y_max, "End point y-coordinate is outside of the defined volume"
assert end_point[2] >= z_min and end_point[2] <= z_max, "End point z-coordinate is outside of the defined volume"

#Create a new object and link it to the scene
obj = bpy.data.objects.new('MyCurveObject', curve)
bpy.context.scene.collection.objects.link(obj)

## light
light_obj = bpy.data.lights.new("MyPointLight", 'POINT')
light_obj.energy = 1.0
light_obj_object = bpy.data.objects.new("MyPointLightObject", light_obj)
bpy.context.scene.collection.objects.link(light_obj_object)
#light_obj_object.location = start_point

# Access the constraint collection of the object
constraint = light_obj_object.constraints.new(type='FOLLOW_PATH')
constraint.target = bpy.data.objects[obj.name]
constraint.influence = 1.0
constraint.use_curve_follow = True

#bpy.data.objects[light_obj.name].select = True
#C = bpy.context.copy()
#C["constraint"] = light_obj
#bpy.ops.constraint.followpath_path_animate(C, constraint=light_obj.name, owner='OBJECT', frame_start=1, length=110)

It should generate a random path in a bounding box (which it does).

Then it creates a pointlight that should follow the path with a "follow path" constraint (at least it creates the point light).

Finally, when I hit "animation play", it should move the point light along the path. But it does not.

In the GUI, when I select my light and go to its path constraint, I just have to press the button "Animate Path" and it does what I need. The button gives me a tooltip that the python command should be bpy.ops.constraint.followpath_path_animate()

In my script, you can see at the end one of my failed tries to somehow get this command working in Blender 3.4 Python. But I have not found the correct way of doing it, yet.

Can someone help me over this and knows how to implement bpy.ops.constraint.followpath_path_animate() in the current context?

Additionally, can somebody explain, why it is so straight forward to access and set e.g. the influence of the constraint by just typing constraint.influence = 1.0, but why it is obviously not possible to just say constraint.followpath_path_animate()?

$\endgroup$

1 Answer 1

1
$\begingroup$

For your last 4 lines which are commented out, should you be using light_obj_object instead of light_obj?

At first, the console was telling me that the context needed an active object, so for your copy context, I added in C["active_object"] = light_obj_object

The next error I was receiving was that the Follow Path constraint was not found. In the bpy.ops.constraint.followpath_path_animate() function, instead of setting constraint = light_obj_object.name, I just set it equal to constraint = "Follow Path"

The line C["constraint"] = light_obj_object was not necessary for it to work for me, same for the line bpy.data.objects[light_obj_object.name].select = True, which I think should actually be bpy.data.objects[light_obj_object.name].select_set(True)

For your last question, I'm honestly not the most well equipped in knowledge about why. If someone else can help out answering, that'd be nice. It just seems like bpy.ops is the only way to be able to access these operations within Python.

$\endgroup$
2
  • 1
    $\begingroup$ Thank you very much! That works now.... Is the assumption correct that in this case, to call follow_path_animate() I have to select the element programmatically by making it the "active_object" in the "context" (my scene?!?)? So it is basically the same as by clicking first the lamp and then clicking the button from the active objects follow path constraint? That concept is quite confusing and yes, it would be very much appreciated, if somebody could explain, why. $\endgroup$
    – Kiamur
    Commented Feb 10, 2023 at 12:27
  • $\begingroup$ Yes the light needs to be the active object. Normally, you just need to 'bpy.context.view_layer.objects.active = some_obj' , but since your context is a copy context, I had to use 'C["active_object"] = light_obj_object' $\endgroup$ Commented Feb 10, 2023 at 22:23

You must log in to answer this question.

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