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
    1. Maxon Developers Forum
    2. aghiad322
    Offline
    • Profile
    • Following 1
    • Followers 0
    • Topics 8
    • Posts 18
    • Groups 0

    aghiad322

    @aghiad322

    0
    Reputation
    9
    Profile views
    18
    Posts
    0
    Followers
    1
    Following
    Joined
    Last Online

    aghiad322 Unfollow Follow

    Latest posts made by aghiad322

    • RE: Ctr+drag copy vs internal copy in CopyTo function in C++

      Hi @ferdinand,

      Thanks for your reply!

      Currently, I can’t use isCloneInit because I’m still developing on the Cinema 4D 2026 SDK. I do plan to migrate to the 2026 version later.

      For context — my plugin is essentially a grouping system based on an ID parameter, similar in concept to how:

      The Simulation system tracks objects containing simulation tags, or

      The Arnold tag groups objects into “trace sets” based on a string ID.

      I’m not scanning the scene constantly for updates. Instead, each tag updates itself through a SceneHook when needed, using the following function:

      void NexusRegistry::UpdateGroupFromTag(BaseDocument* doc, BaseTag* tag)
      {
          if (!tag) return;
          BaseObject* obj = tag->GetObject();
          if (!obj) return;
          BaseContainer* tagContainer = tag->GetDataInstance();
      
          // Read new values from tag
          String id = tagContainer->GetString(ID);
          Int32 hashedID = HashID(id);
          Bool includeChildren = tagContainer->GetBool(CHILDREN);
      
          // Handle old ID if changed
          Int32 oldIdHash = tagContainer->GetInt32(NEXUS_TAG_PREV_ID, NOTOK);
          if (oldIdHash != NOTOK && oldIdHash != hashedID)
          {
              auto it = groups.find(oldIdHash);
              if (it != groups.end())
              {
                  auto& members = it->second.members;
                  members.erase(std::remove_if(members.begin(), members.end(),
                      [obj](const NexusMember& m) { return m.object == obj; }),
                      members.end());
      
                  it->second.dirtyLevel++;
                  if ((Int32)members.size() == 0)
                      groups.erase(it);
              }
          }
      
          // Update new group
          NexusGroup& group = groups[hashedID];
      
          // Remove duplicates of this object first
          group.members.erase(std::remove_if(group.members.begin(), group.members.end(),
              [obj](const NexusMember& m) { return m.object == obj; }),
              group.members.end());
      
          group.members.push_back({ obj, includeChildren });
      
          ((Nexus*)tag)->UpdateInfo(doc, tag);
      
          // Store current ID for next update
          tagContainer->SetInt32(NEXUS_TAG_PREV_ID, hashedID);
      }
      

      To circumvent the tag copy issue, I’m currently deferring registration:

      During CopyTo, tags are added to a pending registration list.

      Then, in the SceneHook Execute() method, I check for tags that have been attached to a document and process them there.

      Here’s that part:

      void NexusRegistry::ProcessPendingTags(BaseDocument* doc)
      {
          if (pendingRegistration.IsEmpty())
              return;
      
          Int32 i = 0;
          while (i < pendingRegistration.GetCount())
          {
              BaseTag* tag = pendingRegistration[i];
              BaseObject* op = tag->GetObject();
      
              if (op)
              {
                  UpdateGroupFromTag(doc, tag);
                  maxon::ResultRef eraseresult = pendingRegistration.Erase(i, 1);
              }
              else
              {
                  i++;
              }
          }
      }
      
      EXECUTIONRESULT NexusRegistry::Execute(BaseSceneHook* node, BaseDocument* doc,
                                             BaseThread* bt, Int32 priority, EXECUTIONFLAGS flags)
      {
          ProcessPendingTags(doc);
          return EXECUTIONRESULT::OK;
      }
      

      Here’s the SceneHook class structure for reference:

      struct NexusMember
      {
          BaseObject* object = nullptr; // weak ref, don’t own it
          Bool isChild = false;         // "include children" flag
      };
      
      struct NexusGroup
      {
          Vector color;
          std::vector<String> links;
          std::vector<NexusMember> members;
          Int32 dirtyLevel = 0;
      };
      
      class NexusRegistry : public SceneHookData
      {
      public:
          static NexusRegistry* Get(BaseDocument* doc);
          static NodeData* Alloc();
          virtual Bool Message(GeListNode* node, Int32 type, void* data);
          virtual EXECUTIONRESULT Execute(BaseSceneHook* node, BaseDocument* doc,
                                          BaseThread* bt, Int32 priority, EXECUTIONFLAGS flags);
      
          std::unordered_map<Int32, NexusGroup> groups;
          maxon::BaseArray<BaseTag*> pendingRegistration;
      
          void ProcessPendingTags(BaseDocument* doc);
          void RebuildRegistry(BaseDocument* doc);
          void UpdateGroupFromTag(BaseDocument* doc, BaseTag* tag);
          void RemoveObjectFromGroups(BaseObject* obj);
          void RemoveTagFromGroup(BaseTag* tag);
          const NexusGroup* GetGroup(Int32 hash) const;
      };
      

      The main purpose of this system is to allow other plugins (e.g., object plugins) to:

      Reference tags that share the same ID,

      Access their data via the registry, and

      Rebuild themselves when the related group’s dirtyLevel changes.

      Thanks for your time, and sorry if this looks a bit rough, I just wanted to show the current design.
      If you have any design suggestions or best practices for handling deferred tag registration or object cloning across documents, I’d really appreciate your insights!

      posted in Cinema 4D SDK
      aghiad322A
      aghiad322
    • RE: Ctr+drag copy vs internal copy in CopyTo function in C++

      Hi @ferdinand , thanks for the reply, my main problem is that "init" is not being called on copying, what im trying to do is that i have a scenehook and it has an array member variable pointing to all tags in the scene with this tag type, and with same parameter (grouping tags based on id parameter), and i need to keep this array in sync with the scene tags.

      Thanks and regards

      posted in Cinema 4D SDK
      aghiad322A
      aghiad322
    • Ctr+drag copy vs internal copy in CopyTo function in C++

      hello,
      i want to distinguish between c4d's internal use of "CopyTo" and when a user drags the object (in this case it's a tag), also is there a message specifically called when user drag copy an object?

      posted in Cinema 4D SDK 2025 c++ windows macos
      aghiad322A
      aghiad322
    • RE: how to store/serialize custom data type?

      @ferdinand the example that i based my custom data type from is "DotsCustomDataTypeClass" in file "customdata_customgui.h",and i kept it's functionality "when click on the gui a new square is added", and this part is saving and loading fine as in the provided video, but the color graident shown in the dialog that i change is not saving as you can see as soon as i click of the tag the gradient data resets, sorry if my question is too general but how can i store the "Gradient" data as if they were like any other parameter.
      this is my data type on a tag ,compiled with cinema 4d 26
      myTag.zip

      posted in Cinema 4D SDK
      aghiad322A
      aghiad322
    • how to store/serialize custom data type?

      hi there , i'm making a custom data type , and if i'm not mistaken the "MyCustomData::DescribeIO(const maxon::DataSerializeInterface& stream)" along with "Describe()" are responsible for storing/serializing the data , as in my custom type i used the example 'Dots' datatype and added extra data i want to use

      maxon::Result<void> iMyCustomData::DescribeIO(const maxon::DataSerializeInterface& stream)
      {
      	iferr_scope;
      
      	PrepareDescribe(stream, iMyCustomData);
              //this is how the example is storing the _points member array
      	Describe("_points", _points, Vector, maxon::DESCRIBEFLAGS::TYPE_ARRAY) iferr_return;
      	Describe("_TimeScaler", _TimeScaler, Float, maxon::DESCRIBEFLAGS::NONE) iferr_return;
              //here i have member variables of my custom type as pointers (Gradient* MyCustomData::_gradient), it gives me error "missing data type registration" since it's a pointer not tthe data type.
      	Describe("_gradient", _gradient, Gradient*, maxon::DESCRIBEFLAGS::NONE) iferr_return;
             // and if i tried to add a member of type "Gradient" instead of pointer "Gradient*" i cant instantiate it since it has a private constructor
      
              Describe("_gradient", _gradient, Gradient, maxon::DESCRIBEFLAGS::NONE) iferr_return;
      	//Describe("_spline", ("_spline, SplineData*, maxon::DESCRIBEFLAGS::NONE) iferr_return;
      
      	return maxon::OK;
      }
      

      so my problem is two parts :
      1-how can i serialize c4d-registered custom data types i.e : Gradient, SplineData ....
      2- i ccouldn't instantiate a member of type "Gradient" instead of a pointer to Gradient "Gradient *"
      i tried dereferencing the allocated gradient but with no avail : Gradient _grad = *(Gradient::Alloc());
      sorry if my cpp skills might be the barrier here .

      posted in Cinema 4D SDK c++
      aghiad322A
      aghiad322
    • RE: Expose cpp-registered datatype to python

      @ferdinand thanks for the reply, all that i'm trying to do is just to link a SplineData parameter "ANIMATION_CLONER_SPLINE" from the python tag to the customGUI that has a datatype "SPLINEVIS" to visualize the spline in the GeUserArea, here is snippet from ".res" file of the python tag

      GROUP{
      	COLUMNS 1;			
      	SPLINE ANIMATION_CLONER_SPLINE {
      		ANIM OFF;			
      		SHOWGRID_H;
      		SHOWGRID_V;			
      		MINSIZE_H 300;
      		MINSIZE_V 180;				
      		EDIT_H;
      		EDIT_V;			
      		X_MIN 0;
      		X_MAX 1;			
      		Y_MIN -1;
      		Y_MAX 1;					
      		X_STEPS 0.01;
      		Y_STEPS 0.01;
      		};
      	SPLINEVIS ANIMATION_CLONER_SPLVIS { ANIM OFF; };
      }
      

      and here is the source code of the custom dataType/Gui
      splinevis.zip
      i want to change the splinedata of "iSplineVisDataType::_spline" , in the code i provided i just initialized it to demonstrate how im using it, but i want this splineData to be initialized from the python tag.
      Or if i can have access to the node "BaseTag" that's hosting the customGui so that i can link it's splineData to the customGui ,that would work.

      posted in Cinema 4D SDK
      aghiad322A
      aghiad322
    • Expose cpp-registered datatype to python

      hi there so i made a custom gui and custom datatype in cpp and i want to use them in a python tag plugin, so i added it in the tag's ".res" file and it's working (i copied the "Dots CustomDataType & CustomGui Example" and tweaked it to my needs) , but i want to access the data type in python source code of the tag plugin so i can initialize some values on the CustomDataType (that will be vizualized in the GeUserArea of the custom gui) when i initialize the python tag, i read in the documentation that maybe i should use "MAXON_DATATYPE_REGISTER_STRUCT" to expose datatype to python but i didn't find examples implementing it, so basically i want a datatype like the BaseContainer that has (SplineData, Gradient, Float) in it .

      posted in Cinema 4D SDK c++ python
      aghiad322A
      aghiad322
    • RE: Effector plugin is only executing in deformation mode

      @ferdinand Thanks a lot it worked

      posted in Cinema 4D SDK
      aghiad322A
      aghiad322
    • RE: Effector plugin is only executing in deformation mode

      @ferdinand i managed to figure out that it's caused by the "Message()" function , if i uncomment the "Message" definition and declaration the problem comes back again even if i left the Message definition blank, here is the compilable code , c4d 26
      Effector.zip

      posted in Cinema 4D SDK
      aghiad322A
      aghiad322
    • RE: Effector plugin is only executing in deformation mode

      @ferdinand exactly it works fine as a deformer like the second image you provided, i also tested in in 2024.1 it's not working as well, but after some experimenting i ran into weird behaviour , so for the matrix it only works if i put the effector as a child of the matrix and in points deformer mode . and if i added the effector to the effector list of the matrix without being a child of the matrix it wont work, i didn't provide method's definition because they aren't being executed in the first place (when set break point in debug mode it wont be reached), here is a screen recording of it

      posted in Cinema 4D SDK
      aghiad322A
      aghiad322