Hi @ezeuz, @ferdinand,
Back in a days, it was run with python file as a second argument, like so:
c4dpy.exe dummy.py -g_encryptPypFile py-commanddata_dialog_r13.pyp
where dummy.py
just a blank file.
Hi @ezeuz, @ferdinand,
Back in a days, it was run with python file as a second argument, like so:
c4dpy.exe dummy.py -g_encryptPypFile py-commanddata_dialog_r13.pyp
where dummy.py
just a blank file.
Thanks @ferdinand ,
Appreciate your answer.
Since cloning might dramatically reduce performance — I'll pay attention to this information, and will try to find the issue.
Currently the thing is — my plugin worked for years (starting R25 if I remember correctly), and this part of the code worked as expected all this time without modifications.
It just iterates through fieldlist layers and calculate dirty value in order to redraw generator within GetVirtualObject() scope.
After updating to 2024.4 I get reported — my plugin stoped to work.
It was hard to debug the issue, since I printed layer or result of IsAlive() — issue didn't replicated. So the quickest resolution was to yield cloned layer.
It's not easy for me to share sample which reproduces the issue, I have complex structure of code. Maybe I'll spend sometime later if I'll not be able to get rid of the cloning.
But since I spend several hours to resolve that issue, I wanted to leave a comment for those who just uses your sample in their code, and it stop to work.
@ferdinand said in Field Refusing Object:
def getFieldLayers(node): """ """ visited = [] end = node.GetUp() if isinstance(node, c4d.GeListNode) else None while node: # If the current node is a newly encountered one. if node not in visited: visited.append(node) # When it is a field layer, yield it and deal with group # fields ... if isinstance(node, c4d.modules.mograph.FieldLayer): yield node linkedNode = node.GetLinkedObject(doc) if linkedNode and linkedNode.CheckType(c4d.Fgroup): # Get the field list and iterate over it. fieldList = linkedNode[c4d.FIELDGROUP_FIELDS] root = fieldList.GetLayersRoot() for nestedNode in getFieldLayers(root): yield nestedNode # There are more special cases in the field list hierarchy, # e.g., folders, which also have to be treated specifically. # I did not do that here. # Normal depth-first traversal of a node tree if node.GetDown() and node.GetDown() not in visited: node = node.GetDown() elif node.GetNext(): node = node.GetNext() else: node = node.GetUp() if node == end: return
If anyone else relies on this code (many thanks @ferdinand for this great example)
for some reason yield node
in 2024.4 emits exception:
ReferenceError: the object 'c4d.modules.mograph.FieldLayer' is not alive
Currently I went with yield node.GetClone()
— issue is gone and it works as expected.
But I'm not sure if it's proper way.
@Paul-Everett not really
In fact, if it's not convex-hull geometry, some edge might be fully or partially covered by some polygon(s) laying in front if this edge.
@SweepingMotion nice finding
Yes, there are quite a few issues in the sample codes everywhere.
To fix the Python Field, I think it's required to change
outputs._value = [
c4d.utils.RangeMap((~mgEffector * mgInput * p).GetLength(), 100., 0., 0., 1., True)
for p in inputs._position
]
to
outValues = outputs._value
for index, p in enumerate(inputs._position):
outValues[index] = c4d.utils.RangeMap((~mgEffector * mgInput * p).GetLength(), 100., 0., 0., 1., True)
outputs._value = outValues
Hi @SweepingMotion ,
Would be helpful if you'll provide sample project, or at least code for the python field.
Hi @merkvilson ,
try to add check for main thread scope:
def Message(self, node, type, data):
if c4d.threading.GeIsMainThread() and type == c4d.MSG_MENUPREPARE:
node.Remove()
@d_schmidt
If this vertex data is going to be utilized by shaders, or deformers, or fields — you don't need to store any data there, your tag will be just a reference, so you'll need to fined derived tag on the cache.
If you want to grab data exactly from the generator's tag, then this approach doesn't suit you.
Hi @d_schmidt, few releases ago Maxon changed the way how vertex maps are applies to the generators.
I think nowadays generators tag data is not taken in respect.
Cinema automatically propagates generators tags onto cache geometry, and evaluates fields from origin tag to each geometry.
If there are no fields — your maps will have values of zero on your cache geo.
Maybe you'll need to utilize AddToExecution()
method to build geometry, return it as result of GetVirtualObjects()
, then Cinema will propagates origin tags onto cache, and then you'll do your tags logic at priority of "Generators" 0+.
Hi Maxon team,
Just want to bump up the issue, which is still here under the Cinema4D 2024.2
Hi,
Is it possible to re-create uniform position over spline for clones when both Offset
and Offset Variation
are defined:
Currently trying to recreate with Python random.random(),
but either I made expression, either python's random is totally different to Cinema's random
@gaschka
I can think like hundreds of operations are nothing for the Python
When it counts as thousands — you'll notice that.
Optimizations requires some knowledge of Cinema tech side, to listen events, understand execution context, and so on.
Because there might be multiple scenarios, which you're not expecting in your "optimal" logic.
Main issue is the user — who will delete your key tags/objects, move objects within hierarchy, wrap objects into a null, and so on
Hi,
I'm developing Python Effector which will have FieldList parameter (separate of the default one).
Since Cinema 2024 introduced some optimizations, Python Effector is not being automatically executed, once any of Field objects related to custom FieldsList object are updated in the document.
I suppose there's no CheckDirty() method for Python Effector to check FieldList dirtyness.
What would be the approach to force Effector update?
Rough sample: py_effector_with_custom_field.c4d
Just drag Spherical Field left to right with the mouse device.
Here left Matrix with Python Effector where Field is attached to custom FieldList — doesn't updating,
but right Matrix with Python Effector where Field is attached to default FieldList — does
Hi @gaschka ,
I assume that would be percentile value, so you can also add unit, like
squash_and_stretch_container[c4d.DESC_UNIT] = c4d.DESC_UNIT_PERCENT
Hi @gaschka
Nothing really confusing in your code, python is not very strict...
I can only suggest to move out constants of the function scope,
and there are plenty space to add verifications...
And c4d.EventAdd()
might be executed just once, in the end of the parent function where you creating objects and attaching tags
Also don't forget to use document's StartUndo()
AddUndo()
EndUndo()
methods when creating your objects.
SOME_PYTHON_TAG_CODE = """
import c4d
def main():
# my code for the Python tag
# Execution
if __name__ == '__main__':
main()
"""
def add_python_tag(obj):
if not isinstance(obj, c4d.BaseObject):
return None
python_tag = obj.MakeTag(c4d.Tpython)
python_tag[c4d.TPYTHON_CODE] = SOME_PYTHON_TAG_CODE
return python_tag
Hi @del ,
Those are invisible tags.
You don't need to work with them directly, and also you shouldn't delete these tags.
Technically all points and polygons information contained in these tags.
SplineObject has their own set of invisible tags.
Hi @love_me_render ,
That's true.
Python is good to operate with several objects PSRs, or to apply built-in commands onto geometry.
But since it's not only slower comparable to c++, but also single-processing — it's not worth to deal with Python for intense computations.
If you pursue easier delivery, install and support — check if Scene Nodes suit you.
Those have great performance to build geometries.
That's not a coding, however your logic skills will be required to build nodes setups.
Hi @m_adam,
Unfortunately I can't update to 2024.2 through Maxon App for some specific reason.
At downloads page there's 2024.1 is only available https://www.maxon.net/en/downloads/cinema-4d-2024-downloads
Hi @m_adam ,
That's sad... Thanks, anyway.