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

    Highlighted Command Text/Icon when it is executed?

    Cinema 4D SDK
    r20 python
    2
    7
    864
    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.
    • B
      bentraje
      last edited by bentraje

      Hi,

      I'm trying to replicate a UI behavior in one of Cineversity's plug-ins where the command text/icon is highlighted when it is toggled for on and off.

      You can check the behavior here:
      https://www.dropbox.com/s/3ozfoplfyg3yaj9/c4d133_command_highlighting.mp4?dl=0

      How do I achieve that?

      Thank you for looking at the problem

      PS. I can't check the code. It's in pypv.

      1 Reply Last reply Reply Quote 0
      • M
        m_adam
        last edited by

        Hi, just to be sure you talk about the blueish things on the menu?
        If that's the case you simply have to return c4d.CMD_VALUE | CMD_ENABLED c4d. in your GetState method of your CommandData.

        Cheers,
        Maxime.

        MAXON SDK Specialist

        Development Blog, MAXON Registered Developer

        1 Reply Last reply Reply Quote 0
        • B
          bentraje
          last edited by bentraje

          @m_adam

          Thanks for the solution. Sorry also for the late response.
          I tried implementing the following logic of the visibility plug-in: If not visible: Don't enable. If visible: Enable. (i.e. the highlighting.

          However, it gives me two errors:

          1. 'MyMenuPlugin' object has no attribute 'status' on the self.state = self.status line. Which is a bit confusing since I already declared status variable above.
          2. Also, I'm not sure if I'm returning properly with the not c4d.CMD_VALUE | c4d.CMD_ENABLED statement. LOL

          Just to recap, I'm after this behavior
          https://www.dropbox.com/s/3ozfoplfyg3yaj9/c4d133_command_highlighting.mp4?dl=0

          Here is the code so far:
          import c4d
          from c4d import gui, plugins, bitmaps, utils, documents
          
          PLUGIN_ID   = 1010203
          
          class MyMenuPlugin(plugins.CommandData):
          
              def toggle_vis_subd(self):
                  self.doc = c4d.documents.GetActiveDocument()
                  bd = self.doc.GetActiveBaseDraw()
                  displayFilter = bd.GetDisplayFilter()
          
                  if displayFilter & c4d.DISPLAYFILTER_HYPERNURBS:
                      bd[c4d.BASEDRAW_DISPLAYFILTER_HYPERNURBS] = False
                      print "Switched Off Subdivision Surface Display Filter"
                  else:
                      bd[c4d.BASEDRAW_DISPLAYFILTER_HYPERNURBS] = True
                      print "Switched On Subdivision Surface Display Filter"
          
                  self.status = bd[c4d.BASEDRAW_DISPLAYFILTER_HYPERNURBS]
                  bd.Message(c4d.MSG_CHANGE)
                  c4d.EventAdd()
                  c4d.StatusClear()
          
              def Execute(self, doc):
                  self.toggle_vis_subd()
          
                  return True
          
              def GetState(self, doc):
          
                  self.state = self.status
          
                  if self.state == False:
                      return not c4d.CMD_VALUE | c4d.CMD_ENABLED
                  if self.state == True:
                      return c4d.CMD_VALUE | c4d.CMD_ENABLED
          
          if __name__ == "__main__":
              status = plugins.RegisterCommandPlugin(PLUGIN_ID, "bt_Visibility",0, None, "bt_Visibility", MyMenuPlugin())
              if (status):
                  print "Visibility plug-in successfully initialized"
          

          Thank you for looking at problem. The visibility code block I think is from a github c4d sample script.

          1 Reply Last reply Reply Quote 0
          • M
            m_adam
            last edited by m_adam

            Hi @bentraje the issue is that GetState is called way before Execute (it's called at the moment you display the command into the UI, so at the plugin registration).

            So either you create a __init__ method en define the default status value either you can do something like that in your get state method

            def GetState(self, doc):
                # Retrieves the status member of self, and if it's not present it will return True
                status = getattr(self, "status", True)
                self.state = status
            
                # Previously you were almost safe but in case of self.state is something different than True or False you returned nothing
                if not self.state:
                    return not c4d.CMD_VALUE | c4d.CMD_ENABLED
                else:
                    return c4d.CMD_VALUE | c4d.CMD_ENABLED
            

            Cheers,
            Maxime.

            MAXON SDK Specialist

            Development Blog, MAXON Registered Developer

            1 Reply Last reply Reply Quote 1
            • B
              bentraje
              last edited by

              @m_adam

              Thanks again for the response, especially the code.

              I no longer have the error but there is a glitch.
              Whenever I execute the command, it works okay at first click but not on the second click. It is permanently disabled. (i.e. I can't toggle with the command).

              I tried using either not c4d.CMD_VALUE only or not c4d.CMD_ENABLED but I still have the same result?

              Is there a way around this?

              1 Reply Last reply Reply Quote 0
              • M
                m_adam
                last edited by

                @bentraje Yes as you pass not c4d.CMD_ENABLE as its stand it's not enabled.

                Besides that, I also reworked a bit your example to make it pythonic by settings state as a property so when you retrieve state its actually the state from the current document.

                import c4d
                from c4d import gui, plugins, bitmaps, utils, documents
                
                PLUGIN_ID   = 1010203
                
                class MyMenuPlugin(plugins.CommandData):
                
                    def Execute(self, doc):
                        self.state = not self.state
                
                        return True
                
                    def GetState(self, doc):
                        # Previously you were almost safe but in case of self.state is something different than True or False you returned nothing
                        if not self.state:
                            return c4d.CMD_ENABLED
                        else:
                            return c4d.CMD_VALUE | c4d.CMD_ENABLED
                
                    @property
                    def state(self):
                        doc = c4d.documents.GetActiveDocument()
                        bd = doc.GetActiveBaseDraw()
                        displayFilter = bd.GetDisplayFilter()
                
                        if displayFilter & c4d.DISPLAYFILTER_HYPERNURBS:
                            return bd[c4d.BASEDRAW_DISPLAYFILTER_HYPERNURBS]
                
                        return False
                    
                    @state.setter
                    def state(self, value):
                        # Checks if the value is a boolean
                        if not isinstance(value, bool):
                            raise TypeError("value is not a bool.")
                
                        doc = c4d.documents.GetActiveDocument()
                        bd = doc.GetActiveBaseDraw()
                        displayFilter = bd.GetDisplayFilter()
                
                        if displayFilter & c4d.DISPLAYFILTER_HYPERNURBS:
                            bd[c4d.BASEDRAW_DISPLAYFILTER_HYPERNURBS] = False
                            print "Switched Off Subdivision Surface Display Filter"
                        else:
                            bd[c4d.BASEDRAW_DISPLAYFILTER_HYPERNURBS] = True
                            print "Switched On Subdivision Surface Display Filter"
                
                        bd.Message(c4d.MSG_CHANGE)
                        c4d.EventAdd()
                        c4d.StatusClear()
                
                if __name__ == "__main__":
                    status = plugins.RegisterCommandPlugin(PLUGIN_ID, "bt_Visibility",0, None, "bt_Visibility", MyMenuPlugin())
                    if (status):
                        print "Visibility plug-in successfully initialized"
                

                Cheers,
                Maxime.

                MAXON SDK Specialist

                Development Blog, MAXON Registered Developer

                1 Reply Last reply Reply Quote 1
                • B
                  bentraje
                  last edited by

                  Thank you @m_adam. Work as expected!
                  (I actually just ended up learning about the decorator property since its new to me. haha. Thanks for that).

                  Just want to confirm, am I right to think this is the code flow:

                  1. Register Plug-In
                  2. @property state
                  3. GetState
                  4. Execute(Button Click)
                  5. @state.setter state
                  6. @property state
                  7. GetState

                  Then back again to #4 for the click.

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