Spaces:
Build error
Build error
import csv | |
import bpy | |
from mathutils import * | |
import sys | |
argv = sys.argv | |
argv = argv[argv.index("--") + 1:] # get all args after "--" | |
D = bpy.data | |
C = bpy.context | |
def copy_armature_animation( | |
source_armature_name, | |
destination_armature_name, | |
start_frame_source, | |
end_frame_source, | |
start_frame_target, | |
): | |
# Get the source and destination armature objects | |
source_armature = bpy.data.objects[source_armature_name] | |
destination_armature = bpy.data.objects[destination_armature_name] | |
# Copy the animation data from the source armature to the destination armature | |
#print(f"copying animation {start_frame_source}-{end_frame_source} to {start_frame_target} ") | |
for i, frame in enumerate(range(start_frame_source, end_frame_source + 1)): | |
bpy.context.scene.frame_set(frame) | |
# Set the location and rotation of the destination bone at the given frame | |
for bone in source_armature.pose.bones: | |
destination_bone = destination_armature.pose.bones.get(bone.name) | |
destination_bone.location = bone.location | |
destination_bone.rotation_quaternion = bone.rotation_quaternion | |
destination_bone.keyframe_insert( | |
data_path="location", frame=start_frame_target + i | |
) | |
destination_bone.keyframe_insert( | |
data_path="rotation_quaternion", frame=start_frame_target + i | |
) | |
# Copy the bone's animation data for each frame in the range | |
def adjust_armature_animation_timing( | |
armature_name, old_start, old_end, new_start, new_end | |
): | |
# Get the armature object by name | |
armature = bpy.data.objects[armature_name] | |
# Calculate the ratio between the old and new keyframe ranges | |
old_range = old_end - old_start | |
new_range = new_end - new_start | |
ratio = new_range / old_range | |
#print(f"Adjsuting timming from {old_start}-{old_end} to {new_start}-{new_end} with ratio: {ratio}") | |
# Iterate through all the armature bones and modify their animation keyframes | |
for fcurve in armature.animation_data.action.fcurves: | |
if fcurve.array_index < 4: | |
for keyframe in fcurve.keyframe_points: | |
# Adjust the keyframe position based on the ratio | |
if keyframe.co.x in range (old_start, old_end): | |
#print(f"keyframe move from {keyframe.co.x}") | |
keyframe.co.x = (keyframe.co.x - old_start) * ratio + new_start | |
#print(f"to {keyframe.co.x}") | |
else: | |
continue | |
def calculate_new_frame_range(frame_rate, timestamp, start_frame): | |
adjusted_end_frame = int(timestamp / 1000 * frame_rate + start_frame) | |
return adjusted_end_frame | |
def change_material_property( | |
material_name, node_name, new_value, start_frame, end_frame | |
): | |
value = bpy.data.materials[material_name].node_tree.nodes[node_name].outputs[0] | |
value.default_value = new_value | |
value.keyframe_insert(data_path="default_value", frame=start_frame+1) | |
value.keyframe_insert(data_path="default_value", frame=end_frame-1) | |
def set_cues_state( | |
global_state, | |
global_color, | |
c1_state, | |
c1_color, | |
c2_state, | |
c2_color, | |
c3_state, | |
c3_color, | |
c4_state, | |
c4_color, | |
start_frame, | |
end_frame, | |
): | |
# cue 1 noise | |
change_material_property( | |
"CUE_MAT_1", "Distortion", float(c1_state), start_frame, end_frame | |
) | |
# cue 2 noise | |
change_material_property( | |
"CUE_MAT_2", "Distortion", float(c2_state), start_frame, end_frame | |
) | |
# cue 3 noise | |
change_material_property( | |
"CUE_MAT_3", "Distortion", float(c3_state), start_frame, end_frame | |
) | |
# cue 4 noise | |
change_material_property( | |
"CUE_MAT_4", "Distortion", float(c4_state), start_frame, end_frame | |
) | |
# cue 1 color | |
change_material_property( | |
"CUE_MAT_1", "Color", float(c1_color), start_frame, end_frame | |
) | |
# cue 2 color | |
change_material_property( | |
"CUE_MAT_2", "Color", float(c2_color), start_frame, end_frame | |
) | |
# cue 3 color | |
change_material_property( | |
"CUE_MAT_3", "Color", float(c3_color), start_frame, end_frame | |
) | |
# cue 4 color | |
change_material_property( | |
"CUE_MAT_4", "Color", float(c4_color), start_frame, end_frame | |
) | |
# global cue on | |
change_material_property( | |
"GLOBAL_CUE_MAT", "MixFactor", float(global_state), start_frame, end_frame | |
) | |
# global cue color | |
change_material_property( | |
"GLOBAL_CUE_MAT", "Color", float(global_color), start_frame, end_frame | |
) | |
def animate_cycle(source_armature, target_armature, csv_file): | |
# Get the current scene | |
scene = bpy.context.scene | |
# Get the frame rate of the current scene | |
frame_rate = scene.render.fps / scene.render.fps_base | |
gait_to_keyframe_start = {0: 10, 1: 80, 2: 60, 3: 250} | |
gait_to_keyframe_end = {0: 49, 1: 99, 2: 74, 3: 310} | |
# column_names = ["Gait", "TS", "State", "Condition", "Shape1", "Shape2", "Shape3", "Shape4", "Color1", "Color2", "Color3", "Color4", "Danger1", "Danger2", "Danger3", "Danger4"] | |
previous_end_frame = 0 | |
with open(csv_file, "r") as csvfile: | |
datareader = csv.reader(csvfile) | |
for i, row in enumerate(datareader): | |
if i == 0 or row[0] is None: | |
continue | |
copy_armature_animation( | |
source_armature, | |
target_armature, | |
gait_to_keyframe_start[int(row[0])], | |
gait_to_keyframe_end[int(row[0])], | |
previous_end_frame + 1, | |
) | |
adjusted_end_frame = calculate_new_frame_range( | |
frame_rate=frame_rate, | |
timestamp=int(float(row[1])), | |
start_frame=previous_end_frame + 1, | |
) | |
adjust_armature_animation_timing( | |
target_armature, | |
previous_end_frame + 1, | |
previous_end_frame + 1 + gait_to_keyframe_end[int(row[0])] - gait_to_keyframe_start[int(row[0])], | |
previous_end_frame + 1, | |
adjusted_end_frame, | |
) | |
set_cues_state( | |
row[3], | |
row[4], | |
row[8], | |
row[5], | |
row[9], | |
row[6], | |
row[10], | |
row[7], | |
row[11], | |
row[2], | |
previous_end_frame, | |
adjusted_end_frame, | |
) | |
#print(previous_end_frame, adjusted_end_frame) | |
previous_end_frame = adjusted_end_frame | |
print(f"Animated row {i}") | |
bpy.context.scene.frame_end = previous_end_frame | |
bpy.ops.render.render(animation=True) | |
print("Cycle_device:") | |
print(bpy.context.preferences.addons["cycles"].preferences.has_active_device()) | |
animate_cycle("Deformation", "Deformation.001", str(argv[0])) | |