Capsules Drag & Drop
-
Hi.
When working on a tag plugin I've recently been encountering a problem when I try to interact with Capsules, my plugin is meant to have parameters dropped onto it from the object it is attached to.
In my code I can properly receive the drag and drop operation and get the information from the parameter that was dropped onto it, the issue comes in when I try to determine which object the parameter came from.
When it comes to the Capsules in the object manager my code does not return the results that I am expecting when I try to verify that the parameters were dragged from the object that the tag is on.
The code below is a stripped down version of my drag and drop code.
Bool TagExample::Message(GeListNode* node, Int32 type, void* t_data) { BaseDocument* doc = node->GetDocument(); if (!doc) return TRUE; BaseTag* tag = static_cast<BaseTag*> (node); if (!tag) return TRUE; if (type == MSG_DRAGANDDROP) { DragAndDrop* dnd = static_cast<DragAndDrop*>(t_data); if (!dnd) return TRUE; if (dnd->type == DRAGTYPE_DESCID) { DescPropertyDragData* dndid = static_cast<DescPropertyDragData*>(dnd->data); AutoAlloc<AtomArray> dndidarr; dndid->arr->CopyTo(dndidarr); if (dndidarr->GetCount() <= 0) return TRUE; BaseObject* tagObject = tag->GetObject(); if (!tagObject) return TRUE; BaseObject *draggedObject = (BaseObject*)dndidarr->GetIndex(0); if (!draggedObject) return TRUE; if (draggedObject != tagObject) ApplicationOutput("Do not equal"); else ApplicationOutput("The objects equal") return TRUE; } } return true; }
For some reason when I drag a parameter from a Neutron Cube, that my tag is on, onto my tag I don't get the expected result of the dragged object and the tag object equalling each other. If I do the same procedure on a regular Cube (Ocube) I am able to properly catch that the objects are one and the same. The same behavior is encountered with other Capsules.
I'm not very familiar with Capsules, is there a specific way that Capsules need to be interacted with in order to achieve the desired results?
Any help would be greatly appreciated.
John Terenece
-
Hey @JohnTerenece ,
Thank you for reaching out to us. I am not 100% sure that I am understanding you correctly, but from what I get, you want to compare the
BaseList2D
representations of twoGraphNode
instances at the specific case of aNodes Mesh
.Why is this Happening?
We have something like this, where the Python Programming tag is your tag plugin:
Fig I.: ANodes Mesh
capsule with a Python tag on it.You now want to drag the
Nodes Mesh
node onto your tag node and compare the values. In general, it is not too surprising that these nodes do not always match, as allBaseList2D
representing aGraphNode
, e.g., theCube [Cube] BaseList2D
shown in the Attribute Manager for the selectedCube GraphNode
, are just dynamically allocated dummy nodes.These dummy nodes live parented to the
NimbusRef
owning them, in the case of 'normal' scene nodes that is the scene hook named 'scene nodes', in case of capsules it is the Object Manager object representing them:
Fig II.: The branches of theNodes Mesh
object from above. It holds twoBaseList2D
dummies, one for the graph container which is a node itself (the root) and one for the cube node. These are however much more volatile (BaseList2D
) nodes than a classic API scene element as they just wrap underlyingGraphNode
data and might be regenerated whenever Cinema 4D feels like it.What can I do?
The easiest way to deal with this is going to source of the data, as these
BaseList2D
are just smoke and mirrors. With BaseList2D::GetNimbusRef you can get the terribly named NimbusBaseInterface reference for aBaseList2D
. The term 'Nimbus' is just an echo of an internal code name and has otherwise no higher meaning. You can think of aNimbusBaseInterface
as the managing entity that ties an element in a classic API scene graph, aBaseList2D
, to a maxon API scene graph. So, aNimbusRef
ties a material nodes graph to aBaseMaterial
(that happens to be a node material), or as in this case, a scene nodes graph to an object in the Object Manager.NimbusBaseInterface::GetGraph
: Returns the Nodes API graph associated with this nimbus handler, i.e., the actual data.NimbusBaseInterface::BaseList2DToUuid and ::BaseList2DToUuid
: Allow you to identifyBaseList2D
wrapping nodes over reallocation boundaries, if they describe the "same" node.
As untested code:
BaseObject* const op; // Try to get the scene nodes nimbus handler for the object #op. const maxon::NimbusBaseRef handler = op->GetNimbusRef(maxon::neutron::NODESPACE()); if (!handler ) return false; // Get the graph that is wrapped by #op and #handler. const maxon::nodes::NodesGraphModelRef& graph = handler.GetGraph(); // Get an identifier which identifies #graph, I would suggest comparing capsules with this hash. const maxon::UniqueHash gid = graph.GetUniqueHashCode(); // I would avoid comparing graphs directly. You should also use ::Compare when you must compare the // graphs directly. const maxon::nodes::NodesGraphModelRef& other; if (graph.Compare(other) == maxon::COMPARERESULT::EQUAL) // Do something when #graph and #other are equal.
Please share a project zip when you require further assistance.
Cheers,
Ferdinand -
Thanks for the response.
I tried implementing the small example bit of code you gave into my own and I was unable to get it properly working. Heres the project file I'm working from that's just a trimmed down version of the sdk example (cinema4dsdk.zip).
Inside of the example.assets under modules I was able to successfully get it to compile but when I tried to do it inside of the cinema4dsdk module it would continuously give errors that I was missing various header files. When I followed the usual procedure to include the various header files requried I started getting errors inside of the header files themselves saying they were missing other files that they had included that I can't find on my computer.
This is the first time I'm encountering these kinds of errors so I'm not entirely sure if I'm missing something extremely simple.
And just to be clear with what I'm attempting to do is I want to be able to catch if a parameter dragged onto my tag is coming from the object that the tag is attached to. With an Ocube my code properly works, with a Neutron Cube my code will not tell me that the dragged parameter's object matches the tag's object.
John Terenece
-
Hello @JohnTerenece,
Thank you for the added information.
Find below my answer. I could not make the circumstance work that the dragged and the host node do not match but I did not spend too much time in dragging things left and right in the editor. Since these classic API nodes which wrap maxon API nodes are volatile, allocated on demand, a mismatch is not too suprising.
Cheers,
FerdinandNote that I modified the resources as well as
projectdefinition.txt
in your project. So copying over source files alone will not be enough. You will have to place this project in your solution and run the project tool on it (your project was missing the necessary framework dependencies to work with nodes in the first place).Result:
-
Thanks for the detailed response.
I was able to successfully compile and run the code you provided but I'm running into some weirdness when trying to drag different parameters onto the tag.
-
Hey @JohnTerenece,
Your question is quite ambiguous, let me unfold some things first:
- It looks like you have a mesh primitive capsule for a cube in your scene. On it, you have an
ExampleTag
. The capsule inlines theBaseList2D
representing theCube [Geometry]
node, just as it is inlining its two tags Phong and Example Tag. - You now drag a parameter from the capsule
BaseObject
, e.g., itsP.X
parameter, and are wondering why it behaves differently than theSegments.X
parameter from the inlinedBaseList2D
representation of theCube [Geometry]
node.
The answer to this is:
- A
GraphNode
and a(Nodes)GraphModelRef
are not the same thing, the latter is the graph while the former is a node in it. TheCube [Geometry]
is a node within a graph, not the graph itself. In the case of a geometry operator capsule this is hidden away from the user as you are not supposed to edit these capsules, but it still applies. - Not every
BaseList2D
representation of an entity inside a graph has aNimbusRef
. It is only theBaseList2D
which represents the graph itself, e.g., theBaseObject
in case of a capsule graph, which holds it. Which is also why I posted the screenshot from the Active Object plugin in my prior answer:
The representations of all entities in a graph are in a "Nodes" branching relation to the entity which holds theNimbusRef
for their graph. - You currently can associate a
BaseList2D
wrapper for a node in a graph with itsNodeGraphModelRef
(i.e., "graph") but you cannot associate it with itsGraphNode
, i.e., the actual node (in the public API).
Finde below my code example.
Cheers,
FerdinandResult:
I compare here a
Mesh Primitive Group
capsule andMesh Primitive
capsule which is what you were using to clarify the relation of things. In both cases the "Cube" is just a node which lives inside the capsule. It is only that theMesh Primitive
capsule inlines its geometry node because other than theMesh Primitive Group
it is not editable. - It looks like you have a mesh primitive capsule for a cube in your scene. On it, you have an
-
Thanks for the response, it's all working properly now.
John Terenece