I have a use case where I have to change an object's material color per keyframe (i.e. the color will change instantly between keyframes). I have been able to easily do this for other data (location, rotation) but have been stuck on the color part. I have to do this programmatically through the Python API.
Other answers I looked at: 1 2
I believe I am doing what the answers in those questions suggest, but have not been successful. Here is a minimal example where I want the cube to snap between red and blue colors for 1000 keyframes:
import bpy
import numpy as np
cube = bpy.data.objects["Cube"]
material = bpy.data.materials.new('material')
material.use_nodes = True
base_color = material.node_tree.nodes["Principled BSDF"].inputs[0]
red = [1,0,0,1]
blue = [1,0,1,1]
base_color.default_value = red
color = red
location = np.array([0,0,0])
for i in range(1000):
cube.active_material = material
bsdf = material.node_tree.nodes['Principled BSDF']
bsdf.inputs['Base Color'].keyframe_insert(data_path="default_value", frame=i)
cube.location = location
cube.keyframe_insert(data_path="location", frame=i)
if color == red:
color = blue
else:
color = red
location += [1,0,0]
# change this path to an absolute path on your computer
bpy.ops.wm.save_as_mainfile(filepath='C:/Users/m/Desktop/test_render.blend')
This does not produce the desired behavior. I can see the the material's base color property has the diamond symbol to the right, indicating it is keyframed. But the cube does not change to blue at any frame. What am I missing? Do I have to change the current value rather than the default value? I tried this, but there is no "value" data path.
Thanks!
i
, set the color and insert the keyframe. $\endgroup$base_color.default_value = color
before thekeyframe_insert
line. and your lineblue = [1,0,1,1]
is not blue. that is pink. set it to blue =[0,0,1,1]
instead. optionally if you prefer, you can have a one liner for the if/else part likecolor = blue if color == red else red
$\endgroup$