• Adding material node to menu category

    c++ 2024 windows
    3
    2
    1 Votes
    3 Posts
    610 Views
    M
    Hi @spedler regarding your issue, it's correct all changes done within the resource editor need to be saved, via the menu (file -> Save Database) otherwise change will get lost. Regarding the needs for the double-click, that's a missing refresh in our cache, I've reported to the responsible dev, thanks a lot ! Cheers, Maxime.
  • ProjectTool & visual studio: Treat Specific Warnings As Errors

    windows c++
    3
    0 Votes
    3 Posts
    672 Views
    B
    Thanks for the reply, @ferdinand
  • ProjectTool & visual studio: /DELAYLOAD

    windows 2024 c++
    3
    0 Votes
    3 Posts
    717 Views
    B
    Thanks for the reply, @ferdinand. I can confirm that below syntax doesn't work. I still get the same error. AdditionalLinkOptions=%(AdditionalOptions) /DELAYLOAD:"mydll.dll" I'll see what alternatives I could use.
  • GvNodeMaster::Execute() returns error

    c++ 2023
    5
    0 Votes
    5 Posts
    1k Views
    F
    @ferdinand said in GvNodeMaster::Execute() returns error: Since you do your own stuff, this could for example fail in the DL_TERMINAL node you implemented in addition to some of the init stuff going wrong. I have confirmed that the error seems to come from my own GvOperatorData()-plugins (shader nodes). When I delete all my own nodes in the graph and only use the build in c4d xpresso nodes, then GvNodeMaster updates correctly. I will look into this, but now I know where to look! We can mark this as solved for now. "I can of course also just have a look at it, but I will not be able to run your project to see and tell you why it fails exactly" At this stage, I was just looking for general feedback on how and when the Execute() function was supposed to work correctly, i.e., if it needed to be called in a special context or similar. This is also why I did not post detailed code initially. I don´t fully agree that detailed code is always needed to discuss an issue, even if it of course sometimes helps in clarifying things! Anyway, thanks a lot for the good support, it is really helpful and I appreciate the availability of this forum - it really helps! Best regards /Filip
  • is it possible for me to create a script, outside of c4d

    python 2024 windows
    2
    1
    0 Votes
    2 Posts
    510 Views
    M
    Hi @pyxelrigger there is no real way to execute a script outside of Cinema 4D without Cinema 4D. The only option is to execute c4dpy which is a complete Cinema 4D instance run as a python interpreter. For more information about it, please read c4dpy manual. Note that you have the same limitation as a standalone Cinema 4D so you can't execute multiple c4dpy instance at the same time or they need to be in different folders. Except that note that tkinter does not come by default with Cinema 4D, so you will need to install manually and don't really officially support, so it may or may not works, but from our personal experience in the SDK team, it should work. Cheers, Maxime.
  • Particle modifier plugin type

    2024
    7
    0 Votes
    7 Posts
    2k Views
    ferdinandF
    Hey @spedler, only the simulation team can speak to the exact details here, but my guess for why it is how it is, is the pesky cpu-gpu upload penalty. If you would upload pre sampled data, or even worse sample on the CPU, this would really slow down any GPU advantage you have. I doubt that this is any different for the GPU part of Xparticles. One could think about plugin access for CPU-sims but most users are likely never going to use that if they can avoid it. The simulation device is set in the simulation scene and by default GPU. [image: 1713257356914-08c2f454-96fb-4d92-9adc-8247e47fc44f-image.png] The more realistic thing would be that we provide some compute shader like access. I could go here into the details of the new particles and the challenges of providing such compute shader access to them but that would be the famous "counting chickens before they hatch". Let's first see how many users and which user type (scripting technical artist vs. C++ development professional) wants a deeper API access for particles. Cheers, Ferdinand
  • 0 Votes
    2 Posts
    765 Views
    ferdinandF
    Hey @ThomasB, Thank you for reaching out to us. Without your code we cannot really help you, we are not the oracle of Delphi There are many things which could go wrong in your plugin. But in general what you are doing is correct; add a dummy point object with your snap points to your cache, when you want to introduce special snapping points for your custom generator object. Snapping onto the points of the returned geometry should work out of the box (but snapping sometimes struggles a bit with deep caches). There is however only limited support for adding special snapping points, as it is not really intended to add you own snap logic in that manner. The snapping module both in Python and C++ does not allow you to implement your own snapping logic, you can just read some data. You should also keep in mind that the snapping is an older part of Cinema 4D which has its flaws. You should check if your problem also does occur when you try to snap onto the converted cache of your object (current state to object). If that is the case, you know it is not something your plugin does, but simply the fact that the snapping struggles with that specific geometry/scenario. Cheers, Ferdinand
  • 0 Votes
    3 Posts
    693 Views
    pyxelriggerP
    Thanks, buddy! It worked. To be honest, I never really understood what Message(c4d.MSG_UPDATE) was all about, and now ExecutePasses is new to me
  • Copying/Pasting GvNodes?

    c++ 2023
    3
    0 Votes
    3 Posts
    680 Views
    F
    "PS: There are also the copy buffer methods on GvNodeMaster if you want to preserve connections, copy multiple nodes at once etc.:" -That looks like it might be exactly what I need! Thanks a lot!
  • How do I get the cache of a cloner in an ObjectData Plugin

    2023 2024 r23 r25 python
    4
    0 Votes
    4 Posts
    1k Views
    ferdinandF
    Good to hear!
  • Rendering debug UI in the viewport via plugin

    2024 c++ windows macos
    8
    0 Votes
    8 Posts
    2k Views
    C
    @ferdinand Thank you very much! I got the min and max distances also working with your input! I used the code example from the docs to traverse through the DeformCache and it worked instantly
  • Copy children to selection with GetClone()

    python 2024
    3
    0 Votes
    3 Posts
    776 Views
    John_DoJ
    Hi @ferdinand, thanks for the feedback, I've got it working with your suggestion. The method B was correct but the undo part was wrong ( the undo step was applied on the original objects instead of the new ones, thus leading to a mess when performing an undo). I also added the bit part to keep new objects folded in the OM. Here is the code : # CopyDeformers import c4d doc = c4d.documents.GetActiveDocument() def main(): doc.StartUndo() objs = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_SELECTIONORDER) if len(objs) >= 2: # Get the last selected object active = objs.pop(-1) # Get the deformers deformers = [i for i in active.GetChildren()] # Copy deformers to selection if deformers: for o in objs: for d in deformers[::-1]: dcopy = d.GetClone(c4d.COPYFLAGS_NO_BITS) doc.InsertObject(dcopy, parent=o) doc.AddUndo(c4d.UNDOTYPE_NEW, dcopy) o.SetBit(c4d.BIT_MFOLD) doc.EndUndo() c4d.EventAdd() if __name__ == '__main__': main()
  • Create folder in Volume Builder

    windows python 2023
    3
    0 Votes
    3 Posts
    686 Views
    D
    hi @i_mazlov, thanks for the answer. good to know about this status / limitation. for my current case I found a solution without folders..
  • How to LoadDocument from string in memory? 🤔

    python
    3
    0 Votes
    3 Posts
    1k Views
    mikeudinM
    Cool! Thank you!
  • fieldlayer with variable tag

    windows python 2023
    2
    1
    0 Votes
    2 Posts
    537 Views
    D
    found the solution ... the corresponding type is called: FLweight
  • Plugins Search Path from Preferences

    python
    3
    0 Votes
    3 Posts
    790 Views
    merkvilsonM
    Thanks @ferdinand I wrote this little script for those who want to add one plugin path via the C4D script. I will update it later. It will NOT overwrite existing paths. Restart is required for instant result. import c4d import os import json def add_plugin_path(path, restart = False): if os.path.exists(path): new_path = path.replace("\\", "/") else: print("Path does not exists") return prefs_folder = c4d.storage.GeGetC4DPath(c4d.C4D_PATH_PREFS) prefs_path = os.path.dirname(prefs_folder) plugins_json_path = os.path.join(prefs_path, 'plugins.json') if os.path.exists(plugins_json_path): with open(plugins_json_path,'r',encoding="utf-8-sig") as plugins: plugins_json_raw = plugins.read() plugins_dict = json.loads(plugins_json_raw) content_dict = plugins_dict["content"]["_impl"]["_data"][1]["content"] # Check if the new path is already in Plugins Path for content_path in content_dict: if os.path.normpath(content_path["_0"]["_path"]) == os.path.normpath(new_path): print(f"'{new_path}' is already in Plugins Path.") return else: plugins_dict = { 'identification': 'plugins', 'content': { 'referenceDataType': 'net.maxon.interface.datadictionary-C', '_impl': { '_mode': 2, '_data': [ { 'dataType': 'net.maxon.datatype.id', 'content': 'searchPaths' }, { 'dataType': '(net.maxon.interface.url-C,bool)', 'isArray': True, 'content': []}]}}} # Create new path content new_content = { "_0": { "referenceIndex": len(plugins_dict["content"]["_impl"]["_data"][1]["content"]), "referenceDataType": "net.maxon.interface.url-C", "_scheme": "file", "_path": new_path, "_authority": {}, "_data": {} }, "_1": True } # Append the new path to the list of paths plugins_dict["content"]["_impl"]["_data"][1]["content"].append(new_content) # Convert the dictionary back to a JSON string updated_plugins_dict = json.dumps(plugins_dict, indent=4) # Write the updated dictionary back to a JSON file with open(plugins_json_path, 'w') as plugins_json: plugins_json.write(updated_plugins_dict) if restart: c4d.RestartMe() custom_path = r"/Path/To/Plugin/Directory/" add_plugin_path(path = custom_path, restart = False)
  • how to store/serialize custom data type?

    c++
    4
    0 Votes
    4 Posts
    869 Views
    ferdinandF
    Hey @aghiad322, as I said, classic API CustomDataType types (e.g., the "dots" example) realize their serialization via CustomDatatypeClass::Read and ::Write. The DotsDataClass example implements both methods to read and write the dots data. If you want things to be stored, e.g., your gradient, you will have to implement it there. E.g., it could look like this: Bool MyDataTypeClass::WriteData(const CustomDataType* t_d, HyperFile* hf) { // Cast the passed in data to your datatype. const MyDataType* const data = static_cast<const MyDataType*>(t_d); // Bail when #data is malformed, has no gradient. _gradient is a member of MyDataType and supposed // to be of type Gradient* just as in your case. if (!data || !data->_gradient) return false; // Wrap the dereferenced _gradient as a GeData instance. GeData geData; geData.SetCustomDataType(*data->_gradient); // Write your data into the hyper file and bail if it somehow fails. if (!hf->WriteGeData(geData)) return false; // Write other data members of your datatype. if (!hf->WriteInt32(data->_someInt32)) return false; if (!hf->WriteFloat(data->_someFloat)) return false; if (!hf->WriteBool(data->_someBool)) return false; return true; } Cheers, Ferdinand
  • 0 Votes
    2 Posts
    571 Views
    ferdinandF
    Hey @BretBays, Thank you for reaching out to us. You might want to have a look at the Python Libraries Manual. Since Cinema 4D 2024.0 there is also mxutils.LocalImportPath which automates injecting module paths and reloading such imported modules (I probably should update the Python libraries manual). The "flaw" of all these approaches is that while you still encrypt your plugins pyp file, the imported module(s) py file(s) will not and cannot be encrypted. You can either ship your common functions unencrypted or develop your plugin as a multi module solution (so that you do not have to replicate your code across plugins) and then package up the plugin into a singular file. There are some Python tools like pysconcat and pymerger which can help you with that. But you should be aware that these can fail when you have complex dependencies. You could also serve the py-cache of your modules, but that will not really stop anyone who wants to read your code. Cheers, Ferdinand
  • Sampling Redshift Materials

    2024 c++ macos
    3
    0 Votes
    3 Posts
    835 Views
    D
    Hi Ilia, At this point this seems a bit over my head, but it seems to be what I need, thanks! Dan
  • Clone orientation without a "Up Vector"

    windows c++ 2024
    8
    0 Votes
    8 Posts
    3k Views
    justinleducJ
    @ferdinand Oh wow! Thank you so much for letting me know about Keenan Crane, as I was not familiar with him. I am in awe of the exhaustive list of tools he and his lab have published. The Globally Optimal Direction Fields paper seems indeed to be exactly what I am looking for. I was also surprised to see that I had already skimmed the Youtube video of the paper back in December. Thank you so much @ferdinand for this invaluable piece of information. Time to dive in! Cheers!