Cannot copy BaseLink from one parameter to another in ShaderData Read in C4D 2024
-
Hi,
So we used to do the following in NodeData::Read() whenever the id of a ShaderLink parameter had to be changed and preserve the shader from old scenes.
BaseContainer &nodeData=static_cast<BaseShader*>(node)->GetDataInstanceRef(); const BaseLink* oldLink=nodeData.GetBaseLink(oldParameter); if (oldLink != nullptr) { GeData linkData; linkData.SetBaseLink(*oldLink); nodeData.SetData(newParameter, linkData); } nodeData.RemoveData(oldParameter);
However, on Cinema4D 2024 this doesn't seem to work if the NodeData is a shader. The old BaseLink parameter gets removed, the new parameter is set but the link still points to nullptr after the document is loaded. It does look a bit weird, so is there something I am missing or a better way to do this?
Thanks,
Bozhidar -
Hey @bojidar,
Thank you for reaching out to us. 2024 is a very broad field. Did this happen with 2023.X to 2024.0.0, the so called 2024.0.0 API migration, or did this happen in a more recent release for you, e.g., from 2024.3.2 to 2024.4.0?
I am not aware of anything which would have impacted this, but we are again here on a broad field.
- You made sure that your
nodeData.SetData(newParameter, linkData)
statement is actually being hit? - Did you make sure that the to be linked shader,
oldLink
, still does resolve? Or in other words that this shader is already present in the document? - What is the return value of your
BaseContainer::SetData
call?
// ... if (oldLink != nullptr) { const BaseList2D* const target= oldLink->GetLink(node->GetDocument(), Xbase) if (!target) return maxon::UnexpectedError(MAXON_SOURCE_LOCATION, "Upsy-daisy, lost shader link."_s); GeData linkData; linkData.SetBaseLink(*oldLink); if (!nodeData.SetData(newParameter, linkData)) return maxon::UnexpectedError(MAXON_SOURCE_LOCATION, "Could not write parameter."_s); }
Cheers,
Ferdinand - You made sure that your
-
From what I can see it works on 2023.2.1 and doesn't work in 2024.0. SetData is indeed called and returns true, however, oldLink->GetLink/ForceGetLink always return nullptr. So I guess the link isn't resolved? But when checking with the active object dialog example the shader is indeed there.
-
Hey @bojidar,
that could be a side-effect of the 2024.0.0 API changes. It is hard to give here good advice, I will ask tomorrow the Tech team who authored most of the low-level changes for 2024, if this rings any bells for them.
Could you please check if the target shader is present at all in such imported scene? You can use the ActiveObject plugin from the C++ SDK or just write your own code which checks. Because when the shader is not present, it is normal that the link does not resolve (on the other hand the shader could be present, but something with the marker realizing the link went wrong).
And finally, could you please provide a file with such problem, and tell us which of your products is affected (I think we have licenses for all of them)? Feel free to use email-support or our contact form when you want more privacy
Cheers,
Ferdinandedit: overlooked that you did already check for the shader being present. something with the marker is then probably going wrong.
-
Hey @bojidar,
okay, now I see that you just edited your posting yesterday after I asked for checking for the shader being present with the Active Object plugin. If that was just a coincident, don't worry, but if you did this intentionally, please do not do that, as otherwise the chances are high that we overlook your answer.
We will also still need a scene file to help you here any further and the name of the plugin you are debugging.
Cheers,
Ferdinand -
Yeah, sorry I changed it right after posting the reply and didn't think it would be a problem.
This is about V-Ray for Cinema4D. In this scene there is a softbox texture(in the V-Ray material diffuse slot). Here the base texture of the softbox(the checker in the screenshot) is lost after loading the scene in 2024 and using the code in the original post, but loads fine in older versions. The old TEXSOFTBOX_BASE_TEX_TEXTURE=613662896 became TEXSOFTBOX_BASE_TEX=1404507874 and the issue should be reproducible with any V-Ray build for C4D 2024 from the last year.
Note that this isn't something critical as we only do it in a few places, however, it is slightly annoying
and mostly wrote to check if there is something obviously wrong with what we are doing . -
Hey @bojidar,
will have a look, thanks. But when you say that it is not super critical for you, I will push the answer a bit. I will come back here latest by Friday the 26th with an update.
Cheers,
Ferdinand -
Hey,
sorry, was very busy last week, will have a look today.
Cheers,
Ferdinand -
Hey @bojidar,
first of all, I can confirm the issue, the file loads fine in 2023.2.2, does not load properly in 2024.4.0, but the checkerboard shader is still part of the scene graph.
I spent today some time on debugging this but did not get very far. The problem is that debugging this from the plugin side (the
NodeData::Read
call of your Vray binary) is not too insightful as the deed is already done there (the Hyperfile has already been loaded when it is passed to yourNodeData::Read
and the data in there is already broken). The other way would be to debug the actual file deserialization when theBaseLink
is being read as a Hyperfile chunk when the c4d file is being loaded. But that is not so easy because there is exists no parameter ID in this context (I cannot just sayif old_vray_param: DebugStop()
because a Hpyerfile operates not in parameters but chunks). And even for an "empty" scene a s*** load links must be deserialized, so just setting a break point here does not lead anywhere. But I stumbled upon this:This is your plugins
NodeData::Read
being called upon scene loading to be further deserialized (i.e., the BaseLink has already been read). The disk level should not be 0 here. Because there should be at least two versions of your plugin, one witholdParameter
, and one without. It could be very well that you not incrementing the version somehow screws with the Hyperfile deserialization here (you would have to do this inRegisterMaterialPlugin
where you are likely still passing the default of0
). So, you should increment the counter for the 2024.4 version of your binary and see if this changes anything.We also had a brief discussion today about if what you are doing is intended. Or in other words - if there is some optimization in our code which mutes reading parameter chunks within a disk level that do not match the description of the atom they are being read for. I do not see any code which would do that (as Hyperfile does not operate with the idea of parameters with IDs but with the idea of sequential chunks). But it would be still interesting to know if you have done this in the past (and it worked then) - deprecated a parameter within one disk level and then "rerouted" it in the next version of your binary?
Another thing to do (which I haven't done yet because I was today busy with cursing at the debugger) would be to write your material in 2023.2.2 with
C4DAtom::Write
to disk, so that one has a bit easier time to see in 2024.4 what happens when we callC4DAtom::Read
on that specific data being deserialized.The last option would be to rewrite the core of Cinema 4D to see the exact point when the hyper file chunk for that parameter is being read. But that is our last option.
Cheers,
Ferdinand -
Hello,
Why is the disk level being 0 there a problem? Isn't that the value of the disk level in the scene we are reading? So since it's an old scene and we didn't have any custom ::Read logic in the build this scene was saved with it should to be 0(the default value)? Also shouldn't the value only be changed in RegisterShaderPlugin(since the problem here is the Softbox shader) and not RegisterMaterialPlugin as the post says? We always change the disk level when adding logic in NodeData::Read and I also noticed it might only be broken with nested shaders as we have recently done the same in our Camera tag and it works fine in 2024. -
Hey @bojidar,
you told me that you did change the description of your plugin
whenever the id of a ShaderLink parameter had to be changed and preserve the shader from old scenes.
It is not the shader which changed, but your material. So you must compile your 2024 material plugin with an incremented disk level. You must increment your disk level every time you release the plugin with a new data container layout. A VRay plugin should therefore not have a disk level of zero (because that means you have shoved all versions of that plugin into that one level).
There is no guarantee that this will fix it, but there is quite a lot of code which is skipped in node deserialization when your disk level is zero or lower.
Cheers,
Ferdinand -
Hey,
Sorry for the really delayed answer... Perhaps I didn't explain something well enough. What we changed was the id of a parameter as seen in the screenshot above in the Softbox shader from 613662896 to 1404507874 . The disk level used to be 0 before the change and then we set it to 1 after. So in more recent V-Ray versions we register the shader with disk level 1 and if I understand how the serialization works the level in the old scene should be 0 and Read should be called with a disklevel=0(since that is what ReigsterShaderPlugin was called with in the old V-Ray version). I was trying to do the same with another shader i.e. increment the disk level from 0 to 1 in RegisterShaderPlugin and do something along the lines ofif (diskLevel < 1) { BaseContainer &nodeData=static_cast<BaseShader*>(node)->GetDataInstanceRef(); const BaseLink* oldLink=nodeData.GetBaseLink(oldParameter); if (oldLink != nullptr) { GeData linkData; linkData.SetBaseLink(*oldLink); nodeData.SetData(newParameter, linkData); } nodeData.RemoveData(oldParameter);
and it just doesn't work in 2024.
-
Hm,
okay, so you say this Vray plugin node does not use disk level 0 in its 2024 version anymore? I did not check your registration call, my alarm bells just went off when I saw the 0 because even a 2023 Vray plugin should not have a disk level of zero. Given how well established VRay is, I would expect here at least a disk level of 1 or 2 for this particular node. Did you have major rewrite of Vray or has this node been particularly uneventful in its change history that it still had a disk level of 0 in 2023?
And this is not about the disk level code you write in your code, but the branching Cinema 4D takes when there is a disk level of zero. A lot of code simply does not run when your current disk level is zero. But when you say your plugin has now a disk level of one, or that you generally increment your disk levels properly, this all does not really matter.
The Tech team touched one part of the non-public underpinning of
BaseLink
for 2024. But I currently do not see how this could only impact links that are the values of orphaned parameters. Will have a look next week again.Cheers,
Ferdinand -
Hey @bojidar,
So, I spent again some time on trying to debug this, and this time manually stepped through the deserialization of
1053286
, i.e., your material type. And I am not really any wiser to what is going wrong there. This could be related to a change one of developers made for 2024 toGeAliasGoal
, a precursor to what you see as aBaseLink
in the public API.But when I look at how it steps through the chunks of the hyper file for your material, I do not really ever see that parameter being deserialized. I think this is more a Tech team than an SDK team issue as they own that part of our APIs. I would have to ask you to file a bug report via our bug tracker for this. Please make sure to include:
- Reproduction steps.
- The file.
You can also include your code, but that is of less importance. Please give me then also a note when you have done this, so that I can attach the relevant people and make sure that they get access to a license of your software. I could also file the bug report for you, the problem would be then however, that you could not see it, as you can only see your own reports as an MRD. I.e., you could not take part in the comments/discussion attached to the issue. I would recommend that you submit it yourself. When you run into problems, ask Deyan, or reach out to us via mail.
Cheers,
Ferdinand