Disable all animation in document
-
Hi,
is there a way to disable in Dope sheet all animation in a document? Bascially trigger the Eye Icon function in timeline Summary -
@ceen Hi, The Summary row mey only a UI aggregate; it is not a single CTrack that can be switched directly.
To reproduce its Animation switch, collect the real CTrack objects and set theirc4d.ID_CTRACK_ANIMOFFvalue:# True = animation enabled, False = animation disabled track[c4d.ID_CTRACK_ANIMOFF] = FalseThis does not delete keyframes and does not hide Timeline rows. Do not use NBIT_TLx_HIDE for this, because those flags only hide rows in the Timeline.
A complete document-wide solution must also traverse Motion Sources indoc.GetNLARoot().Add Motion Sourcemoves/copies animation into that separate NLA hierarchy, so iterating only normal scene objects and tags will miss tracks such as Time and 2D Tracks.It should be noted that
doc.GetNLARoot()is marked asPrivatein the SDK, and I'm not sure whether it should be used."""Toggle the Summary Animation switch for all collected CTracks.""" import c4d def iter_nodes(node): while node: yield node yield from iter_nodes(node.GetDown()) node = node.GetNext() def main(): doc = c4d.documents.GetActiveDocument() tracks, seen = [], set() def add_tracks(owner): for track in (owner.GetCTracks() or []) if owner else []: if id(track) not in seen: seen.add(id(track)) tracks.append(track) def add_tree(root, include_tags=False): for node in iter_nodes(root): add_tracks(node) if include_tags: for tag in node.GetTags() or []: add_tracks(tag) add_tracks(doc) add_tree(doc.GetFirstObject(), include_tags=True) material = doc.GetFirstMaterial() while material: add_tracks(material) add_tree(material.GetFirstShader()) material = material.GetNext() render_data = doc.GetFirstRenderData() while render_data: add_tracks(render_data) video_post = render_data.GetFirstVideoPost() while video_post: add_tracks(video_post) video_post = video_post.GetNext() render_data = render_data.GetNext() layer_root = doc.GetLayerObjectRoot() add_tree(layer_root.GetDown() if layer_root else None) # Private API, but required for Add Motion Source tracks in C4D 2026. add_tree(doc.GetNLARoot().GetDown(), include_tags=True) enabled = any(track[c4d.ID_CTRACK_ANIMOFF] for track in tracks) for track in tracks: track[c4d.ID_CTRACK_ANIMOFF] = not enabled c4d.EventAdd() if __name__ == "__main__": main()Cheers,
Anlv -
Hello @ceen,
Yes, this is possible. @Anlv is right that
ID_CTRACK_ANIMOFFis the toggle you are looking for (thank you for helping out!). You can then either combine it with manual scene traversal code, or use mxutils.RecurseGraph which is for most users probably the simpler option when they do not have intimate knowledge of the Cinema scene graph.Cheers,
Ferdinand"""Loops over all tracks in the scene and toggles their animation state. I.e., running this once will disable all tracks, running it again will enable all tracks, and so on. """ import c4d import mxutils doc: c4d.documents.BaseDocument # The currently active document. op: c4d.BaseObject | None # The primary selected object in `doc`. Can be `None`. def main() -> None: """Called by Cinema 4D when the script is being executed. """ # We walk the document using RecurseGraph, finding all tracks in the scene, no matter where they # are hiding. This is a relatively inefficient call as we really walk everything, and experts # could fine tune this. But for a simple script like this or any code that is not performance # critical, this is just fine. for track in mxutils.RecurseGraph(doc, yieldBranches=True, yieldHierarchy=True, nodeFilter=[c4d.CTbase]): track[c4d.ID_CTRACK_ANIMOFF] = not track[c4d.ID_CTRACK_ANIMOFF] c4d.EventAdd() if __name__ == '__main__': main() -
Hi @ferdinand,
using the
mxutils.RecurseGraphmethod is much clearer and simpler. Thank you, I've learned something new again.Cheers,
Anlv -
Hi,
@ferdinand and @Anlv this is most awesome! All way beyond my capablities so thanks a lot for the scripts!