Custom exporting animation data into aec file crashes Cinema
-
Hi all,
Our studio added an awesome publishing plugin to our pipeline called Pyblish and I'm currently developing sense checks to work with it.
One of the requests is to extract a .aec file, ready to be imported to After Effects.
Unfortunately, when extracting the objects transformations values Cinema crashes and looking at the bug report it shows the following. Let me know if you need full report, please.
CRITICAL: Stop: Current take is nullptr document data could be corrupted [takemanager.cpp(505)]
To understand what I've done here's the latest full code:
This is working in the Pyblish context and I understand if there are a few parts that may not easy to understand without knowing the tool.I commented on the lines which I think are causing the crashing.
""" Extract .aec file into a server path """ import os import pyblish.api as api import c4d from c4d import utils DOC = c4d.documents.GetActiveDocument() DOC_NAME = DOC.GetDocumentName().split('.')[0] DOC_PATH = DOC.GetDocumentPath() def aec_file(data): full_doc_name = DOC.GetDocumentName() doc_name = os.path.splitext(full_doc_name) abs_path = DOC.GetDocumentPath() file_path = '{0}/05_Animations/04_AE'.format(os.path.dirname(os.path.dirname(abs_path))) if os.path.exists(file_path): txt_file_path = os.path.join(file_path, 'AEC', '{}.aec'.format(doc_name[0])) with open(txt_file_path, 'w') as txt_file: for line in data: txt_file.write(''.join(line)) return file_path class ExtractAEC(api.InstancePlugin): """ Extract .aec file into server path """ order = api.ExtractorOrder families = ["animation.assets"] label = "AEC" def process(self, instance): if instance.data["name"] == "Cameras": # Start data file global extract_data extract_data = ['CINEMA 4D COMPOSITION\n\n'] bp_render = DOC.GetFirstRenderData() root_layer = DOC.GetLayerObjectRoot() global layer layer = c4d.documents.LayerObject() layer.SetName('Temp_Layer') layer.InsertUnder(root_layer) cam_lst = [cam[0] for cam in instance.data["cameras"]] # We create a layer and solo the object under it to improve performance. layer_data = layer.GetLayerData(DOC) layer_data['solo'] = True layer.SetLayerData(DOC, layer_data) DOC.ChangeNBit(c4d.NBIT_SOLO_LAYER, c4d.NBITCONTROL_SET) res_x = bp_render[c4d.RDATA_XRES_VIRTUAL] res_y = bp_render[c4d.RDATA_YRES_VIRTUAL] extract_data.extend(['RESOLUTION {0} {1}\n'.format(int(res_x), int(res_y))]) # Time frames global full_start_frame full_start_frame = cam_lst[0][c4d.ID_USERDATA, 3] global full_end_frame full_end_frame = cam_lst[-1][c4d.ID_USERDATA, 4] time_range = full_end_frame + 1 global fps fps = bp_render[c4d.RDATA_FRAMERATE] if bp_render[c4d.RDATA_FIELD] == 0: field = 'NONE' elif bp_render[c4d.RDATA_FIELD] == 1: field = 'EVEN' else: field = 'ODD' aspect = bp_render[c4d.RDATA_PIXELASPECT] extract_data.extend(['FROM {0}\n' 'TO {1}\n' 'RANGE {2}\n' 'FPS {3}\n' 'FIELDS {4}\n' 'ASPECT {5}\n' 'VERSION 7\n\n'.format(full_start_frame, full_end_frame, time_range, fps, field, aspect)]) # Composition extract_data.extend(['COMPOSITION NRM ON "{0}"\n' '{1}\n' '\tSTEREONUM -1\n' '{2}\n\n'.format(DOC_NAME, '{', '}')]) # Cameras for cam in cam_lst: cam_layer = cam.GetLayerObject(DOC) cam.SetLayerObject(layer) start_frame = cam[c4d.ID_USERDATA, 3] end_frame = cam[c4d.ID_USERDATA, 4] focal = utils.RadToDeg(cam[c4d.CAMERAOBJECT_FOV]) extract_data.extend(['CAMERA "{0}"\n' '{1}\n' '\tSHOWFROM {2}\n' '\tSHOWTO {3}\n'.format(cam.GetName().split(' ')[0], '{', start_frame, end_frame)]) for key in range(start_frame, end_frame + 1): # Is this correct? DOC.SetTime(c4d.BaseTime(key, float(fps))) DOC.ExecutePasses(None, True, False, False, 0) c4d.EventAdd(c4d.EVENT_ANIMATE) pos = cam.GetAbsPos() rot = cam.GetAbsRot() # This is where it usually crashes. Not sure if anything to do with converting Radians to Degrees. extract_data.extend(['\tKEY {0} ' '{1:.3f} {2:.3f} {3:.3f} ' '{4:.3f} {5:.3f} {6:.3f} ' '{7} 100 0\n'.format(key, pos.x, pos.y, pos.z, utils.RadToDeg(rot.x), utils.RadToDeg(rot.y), utils.RadToDeg(rot.z), focal)]) cam.SetLayerObject(cam_layer) extract_data.extend('}\n\n') # Trackers if instance.data["name"] == "External Comp Tags": trackers = instance.data["compTags"] for tracker in trackers: tracker_layer = tracker.GetLayerObject(DOC) tracker.SetLayerObject(layer) extract_data.extend(['NULL2 "{0}"\n' '{1}\n' '\tNULLTYPE 1\n' '\tSIZEX 100\n' '\tSIZEY 100\n' '\tANCHOR 3\n' '\tORIENTATION 1\n' '\tCOLOR 1 0 0\n' '\tSHOWFROM {2}\n' '\tSHOWTO {3}\n'.format(tracker.GetName(), '{', full_start_frame, full_end_frame)]) for key in range(full_start_frame, full_end_frame + 1): # Is this correct? DOC.SetTime(c4d.BaseTime(key, float(fps))) DOC.ExecutePasses(None, True, True, True, 0) c4d.EventAdd(c4d.EVENT_ANIMATE) pos = tracker.GetMg().off rot_xyz = c4d.utils.MatrixToHPB(tracker.GetMg(), c4d.ROTATIONORDER_XYZGLOBAL) rot_hpb = c4d.utils.MatrixToHPB(tracker.GetMg(), c4d.ROTATIONORDER_HPB) # # This is where it usually crashes. Not sure if anything to do with converting Radians to Degrees. extract_data.extend(['\tKEY {0} ' '{1:.3f} {2:.3f} {3:.3f} ' '{4:.3f} {5:.3f} {6:.3f} ' '{7:.3f} {8:.3f} {9:.3f}\n'.format(key, pos.x, pos.y, pos.z, utils.RadToDeg(rot_xyz.x), utils.RadToDeg(rot_xyz.y), utils.RadToDeg(rot_xyz.z), utils.RadToDeg(rot_hpb.x), utils.RadToDeg(rot_hpb.y), utils.RadToDeg(rot_hpb.z))]) tracker.SetLayerObject(tracker_layer) extract_data.extend('}\n\n') # Markers first_marker = c4d.documents.GetFirstMarker(DOC) markers = [] # If a marker exists add it to the markers list if first_marker is not None: while first_marker is not None: markers.append(first_marker) first_marker = first_marker.GetNext() for marker in markers: extract_data.extend(['MARKER "{0}" {1}\n'.format(marker.GetName(), marker[c4d.TLMARKER_TIME].GetFrame(24))]) DOC.ChangeNBit(c4d.NBIT_SOLO_LAYER, c4d.NBITCONTROL_CLEAR) layer.Remove() path_file = aec_file(extract_data) self.log.info("AEC extracted to {}".format(path_file))
If there is other solutions for exporting a .aec file with python I would like to know as well, please!
Let me know if you need more information!
Thank you all in advance!
Andre
-
hi,
we are missing one information, from where are you executing this code ?
a script ?Cheers,
Manuel -
Hi @m_magalhaes,
Apologies! Pyblish is called from a script inside Cinema and the script above runs after Pyblish opening and going through each stage.
Hope this helps!
Cheers!
Andre
-
hi,
What come to mind is maybe the crash have nothing to do with that critical stop.
Just in case be sure that you don't have the take dialog tab in a custom layout when you are opening Cinema 4D with a script.Also your code seem to be only a part of the script you are using (because in that state, it simply does nothing).
We don't have any experience with Pyblish.
Is it possible to recreate that crash without using that library ? (that would simplify a lot our job here)I would also suggest to ask them. (we can't debug third party libraries)
But try to reproduce the crash without that library just to be sure if the problem is in our side or their side.
Cheers,
Manuel -
hi,
I will mark this thread as resolved if you don't have anything to add.
Cheers,
Manuel -
Hi Manuel,
Apologies for this, as due to current circumstances I'm inundated in solving other issues.
Can we revisit this please?Thank you in advance and apologies!
Andre
-
Sure.
I will wait for another 14 days
Cheers,
Manuel -
Thank you Manuel!
I appreciate it!
Andre
-
@m_magalhaes
Hi Manuel,Thank you for giving me some time to check this out.
So after a bit of testing and changing the code to work with Cinema I cannot replicate the issue. As you mention it seems to be related to Pyblish.I did find interesting that when running the code in Cinema without Pyblish you can't see the active frame running through the timeline, while you do see it when running through Pyblish. Perhaps that's the correlation with the crash.
I will close this as solve, for the fact that it does not crash in the Cinema context.
Thanks again!
Andre