Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Register
    • Register
    • Login
    1. Maxon Developers Forum
    2. Filip
    3. Posts
    F
    • Profile
    • Following 0
    • Followers 0
    • Topics 13
    • Posts 49
    • Best 5
    • Controversial 0
    • Groups 0

    Posts made by Filip

    • RE: GvNodeMaster::Execute() returns error

      @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

      posted in Cinema 4D SDK
      F
      Filip
    • RE: GvNodeMaster::Execute() returns error

      Here is the code for my MaterialData plugin:

      #include "DL_NodeMaterial.h"
      #include "customgui_matpreview.h"
      
      GvNodeMaster* DL_NodeMaterial::GetNodeMaster() {
      	return node_master;
      }
      
      Bool DL_NodeMaterial::Init(GeListNode* node) {
      	node_master = GvGetWorld()->AllocNodeMaster((BaseList2D*)(this->Get()));
      
      	//Create a terminal node for this material
      	node_master->CreateNode(node_master->GetRoot(), DL_TERMINAL, nullptr, 200,200); 
      
      	DL_SetDefaultMatpreview((BaseMaterial*)node);
      
      	return node_master != nullptr;
      
      }
      
      void DL_NodeMaterial::Free(GeListNode* node) {
      	GvGetWorld()->FreeNodeMaster(node_master);
      }
      
      Bool DL_NodeMaterial::Read(GeListNode *node, HyperFile *hf, Int32 level) {
      	return node_master->ReadObject(hf,true);
      }
      
      Bool DL_NodeMaterial::Write(GeListNode *node, HyperFile *hf) {
      	return node_master->WriteObject(hf);
      }
      
      Bool DL_NodeMaterial::CopyTo(NodeData *dest, GeListNode *snode, GeListNode *dnode, COPYFLAGS flags, AliasTrans *trn) {
      	DL_NodeMaterial* dst = (DL_NodeMaterial*)dest;
      	return node_master->CopyTo(dst->GetNodeMaster(), flags, trn);
      }
      
      
      
      
      Bool DL_NodeMaterial::Message(GeListNode *node, Int32 type, void *data){
      
      	if (GeIsMainThread()) {
      		ApplicationOutput("Main thread"_s);
      	}
      	else {
      		ApplicationOutput("Not main thread"_s);
      	}
      	GvCalcError err = node_master->Execute(GeGetCurrentThread())
      	ApplicationOutput("Errorcode: "_s);
      	ApplicationOutput(String::IntToString(err));
      
      	if (err == GV_CALC_ERR_INIT_FAILED) {
      		ApplicationOutput("Init failed"_s);
      	}
      	if (err == GV_CALC_ERR_NOT_INITIALIZED) {
      		ApplicationOutput("Not initialized"_s);
      	}
      
      	
      
      	return MaterialData::Message(node, type, data);
      }
      
      //Initializes resources for rendering.
      INITRENDERRESULT DL_NodeMaterial::InitRender(BaseMaterial* mat, const InitRenderStruct& irs)
      {
      	return INITRENDERRESULT::OK;
      }
      
      
      void DL_NodeMaterial::CalcSurface(BaseMaterial* mat, VolumeData* vd)
      {
      
      	Vector diff, spec;
      	vd->IlluminanceSimple(&diff, &spec, 0, 0, 0);
      
      	vd->col = 0.8*diff;
      }
      
      Bool RegisterDLNodeMaterial(void)
      {
      	return RegisterMaterialPlugin(ID_DL_NODEMATERIAL, "DL_NodeMaterial"_s, 0, DL_NodeMaterial::Alloc, "DL_NodeMaterial"_s, 0);
      }
      
      

      As you can see, it does not do much besides store and maintain a GvNodeMaster, which is then displayed and edited in a separate GeDialog.

      In the Message() method, I try to update the XPRESSO calculations of the stored GvNodeMaster, but without success. I tried your suggestions of passing a null-pointer for the thread, but this made no difference.

      I am assuming this about 3Delight and that you are trying to implement your own GraphView based material system? If that is the case there can be countless reasons why this is failing for you and we cannot really help you without your code.

      Yes, correct! I have functioning implementation of a basic node material system. When rendering, I parse the GvNodeMaster attached to a material and generate a corresponding OSL-shader graph for the renderer. This works as intended (and I am quite exited about it! 🙂 ). That part does not require the actual XPRESSO nodes to be evaluated (Execute() :ed), since I am doing the parsing myself.

      The reason I am asking about Execute() and performing the XPRESSO calculations is that it would be really nice to be able to drive shader parameters via the existing Cinema 4d xpresso nodes! I understood from the Redshift docs that this is supported for that renderer, so it appears possible. If not, it is not a dealbreaker for me, but it would be a really nice feature to support.

      So, any ideas on why the execution of the XPRESSO graph does not work would be really appreciated! In the final implementation, I am not sure that the graph execution would happen in the Message() function of the MaterialData, this is just my first step of trying to get it to work somewhere in the code.

      Cheers
      /Filip

      posted in Cinema 4D SDK
      F
      Filip
    • GvNodeMaster::Execute() returns error

      Hi!
      In my plugin, I have a MaterialData that owns a GvNodeMaster, and I would like to update the xpresso calculations in that GvNodeMaster. To this end, in the Message() function of the material data, I try to call Execute() on the GvNodeMaster, as follows:

      GvCalcError err = node_master->Execute(GeGetCurrentThread());
      

      This, however, always returns the error code GV_CALC_ERR_INIT_FAILED or GV_CALC_ERR_NOT_INITIALIZED. Are there some other steps I need to take before I can call Execute() on the node master?

      I guess the broader question here is: How do I correctly force an update on the calculations of a GvNodeMaster?

      Best regards
      /Filip Malmberg

      posted in Cinema 4D SDK c++ 2023
      F
      Filip
    • RE: Copying/Pasting GvNodes?

      "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!

      posted in Cinema 4D SDK
      F
      Filip
    • Copying/Pasting GvNodes?

      Hi!
      I am writing a plugin that utilizes a custom node editor based on Xpresso (GvNodeMaster, GvNodeGUI, etc.), displayed in a GeDialog.

      Now I would like to implement Copy/Paste functionality, i.e. to be able to copy and paste selected GvNodes both within a single GvNodeMaster and between different GvNodeMasters. My GvNodeMasters are owned and stored within custom BaseMaterials.

      1. Is there some built in functionality I could use for this? The Xpresso editor implements this functionality, is there any way I can call those copy/paste functions?

      2. If not, how do I create a copy of a GvNode and insert it into another GvNodeMaster? Using GetClone() does not seem to work, which makes sense as GvNode according to the docs are not really normal BaseList2D:s*

      Any suggestions?

      Thanks!
      /Filip

      *) From the docs: "The GvNode is a double BaseList2D node. Internally it has an operator that corresponds to GvOperatorData. Use GetOperatorContainer() to access most parameters."

      posted in Cinema 4D SDK c++ 2023
      F
      Filip
    • RE: GvOperatorData, GetDDescription() problems

      "you are trying to write a node material wrapper for a render engine, right?"
      Yes, correct! I am working on node based shading for the 3Delight for Cinema 4d bridge plugin. The reason I want dynamic nodes is to allow using custom OSL shaders, with some metadata to describe the GUI. This allows users to add custom shaders, without having to touch C++. We currently have that implemented for non-node based shaders, and it is a feature I would like to keep.

      Thanks for the clarifications regarding the limitations of the XPRESSO-based alternative! It looks like I may have to reconsider using the new Nodes API. I opted for the XPRESSO option mainly because I am more familiar with the classic SDK, but maybe now is the time to take the plunge :-).

      Thanks for the response and support!
      /Filip

      posted in Cinema 4D SDK
      F
      Filip
    • RE: GvOperatorData, GetDDescription() problems

      So, I found this thread ("Item selection in GvOperatorData::FillPortsMenu") which suggests that I may need to implement the FillPortsMenu() and iGetPortDescription() functions myself to get this work. I have made some progress, and can now get the elements to show up in the port menu (when I click the top corners of the node in the Xpresso editor), but I have not yet implemented the functionality to actually add the ports to the node. Anyway, the approach seems promising.

      Is this the correct way to approach this, or is there a simpler way? I was kind of hoping/expecting that GvOperatorData would behave the same as other plugin types in this regard, and that the ports would be visible in the menu by default - is there such an option?

      Best regards
      /Filip

      posted in Cinema 4D SDK
      F
      Filip
    • RE: Creating and initializing nested ObjectData

      Do you need to able to place the "Parent" and "Child" objects anywhere in your scene hierarchy? Otherwise, could one possibility be to make "Child" a generator object, that implements GetVirtualObjects() to generate the desired null objects based on the "parent" object? The "parent" object would need to be placed under the "child" object in the hierarchy, which may or may not be a problem depending on the problem you are trying to solve.

      Or do you also need the generated nulls to be editable, i.e., not virtual objects created by a generator?

      Best regards
      /Filip

      posted in Cinema 4D SDK
      F
      Filip
    • GvOperatorData, GetDDescription() problems

      I am implementing a custom C++ Xpresso node, where the majority of the parameters/ports are to be generated dynamically via GetDDescription().

      The dynamically added elements correctly show up in the attribute manager, but my problem is that they do not show up as ports that can be added to the node in the Xpresso editor.

      A minimal example of the GetDDescription() that exhibits this problem looks like this:

      Bool NodeTest::GetDDescription(GeListNode * 	node, Description * 	description, DESCFLAGS_DESC & 	flags) {
      	if (!description->LoadDescription(node->GetType()))
      		return false;
      
      	flags |= DESCFLAGS_DESC::LOADED;
      
      	BaseContainer bc = GetCustomDataTypeDefault(DTYPE_LONG);
      	bc.SetInt32(DESC_ANIMATE, DESC_ANIMATE_ON);
      	String param_name = String("Dynamic int");
      	bc.SetString(DESC_NAME, param_name);
      	bc.SetString(DESC_SHORT_NAME, param_name);
      	bc.SetBool(DESC_INPORT, true);
      	bc.SetBool(DESC_EDITPORT, true);
      	description->SetParameter(DescLevel(1000, DTYPE_LONG, 0), bc, DescLevel(ID_GVPORTS));
      
      	return GvOperatorData::GetDDescription(node, description, flags);
      }
      

      Here, the "NodeTest" class is derived from GvOperatorData. When I implement a similar version of GetDDescription() for other plugin types, e.g., a BaseShader, the dynamically added element correctly show up both in the active object manager and as Xpresso ports. Also, if I add non-dynamic elements to the "NodeTest" class via a description resource, everything works correctly. It is just for elements added dynamically to the GvOperatorData-derived plugin that I am experiencing this issue.

      Any suggestions? Are there any special steps I need to take to make the elements appear as Xpresso ports?

      Best regards
      /Filip

      posted in Cinema 4D SDK sdk s26
      F
      Filip
    • RE: Custom XPRESSO graph editor, show nodes in object manager

      Great, thanks a lot for looking into this and for the detailed explanations!

      Now I know better what my options are! I am marking this thread as "solved".

      Best regards
      Filip Malmberg

      posted in Cinema 4D SDK
      F
      Filip
    • RE: Custom XPRESSO graph editor, show nodes in object manager

      "I will have a look tomorrow how we have solved such things in the past."
      -Awesome, thanks!

      "But you still did not tell us how you store your node graph. ..."
      -The GvNodeMaster is stored as a private member of a BaseMaterial plugin. I have implemented the Read(), Write(), CopyTo() and GetBranchInfo() functions for this BaseMaterial as follows, where "node_master" is the GvNodeMaster member:

      Bool DL_NodeMaterial::Read(GeListNode *node, HyperFile *hf, Int32 level) {
      	return node_master->ReadObject(hf,true);
      }
      
      Bool DL_NodeMaterial::Write(GeListNode *node, HyperFile *hf) {
      	return node_master->WriteObject(hf);
      }
      
      Bool DL_NodeMaterial::CopyTo(NodeData *dest, GeListNode *snode, GeListNode *dnode, COPYFLAGS flags, AliasTrans *trn) {
      	DL_NodeMaterial* dst = (DL_NodeMaterial*)dest;
      	return node_master->CopyTo(dst->GetNodeMaster(), flags, trn);
      }
      
      
      Int32 DL_NodeMaterial::GetBranchInfo(GeListNode *node, BranchInfo *info, Int32 max, GETBRANCHINFO flags){
      	return node_master->GetBranchInfo(info, max, GETBRANCHINFO::NONE);
      }
      

      Out of these, I am mainly unsure about the GetBranchInfo() function, as this is a part of the SDK I have not worked with before. Any input on this part would be greatly appreciated!

      /Filip

      posted in Cinema 4D SDK
      F
      Filip
    • RE: Custom XPRESSO graph editor, show nodes in object manager

      Making some progress on this! I have registered a custom mode with ActiveObjectManager_RegisterMode(), and wrote a message hook that traverses the nodes in my GvNodeMaster and fills the atom array with the currently active one.

      When I select a node in the GvNodeGui of my dialog, and manually set the active object manager to show my custom mode, the attributes of the selected node are correctly shown in the active object manager. So far so good!

      A remaining problem, however, is that whenever I click something in the GvNodeGui, the active object manager immediately switches its mode back to "Node", and then the active object manager no longer shows the active node in my dialog!

      Is there some way to get around this? I.e. is there some message I could intercept when the user interacts with my dialog, and from there set the active object manager mode to my custom mode?

      The context here (as you may have guessed from me mentioning BaseMaterials) is that I'm writing a node editor for a 3rd party render engine, and I would like for the shader nodes to be visible in the active object manager. From what I can tell, the Arnold plugin does show shading nodes in the active object manager in this way from a custom XPRESSO-based dialog, which leads me to believe it should be possible. A fallback approach would be to add a DescriptionCustomGUI to my shader editor dialog, and just show the attributes there (Like Redshift does?), but I would prefer using the active object manager if possible!

      Best regards
      /Filip

      posted in Cinema 4D SDK
      F
      Filip
    • RE: Custom XPRESSO graph editor, show nodes in object manager

      OK, thanks! I will continue looking into this and will post here when I find a good solution for my case.

      /Filip

      posted in Cinema 4D SDK
      F
      Filip
    • RE: Custom XPRESSO graph editor, show nodes in object manager

      Thanks for the answer! I will look into this and see if it helps!

      "I assume you are implementing your own nodes UI from scratch; you are neither using the GraphView (i.e., Xpresso), nor Nodes API? But the entities in your graph are instances of BaseList2D, right?"
      No, I am using GraphView/Xpresso! But the GvNodeMaster is not from an Xpresso tag, it is stored in a BaseMaterial plugin. I also have a dialog that displays a GvNodeGUI for this nodemaster, when an item of this BaseMaterial type is selected by the user.

      Does this change your answer, i.e., is there an easier way to get a selected GvNode to show up in the attribute manager, even when it does not belong to an Xpresso tag?

      posted in Cinema 4D SDK
      F
      Filip
    • Custom XPRESSO graph editor, show nodes in object manager

      Hi,
      I have a dialog that displays an XPRESSO style node graph - a NodeGUI, showing a gvnodemaster that is managed by my plugin. This works fine, with one exception: When I select a node in the dialog, it´s attributes are not shown in the object manager.

      How can I make that happen? I have looked at the ActiveObjectManager_RegisterMode function, but I can´t seem to get that to work. Any suggestions or relevant examples I could look at?

      (I am using the C++ SDK)

      Thanks!
      /Filip Malmberg

      posted in Cinema 4D SDK s26 sdk
      F
      Filip
    • RE: Node ID relevant bits?

      Hi @Virtualritz! Nice to see you on this forum. (Filip here, we talked on the 3delight discord)

      posted in Cinema 4D SDK
      F
      Filip
    • RE: Purely dynamic description for shader?

      Hi all! Thanks for your input in this matter.

      For now, I have solved my problem by creating the needed resource files from my own code, before I register the plugin using these newly created resource files. This will do for now, although it means I have to ensure that the "res" folder of my plugin has write permission. I will try to solve that in the installer.

      "What might be the confusion here is, that you can of course register the same implementation multiple times. But these then would pop up as different plugins in Cinema 4D - which is probably not what @Filip is trying to do. At least from my current understanding."
      -This is actually exactly what I am doing! I am registering the same plugin class multiple times, using a different ID. Since the behaviour of the class depends on the ID, this appears to the user to be a series of entirely different shader plugins, which is my intention. The problem was that each such plugin also needed its own unique resource files (to avoid the problem that the resource name has to be unique). But as stated above, I'm solving this by creating the resource files themselves on the fly, whenever they are needed.

      I consider this problem solved for now.

      Best regards
      /Filip

      posted in Cinema 4D SDK
      F
      Filip
    • RE: Purely dynamic description for shader?

      Thanks for the detailed breakdown @ferdinand! Yes, I'm very familiar with how plugins are "usually" registered. Since what I'm trying to do here (registering "auto generated" plugins dynamically) is a bit unusual, I just wanted to check if there was any possible workarounds that I was missing.

      Another option I am considering is to write the neccesary description files from to disk from my plugin, and then use them in registration. This would require that my plugin has write access to the directory where the files would be stored. This has to be the "/res" directory of the plugin, right? Is there anyway I could guarantee to have write access there?

      /Filip

      posted in Cinema 4D SDK
      F
      Filip
    • RE: Purely dynamic description for shader?

      Thanks for the input @kbar ! That's certainly a possibility, and I believe that is how RSL shaders were handled in the old cineman module. I'll consider this.

      /Filip

      posted in Cinema 4D SDK
      F
      Filip
    • RE: Purely dynamic description for shader?

      A possible workaround would be to ask users to create a "dummy" description resource file for every OSL shader they want to load, but since everything else would be handled dynamically it would be a lot more elegant if I was able to use the same resource file for multiple shaders.

      /Filip

      posted in Cinema 4D SDK
      F
      Filip