I guess a Python script would do it fine, but I don't use Python. I can write you a quick plugin if that's any use? A plugin would give a few more options than a script I think.
Steve
I guess a Python script would do it fine, but I don't use Python. I can write you a quick plugin if that's any use? A plugin would give a few more options than a script I think.
Steve
Hi rui,
Yes, it's a pain in the neck doing macOS development. I almost gave up on it at one point it's such a hassle. But once you figure out all the hoops to jump through, it's not too bad. You might want to take a look at my guide to notarizing a mac plugin on my site at https://microbion.co.uk/html/createplugins_r23_3_notarize.htm. This explains the steps needed; the first step is the Apple developer account, which is what I think the tutorial you read must have been referring to. Unfortunately, unlike an Apple ID, getting a dev account is not free.
Steve
When rebuilding my plugins for R2024, I had to notarize the Mac version again for the new builds. The process worked fine, but I noticed that there was a message from Apple stating that the use of 'altool' to notarize was not going to be supported by the end of 2023.
In fact, they now say "The Apple notary service no longer supports altool from November 1, 2023. You use notarytool instead." See https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution
So I looked into using 'notarytool' and surprisingly (for Apple and XCode) it's significantly simpler and faster than the previous method. I've written some notes on how to use it for anyone interested, which are on my site at https://microbion.co.uk/html/r2024macosnotarize.htm
Steve
@m_adam Thanks very much for your comments. You asked which parts of the manual page weren't clear. It's more that it's incomplete, in that it doesn't tell you how to get a bundle ID, app password or provider ID. Also, I don't think the statement that adding a timestamp is optional if you enable the hardended runtime is correct - from what I can see, you must provide a timestamp even though you enable the hardended runtime.
The other thing is that invariably at some point the process is going to fail and there's no mention of what to do when it does. It's extremely frustrating when the notarization fails and you have to figure out why. Apart from that, the page is actually very good - just needs a bit more detail (IMO).
Steve
No problem, give me a couple of days to get an initial test version working. Are you on PC or Mac?
Steve
Take a look at the command line arguments passed to the project tool in your screen shot. The project tool is looking in the wrong place.
Steve
Hi Bjorn,
I have a working version of this now which you can download from my site at https://microbion.co.uk/files/rounditr2024.zip
It's PC-only at the moment and requires C4D R2024. Try this and see if it does what you need. There's some basic documentation included which I'll tidy up for the final version.
There doesn't seem to be a DM facility here so we'd better take any further discussion to email. You can get hold of through the contact page on my site (link is in the PDF in the zip file). Do let me know what you think.
Cheers,
Steve
In C++ - I expect it's the same in Python - I would call GeGetPluginPath() to find the absolute path to the plugin, then append the filename to that path. This should work no matter where the user has installed your plugin.
Steve
@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
Hi @ferdinand,
No problem, I got there in the end and it's actually not too tricky once you know how it's supposed to work. I'll have a go now at a material node, there are more examples of those so hopefully it'll be straightforward. I'll be sure to be back if it isn't!
In the meantime I've uploaded a detailed explanation of all the steps needed to build this kind of node to my site at https://www.microbion.co.uk/html/create_nodes_corenode1.htm so if anyone wants to see how it was done, it's all there. Hopefully it's fairly accurate; all I can say is that this is what I did and it worked for me
Thanks again for your help,
Cheers,
Steve
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
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
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
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
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
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
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
@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
See the function PluginMessage() and listen for messages such as C4DPL_END or C4DPL_ENDACTIVITY.
Steve
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