Where is information on the Python Tag?

On 10/02/2018 at 04:50, xxxxxxxx wrote:

I have been trying to find information specific about the Python tag, without success.
Is there dedicated documentation about it?


On 12/02/2018 at 05:26, xxxxxxxx wrote:

Hi Thanassis,

no, there's actually no special documentation for the Python Tag. What information are you looking for?

In the end the Python Tag is a normal TagData plugin, where the Execute() function is exposed to the user and can be implemented via Python.

So, the usual rules for NodeData plugins and threaded functions apply for the tag as well.
- do NOT use GetActiveDocument() (but instead get the document from the tag or host object via GetDocument())
- do NOT modify the scene (inserting, deleting objects, changing the hierarchy,...), instead only influence the host objects parameters
- no need for EventAdd(), opposed to scripts in Script Manager or CommandData plugins

Like in other places in Cinema 4D, there are a few global variables defined for convenience:
- doc - The document the tag belongs to or is inserted in
- op - Referring to the Python tag itself, use GetObject() to get the host object
- flags - The execution flags, see TagData.Execute() parameter description
- priority - The execution priority, see TagData.Execute() parameter description
- bt - a BaseThread - private, not in use, see TagData.Execute() parameter description
- tp - the Thinking Particles master system

On 12/02/2018 at 06:20, xxxxxxxx wrote:

Thanks Andreas,
I still have a few questions though.

1. Adding objects is allowed, as I have seen it working. Is it advised against, or it shouldn't work in the first place?
2. Does each Python node have a Unique identifier, equivalent to the GUID() for objects?

My overall query is because I'm trying to make a Python node that outputs the Object or Hierarchy mesh Cache of an input so I can feed it into various XPRESSO nodes that by default don't accept anything else.
e.g. Matterwaves e.t.c.


On 12/02/2018 at 08:26, xxxxxxxx wrote:

Since when are we talking about an Xpresso Python Scripting node?

And no, a Python tag is not supposed to insert objects into the scene. It is not only not recommended, it is forbidden. The outcome of such wrong behavior is pretty much undetermined, there may be scenes, where it seems to work, in others it crashes immediately and in the rest it may have strange side effects on other parts of the scene. It is forbidden, full stop.

The correct or recommended way for creating an object is to assign the new object to an output of a Python Scripting node and then connect it an object node.

Xpresso (or rather GraphView) nodes do not have a GUID, nor am I aware of a unique ID at all. But I'll check with the team tomorrow and will get back to you, if somebody has an idea.

On 12/02/2018 at 10:39, xxxxxxxx wrote:

Sorry Andreas, that was another question I had in regards to the Python node... apologies for the confusion!

Thanks for the answer, and I'd be very interested in the ID.


On 13/02/2018 at 05:43, xxxxxxxx wrote:

Hi Thanassis,

no need to apologize, by now I'm pretty used to being tricked into your pitfalls... :wink:

Regarding IDs it's a bit unfortunate. GvNode does not support GUIDs and GeMarker (link to C++ docs) is not available in Python. I guess, the only option is to do it manually with AddUniqueID() and FindUniqueID().
May I ask, what you are planning to do with this such ID?

On 13/02/2018 at 05:58, xxxxxxxx wrote:

Originally posted by xxxxxxxx

May I ask, what you are planning to do with this such ID?

As I mentioned earlier, I am trying to create an XPRESSO node that allows any object to be used as an input, as if it was a mesh object (for example Matterwaves).
A little birdie, wrote me a Python Node that creates a hidden mesh object from any input. It works great if are using only one of these nodes is in the Graph, but once you use another one, you get conflicting meshes.
I want to be able to name the hidden mesh with a unique name for each of the python nodes.

Fast forward yesterday, and I realized I can do that using the input object's GUID, since it's NOT the node's uniqueness I'm really interested in, but the input object's.

I'll send you the scene privately, and when it works as expected, I'll release it to the Public for free, as usual :-)

On 13/02/2018 at 06:10, xxxxxxxx wrote:

Before I send anything, I would like to try by myself something first.
I was trying to use SearchObject() to find and delete an object from my scene, but I was getting an error.
Can I use the syntax: doc.SearchObject(somename).Remove() within a Python Node, or do I need to do something else first?


On 13/02/2018 at 06:13, xxxxxxxx wrote:

As mentioned earlier in this thread, Python node shouldn't modify the scene directly, either. It should rather work into an object node.

On 13/02/2018 at 06:32, xxxxxxxx wrote:

