[feature] spline animation

This commit is contained in:
jrkb 2025-06-05 10:59:14 +02:00
parent f02f8fc2f0
commit cd99362bb1

105
butils.py
View file

@ -221,26 +221,26 @@ def get_hook_modifiers(blender_object: bpy.types.Object):
return [m for m in blender_object.modifiers if m.type == "HOOK"]
class BezierSplinePoint:
class HookBezierSplinePoint:
def __init__(
self,
co: mathutils.Vector,
handle_left: mathutils.Vector,
co: mathutils.Vector,
handle_right: mathutils.Vector,
):
self.co: mathutils.Vector = co
self.handle_left: mathutils.Vector = handle_left
self.handle_right: mathutils.Vector = handle_right
self.handle_left: mathutils.Vector = mathutils.Vector(handle_left)
self.co: mathutils.Vector = mathutils.Vector(co)
self.handle_right: mathutils.Vector = mathutils.Vector(handle_right)
class BezierSpline:
class HookBezierSpline:
def __init__(
self,
n: int,
use_cyclic_u: bool,
resolution_u: int,
):
self.bezier_points = [BezierSplinePoint] * n
self.bezier_points = [HookBezierSplinePoint] * n
self.use_cyclic_u: int = use_cyclic_u
self.resolution_u: int = resolution_u
self.beziers: []
@ -249,34 +249,31 @@ class BezierSpline:
def calc_length(self, resolution) -> float:
# ignore resolution when accessing length to imitate blender function
print(f"{self.total_length=}")
return self.total_length
class BezierData:
class HookBezierData:
def __init__(self, n):
self.splines = [BezierSpline] * n
self.splines = [HookBezierSpline] * n
class BezierCurve:
class HookBezierCurve:
def __init__(self, blender_curve: bpy.types.Object, resolution_factor=1.0):
self.data = BezierData(len(blender_curve.data.splines))
self.data = HookBezierData(len(blender_curve.data.splines))
i = 0
hooks = get_hook_modifiers(blender_curve)
print(f"{blender_curve.name=} =============================================")
for si, blender_spline in enumerate(blender_curve.data.splines):
self.data.splines[si] = BezierSpline(
self.data.splines[si] = HookBezierSpline(
len(blender_spline.bezier_points),
blender_spline.use_cyclic_u,
blender_spline.resolution_u,
)
for pi, blender_bezier_point in enumerate(blender_spline.bezier_points):
self.data.splines[si].bezier_points[pi] = BezierSplinePoint(
blender_bezier_point.co,
self.data.splines[si].bezier_points[pi] = HookBezierSplinePoint(
blender_bezier_point.handle_left,
blender_bezier_point.co,
blender_bezier_point.handle_right,
)
print(pi)
for hook in hooks:
hook_co = False
hook_handle_left = False
@ -293,40 +290,57 @@ class BezierCurve:
blender_curve.matrix_world.inverted()
@ hook.object.matrix_world.translation
)
print(f"co {location=}")
self.data.splines[si].bezier_points[pi].co = (
self.data.splines[si]
.bezier_points[pi]
.co.lerp(location, hook.strength)
)
# if hook_handle_left:
# location = (
# hook.object.matrix_world.translation
# - blender_curve.matrix_world.translation
# ) + mathutils.Vector((-1, 0, 0))
# print(f"handle_left {location=}")
# self.data.splines[si].bezier_points[pi].handle_left = (
# self.data.splines[si]
# .bezier_points[pi]
# .handle_left.lerp(location, hook.strength)
# )
# if hook_handle_right:
# location = (
# hook.object.matrix_world.translation
# - blender_curve.matrix_world.translation
# )
# self.data.splines[si].bezier_points[pi].handle_right = (
# self.data.splines[si]
# .bezier_points[pi]
# .handle_right.lerp(location, hook.strength)
# )
if hook_handle_left:
location_left = location + (
self.data.splines[si].bezier_points[pi].co
- self.data.splines[si].bezier_points[pi].handle_left
)
self.data.splines[si].bezier_points[pi].handle_left = (
self.data.splines[si]
.bezier_points[pi]
.co.lerp(location_left, hook.strength)
)
if hook_handle_right:
location_right = location + (
self.data.splines[si].bezier_points[pi].co
- self.data.splines[si].bezier_points[pi].handle_right
)
self.data.splines[si].bezier_points[pi].handle_right = (
self.data.splines[si]
.bezier_points[pi]
.co.lerp(location, hook.strength)
)
elif hook_handle_left:
location = (
blender_curve.matrix_world.inverted()
@ hook.object.matrix_world.translation
)
self.data.splines[si].bezier_points[pi].handle_left = (
self.data.splines[si]
.bezier_points[pi]
.handle_left.lerp(location, hook.strength)
)
elif hook_handle_right:
location = (
blender_curve.matrix_world.inverted()
@ hook.object.matrix_world.translation
)
self.data.splines[si].bezier_points[pi].handle_right = (
self.data.splines[si]
.bezier_points[pi]
.handle_right.lerp(location, hook.strength)
)
i += 1
(
self.data.splines[si].beziers,
self.data.splines[si].lengths,
self.data.splines[si].total_length,
) = get_real_beziers_and_lengths(self.data.splines[si], resolution_factor)
print(f"total length {self.data.splines[si].total_length}")
def get_real_beziers_and_lengths(bezier_spline_obj, resolution_factor):
@ -391,7 +405,7 @@ def calc_point_on_bezier_spline(
if p.handle_left == p.co and len(bezier_spline_obj.bezier_points) > 1:
beziers, lengths, total_length = (
get_real_beziers_and_lengths(bezier_spline_obj, resolution_factor)
if not isinstance(bezier_spline_obj, BezierSpline)
if not isinstance(bezier_spline_obj, HookBezierSpline)
else (
bezier_spline_obj.beziers,
bezier_spline_obj.lengths,
@ -411,7 +425,7 @@ def calc_point_on_bezier_spline(
beziers, lengths, total_length = (
get_real_beziers_and_lengths(bezier_spline_obj, resolution_factor)
if not isinstance(bezier_spline_obj, BezierSpline)
if not isinstance(bezier_spline_obj, HookBezierSpline)
else (
bezier_spline_obj.beziers,
bezier_spline_obj.lengths,
@ -460,16 +474,15 @@ def calc_point_on_bezier_curve(
output_spline_index=False,
resolution_factor=1.0,
):
# bezier_curve = BezierCurve(bezier_curve_obj)
# curve = bezier_curve.data
curve = bezier_curve_obj.data
bezier_curve = HookBezierCurve(bezier_curve_obj)
curve = bezier_curve.data
# curve = bezier_curve_obj.data
# Loop through all splines in the curve
total_length = 0
for i, spline in enumerate(curve.splines):
resolution = int(spline.resolution_u * resolution_factor)
length = spline.calc_length(resolution=resolution)
print(f"{utils.LINE()} {length=}")
if total_length + length > distance or i == len(curve.splines) - 1:
if output_spline_index and output_tangent:
# return value from c_p_o_b_s is a tuple