Skip to content

Instantly share code, notes, and snippets.

@xDShot
Created October 10, 2025 21:24
Show Gist options
  • Save xDShot/3008aa58db1c9225e2bd771269974fd4 to your computer and use it in GitHub Desktop.
Save xDShot/3008aa58db1c9225e2bd771269974fd4 to your computer and use it in GitHub Desktop.
Gets bones move velocity
import bpy
from mathutils import Vector
def get_bone_fcurves(armature_object, bone_name):
"""
Retrieves a list of F-curves associated with a specific bone in an armature.
Args:
armature_object (bpy.types.Object): The armature object.
bone_name (str): The name of the bone.
Returns:
list: A list of bpy.types.FCurve objects associated with the bone.
"""
fcurves = []
if armature_object and armature_object.animation_data and armature_object.animation_data.action:
# Construct the expected data_path prefix for the bone
# bpy.utils.escape_identifier handles special characters in bone names
bone_path_prefix = f'pose.bones["{bpy.utils.escape_identifier(bone_name)}"]'
for fcurve in armature_object.animation_data.action.fcurves:
if fcurve.data_path.startswith(bone_path_prefix):
fcurves.append(fcurve)
return fcurves
def get_bone_location_fcurves(armature_object, bone_name):
"""
Finds and returns the F-Curves affecting the location of a specified bone
in a given armature.
Args:
armature_object (bpy.types.Object): The armature object.
bone_name (str): The name of the bone within the armature.
Returns:
list: A list containing the F-Curves for X, Y, and Z location,
or None if not found.
"""
armature = armature_object
if not armature.animation_data or not armature.animation_data.action:
print(f"No active action found for armature '{armature_object_name}'.")
return None
action = armature.animation_data.action
location_fcurves = [None, None, None] # For X, Y, Z location
# The data path for a bone's location F-Curve looks like:
# 'pose.bones["BoneName"].location'
expected_data_path = f'pose.bones["{bpy.utils.escape_identifier(bone_name)}"].location'
found_bone = False
for fcurve in action.fcurves:
if fcurve.data_path == expected_data_path:
if fcurve.array_index == 0: # X Location
found_bone = True
location_fcurves[0] = fcurve
elif fcurve.array_index == 1: # Y Location
found_bone = True
location_fcurves[1] = fcurve
elif fcurve.array_index == 2: # Z Location
found_bone = True
location_fcurves[2] = fcurve
if found_bone:
return location_fcurves
else:
return None
obj = bpy.data.objects['inverse kinematics skeleton']
act = bpy.data.objects['inverse kinematics skeleton'].animation_data.action
act_name = act.name
act_length = int(act.frame_range[1])
curves = act.fcurves
move_helper_name = "Movement helper" # Replace with your bone name
loc_fcurves = get_bone_location_fcurves(obj, move_helper_name)
if loc_fcurves:
print(f"F-Curves for bone '{move_helper_name}' location:")
if loc_fcurves[0]:
print(f" X Location F-Curve: {loc_fcurves[0]}")
if loc_fcurves[1]:
print(f" Y Location F-Curve: {loc_fcurves[1]}")
if loc_fcurves[2]:
print(f" Z Location F-Curve: {loc_fcurves[2]}")
else:
raise Exception(f"Could not find location F-Curves for bone '{move_helper_name}' in action '{act_name}'.")
def parse_keyframe_points(axis_name, fcurve):
print(f"Axis {axis_name}:")
keypoints = []
for keyframe_point in fcurve.keyframe_points:
frame = keyframe_point.co[0] # X-coordinate is the frame
value = keyframe_point.co[1] # Y-coordinate is the value
print(f"\tFrame: {frame}, Value: {value}")
keypoints.append([frame, value])
print(keypoints)
return keypoints
keys = ( parse_keyframe_points("X", loc_fcurves[0]), parse_keyframe_points("Y", loc_fcurves[1]), parse_keyframe_points("Z", loc_fcurves[2]) )
def get_axis_velocity(axis_name, keyframe):
frames_range = keyframe[1][0] - keyframe[0][0]
start = keyframe[0][1]
end = keyframe[1][1]
velocity = start - end
velocity = velocity / frames_range
print(f"Axis {axis_name}, frames_range: {frames_range}, Points: {start:.3f} {end:.3f}, velocity: {velocity:.3f}")
return velocity
vel_x = get_axis_velocity("X", keys[0])
vel_y = get_axis_velocity("Y", keys[1])
vel_z = get_axis_velocity("Z", keys[2])
velocity = Vector((vel_x, vel_y, vel_z)) * act_length
print(f"Frames range: {act_length}")
print(velocity.x, velocity.y, velocity.z)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment