How to apply new fixed FieldList securely
-
Re: Fieldlist HasContent() GetCount() bug workaround
Hello guys!
I think i've found the solution how to fix FieldsLists with "ghost" layers (without linked FieldObjects, deleted in OM). I want to apply it to fix my ObjectPlugin FieldLists but i do not know how to make it securely. Maybe after each object deletion in Cinema 4D scene? How to implement this? There better solution?
Here is a code that works for me:def get_field_layers(op): """ Returns all field layers that are referenced in a field list. Source: https://developers.maxon.net/forum/topic/11809/iterating-trough-field-list/2?_=1678357010902 """ def flatten_tree(node): """ Listifies a GeListNode tree. """ r = [] while node: r.append(node) for child in node.GetChildren(): r += flatten_tree(child) node = node.GetNext() return r # get the GeListHead for the FieldList root = op.GetLayersRoot() if root is None: return [] # Get the first node under the GeListHead first = root.GetFirst() if first is None: return [] # traverse the graph return flatten_tree(first) def CleanUpFieldListDeadLayers(doc, fieldlist): for f in get_field_layers(fieldlist): if f.CheckType(c4d.FLfield) and not f.GetLinkedObject(doc): f.Remove() return fieldlist def main(): fixed_fieldlist = CleanUpFieldListDeadLayers(doc,op[c4d.MYPLUGIN_FIELDLIST]) op[c4d.MYPLUGIN_FIELDLIST] = fixed_fieldlist if __name__ == '__main__': main()
-
Hello @mikeudin,
Thank you for reaching out to us. Yes, what you are doing is technically correct. But I personally would not remove these "ghost" layers as you have put it. I would have to read a lot of our code base to give you here a definitive answer on "how and when it is safe to delete them".
Since Cinema 4D leaves back these
Flfield
ghost layers itself when the user deletes an associatedOfield
object but stops rendering them in the field list GUI, I would say their existence is intentional. Whom relies when on their existence is hard to answer as lined out above. You are probably safe to delete them when you are on the main thread, but many things in MoGraph have been implemented in a very hacky manner, so you might run into problems anyway.I personally would avoid deleting these layers when it is not an absolute necessity to do so.
Cheers,
Ferdinand -
@ferdinand Thank for your response!
I finally decided to simple check fieldlist without editing it. I hope this is legal.def CheckFieldListHasContent(doc, fieldlist): if not fieldlist.HasContent(): return False for f in get_field_layers(fieldlist): if f.CheckType(c4d.FLfield) and not f.GetLinkedObject(doc): f.Remove() return fieldlist.HasContent()
-
Hey @mikeudin,
I hope this is legal.
Well, first of all, there is no such thing as an illegal action in our APIs. Even for cases such as the threading restrictions of Cinema 4D where we use strong terminology such as 'forbidden functions', things are just a suggestion in the end. You can violate each and every rule on that page and get away with it when you know what you are doing. We just assume that the average well-informed user will not be able to do so and therefore give out this absolute rule.
In this case the situation is more complicated. MoGraph has been implemented in a very non-conformative manner, it itself does things which are quite unusual for the classic API and breaks with some of the paradigms of the classic API to achieve what it does. That is why I did indicate that I would tread with caution here and that I would only modify MoGraph data when I must. I would not remove hidden field layers for purely 'cosmetic' reasons.
So, in short. Nothing what you do there is illegal. But you are walking on slightly shaky ground. My well-meaning advice would be: Avoid doing that if you can afford to. Otherwise, go ahead and do it, but there is no super-safe route here due to the nature of MoGraph.
Cheers,
Ferdinand -
Hello @mikeudin ,
without further questions or postings, we will consider this topic as solved by Friday, the 11th of august 2023 and flag it accordingly.
Thank you for your understanding,
Maxon SDK Group