On 22/05/2017 at 13:01, xxxxxxxx wrote:

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

Have searched through the forum and found some topics, but can't manage to get it working.
I have a CommandData plugin, with an async dialog and userarea.
I'd like to represent "items" in the userarea, which the user can select. These items display some attributes (name, size, type, ...) defined as strings, integers, real. For these attributes to be edited, I would like to use the Attribute Manager.
I know I could provide some gadgets in the dialog next to the user area, or a separate dialog. But instead I want to use the AM for this.

So far, I have registered a new mode for the ActiveObjectManager. Created a NodeData per "item".
And registered a description for the NodeData to load during GetDDescription.

When I manually switch to the newly registered mode of the AM, the messagehook gets called and processes AOM_MSG_GETATOMLIST, where I collect the selected item (NodeData) into ((AtomArray* )data)->Append().
For testing purposes I send a message to the NodeData (while processing AOM_MSG_GETATOMLIST), and in MyNodeData::Message I print the incoming messages to the console. So far, so good.

However, the GetDDescription of MyNodeData never gets called. as such the AM remains empty.

Am I approaching this whole thing in the wrong way, or am I simply missing something minor?


On 23/05/2017 at 09:36, xxxxxxxx wrote:

Hi Daniel,

where do you store your NodeData instances?
They need to be part of the document, in order to work in the AM.

On 23/05/2017 at 09:51, xxxxxxxx wrote:

Hello Andreas,
I see.
I remember having read something to that regard ( but assumed the NodeData needed to be part of the document for the animation keyframe.

So, with this new piece of information I'll have to rethink the whole concept, I am afraid.
Currently the NodeData is only stored into the Item's class. Not added to the document. And as the item does not represent anything related to Cinema 4D (not an object, nor tag, nor material, ...), I don't see any way to add it to the document.

Back to the drawing board.

On 23/05/2017 at 09:56, xxxxxxxx wrote:

Not so fast, no need to give up. You can still go with this concept. The magic word here is SceneHook. Like every NodeData plugin a SceneHook can hold a so called branch, to expose entities to the scene. So basically you'd implement SceneHook and have this SceneHook host your NodeData items in its branch. It's a few lines of code, as you will need to implement Read()/Write()/CopyTo() for your SceneHook, but there's no magic to it.
It's a bit late here by now, but i think I can provide you with a skeleton tomorrow.

On 23/05/2017 at 09:59, xxxxxxxx wrote:

Thanks Andreas.
I have created more than one plugin making use of scenehook, so that should not be a problem to add one. The Read/Write/CopyTo, however, is something new to me. A skeleton would be more than welcome to get an idea (for me and all the others).

On 23/05/2017 at 10:44, xxxxxxxx wrote:

Understand those function like CreateLayout in a Gedialog.
CreateLayout is called everytime you make Gedialog.Open()

So for Read/write/CopyTo as you could see thoses methode are aviable in NodeData in the scene. 
So we will speak of an ObjectData.

When you open a document. Read() is called. Because you read from the c4d file.
When you save a document. Write() is called. Because your write from the c4d file.
When you Copy this object. CopyTo is called. YOu also get the methode Obj.CopyTo whol lunch this function. While GetClone don't lunch this function.

I guess you got it, A bit tricky to understand but when you got it it's ok :)

On 24/05/2017 at 02:52, xxxxxxxx wrote:

Hi, me again...

@gr4ph0s: While not wrong, in the case of a SceneHook exposing a branch with custom nodes it's a bit different.

Luckily Sebastian has a way better memory than I do and he made me aware we already have a skeleton for this purpose in the forum. See this thread. And if there are any open questions lets continue discussion here.

On 24/05/2017 at 03:38, xxxxxxxx wrote:

Thanks for the link. Checking it out right now.

On 28/05/2017 at 22:57, xxxxxxxx wrote:

According the provided link I implemented the Read/Write/CopyTo into my scenehook, as well as a GetBranchInfo.
I have a GeListHead member, which is autoalloc-ed, and during the Init of the scenehook, I set the passed node as the parent of GeListHead (as the example shows). For testing purposes I allocated an instance of a NodeData plugin, filled in some data into its basecontainer and inserted this into the GeListHead, in order to retrieve it in another part of the plugin. Unfortunately, this last step went always unsuccessful, whatever I tried.

I am not sure I understand the concept of the GeListHead.
There are several functions to insert an item into the "list". Whichever I tried, I never was able to obtain back the information I put in.

The example uses a GetNodeRoot function in the MyWorker class, but it's is never shown what it actually does. I assume I need to get the SceneHookData (using FindSceneHook), typecast it to my derived class and access its autoalloc-ed GeListHead.

While I can access the member, its data does not reflect the data that was stored during the scenehook::Init. So, I certainly must do something wrong.

Additionally, when I start Cinema 4D in debug from within Visual Studio, my scenehook::Init is called 4 times in a row. Four different instances of the scenehook have been created.
However, when I create a new document (File>New) the scenehook::Init function is only called once, as expected. Even with the new document, I am unable to retrieve the stored data.

One positive point is that I was able to display a resource description into the Attribute Manager, using the allocated NodeData. So something is working, but as soon as I tried two instances of the NodeData other issues popped up.
First, I'd like to resolve the issues retrieving the stored data in the GeListHead.

So, how should I look at GeListHead?
Is the parent the rootnode of a tree structure? Should I add a node as child of the parent, or simply perform an InserLast, or other?

thanks in advance

On 29/05/2017 at 09:42, xxxxxxxx wrote:


a GeListHead is nothing more than the root/base/anchor of a list of GeListNodes, really nothing special, just have one as a member of your SceneHook and attach/insert your custom NodeData entities to it.
There are manuals on GeListHead and GeListNode that may shed some more light.
And yes, the SceneHook node is the parent of the GeListHead. 
The GetNodeRoot() implementation would look pretty much as you describe.

The AddNode() code in the example looks a bit strange, as it redefines the local node pointer, loosing the formerly allocated node, which is the one that should actually be inserted. The line "head->GetDown()" basically accesses the first stored node. So if you use the code exactly as in the example (with the above mentioned error), there will indeed never be stored anything, as the freshly allocated node is forgotten and there will never be a first node and the function returns early.

The way of insertion is pretty much up to you. In my use cases I tend to use "head->InsertLast(node)", but that may be different depending on the use case.

SceneHook::Init() (well, actually NodeData::Init()) being called several times during startup is normal. Just check the document  in there, you will see it will be calls for different ones, that get created during C4D's startup.

On 30/05/2017 at 13:00, xxxxxxxx wrote:

In one way or another I must have missed or overlooked the manual for GeListHead while reading through the SDK documentation. Thanks for providing a direct link to it.

In the end it was an obvious mistake of mine (obvious ... once the mistake was found). I simply did not correctly cast the obtained scenehook to my derived scenehook class.

  BaseSceneHook* bsh = GetActiveDocument()->FindSceneHook(SCENEHOOK_PLUGIN_ID);  
  if (bsh)  
      MySceneHook* sh = (MySceneHook* )bsh;  
      // above is NOK, instead should be:  
      MySceneHook* sh = bsh->GetNodeData<MySceneHook>();  

From then on obtaining the appropriate nodedata from the branch and the content of its basecontainer was a piece of cake.
Spent quite some time on this issue, and got totally sidetracked.

But now I can focus on the next issue ...