Unfortunately not (in my case) because my MacBook is too old to run Ventura. This means I can only build macOS plugins for R2024 or earlier, because I can’t run R2025 on my Mac (requires Ventura to run). Therefore, I’ve made the decision not to build my plugins for R2025 on macOS until/unless I can afford to buy a newer Mac. It just isn’t worth it for free plugins. If I had a newer Mac I would almost certainly do as you suggest; I’ve done it before with older macOS versions.
Posts made by spedler
-
RE: Development requirements for C4D 2025
-
RE: Create a dynamic list of structs or BaseContainers
Why not just use a BaseArray of the data structures you want to use? Re-initialise this every time InitRender is called then you can iterate through it when needed (presumably in the Output function?).
You’ll also need to implement CopyTo() to make sure the data is available when rendering to the picture viewer.
Steve
-
Notarizing a Mac plugin
Just to note for info, the SDK docs for 2025 have a page for notarizing a Mac plugin. However, it still refers to using 'xcrun altool ...' but as I have just discovered, the use of altool has been discontinued and you must use 'xcrun notarytool ...' instead. The command line is almost the same but slightly different if you don't use a keychain profile but enter your Apple ID, app-specific password, and team ID separately.
Thought I'd mention it so the page can be corrected (in all that wonderful free time I'm sure you have!).
Steve
-
RE: Development requirements for C4D 2025
That’s a very useful site, thank you. I already have Xcode 13.4 installed but I don’t know if it will still be available after upgrading the OS to Ventura. If not, I can get it from there and reinstall.
-
RE: Development requirements for C4D 2025
Hi @ferdinand,
Yes, I've seen those hacks needed to run Xcode 13 on Ventura. TBH, I think while Macs are lovely machines, Xcode as a dev tool is a pig, even more so if you can't match Xcode versions with the OS version, as here.
I'll try installing Ventura then seeing what happens when running Xcode 13 in the way you suggest, but it's getting to the point where supporting macOS for freebie plugins just isn't worth the time and effort required. I'd be interested to hear what the techs say about this. There's an interesting page on Stack Overflow about it.
Cheers,
Steve -
RE: Development requirements for C4D 2025
Thanks Ferdinand. There's still my point about macOS. If Xcode 13 is required for R2025 development, this won't run on Ventura (macOS 13), but C4D R2025 won't install on Monterey (macOS 12). How do we square this circle? Can Xcode 14 be used for R2024 development?
Cheers,
Steve -
Development requirements for C4D 2025
The latest C++ SDK docs don't state the dev environment for C4D 2025, only for 2024. For Windows, I have rebuilt plugins for 2025 using VS2019 and it works fine, but the Mac is more complex (inevitably). My MacBook runs macOS 12 (Monterey) with Xcode 13, but when I tried to install Cinema on it, I get an error saying that it requires macOS 13.6 or later (Ventura). However, if I install Ventura, it seems that Xcode 13 won't run on that, and Xcode 14 is required. But if I do that, will I be able to build plugins for R2024 using Xcode 14? Because if not, that raises the annoying prospect of having to maintain two separate versions of macOS and Xcode if I want to support both R2024 and R2025.
Some guidance on this would be very helpful.
Cheers,
Steve -
RE: Retrieving a shader from a LayerShaderLayer
Hi Ferdinand,
That’s great, really very helpful, thank you. I’m glad my code was right in principle even if it didn’t work! I would never have guessed the layer returned a void pointer. That should now work perfectly and do exactly what I need.
Thanks again for taking the time to look into this, very much appreciated.
Cheers,
Steve -
RE: Retrieving a shader from a LayerShaderLayer
Hi Ferdinand,
No worries, I know you must be very busy. The shader works in itself, it’s just that I’d like to tidy the interface to avoid confusing users. Whenever you have some time to look at it is fine.
Cheers,
Steve -
RE: Retrieving a shader from a LayerShaderLayer
Just one small correction - the returned value of 14 when GeData::GetType() is called equates to DA_VOID, not DA_MISSINGPLUG. My mistake, sorry about that. That value makes a bit more sense; still fails though
Steve
-
RE: Retrieving a shader from a LayerShaderLayer
Hi Ferdinand,
No worries, attached is a zip with the compiled test plugin and a scene file. Just open the file, switch to the material in the AM and check the console for output. The plugin's source is in the previous file I uploaded.
Cheers,
Steve
Attached: LayerShaderTest_Scene.zip -
RE: Retrieving a shader from a LayerShaderLayer
Hi Ferdinand,
There is no scene file worth sending because all I do is add my shader to a layer shader and try to retrieve a pointer to it from the layer shader. So at it's most simple all I would do is create a new standard C4D material (not Redshift or any other renderer) in a blank scene, add a layer shader to the mat's color channel and add my shader as the only layer in that layer shader.
To show what I mean, I've created an absolutely bare-bones shader to reproduce the problem. A zip with source and resource is attached to this post. It should be straightforward to build if anyone wants to do that.
It may be, of course, that what I'm trying to do is not possible. In case you're wondering what exactly I am trying to do, all I want is to discover which channel the instance of the shader is in. This is easy at render time by checking the cd->texflag in the Output function but I couldn't find a way to do it when not rendering. The reason I want to do this is because I want to disable parts of the shader's UI depending on the channel. For example, my shader has a colour gradient which is used in the Color channel but not in the Bump channel. Now, this all works fine if the shader is not in a Layer shader, but if it is I need to traverse the layer shader to find out if my shader is present. But I can't do that because I can't get a pointer to any of the shaders in the layer shader.
(There may well be a better/easier way to do this, in which case I'd really love to know what it is )
Cheers,
Steve
Attached: LayerShaderTest.zip -
RE: Retrieving a shader from a LayerShaderLayer
Hi @ferdinand,
Many thanks for your very helpful comments and code. I've investigated this a bit further and I may have found where the problem lies. This is the slightly modified code snippet:
while(lslayer != nullptr) { if (lslayer->GetType() == LayerType::TypeShader) { if(lslayer->GetParameter(LAYER_S_PARAM_SHADER_LINK, gd) == true) { if(gd.GetType() == DA_ALIASLINK) { const BaseLink* link = gd.GetBaseLink(); if (link != nullptr)
The main difference is that I've added a check for the GeData type. This test always fails: that is, the GeData type returned is not DA_ALIASLINK but a value of 14, which appears to be DA_MISSINGPLUG - a mssing datatype plugin, whatever that means.
Given that, if that check is not carried out and it is assumed that it must be a DA_ALIASLINK (as I did in the previous code) it's not surprising that a nullptr is always returned, in fact it's surprising Cinema doesn't crash . In fact, in the debugger if you manually bypass that GetType() check, Cinema triggers a breakpoint in c4d_gedata.h but it doesn't actually crash.
Unless, again, I've done something wrong this is looking like a bug but it's odd that the Python version works correctly. Should I submit a bug report?
Cheers,
Steve -
Retrieving a shader from a LayerShaderLayer
I've been puzzling over this all morning. I'm writing a shader and if this is in a Layer shader and I want to get a pointer to it (my shader, that is). This is the code I have:
BaseShader* MyPlugin::WalkLayers(LayerShader* ls, const BaseDocument *doc) const { BaseShader* ret = nullptr; LayerShaderLayer* lslayer = nullptr; GeData gd; lslayer = ls->GetFirstLayer(); while(lslayer != nullptr) { if (lslayer->GetType() == LayerType::TypeShader) { if(lslayer->GetParameter(LAYER_S_PARAM_SHADER_LINK, gd) == true) { const BaseList2D* blist = gd.GetLink(doc); if (blist != nullptr) { ret = (BaseShader*)blist; if (ret->GetType() == ID_MYSHADER) break; } else ApplicationOutput("gd.GetLink() returns a null pointer."); } ret = nullptr; lslayer = lslayer->GetNext(); } } return ret; }
The problem is that the call to GeData::GetLink() always returns a null pointer. I've checked the layer name and it returns the name of my shader, but I just can't get the link to work. I must be missing something obvious, but what?
Many thanks,
Steve -
RE: Plugin: Render Message
@kmhfygg I must admit it isn't entirely clear what you are asking for. Since you have developed your plugin already, you are not asking for a licence for C4D itself. And since it's a free plugin, you don't need to licence it to other users.
I'm guessing that you need a plugin ID number, which makes your plugin unique and distinguished from all other plugins. To get that, go to the 'Support' menu at the top of the page, choose 'Plugin IDs' and follow the procedure to receive a new and unique ID number. You need to do that for every plugin you develop and intend to release.
Steve
-
RE: Python: Cinema exit event
See the function PluginMessage() and listen for messages such as C4DPL_END or C4DPL_ENDACTIVITY.
Steve
-
RE: Sampling a Fusion shader
Hi @ferdinand,
Thanks for this, inserting the colour shaders uner the Fusion shader and then inserting the Fusion shader under my shader works fine.
I must admit this is my fault. Because the shaders are all created in the InitRender() of my plugin, I didn't think they needed to be (or could be) inserted under my shader. I figured it would be different if the shaders were going to be added to a link field and stay in the document, but not if they're just created then destroyed when done with. So that's very useful to know.
Thanks again,
Steve -
Sampling a Fusion shader
I'm writing a ShaderData plugin and what I want to do is sample a Fusion shader created programatically in the InitRender() function of my plugin.
I'm not even sure if this is feasible, but it doesn't work as expected. Here is the code to create the Fusion shader:
m_fusion = BaseShader::Alloc(Xfusion); GeData gd; if (m_fusion != nullptr) { m_fusionBlendShader = BaseShader::Alloc(Xcolor); if (m_fusionBlendShader != nullptr) { m_fusionBlendShader->InitRender(irs); gd.SetBaseList2D(m_fusionBlendShader); const DescID blendID = ConstDescID(DescLevel(SLA_FUSION_BLEND_CHANNEL, DTYPE_BASELISTLINK, 0)); m_fusion->SetParameter(blendID, gd, DESCFLAGS_SET::NONE); } m_fusionBaseShader = BaseShader::Alloc(Xcolor); if (m_fusionBaseShader != nullptr) { m_fusionBaseShader->InitRender(irs); gd.SetBaseList2D(m_fusionBaseShader); const DescID baseID = ConstDescID(DescLevel(SLA_FUSION_BASE_CHANNEL, DTYPE_BASELISTLINK, 0)); m_fusion->SetParameter(baseID, gd, DESCFLAGS_SET::NONE); } m_fusion->InitRender(irs); m_fusionInitCount++; }
I've just used color shaders in the Fusion blend and base channels for convenience; this should cause the Fusion to return pure white.
Everything seems to work as expected, in that it compiles and runs and the shaders are all allocated, but when I sample the Fusion shader in my shader's Output function, it always returns black. I'm not sure if this is because I haven't set the blend and base channels correctly or if this simply can't work, so any advice would be greatly appreciated.
Many thanks,
Steve -
RE: Use new node in an RS material
Hi @m_adam
Thanks very much for this, it's extremely helpful and gives a lot of detail about how nodes actually work.
From what you say, it does indeed sound as though implementing a shader in RS is basically not possible. That's a shame, but at least I won't be wasting time trying to get it to work but not knowing it can't be done! Still, I've learnt quite a lot while trying to make it work, so it's not all bad.
Thanks again,
Steve -
Use new node in an RS material
I've written a new node which outputs a colour and I want to use this in an RS material in the node editor - but it isn't present in the node list.
The node itself is fine and does what it is supposed to. It is in the node list in the category I want (Color) and I can add it to the node editor, if - and only if - the editor mode is 'Scene'. If I change the mode to 'Material', or create an new RS standard material and edit it, then my node disappears from the node list (so do a bunch of other nodes in the Color category) so I can't use it in the material.
My question is simply what other steps are needed to make this node available in the node list when the editor is in material mode? There must be something I haven't done - the node is just a core node written as shown in the SDK. What have I omitted to do?
Thanks,
Steve