Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python 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

    BaseLink from cloned document

    Cinema 4D SDK
    r19 r20 r21 c++
    4
    11
    1.5k
    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.
    • M
      mp5gosu
      last edited by

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

      1 Reply Last reply Reply Quote 0
      • rsodreR
        rsodre
        last edited by

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

        1 Reply Last reply Reply Quote 0
        • M
          m_adam
          last edited by

          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.

          MAXON SDK Specialist

          Development Blog, MAXON Registered Developer

          rsodreR 1 Reply Last reply Reply Quote 0
          • rsodreR
            rsodre @m_adam
            last edited by

            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.

            1 Reply Last reply Reply Quote 0
            • M
              m_adam
              last edited by m_adam

              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, I use the ID 1000000 but please use anunique ID from plugincafe
              	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.

              MAXON SDK Specialist

              Development Blog, MAXON Registered Developer

              rsodreR 2 Replies Last reply Reply Quote 0
              • rsodreR
                rsodre @m_adam
                last edited by

                Hi @m_adam,
                I finally got a change to try this solution and remove my search by name hack.
                Works perfectly, thanks!

                1 Reply Last reply Reply Quote 0
                • rsodreR
                  rsodre @m_adam
                  last edited by rsodre

                  @m_adam said in BaseLink from cloned document:

                  // Store the GeData in the document
                  doc->GetDataInstance()->SetData(1000000, baseLinkData);
                  

                  What's the rules to store data in a document?
                  I mean, which IDs can I use?

                  Your example works, but I hit a debug breakpoint when destroying the cloned document with KillDocument()
                  I don't know if it's related to that or not.

                  From ddoc.h...

                  DOCUMENT_HOOKS = 1000000, // 2000 IDs reserved from here
                  
                  1 Reply Last reply Reply Quote 0
                  • M
                    m_adam
                    last edited by

                    Hi @rsodre correct, in general, when dealing with BaseContainer to store data when you are not the owner of it(aka an ObjectData, ShaderData, etc..) you should register a unique ID (from plugincafe) this way you are sure to not have a conflict.
                    I should have mentioned in my snippet sorry.

                    Cheers,
                    Maxime.

                    MAXON SDK Specialist

                    Development Blog, MAXON Registered Developer

                    1 Reply Last reply Reply Quote 0
                    • rsodreR
                      rsodre
                      last edited by rsodre

                      I don't understand the relation between the document BaseContainer data and plugin ids.
                      Are you saying that I can use my custom plugin IDs as the data ID on the container?

                      About the debug breakpoint, I found out that it was because I'm killing the cloned document on the end of my ProgressDialog::Main(), which is a bad idea. Moved it to AskClose().

                      1 Reply Last reply Reply Quote 0
                      • P
                        PluginStudent
                        last edited by

                        There is no relationship between BaseContainer IDs and plugin IDs.

                        All you need is a unique ID, that you can use as a BaseContainer ID. This forum (the plugin ID page) provides such IDs.

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