python中处理动画曲线最诡异的部分就是DescIDs。
整个c4d都在使用DescID,但动画环节尤其重要。DescID是一个多层级的ID,可以定义多层级数据,比如用户数据userdata,第一个元素的DescID永远是ID_USERDATA,第二个元素是每个userdata的索引。DescID的多层级也可以给子通道使用,比如position scale rotation或者颜色的子向量。
每个DescID的元素都是一个描述等级,描述等级也有三个元素,分别是id,数据类型,创建者。
给描述元素创建tracks
描述元素木有子通道,DescID就是描述元素的ID
# Track for Object Enabled Boolean
enabled =c4d.CTrack(op, c4d.DescID(c4d.ID_BASEOBJECT_GENERATOR_FLAG))
op.InsertTrackSorted(enabled)
# Track for Light Brightness Real
track =c4d.CTrack(op,c4d.DescID(c4d.LIGHT_BRIGHTNESS))
op.InsertTrackSorted(track)
创建点X,Y,Z的tracks
每个向量都有自己的动画曲线,就跟时间线一样。每个容器的DescID包含两个级别。第一级就是position track本身,其有一个vector 类型。这是你在时间线上看到的父position。第二级就是特殊的轨道,并是real类型
trackX =c4d.CTrack(op,
c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_POSITION,c4d.DTYPE_VECTOR,0),
c4d.DescLevel(c4d.VECTOR_X,c4d.DTYPE_REAL,0)))
trackY =c4d.CTrack(op,
c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_POSITION,c4d.DTYPE_VECTOR,0),
c4d.DescLevel(c4d.VECTOR_Y,c4d.DTYPE_REAL,0)))
trackZ =c4d.CTrack(op,
c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_POSITION,c4d.DTYPE_VECTOR,0),
c4d.DescLevel(c4d.VECTOR_Z,c4d.DTYPE_REAL,0)))
op.InsertTrackSorted(trackX)
op.InsertTrackSorted(trackY)
op.InsertTrackSorted(trackZ)
用户数据的tracks
创建或者遍历userdata时,获取的id就是DescID。对于有类似向量,颜色子通道的物体,还是需要给每个通道添加track。下面的代码描述了DescID和DescLevel,同时包含一些自定义的函数并创建userdata的track。仅考虑了部分类型。
importc4d
def CreateUDTrack(op,id):
tracks =[]
# element0 is always UD group
# element1 is the UD itself
ud =id[1]
dtype =ud.dtype
if dtype ==c4d.DTYPE_VECTOR or dtype ==c4d.DTYPE_COLOR:
# get datatypes with subchannels and add multiple tracks
for v in xrange(c4d.VECTOR_X, c4d.VECTOR_Z+1):
descID =c4d.DescID(id[0],id[1],c4d.DescLevel(v,c4d.DTYPE_REAL))
tracks.append(c4d.CTrack(op,descID))
else:
# just add the single track
tracks.append(c4d.CTrack(op,id))
return tracks
def main():
for id, bc in op.GetUserDataContainer():
# id is the DescID, bc is the container
print bc[c4d.DESC_NAME], id
# look at each DescLevel
# this isn't necessary, just instructive
for level in xrange(id.GetDepth()):
print "Level ", level, ": ", \
id[level].id, ",", \
id[level].dtype, ",", \
id[level].creator
# Create tracks using custom function
tracks =CreateUDTrack(op,id)
# Loop through returned tracks and insert
for track in tracks:
op.InsertTrackSorted(track)
if__name__=='__main__':
main()
查找track
C4D 13之后就可以用FindCtrack用DescID找到已存在的动画曲线了。不确定曲线是否存在这绝对是个好方法。另外,c4d会直接用相同的参数创建曲线。
# Track for Light Brightness Real
dBrightness =c4d.DescID(c4d.LIGHT_BRIGHTNESS) #assign the DescID to a var for convenience
tBrightness =op.FindCTrack(dBrightness) #find the track
if not tBrightness: #if track isn't found, create it
tBrightness =c4d.CTrack(op,dBrightness)
op.InsertTrackSorted(tBrightness)
添加key
一旦有了track,添加关键帧就很简单。所有的关键帧都应用到了F-Curve,这是一个CCure对象。因此,需要先获取CCure,再使用AddKey或者InsertKey来添加。FillKey可以用默认值添加,设置合适的插值。同样,可以用浮点数来setValue。
#Get the curve
curve =track.GetCurve()
#Add keys using AddKey
#Creates the key at the proper time
#Then you modify the key
keyDict =curve.AddKey(c4d.BaseTime(0))
#keyDict is a dict with key=CKey and int=index
myKey =keyDict["key"]
#Use FillKey to fill the key with default values (interpolation)
trk.FillKey(doc,op,myKey)
#Use SetValue or SetGeData to set the key value
myKey.SetValue(curve,1)
#myKey.SetGeData(curve,1)
#Add keys using InsertKey
#Define the key first
key =c4d.CKey()
#Use FillKey to fill the key with default values (interpolation)
trk.FillKey(doc,op,key)
key.SetTime(curve,c4d.BaseTime(1))
key.SetValue(curve,.5)
#key.SetGeData(curve,1)
#Then insert it
curve.InsertKey(key)
设置关键帧选择
另一个有关DescID的例子就是设置选中物体的关键帧。可以和录制按钮一起使用来创建track,但是上面说的方法更加稳定。可以在特定的特殊物体上指定关键帧。
# Put the "Position" desclevel in a variable for convenience
pos =c4d.DescLevel(c4d.ID_BASEOBJECT_REL_POSITION, c4d.DA_VECTOR)
# Set Keyframe selection on each vector X,Y,Z
op.SetKeyframeSelection(c4d.DescID(pos,c4d.DescLevel(c4d.VECTOR_X, c4d.DA_REAL, c4d.DA_VECTOR)), True)
op.SetKeyframeSelection(c4d.DescID(pos,c4d.DescLevel(c4d.VECTOR_Y, c4d.DA_REAL, c4d.DA_VECTOR)), True)
op.SetKeyframeSelection(c4d.DescID(pos,c4d.DescLevel(c4d.VECTOR_Z, c4d.DA_REAL, c4d.DA_VECTOR)), True)
# Update the C4D Interface
c4d.EventAdd()