MSG_MENUPREPARE not sent to BaseShaders

Hi,

I think this is either an API bug, or a mistake in the docs:
https://developers.maxon.net/docs/Cinema4DCPPSDK/html/group___m_s_g.html#ga58e4d06ecc0352d135578cbc4d4e7b5e

Quote:

#define MSG_MENUPREPARE
Allows tags, objects, shaders etc. to do some setup work when called from the menu. The corresponding data is the current BaseDocument.

I just noticed that MSG_MENUPREPARE is not received in my ShaderData plugin, at least not in R25 (didn't check earlier releases). Is there any other way to have a shader do something when it's created by the user?

Cheers,
Frank

www.frankwilleke.de
Only asking personal code questions here.

Hello @fwilleke80,

Thank you for reaching out to us. For clarity, you are talking about a shader being created with this menu, right?

5a0bb773-7813-4d02-a3de-5f81d97f763d-image.png

I debugged a bit against Cinema 4D to find out more. Other than the more "top-level" menus as they exist for object, material, and tag creation, we are here deep inside the parameters of a node, as this all happens inside the custom GUI TexBoxGui, or more specifically its internal counterpart, which is used to display such base link parameters for shaders.

When you click on the little popup arrow button, Cinema builds first the popup menu, evaluates the user input, and then sends the data on a gigantic message journey (which I frankly did not step through in its entirety), and at the end the data then comes out as an already instantiated BaseList2D which is set via TexBoxGui::SetData(). So, there is no obvious point for me where the message should be emitted, aside from the distant corner in the classic API core where the shader, which is then finally set, is actually being instantiated. TexBoxGui, the initiator of the action, does not send any messages you can receive.

When we go the other way around, and simply listen for what is being received in a ShaderData::Message when it is created with that menu, we see three message ids (each sent multiple times): MSG_MULTI_RENDERNOTIFICATION = 1001071, MSG_FILTER = 14 (which are all for the render notifactions), and 5707 which is not a MSG_ message but the id of Xbase. So, nothing particularly useful for what you want to do.

The bottom line here is:

  1. I will ask the devs was their take on this is.
  2. I have added a task for us to update the docs, thanks for the hint! This might also extend further than just shaders, because while I could find the message being set off for objects and materials, I could not find it being set off for tags in our C++ code base. But I might have just overlooked it, will have to try with a TagData plugin.

Finally, could you elaborate why you need MSG_MENUPREPARE and why NodeData::Init won't be sufficient? You have in both cases access to the document the node is contained in, and you are relatively early in the life cycle of a node. I assume it is because you expect MSG_MENUPREPARE to be more "unique" (for the lack of a better word), as NodeData::Init is being called quite often in more recent versions of Cinema 4D?

Cheers,
Ferdinand

MAXON SDK Specialist
developers.maxon.net

Hi @ferdinand,
thanks for your reply!

For clarity, you are talking about a shader being created with this menu, right?

Exactly.

Finally, could you elaborate why you need MSG_MENUPREPARE and why NodeData::Init won't be sufficient?

The whole point of MSG_MENUPREPARE is to have access to the document the new node is being added to.
I wanted to link something from the document in a LINK element in the shader's description.
In MSG_MENUPREPARE, I get a pointer to the parent document as message data, so it's no problem to find a scene element and link it in the shader. In NodeData::Init(), node->GetDocument() returns nullptr, unfortunately. The node isn't yet part of the document, when Init() is called.

Cheers,
Frank

www.frankwilleke.de
Only asking personal code questions here.

Hello @fwilleke80,

In NodeData::Init(), node->GetDocument() returns nullptr, unfortunately. The node isn't yet part of the document, when Init() is called.

Eh, right. Well, the only way I see left is the clunky way. You could listen for MSG_MULTI_RENDERNOTIFICATION, as a shader must be rendered when it is instantiated from a menu. Then you need some flag which indicates if something from the document has been evaluated or not for the given node. When a render notification is raised, you check for that flag in the node and carry out something the first time the shader is being rendered. Pretty ugly design, I agree, but the only way I currently see.

We will see what the developers say, but this can take time, especially since we are currently in a high-workload phase with a closing in release.

Cheers,
Ferdinand

MAXON SDK Specialist
developers.maxon.net

Thanks!
No stress, I basically just needed this to be validated, so I can use a hacky workaround with peace of conscience :-)

Cheers,
Frank

www.frankwilleke.de
Only asking personal code questions here.

I've changed this back to "Normal topic".
It was a question, and it was answered, but since there's no solution, I didn't want to mark it as "solved.

www.frankwilleke.de
Only asking personal code questions here.