Your browser does not seem to support JavaScript. As a result, your viewing experience will be diminished, and you have been placed in read-only mode.
Please download a browser that supports JavaScript, or enable it if it's disabled (i.e. NoScript).
Hi for everyone! I have an easy code which show the hidden layer but i don't understand how change it for do the same for:
Code
import c4d
def main():
doc.StartUndo() root = doc.GetLayerObjectRoot() LayersList = root.GetChildren() for layer in LayersList: doc.AddUndo(c4d.UNDOTYPE_CHANGE,layer) layer [c4d.ID_LAYER_VIEW] = 1 doc.EndUndo() c4d.EventAdd()
if name=='main': main()
Also, you are not looking at "only the children". The object you get from GetLayerObjectRoot() is a GeListHead, not a LayerObject, so you need to go from root either to the first layer in the list by GetDown(), or you get the full layer list on the top level(!) by GetChildren().
Each of these layers in the returned list can have children, though, since layers form a full tree structure. So if you want to visit all layers, you need to recurse into the child lists as well. E.g.:
import c4d def visitLayer(layer): if layer == None: return print (layer.GetName(), "Selected" if layer.GetBit(c4d.BIT_ACTIVE) else "Unselected") visitLayer(layer.GetDown()) visitLayer(layer.GetNext()) def main(): first = doc.GetLayerObjectRoot().GetDown() visitLayer(first) if __name__=='__main__': main()
Check for the active bit by GetBit(c4d.BIT_ACTIVE) to test whether a layer is selected. Layers are GeListNodes, so you can get from one layer object to the other with the usual functions GetNext(), GetDown() etc.
GetBit(c4d.BIT_ACTIVE)
GeListNode
GetNext()
GetDown()
Hello @roman,
thank you for reaching out to us. And thank you @Cairyn for providing an answer. A minor problem with the answer provided by @Cairyn is that it is recursive. We recommend walking node graphs iteratively and not recursively, because of the vastness of node graphs in Cinema 4D and danger of producing stack overflows when walking them recusively. In this case, the case of layers, it is unlikely that one will hit the recursion limit of Python (one thousand recursions by default on most systems¹) or produce a stack overflow in C++ (depends on many things).
Cheers, Ferdinand
¹ The recursion limit of Python is defined and set in sys via sys.get/setrecursionlimit. One can raise the limit of one thousand which is rather conservative, but if it is set to high, it will then fail to prevent what it is intended for: to prevent stack overflows and crashing the Python interpereter.
sys
sys.get/setrecursionlimit
@cairyn said in Layer Selection Python:
Also, you are not looking at "only the children". The object you get from GetLayerObjectRoot() is a GeListHead, not a LayerObject, so you need to go from root either to the first layer in the list by GetDown(), or you get the full layer list on the top level(!) by GetChildren(). Each of these layers in the returned list can have children, though, since layers form a full tree structure. So if you want to visit all layers, you need to recurse into the child lists as well. E.g.: import c4d def visitLayer(layer): if layer == None: return print (layer.GetName(), "Selected" if layer.GetBit(c4d.BIT_ACTIVE) else "Unselected") visitLayer(layer.GetDown()) visitLayer(layer.GetNext()) def main(): first = doc.GetLayerObjectRoot().GetDown() visitLayer(first) if __name__=='__main__': main()
Thank you a lot Cairyn!!!
@cairyn, i don't understand just one thing how should i change a code if i want to do it with selected objects not for all.
def visitLayer(layer): if layer == None: return print (layer.GetName()) doc.AddUndo(c4d.UNDOTYPE_CHANGE, layer) layer [c4d.ID_LAYER_VIEW] = 1 visitLayer(layer.GetDown()) visitLayer(layer.GetNext())
def main(): doc.StartUndo() first = doc.GetLayerObjectRoot().GetDown() visitLayer (first)
doc.EndUndo() c4d.EventAdd()
@roman If you mean handle only the selected layers then you just need to insert a check for the active bit:
print (layer.GetName()) if layer.GetBit(c4d.BIT_ACTIVE) : doc.AddUndo(c4d.UNDOTYPE_CHANGE, layer) layer [c4d.ID_LAYER_VIEW] = 1
If you really mean selected objects, I'm not sure what you mean as your code doesn't refer to any objects?
@cairyn For example, we have 20 layers and i need to change visibility just for 2 layers in this list. That's what i meant when i talked about selected layers.
I tried to use same code but it showed to me first layer in list....while i want to work with active layers which i have selected.
And i wanted to ask which command delete layer?
Sorry for stupid questions, but SDK a little bit unobvious.
@roman Just insert the code from my last post into the overall script.
Here, I did it for you this time:
import c4d def visitLayer(layer): while layer != None: if layer.GetBit(c4d.BIT_ACTIVE) : doc.AddUndo(c4d.UNDOTYPE_CHANGE, layer) layer [c4d.ID_LAYER_VIEW] = not layer [c4d.ID_LAYER_VIEW] visitLayer(layer.GetDown()) layer = layer.GetNext() def main(): doc.StartUndo() first = doc.GetLayerObjectRoot().GetDown() visitLayer(first) doc.EndUndo() c4d.EventAdd() if __name__=='__main__': main()
This script toggles the editor visibility of the currently selected layers. Execute it twice to get the original visibility state back.
Note:
BIT_ACTIVE
(If you are not happy about the structure of Maxon's API documentation, I do have many beginner-oriented lessons and examples in my course https://www.patreon.com/cairyn -- although Patreon is admittedly not ideal for searching; I really need to make this into a proper book.)
As for deleting a layer, a LayerObject is a BaseList2D which is a GeListNode, so you can use the Remove method. Like here:
LayerObject
BaseList2D
Remove
import c4d def visitLayer(layer): while layer != None: nextLayer = layer.GetNext() if layer.GetBit(c4d.BIT_ACTIVE) : doc.AddUndo(c4d.UNDOTYPE_DELETE, layer) layer.Remove() else: visitLayer(layer.GetDown()) layer = nextLayer def main(): doc.StartUndo() first = doc.GetLayerObjectRoot().GetDown() visitLayer(first) doc.EndUndo() c4d.EventAdd() if __name__=='__main__': main()
The infrastructure of C4D will remove the objects from that layer and throw the layer away once there are no more references.
Note: Since the layer tree is a linked structure, you will need to pay extra attention to the tree walking, be it recursion or iteration, when you remove layers out of the structure. That's why the visitLayer function looks a bit different here.
@cairyn Thank you again. I will check your patreon