Hello @jenandesign,
thank you for your follow-up questions. I must unfortunately point out that we do not condone diary-style topics, where developers document various stages of their problem solving. The forum guidelines state:
The initial question of a topic author must be consolidated into a singular posting. Diary style topics with multiple postings are not allowed. See Structure of a Question for more information on how to make a good initial posting. When you want to add information at a later point, please use the edit function.
For an ongoing topic, i.e., information exchange after the initial question, we usually cut everyone some slack, but there are also limits to that. I have consolidated your postings here for you. Please make sure to avoid posting multiple messages in favor of editing your last message. Irrelevant information should also be removed, e.g., code that is not relevant anymore.
About your Question
Please share details of what you are doing. Because we are very accustomed to our APIs, we can of course often guess things, but that tends to be a lot of extra work for us, as we then for example have to write lengthy paragraphs such as this to contextualize our answers.
- What do you want to do?
- Where are you stuck, what is your question?
- Provide a scene file and/or executable code.
When I read here between the lines, I understand that you want to:
- Add spline field layers for all direct spline children of some root object.
- You attempt to do that from inside a Python Programming tag.
Inside the main
function of a Python Programming tag, you are bound to the threading restrictions of Cinema 4D. Adding or removing scene elements and invoking events it not allowed among other things. Your code violates both restrictions.
There are ways to circumvent that problem, you for example can offload work to NodeData.Message
which most of the time runs on the main thread (i.e., the message
function inside a Python Programming tag). But that does not alleviate the fundamental logic problem your code has. TagData.Execute
, the main
function, can be called multiple times per scene execution, and a tag is executed at least once per scene execution. Every time the user does something in a document which changes its "state", the scene will be executed and so your tag. So, even when ignoring all the other problems, your code would constantly overwrite the content of the deformer field list, invalidating all manual changes made by a user.
Adding things to a scene most of the time either constitutes a command (CommandData
or a Script Manager script) or a tool (ToolData
, ToolDescriptionData
). There are more fringe plugin types which can be used as for example MessageData
, but they are mostly irrelevant.
Anything that itself is a scene element, e.g., an object, tag, material, shader, should not modify the state of the scene it is part of. There are ways to circumvent these problems, but this is a case of "if you have to ask, you should not do it". In your case this probably means that you should rewrite your script to work as command/Script Manager script.
Cheers,
Ferdinand
Result:

Code:
"""Demonstrates how to add spline field layers to a field list.
THIS SCRIPT VIOLATES THE THREADING RESTRICTIONS OF CINEMA 4D. IT WILL CAUSE CRASHES AND LOSS OF
DATA.
"""
import c4d
doc: c4d.documents.BaseDocument
op: c4d.BaseTag
def main() -> None:
"""Called by Cinema 4D to execute the tag.
"""
# Attempt to access our input data.
try:
deformer: c4d.BaseList2D = op[c4d.ID_USERDATA, 1]
null: c4d.BaseList2D = op[c4d.ID_USERDATA, 2]
fields: c4d.FieldList = deformer[c4d.FIELDS]
if None in (deformer, null):
return
except:
return
# At least throttle the output by not constantly overwriting an already populated list.
if fields.GetCount() > 0:
return
# Add the layers and write the data back.
root: c4d.GeListHead = fields.GetLayersRoot()
for spline in null.GetChildren():
layer: c4d.modules.mograph.FieldLayer = c4d.modules.mograph.FieldLayer(c4d.FLspline)
layer.SetLinkedObject(spline)
# This is the illegal operation, we insert an element into the scene graph while being
# outside of the main thread. Sooner or later this will lead to crashes.
layer.InsertUnderLast(root)
deformer[c4d.FIELDS] = fields