Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Custom exporting animation data into aec file crashes Cinema

    Cinema 4D SDK
    r19 python
    2
    9
    1.3k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • A
      AndreAnjos
      last edited by AndreAnjos

      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

      1 Reply Last reply Reply Quote 0
      • ManuelM
        Manuel
        last edited by Manuel

        hi,

        we are missing one information, from where are you executing this code ?
        a script ?

        Cheers,
        Manuel

        MAXON SDK Specialist

        MAXON Registered Developer

        1 Reply Last reply Reply Quote 0
        • A
          AndreAnjos
          last edited by AndreAnjos

          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

          1 Reply Last reply Reply Quote 0
          • ManuelM
            Manuel
            last edited by

            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

            MAXON SDK Specialist

            MAXON Registered Developer

            1 Reply Last reply Reply Quote 0
            • ManuelM
              Manuel
              last edited by

              hi,

              I will mark this thread as resolved if you don't have anything to add.

              Cheers,
              Manuel

              MAXON SDK Specialist

              MAXON Registered Developer

              1 Reply Last reply Reply Quote 0
              • A
                AndreAnjos
                last edited by

                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

                1 Reply Last reply Reply Quote 0
                • ManuelM
                  Manuel
                  last edited by

                  Sure.

                  I will wait for another 14 days 🙂

                  Cheers,
                  Manuel

                  MAXON SDK Specialist

                  MAXON Registered Developer

                  1 Reply Last reply Reply Quote 0
                  • A
                    AndreAnjos
                    last edited by

                    Thank you Manuel! 🙂

                    I appreciate it!

                    Andre

                    1 Reply Last reply Reply Quote 0
                    • A
                      AndreAnjos
                      last edited by

                      @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

                      1 Reply Last reply Reply Quote 0
                      • First post
                        Last post