Melange - Copying Tracks To Other Objects [SOLVED]

On 05/10/2016 at 10:59, xxxxxxxx wrote:

User Information:
Cinema 4D Version:    
Platform:   Windows  ;   
Language(s) :     C++  ;

I'm writing an application using the Melange SDK. And I'm getting crashes when trying to copy more than one track using AppendCTrack().
In my app I have options to copy all tracks,  just one, or a few of them.
Using the GetCTrackRoot() function I can copy all of them just fine. But copying just a few of them using the AppendCTrack() function crashes.

Here is a little example:

#include <windows.h>  
#include <iostream>  
using namespace std;  
#include "c4d_file.h"  
#include "default_alien_overloads.h"  
using namespace melange;  
#define    APPID 1234567  
void GetWriterInfo(Int32 &id, String &appname)  
  id = APPID;  
  appname = "My App";  
const String sourceFile = "C:\\Users\\user\\Desktop\\source.c4d";  
const String targetFile = "C:\\Users\\user\\Desktop\\target.c4d";  
const Filename newFile = "C:\\Users\\user\\Desktop\\My Project.c4d";  
int main(int argc, Char* argv[])  
  BaseDocument *sourceDoc = LoadDocument(sourceFile, SCENEFILTER_OBJECTS); if (!sourceDoc) return false;  
  BaseDocument *targetDoc = LoadDocument(targetFile, SCENEFILTER_OBJECTS); if (!sourceDoc) return false;  
  BaseObject *sourceObj = sourceDoc->GetFirstObject()->GetNext(); if (!sourceObj) return false;  
  BaseObject *targetObj = targetDoc->GetFirstObject(); if (!targetObj) return false;  
  //Copy all of the source object's tracks to the targt object  
  //This works fine  
  sourceObj->GetCTrackRoot()->CopyTo(targetObj->GetCTrackRoot(), COPYFLAGS_0, nullptr);  
  //Copy the rotation tracks from the source object to the target object  
  //Crashes if more than one of these is executed!!?  ---OUCH!---  
  targetObj->AppendCTrack(sourceObj->FindCTrack(DescID(DescLevel(ID_BASEOBJECT_REL_ROTATION), DescLevel(VECTOR_X))));  
  targetObj->AppendCTrack(sourceObj->FindCTrack(DescID(DescLevel(ID_BASEOBJECT_REL_ROTATION), DescLevel(VECTOR_Y))));  
  targetObj->AppendCTrack(sourceObj->FindCTrack(DescID(DescLevel(ID_BASEOBJECT_REL_ROTATION), DescLevel(VECTOR_Z))));  
  //Save the results in a new c4d file      
  SaveDocument(targetDoc, newFile, SAVEDOCUMENTFLAGS_0);  
  return 0;  

Why does the AppendCTrack() crash if more than one instance is called?
What is the proper way to copy multiple tracks from one object to another?
The target objects will most likely not have any existing tracks. But some might.


On 05/10/2016 at 12:33, xxxxxxxx wrote:

Never mind. I think I figured it out.
I guess it doesn't like it when I combine FindCTrack() & AppendCTrack() in the same line of code.
If I break it up into separate lines of code it seems to work:

    //Copy the rotation tracks from the source object to the target object      
  CTrack *rh = sourceObj->FindCTrack(DescID(DescLevel(ID_BASEOBJECT_REL_ROTATION), DescLevel(VECTOR_X)));   
  CTrack *rp = sourceObj->FindCTrack(DescID(DescLevel(ID_BASEOBJECT_REL_ROTATION), DescLevel(VECTOR_Y)));  
  CTrack *rb = sourceObj->FindCTrack(DescID(DescLevel(ID_BASEOBJECT_REL_ROTATION), DescLevel(VECTOR_Z)));  

I'm guessing it has something to do with the pointers allocating. *Shrug*


On 06/10/2016 at 06:29, xxxxxxxx wrote:

Hi ScottA, thanks for writing us.

I'm glad you find your own way to go and if anything else arises we'll be glad to help.
Just one small hint: before using a pointer in the AppendCTrack(), although not mandatory, I'll check it not for being null.

Best, Riccardo

On 06/10/2016 at 07:08, xxxxxxxx wrote:

Thanks Riccardo.
I do have another question. How do we create a new track in Melange?
Here is how I do it with the C4D SDK:

    CTrack *px = CTrack::Alloc(obj, DescID(DescLevel(ID_BASEOBJECT_REL_POSITION, DTYPE_VECTOR, 0), DescLevel(VECTOR_X, DTYPE_REAL, 0)));  

In General. I'm having trouble understanding how Alloc works in Melange.
It seems to be quite different from the C4D SDK.


Edit- Found it. Melange does things very different from the C4D SDK.
Is this intentional for some reason?
I'm not enjoying having to learn two different SDKs to do the same tasks for the same program.

    CTrack *px = CTrack::Alloc(targetObj, DescID(DescLevel(ID_BASEOBJECT_REL_POSITION, DTYPE_VECTOR, 0), DescLevel(VECTOR_X, DTYPE_REAL, 0)), "X");  
  if (px) targetObj->AppendCTrack(px);

On 07/10/2016 at 09:32, xxxxxxxx wrote:

Hi ScottA, as far as I understand your concerns, honestly, the two approaches are quite similar and the differences reside on the name rather than on the delivered functionality.
With reference to the Alloc() method, which in MELANGE differs for the third and last parameter, I'd say  it's indeed useful to identify the track with a String which could make sense in a context where GUI could also be missing.
In regards to adding a track to an object, I'd say that the difference, apart the naming, is mostly related to the fact the in CINEMA the track is added and immediately sorted to reflect a proper representation in the UI whilst in MELANGE, where this sorting is not needed, it only needs to be appended to the track list.

Hoping these comments might make sense to you, give best.

On 07/10/2016 at 11:05, xxxxxxxx wrote:

I'm mostly just grumbling because it took me years to figure out the C4D SDK and write notes for it so I can focus on creating my stuff. Instead of trying to decode the SDK.
Now I need to write a whole bunch of new notes for Melange just to do the same tasks.

Rather than copying how the C4D SDK handles tracks. The usage of append in the Melange SDK looks like the developers might have decided that using append might make it easier to handle tracks than how the C4D SDK handles them.
It might be simpler. But it's new. And when things change in SDKs. It disrupts the productivity of the users. Until they learn the new changes.

Anyway. I'm getting there and slowly making progress with it. Thanks to your help.
It's just painful. Don't mind my grumblings. 🙂