Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    How to Solo a Layer

    Cinema 4D SDK
    3
    3
    723
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • dskeithD
      dskeith
      last edited by dskeith

      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 with rawdata=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 use doc.ChangeNBit(c4d.NBIT_SOLO_LAYER, c4d.NBITCONTROL_SET).

      ...I think.

      1 Reply Last reply Reply Quote 0
      • P
        PluginStudent
        last edited by

        Did you look into the C++ docs on this issue? Because there you find a Layer Manual.

        1 Reply Last reply Reply Quote 0
        • r_giganteR
          r_gigante
          last edited by r_gigante

          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

          1 Reply Last reply Reply Quote 0
          • First post
            Last post