Thanks @PluginStudent for stepping in.
Hi @pim , thanks for reaching out us.
Looking at the error it looks like at the link time the linker is missing the Cinema 4D static libs.
With regard to your question do you confirm that:
Looking forward your answers, give best.
Hi @moko , thanks for reaching out us.
With regard to your request, please consider that all the information to adapt the code are already included in the thread you've pointed to.
Please also consider that being provided with the ID of a specific parameter is done by dragging and dropping that parameter string directly into the Python Console
Feel free to come back with any further question about development issue, but for time being, I warmly recommend you to give yourself a try since with this information you can easily find your way.
Lsat but not least, for the future be sure to make use of the tagging system when posting a new topic and to select the proper category.
Well @pim , that's indeed the issue. Sticking to the recommended IDE is always recommended.
Hi @pim thanks for reaching out us.
With regard to your request, well just having the "special" command-line args recognized is as easy as uncommenting this line.
It's indeed a working plugin and it should not be registered since it's not a plugin but rather a behavior defined when a
C4DPL_COMMANDLINEARGS is intercepted.
Hi @matniedoba, thanks for reaching out us.
With regard to your issue, given that it's not our primary task to debug plugins, to understand what's getting wrong I need you to provide:
I also second @zipit recommendations because improving code design via better function abstraction and documentation will lead to an increased clarity, reliability and, in the end, comprehension.
I'll try to find time in the course of the week to have a look at your issue given the items requested above.
Hi @pim , thanks for reaching out us.
Although you've already set this thread as SOLVED can you, for the sake of a better knowledge-sharing, describe better what you mean by "I tried to update a R20 C++ plugin."? What steps did you actually run through? What version of VisualStudio are you using? What version of ProjectTool did you used?
Finally, please make sure you use our tagging system to enhance topic search.
Hi @RenatoT thanks for reaching out us.
Can you please:
With regard to HandleShaderMessage, I confim that it is indeed used by shaders in NodeData::Message() when they have subchannels. The code snippet found the call documentation represents exactly what is used in the Fusion shader with regard to the Base, Mask and Blend channels.
Instead with regard to SHADERINFO_DYNAMICSUBSHADERS, assuming I've checked the version of Cinema you're working with, it is used no more.
Looking forward your further notes, give best.
Hi @dskeith thanks for reaching out us.
As pointed out by @PluginStudent, the NBIT_SOLO_LAYER behavior is explained in the Layer Manuel although it make sense to add a note to the Python API as well.
With regard to a complete example, I've partially reworked your code to make sure that by executing the script multiple times you can run across all the solo configurations that the scene can handle.
import c4d # Main function def main(): layer_root = doc.GetLayerObjectRoot() if not layer_root: return # Get the first layer in the scene layer = layer_root.GetDown() if not layer: return soloSet = False while layer is not None: # Set `rawdata` to True flag so to get the original layer values without any additional global changes layer_data = layer.GetLayerData(doc, rawdata=True) # check the current layer solo state: if layer_data["solo"] == False: # if not "solo" then set to True layer_data["solo"] = True # update the layer layer.SetLayerData(doc, layer_data) # update the flag soloSet = True break # deactivate if layer solo was True layer_data["solo"] = False layer.SetLayerData(doc, layer_data) # go to next layer layer = layer.GetNext() # if one (or more) solo was set the set NBIT_SOLO_LAYER otherwise clear if soloSet == True: doc.ChangeNBit(c4d.NBIT_SOLO_LAYER, c4d.NBITCONTROL_SET) else: doc.ChangeNBit(c4d.NBIT_SOLO_LAYER, c4d.NBITCONTROL_CLEAR) # Add an event c4d.EventAdd() # Execute main() if __name__=='__main__': main()
Hi @C4DS, thanks for reaching out us.
There's actually nothing weird in your code rather than you're just attempting to back-port a code designed to work from R21 onward to R20.
Please have a look at our asynctest example on GitHub on how it was handled in R20.
Thanks @kosmos3d for the contribution and making the whole community aware of it.
Thanks a lot @zipit . I indeed agree and will update the documentation accordingly.
Best and stay safe!
Hi @geese780 , thanks for reaching out us.
As suggested from @PluginStudent , the Getting Started section as well as the related sections found there are indeed good starting points.
On top of this material I recommend having a look at our PluginCafé Channel on GitHub where you can find different repositories for your tastes.
Among the examples in the C++ Repository, I warmly recommend checking the MicroSDK which is a full-rounded, 100% complete example on how both C4D Classic API and Maxon API can coexist in a single plugin.
Other relevant topics - but please not limit your curiosity to such list - to investigate, fitting with your scope are:
About IDE: the VS2017 Community Edition should work pretty well and doesn't need you to spend a buck!
Finally, although related to R20, you can find very detailed information on Compiling the Cinema 4D R20 C++ SDK Examples.
Feel free to come for any further support.
I need to spend some further consideration since it looks like I was unprecise.
BaseArray::Append() and the capacity of a BaseArray is reached - BaseArray default size is 16 elements - the internal
BaseArray::IncreaseCapacity()is called and it sequentially allocates a new memory block, copies the values of the previous block to the new one, and then the old one is released. Being the values passed to the
BaseArray::Append() a reference to myArray, it references the first element of the old block and because the code in
Append() accesses the reference after the old block has been released, that access is illegal.
To temporarily mitigate it you have to cast the value returned from the  operator before appending it to the proper type.
Actually by writing
Int32(myArray) - and here I was indeed unprecise because it is NOT casting but temporary local creating of a copy - a local
Int32 copy of
myArray is made on the stack at first by the compiler (before calling
Append) and then
Append(Int32(myArray)) references that local copy which is legal.
This behavior is NOT a bug - another initial overlook of mine - but rather a behavior by design which for example is also part of std::vector::push_back().
So, as a rule of thumb, cases where references to array elements are used while the array gets resized must be avoided. This note will be added to the BaseArray Manual in our documentation.
Sorry for the confusion I initially generated and, if further clarification are needed, feel free to come back.
Hi @C4DS thanks for reaching out us and sorry for getting late here.
With regard to the strange behavior you've pointed out, it seems to be a bug that is now under review. To temporarily mitigate it you have to cast the value returned from the
 operator before appending it to the proper type.
