Tag vs Generator vs Script vs Node
-
On 04/07/2018 at 08:08, xxxxxxxx wrote:
I know this will come off as a newbie question - which it is.
However I'd love to get a short & clear summary (or to be pointed toward the resource, I've searched and couldn't find definite clear answers) of the important differences and uses of the various ways to use python in C4D (as per subject; tag, generator, user script & xpresso node).
I've stumbled across a great reply on CGtalk about python tags:
"It is a very common misunderstanding in the use of Python tags: many people think they can use them for just anything because Python is a general language. But there is one handicap: execution timeframe.Tags are evaluated every time the object tree itself is evaluated. Which is very, very often (even during seemingly simple operations, like moving the view). Why is that done? Because potentially any change in the scene may have an effect on something and require a change. If your Python tag for example determines an object's color by the position of the camera... it needs to be executed at any movement of the camera"
This is great, concise and clear, and exactly what I'm looking for.
I would love to get an equivalent overview of the other ones - specifically as it relates to when NOT to use them.My application requires a separate thread running at short intervals (10-20ms) to poll a serial port constantly, storing variables and affecting the rotations of several objects in the scene (based on the serial reception), as well as a user data / gui interface. So far it's working in a tag, but upon reading the above (execution timeframe) I'm thinking I should perhaps move it to a generator? Or a standalone script? But then scripts run only once - wouldn't work for my gui needs and constant polling...
-
On 04/07/2018 at 22:57, xxxxxxxx wrote:
And to add to the confusion:
In Cinema 4D there exists a Python tag, but you can also write a TagPlugin in Python.
I assume the above mention of "tag" as being "Python tag" -
On 05/07/2018 at 01:40, xxxxxxxx wrote:
Hello,
applications like Cinema 4D can be extended by writing and adding plugins. The Python API allows you to create plugins that add functionality to the program.
Such a Python plugin typically contains the Python source code that defines the behaviour. A plugin is written by implementing and registering a custom class based on a plugin hook. E.g. you can create new objects by implementing a plugin based on the ObjectData class. The same is true for tags (TagData), shaders (ShaderData), tools (ToolData), etc. You find a list of plugin hooks on c4d.plugins. See also Plugin Structure. You find example plugins on GitHub.
Short: Plugins allow you to do everything (that is possible within Cinema 4D).
But there are also some elements in Cinema 4D that allow you to insert Python code to change the behaviour of that element.
The "Python Tag" is a tag. It allows you to insert custom Python code to define its behaviour as a tag. Tags are not supposed to do everything. The code of a tag is executed within the execution pipeline. That means that a tag should only modify the host object e.g. like the "Look-At-Camera" tag. Tags work as expressions. The "Python Tag" allows to prototype and build a simple tag. For a more complete custom tag you would have to write a tag plugin based on TagData.
Similarly, the "Python Generator" object is a generator. That means it creates virtual objects (it is no modifier). The custom Python code allows you to define what objects are created. That is what a generator does, it is not supposed to do anything else. The "Python Generator" object only gives limited access to the whole "generator" feature set. For a complete custom generator you have to write a ObjectData plugin.
So "Python Tag" and "Python Generator" are specific Python tools to (rapidly) developed specific custom items. But they do not allow to do "everything". The same is true e.g. for the Xpresso "Python Operator" that lets you define the behaviour of that node. But again, this Xpresso node should only do what Xpresso nodes are supposed to do.
There is also the "Script Manager" that allows you to run Python scripts. And a script is exactly that: some code that is executed once. And after that execution all local resources of that script are freed.
So if you want to have a custom thread running in parallel, you cannot use "Python Tag" or "Python Generator" since they are not build for that. Also you can't use a script since that script is only execute once.
This means you have to write a plugin that implements and starts that thread. Custom threads can be based on C4DThread. A custom GUI is typically created by implementing a CommandData plugin that hosts and opens a GeDialog based window. You find an example in Py-MemoryViewer.pyp.
best wishes,
Sebastian -
On 05/07/2018 at 09:42, xxxxxxxx wrote:
Originally posted by xxxxxxxx
So if you want to have a custom thread running in parallel, you cannot use "Python Tag" or "Python Generator" since they are not build for that. Also you can't use a script since that script is only execute once.
Thanks for the in-depth explanation, I appreciate you taking the time - although I was afraid the answer would inevitably end up being "you gotta do it as a plugin"...
We're working on it, and ultimately this is where we're headed (plugin route). But in the meantime, and for fast prototyping & development, we're using the Python Tag as a starting point. I should mention that it is converted to an actual tag plugin through the prototype converter - not sure if it changes anything in terms of what's doable or what it shouldn't be used for.
The point is - it works. We're using a C4DThread class to run a side thread polling the serial port without blocking, and the tag essentially just keeps track of all configuration variables and register the changes on the object (if axes are rotated, it sends out the values over serial, etc...). I wouldn't think of "releasing" it publicly as is, but as long as it works internally, and allows us to keep developing, it works for us.
So, I guess that's a bit what I was asking: beside the very valid "it's not what it's for" logical reason, are there any other important considerations we should be aware of, in terms of tag/generator limitations or potential issues? So far the tag (converted through the prototype converter) is great since it allows to capture Message events on its user data, run a thread, update variables based on object's rotations, etc...
-
On 05/07/2018 at 20:28, xxxxxxxx wrote:
Just to clarify - I really don't mean to come off the wrong way!_<_o:_<_o:p_>_o:p>
I'm not saying "well it works for me so whatever", what I'm trying to gather here is more along the lines of "although this may work, you should be careful about this and that, as your implementation may burn through cycles or whatnot...".
I'm not a programmer, I'm a 3D generalist and a cinematographer. I've got around to learn just enough code in various languages (C, python, 4dgl, etc) to start messing with microcontrollers so I could elevate my craft and realize my vision. What started as a side project and a hobby grew into an R&D company in robotics and I'm at a point in my development where it makes sense - internally for now - to have a functional C4D plugin that communicate with our prototype.
I realize I may be asking for basic support that goes beyond the purpose of this forum, and that a "go do your homework" answer may be called for. -
On 06/07/2018 at 02:35, xxxxxxxx wrote:
Hello,
if I understand you correctly, you now have a TagData plugin, right? And this tag somehow makes and uses a custom thread?
When it comes to threads, it is really important to know where and when this thread is created, who owns that thread and when it is deleted.
A tag is part of the scene. So at any time you can add this tag, delete it or copy it to have two tags. What would that do with this thread?
Also, a tag is part of the scene. That means if you edit the parameters of the tag, the undo system will create a copy of that tag to store its previous state. And this can have all kinds of consequences for internal data of that tag.
The typical way of detecting changes to a the scene is to implement a MessageData plugin that catches the message EVMSG_CHANGE. Then you can check the scene of any object of interest has changed. Any parallel thread would exist independent of any specific object.
best wishes,
Sebastian