Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python 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

    A SetBit problem aka cann't select node.

    Cinema 4D SDK
    python windows
    2
    5
    549
    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.
    • DunhouD
      Dunhou
      last edited by

      Hi !

      I am try to set my scatter rig , the basic rule is :

      • node selected : set the node to the Scatter Object , try find selection tag and set to the "Scater Aera"
      • tag selected : set the node which tag on to the Scatter Object , tag to the "Scater Aera"

      All they worked , but in the context " only tag selected " , the the scatter object doesn't active in object manager , I cann't find how this heppend .

      the scatter shoud be :
      aea081a5-458d-404b-af1e-a142f48905d4-1.gif
      the " tag " context , it returns like this , the scatter is set right and active is object manager , but it doesn't active in attribute manager .
      09efad69-5c37-429b-bb46-8ba1fe70ca6b-2.gif

      How can I fix this ?
      ( It's a bare-bone rig that i can show this problem and easy to read , If a non delete setting is needed please let me kow)

      @ Windows 11 21H2 Cinema 4D 2023.0.0

      from typing import Optional
      import c4d
      
      doc: c4d.documents.BaseDocument  # The active document
      op: Optional[c4d.BaseObject]  # The active object, None if unselected
      
      def redshift_scatter() -> c4d.BaseObject :
      
          # Modifier ID
          ModifierID = 1018545 
          ModifierName = 'Scatter : '
          selection = False
          
          doc.StartUndo()
              
          selectedtag = doc.GetActiveTag()
          node = doc.GetActiveObject()
      
          # pass if nothing selected
          if not node and (not selectedtag or not selectedtag.CheckType(5673)) :
              return
          
          # node selected
          if node :
              
              
              doc.AddUndo(c4d.UNDOTYPE_BITS,node)
              node.DelBit(c4d.BIT_ACTIVE)
              
              tags = [tag for tag in node.GetTags() if tag.CheckType(5673)]
              if len(tags)==[]:
                  pass
              if len(tags) == 1 :
                  scatter_selection = tags[0].GetName()
                  selection = True
              else:
                  if selectedtag in tags :
                      scatter_selection = selectedtag.GetName()
                      selection = True
                      doc.AddUndo(c4d.UNDOTYPE_BITS,selectedtag)
                      selectedtag.DelBit(c4d.BIT_ACTIVE)
                      
          
          # selection tag
          elif (selectedtag and selectedtag.CheckType(5673)) and not node:
              
              scatter_selection = selectedtag.GetName()
              selection = True
              node = selectedtag.GetObject()
              # deselect tag
              doc.AddUndo(c4d.UNDOTYPE_BITS,selectedtag)
              selectedtag.DelBit(c4d.BIT_ACTIVE)
      
      
          # world matrix.
          pos = node.GetMg()
          # Modifier 
          Modifier = c4d.BaseObject(ModifierID)
          Modifier[c4d.ID_MG_MOTIONGENERATOR_MODE] = 0
          Modifier[c4d.MG_OBJECT_LINK] = node
          #Modifier[c4d.MG_POLYSURFACE_SEED] = seed
          Modifier[c4d.MG_POLY_MODE_] = 3 # surface
          
          if selection :
              Modifier[c4d.MG_POLY_SELECTION] = scatter_selection
              
          Modifier.SetName(ModifierName + node.GetName())
          Modifier.SetMg(pos) # Set the world (global) matrix.
          Modifier.InsertAfter(node)
          doc.AddUndo(c4d.UNDOTYPE_NEWOBJ,Modifier)
          Modifier.SetBit(c4d.BIT_ACTIVE)
      
          doc.EndUndo()
          c4d.EventAdd()
      
          return Modifier
      
      if __name__ == '__main__':
          redshift_scatter()
      
      

      thanks 😊

      https://boghma.com
      https://github.com/DunHouGo

      ferdinandF 1 Reply Last reply Reply Quote 0
      • ferdinandF
        ferdinand @Dunhou
        last edited by ferdinand

        Hello @dunhou,

        Thank you for reaching out to us. We are quite busy now now, I must unfortunately push your question to the end of next week.

        Please excuse the delay and cheers,
        Ferdinand

        PS: I glanced at your post, and this might be a priority issue in the internal event loop, and you seem to have a problem with the Attribute Manger not updating as you want it to. You can try your luck with c4d. SendCoreMessage(c4d.COREMSG_CINEMA_FORCE_AM_UPDATE) after your last EndUndo and EventAdd, but that is more a guess than a solution, as I do not have time to read and run your script right now.

        MAXON SDK Specialist
        developers.maxon.net

        DunhouD 1 Reply Last reply Reply Quote 0
        • DunhouD
          Dunhou @ferdinand
          last edited by

          @ferdinand

          That's all right I will move on another work for now.
          Thanks for your time 😊

          https://boghma.com
          https://github.com/DunHouGo

          ferdinandF 1 Reply Last reply Reply Quote 0
          • ferdinandF
            ferdinand @Dunhou
            last edited by ferdinand

            Hey @dunhou,

            sorry for the delay, 2023.1 was consuming my time. The problem with your code is that it produces what is called a TriState selection in the C++ API, i.e., multiple things are selected and Cinema 4D tries then to display the intersection of attributes of the selected entities in the Attribute Manager. Which happened to be the empty set in your case, hence the empty Attribute Manager. The most straight forward way to solve this, is to simply use BaseDocument.SetActiveObject and start a new selection.

            Find your modified code below; I have marked the minor change I made with a change fence. Also find a more technical explanation there.

            Cheers,
            Ferdinand

            The result:
            56d93d83-2dbd-4322-9d97-6e4aa75803ab-image.png
            The code:

            from typing import Optional
            import c4d
            
            doc: c4d.documents.BaseDocument  # The active document
            op: Optional[c4d.BaseObject]  # The active object, None if unselected
            
            def redshift_scatter() -> c4d.BaseObject :
            
                # Modifier ID
                ModifierID = 1018545 
                ModifierName = 'Scatter : '
                selection = False
                
                doc.StartUndo()
                    
                selectedtag = doc.GetActiveTag()
                node = doc.GetActiveObject()
            
                # pass if nothing selected
                if not node and (not selectedtag or not selectedtag.CheckType(5673)) :
                    return
                
                # node selected
                if node :
                    doc.AddUndo(c4d.UNDOTYPE_BITS,node)
                    node.DelBit(c4d.BIT_ACTIVE)
                    
                    tags = [tag for tag in node.GetTags() if tag.CheckType(5673)]
                    if len(tags)==[]:
                        pass
                    if len(tags) == 1 :
                        scatter_selection = tags[0].GetName()
                        selection = True
                    else:
                        if selectedtag in tags :
                            scatter_selection = selectedtag.GetName()
                            selection = True
                            doc.AddUndo(c4d.UNDOTYPE_BITS,selectedtag)
                            selectedtag.DelBit(c4d.BIT_ACTIVE)
                            
                # selection tag
                elif (selectedtag and selectedtag.CheckType(5673)) and not node:
                    
                    scatter_selection = selectedtag.GetName()
                    selection = True
                    node = selectedtag.GetObject()
                    # deselect tag
                    doc.AddUndo(c4d.UNDOTYPE_BITS,selectedtag)
                    selectedtag.DelBit(c4d.BIT_ACTIVE)
            
                # world matrix.
                pos = node.GetMg()
                # Modifier 
                Modifier = c4d.BaseObject(ModifierID)
                Modifier[c4d.ID_MG_MOTIONGENERATOR_MODE] = 0
                Modifier[c4d.MG_OBJECT_LINK] = node
                #Modifier[c4d.MG_POLYSURFACE_SEED] = seed
                Modifier[c4d.MG_POLY_MODE_] = 3 # surface
                
                if selection :
                    Modifier[c4d.MG_POLY_SELECTION] = scatter_selection
                    
                Modifier.SetName(ModifierName + node.GetName())
                Modifier.SetMg(pos) # Set the world (global) matrix.
                Modifier.InsertAfter(node)
                doc.AddUndo(c4d.UNDOTYPE_NEWOBJ,Modifier)
            
                # --- Change Start -----------------------------------------------------------------------------
            
                # This line was the problem in your code. You sort of did everything correctly, you
                # deleted the selection bits in line #26, #39, and #49. But your code has sort of a fault, as
                # in that you do not make sure that all tags are deselected in all cases. #tag in line #28
                # contains only a subset of tags. Cinema 4D considers the scene state therefore to still be a 
                # multi-selection after your script ran.
            
                # Cinema 4D allows you to select multiple objects and will then display the intersection of
                # attributes of all selected nodes in the Attribute Manager. In the C++ API this is called a 
                # TriState, the Python API does not really understand the concept. So what happened here, is 
                # that Cinema 4D tried to build that TriState for the old selected tag and the 
                # new object, which happens to be the empty set, hence the empty AM in your screen cast.
            
                # You could either make sure that really everything is deselected by managing the bits more 
                # carefully, or do what I have done here, use the convenience function BaseDocument::
                # SetActiveObject() to "nuke" the scene selection state. The second argument defines if you
                # want to add to an existing selection or start a new one. c4d.SELECTION_NEW is the default
                # value, I have added it here only for verbosity.
            
                # Modifier.SetBit(c4d.BIT_ACTIVE)
                doc.SetActiveObject(Modifier, c4d.SELECTION_NEW)
                # --- Change End -------------------------------------------------------------------------------
            
                doc.EndUndo()
                c4d.EventAdd()
            
                return Modifier
            
            if __name__ == '__main__':
                redshift_scatter()
            

            MAXON SDK Specialist
            developers.maxon.net

            DunhouD 1 Reply Last reply Reply Quote 0
            • DunhouD
              Dunhou @ferdinand
              last edited by

              @ferdinand Thanks for the new solution for SetActiveObject . It works as expected.

              Much appreciated !

              https://boghma.com
              https://github.com/DunHouGo

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