Store BaseShaders in hyperfile.

On 08/09/2017 at 03:52, xxxxxxxx wrote:

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


I have a Custom Gui which handles a custom data type.
The data type is basically a container of BaseShaders.
I need to create a Layer Shader-like shader data that you can add and remove shaders dynamically.

I add dynamically the shaders in the custom gui using a button and HandleShaderPopupI.
First of all, it appears that I have to pass a non-null parent parameter otherwise the returned shader is null. Why is this necessary ?

The custom gui belongs in a shader data plugin.
Considering I run the above HandleShaderPopupI in a iCustomGui's Button Command, can I get the ShaderData it belongs to and use it as a parent ?

Now, in CopyData, WriteData e.t.c, I have to store the shaders in hf. To do that I use shader->Write(hf)...
I assume I have to store ONLY the BaseShader, not the parent as well, right ?
Also, since the Custom Data Type handles the shaders in BaseLinks, I need a valid BaseDocument pointer (to use GetLink).
So my question here is, what the best way to write BaseShaders in Hyperfiles ?

Thank you for your time.

On 11/09/2017 at 02:09, xxxxxxxx wrote:


a BaseShader should be inserted into a host object using InsertObject() (see BaseShader Manual). If the shader is owned by an object, this object should take care of saving the shader.

A custom GUI element can send the private message MSG_DESCRIPTION_GETOBJECTS using SendParentMessage() (see GeDialog Manual). This way the custom GUI gets the objects currently displayed by the DescriptionCustomGUI owning the custom GUI. Sending the message can look like this:

DescriptionGetObjects dgo;  
m.SetInt32(BFM_ACTION_ID, GetId());  
m.SetVoid(2, &dgo);  

The links to the host object or objects are stored in the DescriptionGetObjects "bc" BaseContainer.

Please be aware that MSG_DESCRIPTION_GETOBJECTS is marked as private. This means that this message is not meant for public use and may have some shortcomings or limitations.

If for some reasons the shaders should not be saved with an object, it should be possible to store them in a HyperFile. See the HyperFile Manual.

best wishes,

On 11/09/2017 at 13:41, xxxxxxxx wrote:

Hello and thank you very much for your help.

As a reminder: I have a ShaderData plugin in which you can add dynamically other shaders.
Once a new shader is created, I insert it to this NodeData using InserShader (casting Get() to BaseList2D).
How should I handle the CopyTo call in shader data ? 
Should I copy the children Shaders one by one and insert them to the destination Node Data or does this happen automatically ?

Other than that, since the shader handling and modification takes place in an iCustomGui, 
I keep references to these shaders in a CustomDataType (with BaseLinks) along with other data integers and vectors.
What I do right now and I would really like your opinion, is that I keep the shaders as children in the NodeData's BaseList2D and all the other data
related to shaders in the CustomDataType. The custom data type also has BaseLinks pointing to the above shaders.
Is this logic correct ?

Thank you very much for your patience !

On 12/09/2017 at 00:08, xxxxxxxx wrote:

Hello again.

Lets say I have 3 shaders A, B and C, which are inserted in this sequence via NodeData's UI.
I have a CustomDataType that keeps links to these shaders. How can I preserve these links after to the same shaders after loading the file ?

Thank you.

On 12/09/2017 at 02:41, xxxxxxxx wrote:


when you insert a shader using InsertShader(), the host object takes ownership (to be precise: the BaseList2D base class) So in your CopyTo() implementation you should only have to make sure the CopyTo() function of the base classes is called. This is typically done by calling the "SUPER" class. See NodeData::CopyTo() Manual.

You should be able to store references to these shader in your custom data type using BaseLink elements. See BaseLink Manual.

best wishes,