ok, Im confused.
I thought you said "Python Tag" doesn't modify the scene.
Not Python XPRESSO node.

Anyway, I managed to make this work, so it seems...
Here's the file link:
https://www.dropbox.com/s/tmhw3x0rjh55onl/Object Cache 99A Troubleshooting 03A.c4d?dl=0

On 13/02/2018 at 06:48, xxxxxxxx wrote:

The correct or recommended way for creating an object is to assign the new object to an output of a Python Scripting node and then connect it an object node.

On 13/02/2018 at 06:54, xxxxxxxx wrote:

Originally posted by xxxxxxxx

The correct or recommended way for creating an object is to assign the new object to an output of a Python Scripting node and then connect it an object node.

But this defeats the "simple" nature of what I'm aiming to do.
What issues could I expect from the current implementation?


p.s. here's a version with slightly different code.
The "doc.SearchObject(uniqueName)" is now assigned to a variable.

http://https://www.dropbox.com/s/fha59mg21p9m1ru/Object Cache 99A Troubleshooting 05A.c4d?dl=0

On 15/02/2018 at 02:48, xxxxxxxx wrote:


sorry, to let you wait.
And I'm also sorry, this is not as easy, as you wished. Since when are you scared by challenges?
Xpresso is being executed/evaluated during scene execution. Nothing/nobody is supposed to change the scene during execution.

The resulting issues range from priority or updating issues to crashes. There's no "works always" or "fails exactly with this issue" here. It may even work for quite some time without issues, but then with the correct scene, it suddenly destroys the user's work. So, no, we can not recommend it.

How about implementing a command, which creates the needed nodes and objects in one go? Basically creating a hidden object (or just on a special layer?), the Python node (with code and object output port) and an object node connected to it? A bit more work and yes, not the "perfect" workflow you had in mind, but instead safe.

On 15/02/2018 at 05:15, xxxxxxxx wrote:

I'm always scared of challenges. I just hide it well :-)

I was aware that it's not allowed to change the scene during execution, but I thought it was something you "Couldn't" do, not "Shouldn't" do. So, when I saw this node working, I was pleasantly surprised. :-)

The funny thing is that a "poor man's" version of this node is possible with very simple code, but only works with simple generators and primitives:

import c4d
def main() :
global MeshObject
MeshObject = Object.GetCache()

So my questions are:
1. Is this allowed (the poor man's code)?
2. Can the previous node (the complex one) be written so that the data is not an object, but a Cache that lives in memory just like the small version.

Thanks as always Andreas!

On 15/02/2018 at 06:31, xxxxxxxx wrote:

Actually in your "poor man's" version, you are returning an object (or are delivering an object to the output). A cache is nothing else but a PolygonObject. As long as you can work with it without inserting it into the scene, you are fine.

On 15/02/2018 at 07:40, xxxxxxxx wrote:

So, as a dumbed-down rule of thumb, as long as doc.InsertObject(obj) is NOT in the code, it should be safe to proceed?
Are there any other ways to insert objects I should try to avoid?


On 15/02/2018 at 09:06, xxxxxxxx wrote:

Well, all types of inserting something into the scene, like InsertMaterial(), InsertTag(), ...
This includes also all kinds of GeListNode.InsertX() functions (e.g. InsertAfter()) on entities that are already part of the scene.
And of course the corresponding Remove() functions.
Basically everything that alters the scene tree.

On 15/02/2018 at 09:44, xxxxxxxx wrote:

Nice. "insert" and "delete" are the main things to try to avoid, but passing the cache of an object to a node input doesn't mean the scene is altered. Is that a correct assumption?
Also, can I assume that as long as an Event Add doesn't add or remove anything in my Object manager, I'm generally moving in the right direction?

On 16/02/2018 at 04:32, xxxxxxxx wrote:

Yes, the assumption is correct. You'd feed the object into an Object node, in order to introduce it to the scene.

EventAdd() doesn't change anything itself. It's an event being posted, that informs other parts of Cinema 4D, something (!) has changed. The other parts will then check, if anything relevant for them has changed and act accordingly. But it's not like, an object is only inserted into the scene, after you called EventAdd(). It is actually inserted on the "Insert()" call, it just doesn't show up to the user, because a UI update is still missing in the Object Manager (which is then triggered later on by EventAdd().

By the way, EventAdd() is another function that shouldn't be called in NodeData derived plugins, especially not in execution or drawing pipeline.

On 16/02/2018 at 04:41, xxxxxxxx wrote:

Thanks Andreas.