How to Solo a Layer
-
Hi,
I just spent a bit of time debugging a couple issues when trying to Solo a Layer in the Layer Manager, and figured I would post my findings to save someone else some trouble:
Q: How do you solo a layer?
layer_root = doc.GetLayerObjectRoot() if not layer_root: return # Get the first layer in the scene layer = layer_root.GetDown() if not layer: return # Be sure to use the `rawdata` flag so that you get the stored layer state, not the "effective" layer state layer_data = layer.GetLayerData(doc, rawdata=True) start_solo_state = layer_data["solo"] solo_state = True layer_data["solo"] = True # SetLayerData needs a complete LayerData dict, it doesn't work with something like `{"solo": True}` # doing that will force all other layer state flags to be False layer.SetLayerData(doc, layer_data) # This isn't documented near SetLayerData, but you must call this method or C4D won't know to update the # solo state of layers in the scene. set_or_clear = doc.ChangeNBit(c4d.NBIT_SOLO_LAYER, c4d.NBITCONTROL_SET) # Let C4D know something has changed to trigger a redraw c4d.EventAdd()
Documentation Request:
Please update the docs for SetLayerData to include an example like the above, and make a note that if you plan to SetLayerData you should call GetLayerData withrawdata=True
.Thanks,
Donovan
-- Edit 2020/03/20 --
Actually this isn't working well in all circumstances. If all layers are unsoloed I'm not getting the expected refresh.
Okay, I think I figured out the issue (but haven't updated the logic above to account for it):
If you turn off solo on all layers, you need to use
doc.ChangeNBit(c4d.NBIT_SOLO_LAYER, c4d.NBITCONTROL_CLEAR)
, but if even one layer has the solo flag on, you need to usedoc.ChangeNBit(c4d.NBIT_SOLO_LAYER, c4d.NBITCONTROL_SET)
....I think.
-
Did you look into the C++ docs on this issue? Because there you find a Layer Manual.
-
Hi @dskeith thanks for reaching out us.
As pointed out by @PluginStudent, the NBIT_SOLO_LAYER behavior is explained in the Layer Manuel although it make sense to add a note to the Python API as well.
With regard to a complete example, I've partially reworked your code to make sure that by executing the script multiple times you can run across all the solo configurations that the scene can handle.
import c4d # Main function def main(): layer_root = doc.GetLayerObjectRoot() if not layer_root: return # Get the first layer in the scene layer = layer_root.GetDown() if not layer: return soloSet = False while layer is not None: # Set `rawdata` to True flag so to get the original layer values without any additional global changes layer_data = layer.GetLayerData(doc, rawdata=True) # check the current layer solo state: if layer_data["solo"] == False: # if not "solo" then set to True layer_data["solo"] = True # update the layer layer.SetLayerData(doc, layer_data) # update the flag soloSet = True break # deactivate if layer solo was True layer_data["solo"] = False layer.SetLayerData(doc, layer_data) # go to next layer layer = layer.GetNext() # if one (or more) solo was set the set NBIT_SOLO_LAYER otherwise clear if soloSet == True: doc.ChangeNBit(c4d.NBIT_SOLO_LAYER, c4d.NBITCONTROL_SET) else: doc.ChangeNBit(c4d.NBIT_SOLO_LAYER, c4d.NBITCONTROL_CLEAR) # Add an event c4d.EventAdd() # Execute main() if __name__=='__main__': main()
Cheers