For anyone that wants it this si the completed script i used for my needs. so that i could pass the look dev information changes per frame onto the rest of my team.::
import c4d
import sys
import os
# Your predefined constants and variables
doc: c4d.documents.BaseDocument # The active document.
op: c4d.BaseObject # The active object, can be `None`.
IGNORE_DIRECT_ACCESS_TYPES: tuple[int] = (c4d.DTYPE_BUTTON,
c4d.DTYPE_CHILDREN,
c4d.DTYPE_DYNAMIC,
c4d.DTYPE_GROUP,
c4d.DTYPE_SEPARATOR,
c4d.DTYPE_STATICTEXT,
c4d.DTYPE_SUBCONTAINER)
def main() -> None:
"""
Main function to iterate over each frame and print object data.
"""
if not op:
raise RuntimeError("Please select an object.")
# Get the start and end frames of the document's active timeline
start_frame = doc.GetLoopMinTime().GetFrame(doc.GetFps())
end_frame = doc.GetLoopMaxTime().GetFrame(doc.GetFps())
# Iterate through each frame in the range
for frame in range(start_frame, end_frame + 1):
# Set the document's time to the current frame
doc.SetTime(c4d.BaseTime(frame, doc.GetFps()))
# Update the scene to reflect changes at the current frame
c4d.DrawViews(c4d.DRAWFLAGS_FORCEFULLREDRAW)
c4d.EventAdd()
# Print frame information
print(f"Frame: {frame}")
# Iterate over the user data container
for pid, bc in op.GetUserDataContainer():
if pid.GetDepth() < 2 or pid[0].id != c4d.ID_USERDATA:
raise RuntimeError("This should never happen.")
eid: int = pid[1].id
dtype: int = pid[1].dtype
if dtype in IGNORE_DIRECT_ACCESS_TYPES:
continue
try:
value: any = op[pid]
except:
print ("Stepping over type which is inaccessible in Python.")
continue
# Print the value for each user data parameter
print(f"Name: {bc[c4d.DESC_NAME]}, Value: {value}")
print("-" * 80)
if __name__ == '__main__':
# Change the standard output to a file on the desktop
desktop_path = os.path.join(os.path.expanduser('~'), 'Desktop')
output_file_path = os.path.join(desktop_path, 'c4d_output.txt')
with open(output_file_path, 'w') as file:
sys.stdout = file
main()
sys.stdout = sys.__stdout__