Well, ultimately I want to get at the keys, but that part is trivial (get the CCurve, get the CKeys).
My questions are in the bullet points: I am missing these functions, how can I implement them with my own code? (Or potentially better: Where in the API are they? Not that I have much hope about that...)
Let's look at the first bullet point: where do I get a list of all tracks in a scene (regardless of the timeline for now)? Here's what code I currently have, in absence of an API function:
"""Name-en-US: Test - List all tracks
Description-en-US: track list"""
import c4d
from c4d import gui
def GetNextObject(op):
if op==None: return None
if op.GetDown(): return op.GetDown()
while not op.GetNext() and op.GetUp(): op = op.GetUp()
return op.GetNext()
def IterAllObjects(doc):
if doc is None: return
op = doc.GetFirstObject()
while op is not None:
yield op
op = GetNextObject(op)
def IterAllShaders(obj):
if obj is None: return
op = obj.GetFirstShader()
while op is not None:
yield op
op = GetNextObject(op)
def IterAllMaterials(doc):
if doc is None: return
op = doc.GetFirstMaterial()
while op is not None:
yield op
op = op.GetNext()
def IterAllObjTracks(doc):
if doc is None: return
for track in doc.GetCTracks():
yield track, "Document"
for obj in IterAllObjects(doc):
for track in obj.GetCTracks():
yield track, obj.GetName()
for tag in obj.GetTags():
for track in tag.GetCTracks():
yield track, obj.GetName() + "::" + tag.GetName()
for shader in IterAllShaders(tag):
for track in shader.GetCTracks():
yield track, obj.GetName() + "::" + tag.GetName() + "::" + shader.GetName()
if tag.GetType() == c4d.Texpresso:
nodemaster = tag.GetNodeMaster()
if nodemaster:
node = nodemaster.GetRoot()
while node is not None:
for track in node.GetCTracks():
yield track, obj.GetName() + "::" + tag.GetName() + "::" + node.GetName()
node = GetNextObject(node)
for shader in IterAllShaders(obj):
for track in shader.GetCTracks():
yield track, obj.GetName() + "::" + shader.GetName()
def IterAllMatTracks(doc):
if doc is None: return
for mat in IterAllMaterials(doc):
for track in mat.GetCTracks():
yield track, mat.GetName()
for shader in IterAllShaders(mat):
for track in shader.GetCTracks():
yield track, mat.GetName() + "::" + shader.GetName()
def GetActiveTracks(doc, timeline_bit=c4d.NBIT_TL1_SELECT):
# Timeline 1: c4d.NBIT_TL1_SELECT,
# F-Curve 1: c4d.NBIT_TL1_FCSELECT,
if doc is None: return
active_tracks = []
for track, name in IterAllObjTracks(doc):
if track.GetNBit(timeline_bit):
active_tracks.append(track)
for track, name in IterAllMatTracks(doc):
if track.GetNBit(timeline_bit):
active_tracks.append(track)
return active_tracks
def main():
print " "
print "All Tracks"
print "============="
for track, name in IterAllObjTracks(doc):
print name, track.GetName()
for track, name in IterAllMatTracks(doc):
print name, track.GetName()
print " "
print "Active Tracks"
print "============="
activeTracks = GetActiveTracks(doc)
if activeTracks:
for track in activeTracks:
print track.GetName()
if __name__=='__main__':
main()
Note that it is not sufficient to go through all objects, I also need to consider all materials, all tags, all shaders which may not be limited to materials but also exist on objects or tags, and all nodes within an XPresso tag. Any of these may have an animation track.
The code above works fine, but I can only find what I am looking for... For example, I have added an animation track in a test scene to the project's Dynamics settings. This code does not find that track because I have no idea in what object I need to look. (It's not the document, I already consider that one - if the doc can even hold any tracks at all, which I don't know).
I also cannot know what I may miss with this code: Can an XPresso node have shaders again? May a shader have sub-trees that I don't know about? Can further tracks hide in proprietary plugins? Are there tag types with other subtrees of BaseList2D that may have tracks? How can I ever be sure that I have collected all the tracks?