• Categories
    • Overview
    • News & Information
    • Cinema 4D SDK Support
    • Cineware SDK Support
    • ZBrush 4D SDK Support
    • Bugs
    • General Talk
  • Unread
  • Recent
  • Tags
  • Users
  • Register
  • Login
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
  • Register
  • Login

R20 Script State Function

Cinema 4D SDK
python r20
5
7
1.6k
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.
  • M
    Motion4D
    last edited by a_block Feb 28, 2019, 9:38 PM Sep 12, 2018, 6:25 PM

    So it was announced that scripts will now get access to an on/off state for their icons.
    I see that right in the script manager it tells how to work with it using the state() function. I have 2 questions about this.

    1. Only passing True, False and c4d.CMD_ENABLED|c4d.CMD_VALUE will effect the icon state correct? it can't be done outside of the state() function?
    2. I noticed when I put a print function inside of the state() function it seemed to loop endlessly? if I use this code:
    def state():
        obj = doc.GetSelection()
        if obj != []:
            print "disabled"
            return c4d.CMD_ENABLED
        else:
            print "enabled"
            return c4d.CMD_ENABLED|c4d.CMD_VALUE
    

    It also seems to update in real time, if I select something the icon becomes instantly enabled without executing the script. I feel like I'm doing it wrong haha.

    1 Reply Last reply Reply Quote 0
    • D
      dskeith
      last edited by dskeith Sep 15, 2018, 6:11 PM Sep 13, 2018, 5:12 AM

      1. Only passing True, False and c4d.CMD_ENABLED|c4d.CMD_VALUE will effect the icon state correct? it can't be done outside of the state() function?

      Yes. You may be able to perform calculations elsewhere and store a state value in the document's container that you access in the state() method, but I don't believe you can change the state elsewhere.

      1. I noticed when I put a print function inside of the state() function it seemed to loop endlessly? if I use this code:

      Yes, it's "looping" every time the Cinema 4D interface updates/redraws.

      Background

      The state() function is seemingly run every time Cinema 4D's interface is redrawn. It's really there for determining whether a command that requires an object be selected is enabled or not. As it's run so frequently, any code you put in there could slow down all of C4D, so ensure that your state check is actually important, and if so, do your check as quickly as possible.

      Example

      For example, a script that prints the name of the selected object should only be enabled when an object is selected.

      """Name-en-US: Echo Name
      Description-en-US: Opens a message dialog with the name of the selected object.
      """
      
      import c4d
      from c4d import gui
      
      def state():
          """Gray out icon if no objects are selected, or more than one object is selected.
          """
      
          # `op` is a variable provided by C4D that represents the selected object.
          # I'm not certain, but I think this is faster than call doc.GetActiveObject()
          # but it will return `False` if more than one object is selected.
          if op is not None:
              return c4d.CMD_ENABLED
          
          else:
              return False
      
      def main():
          """Open a dialog with the selected object's name.
          """
          
          if op is None:
              return
      
          active_obj_name = op.GetName()
          gui.MessageDialog("You selected: " + active_obj_name)
      
      if __name__=='__main__':
          main()
      

      References

      • Python API Docs: c4d.plugins.CommandData.GetState
      • C++ API Docs: Command Data Class
      1 Reply Last reply Reply Quote 1
      • Y
        y_puech
        last edited by Sep 13, 2018, 2:55 PM

        Hi,

        state() is called by Cinema 4D whenever needed to update the UI.
        main() of a script is called when a script is executed but state() does not get called.
        If you implement state() it is important to use main() like the default script does. Otherwise any code called outside of main() is evaluated with state().

        Note returning c4d.CMD_ENABLED enables the state and returning 0 disables the state. Also True or False can be returned to respectively enable/disable the state.
        c4d.CMD_VALUE can be returned in association with c4d.CMD_ENABLED to enable and check the script state.

        The state() implementation posted by Donovan can be optimized and simply be defined as:

        def state():
            return op is not None
        

        Former MAXON SDK Engineer

        1 Reply Last reply Reply Quote 0
        • M
          Motion4D
          last edited by Sep 13, 2018, 9:00 PM

          @y_puech and @dskeith Thank you both, that is extremely helpful as I didn't see any other documentation on that. I can see how state() could become very dangerous very quickly. I will certainly proceed with caution and hope this will help others will to not abuse the state() function as well:)

          1 Reply Last reply Reply Quote 0
          • M
            mogh
            last edited by Feb 27, 2019, 9:08 AM

            I guess I'll append my question here.
            How could this be optimized ?

            def state():
                test = doc.GetActiveBaseDraw()
                if test[c4d.BASEDRAW_DATA_SHOWSAFEFRAME] == 1:
                    return c4d.CMD_ENABLED|c4d.CMD_VALUE 
                else:
                    return c4d.CMD_ENABLED
            

            Thanks in advance,
            kind regards
            mogh

            1 Reply Last reply Reply Quote 0
            • a_blockA
              a_block
              last edited by Feb 28, 2019, 9:36 PM

              Hi mogh,

              I don't see much room for optimization here.

              Cheers,
              Andreas

              1 Reply Last reply Reply Quote 0
              • M
                mogh
                last edited by Mar 7, 2019, 10:31 AM

                Thanks a_block,

                Sadly I had to disable the state() function because it breaks (delays forever) Material Preview/Shader rendering.

                This State() function should somehow be isolated if possible ... but i guess this is the limitation of "checking the gui state".

                kind regards
                mogh

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