myArray.Append(Int32(myArray)) iferr_return; is expected to work.
Hi @kbar , the Custom Error example is available on GitHub.
It's made of:
Because of the release of the framework, the repository now contains a new folder named frameworks, whose contents should be copied in the SDK frameworks folder.
The same code runs compiles on both R20 and R21 and doesn't hit any Critical break point.
Last, with regard to registration the way to go is
MAXON_COMPONENT_OBJECT_REGISTER as you've already pointed out and the
MAXON_ERROR_REGISTERX is simply wrong due to the additional "X" at the end: the correct macro is
Hi Peter, see if the code below can temporary solve your issue.
import c4d def Rename (op): # check for op being valid if op is None: return # get the name name = op.GetName() # find last "."" pos = name.rfind(".") if pos != -1: # get substring name = name[0:pos] # remove the additional "." name = name.replace(".", "_") # set the name op.SetName(name) # iterate over the child if op.GetDown() is not None: Rename(op.GetDown()) # iterate over the sibling if op.GetNext() is not None: Rename(op.GetNext()) # Main function def main(): # retrieve the first item in the Object Manager and pass it to Rename Rename(doc.GetFirstObject()) # notify Cinema c4d.EventAdd() # Execute main() if __name__=='__main__': main()
The code above is just a draft example on how you can get it done but it should be on you to adapt it to your specific needs. Using a code without any grain of salt can be dangerous and error prone and it should also be noted that we're here to support rather than to provide solution.
I again iterate the suggestion to have a look to BaseList2D and GeListNode to get familiar with the concepts needed to properly traverse the scene and manage the information found belonging to the encountered objects and also, in your case, to Python tutorials for beginners.
Finally, if no further help is needed, remember to mark the thread as "SOLVED".