BaseLink from cloned document



  • Hi!

    I need to get a linked object from a cloned document.
    At first I tought it was trivial and would just work, learned about AliasTrans, but that didn't help either.
    This is what I'm trying...

    	void NewAnimationProgressDialog::Setup( BaseDocument* doc, BaseObject* node )
    	{
    		AutoAlloc<BaseLink> nodeLink;
    		nodeLink->SetLink( node );
    		
    		AutoAlloc<AliasTrans> aliastrans;
    		document_ = static_cast<BaseDocument*>( doc->GetClone( COPYFLAGS_NONE, aliastrans ) );
    		aliastrans->Translate( true );
    		
    		node_ = GetBaseLinkLink<BaseObject>( document_, nodeLink );
    		// node_ is null!
    	}
    


  • You might have to use ForceGetLink()
    See the description in the docs. That may reflect what you are trying to do.



  • I only want the object from the cloned document, not elsewhere.
    The problem is that the BaseLink does not find it on the clone.



  • Hi @rsodre I'm wondering whats your final purpose?

    The normal use case is to copy the linked C4DAtom and insert it in the new doc like its demonstrated in the C++ C4DAtom Copy documentation.

    While in your case you do BaseDocument::GetClone and expect the BaseLink that you have in memory (The BaseDocument have no idea of this BaseLink) to be updated.

    But this is the BaseDocument::CopyTo (called by GetClone) that create an AliasTrans, recreate everything and update this document BaseLink as its explained in the doc.

    So I don't see a way to have its memory only Link being updated.

    Cheers,
    Maxime.



  • Hi @m_adam.

    I'm baking a heavy procedural animation, so basically what I do is:

    • Some modifiers create the procedural animation
    • The last modifier is a recorder, where I set an output alembic file and have a button to start recording
    • Button pressed, I open a custom modal dialog
    • In the dialog, I clone the active Document
    • For every frame in the cloned doc frame range:
      -- Set time/frame
      -- call ExecutePasses()
      -- call the recorder's StoreFrame() function
    • Call the recorder's SaveAnimation() function
    • Close the dialog

    Now I can go back to the active scene, delete the procedural animaiton nodes and playback from alembic.

    When I open the modal dialog, I pass the active doc and recorder custom ObjectData. I need to retrieve the recorder's equivalent in the cloned document to call the save functions, that's why I make a BaseLink that need to be retrieved on the clone.



  • Hi @rsodre, unfortunately as explained in my previous post, your GeDialog the one that hosts your BaseLink as its not part of the cloned document is not updated by the AliasTrans, during the GetClone operation.

    so a quick workaround is to store this BaseLink in the BaseContainer of the document and then retrieve it (Kudo to @m_magalhaes for the idea).
    Then there are two issues in your code, first, you never initialize the ailiasTrans, and you don't pass the flag COPYFLAGS::DOCUMENT while you are copying a document.

    And here a code sample that demonstrates the use of a BaseContainer.

    	BaseObject* const obj = doc->GetActiveObject();
    	if (obj == nullptr || !obj->IsInstanceOf(Ocube))
    		return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION);
    
    	doc->SetName("Original"_s);
    
    	// Build the BaseLink
    	AutoAlloc<BaseLink> nodeLink;
    	if (!nodeLink)
    		return maxon::NullptrError(MAXON_SOURCE_LOCATION);
    	
    	nodeLink->SetLink(obj);
    
    	// Store it in GeData
    	GeData baseLinkData;
    	baseLinkData.SetBaseLink(*nodeLink);
    
    	// Store the GeData in the document
    	doc->GetDataInstance()->SetData(1000000, baseLinkData);
    
    	// Copy the document, dont forget to initialize the AliasTrans
    	AutoAlloc<AliasTrans> aliastrans;
    	aliastrans->Init(doc);
    	BaseDocument* newDoc = static_cast<BaseDocument*>( doc->GetClone( COPYFLAGS::DOCUMENT, aliastrans ) );
    	newDoc->SetName("Copy"_s);
    	aliastrans->Translate( true );
    
    	// Read the GeData in the document
    	const GeData baseLinkDataNewDoc = newDoc->GetDataInstance()->GetData(1000000);
    	BaseLink* baseLinkNewDoc = baseLinkDataNewDoc.GetBaseLink();
    	if (baseLinkNewDoc == nullptr)
    		return maxon::NullptrError(MAXON_SOURCE_LOCATION);
    
    	BaseList2D* test = baseLinkNewDoc->GetLink(newDoc);
    	if (test == nullptr)
    		return maxon::NullptrError(MAXON_SOURCE_LOCATION);
    	
    	ApplicationOutput("@, @"_s, test->GetName(), test->GetDocument()->GetName());
    
    	test = baseLinkNewDoc->ForceGetLink();
    	if (test == nullptr)
    		return maxon::NullptrError(MAXON_SOURCE_LOCATION):
    
    	ApplicationOutput("@, @"_s, test->GetName(), test->GetDocument()->GetName());
    
    	return maxon::OK;
    }
    

    Cheers,
    Maxime.