Forcing One instance of Script Dialog



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 03/08/2012 at 09:22, xxxxxxxx wrote:

    When the users creates a script that opens a dialog window and docks it into the layout. It can spawn multiple copies of itself when the users executes that script from the UI. Ouch!

    Is there something in the SDK that will check to see if the dialog the script creates is open. And not create multiple copies of it?
    I see window open functions for plugins. But I don't see anything that deals with dialogs created with scripts.

    I have created my own work around for this. Which works ok. But not 100% safe.
    I would rather use a built in SDK method that is bullet proof instead of using my hack.

    -ScottA



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 03/08/2012 at 09:57, xxxxxxxx wrote:

    Simple: Async Dialogs should not be opened from the Script Manager. ^^

    _nik



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 03/08/2012 at 10:44, xxxxxxxx wrote:

    Party Pooper.
    Seriously though.
    If there's a supported way to do this with the SDK I'd like to know.

    Otherwise.....I will be forced share my workaround hack.
    And assert my position as supreme ruler. 😈
    Don't make me do it Maxon. I'll do it........ I'll do it. 🙂

    -ScottA



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 04/08/2012 at 02:16, xxxxxxxx wrote:

    Pff.. :b
    Ye seriously, there is no "official" way to solve this. In a CommandData plugin for example, C4D keeps an instance of your plugin aside that you use to recognize whether the dialog is already created or not.

    You could save your dialog instance in a module, but that really is not a good way to handle it. I just post it here for completeness, but really: Don't use this!

    import c4d   
    # ...   
    dlg = getattr(c4d, 'my_dialog', None)   
    if not dlg:   
        dlg = Dialog()   
        setattr(c4d, 'my_dialog', None)   
    dlg.Open()
    

    What workaround were you talking about? :)

    -Nik



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 04/08/2012 at 08:34, xxxxxxxx wrote:

    The work around I came up with works on a different principle.
    Since we can't create a container in a script dialog and use it's data to test if the dialog is open or closed. What I needed was something that was already globally available that the script could use as a sort of "state switch".

    There's a ton of settable color attributes available for the UI. And I found something really obscure in there called IRR color. Which changes the border color of the IRR.
    I thought... Who in the heck would want to change that thing?
    So I use it for something more useful...Like a switch that tells my dialog plugin when it can and can't launch. Forcing only one copy of the dialog to be open at a time.

    #This is a trick to force only one script manager dialog instance to open  
    #The script toggles the IRR window color and uses it like a switch to tell the script whether it is allowed to launch or not  
    #The close button and/or the "X" in the menu sets the IRR color back to it's original white color when the dialog is closed  
      
    import c4d  
    from c4d import gui  
      
    class YourDialog(gui.GeDialog) :  
      
      BUTTON_ID = 1001   
      color = c4d.GetViewColor(c4d.VIEWCOLOR_IRR)   
      
      def CreateLayout(self) :   
          c4d.SetViewColor(c4d.VIEWCOLOR_IRR,c4d.Vector(0,0,0))    #Change the IRR color to black      
          c4d.EventAdd()  
            
          self.AddButton(self.BUTTON_ID, c4d.BFH_SCALE|c4d.BFV_SCALE, 100, 25, "Close Dialog")  
          return True  
      
      def Command(self, id, msg) :  
          if id==self.BUTTON_ID:   
              c4d.SetViewColor(c4d.VIEWCOLOR_IRR,self.color)    #Set the color back to the original white value  
              c4d.EventAdd()  
              self.Close()  
          return True  
            
      
            
      def DestroyWindow(self) :  #Use this method to toggle the IRR back to it's original white color   
          c4d.SetViewColor(c4d.VIEWCOLOR_IRR,self.color)    #Set the color back to the original value  
          c4d.EventAdd()      
            
       
      
    if __name__=='__main__':  
      dlg = YourDialog()   
      bgcolor = dlg.color  
      
      #If the IRR color is white(default) then go ahead and open this dialog window  
      if bgcolor.x == 1: dlg.Open(dlgtype= c4d.DLG_TYPE_ASYNC, xpos=600, ypos=500, defaultw=200, defaulth=200)
    

    It works great!
    But the down side is that the user could still change the IRR color(why anyone would do that I have no idea..But users often do crazy things) and cause problems.
    And I think I would also need to use another UI attribute If I wanted to apply it to two keep two dialogs.

    It would be handy if we had a bunch of empty global booleans in our preferences so we could use them for special cases like this.
    But then we'd all be doing things that we aren't supposed to do. 😂

    -ScottA

    *Edit- I also use a variation of this same code using a null and a user data boolean entry to force only one instance of a dialog to be open. Which is more safe. But requires more initial set up.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 04/08/2012 at 09:29, xxxxxxxx wrote:

    What the heck.
    I guess I should just post that code version too:

    #This is a trick to force only one script manager dialog instance to open  
    #The script toggles a User Data boolean and uses it like a switch to tell the script whether it is allowed to launch or not  
    #The close button and/or the "X" in the menu sets the switch back to it's original off state when the dialog is closed  
      
    import c4d  
    from c4d import gui  
      
    class YourDialog(gui.GeDialog) :  
      
      BUTTON_ID = 1001   
      
      def CreateLayout(self) :   
          obj[c4d.ID_USERDATA, 1]=1    #Toggle the UserData boolean to enabled  
          c4d.EventAdd()  
            
          self.AddButton(self.BUTTON_ID, c4d.BFH_SCALE|c4d.BFV_SCALE, 100, 25, "Close Dialog")  
          return True  
      
      def Command(self, id, msg) :  
          if id==self.BUTTON_ID:   
              c4d.EventAdd()  
              self.Close()  
          return True  
      
      def DestroyWindow(self) :        #Use this method to toggle the switch back to it's original off state  
          obj[c4d.ID_USERDATA, 1]=0  
          c4d.EventAdd()   
      
    if __name__=='__main__':  
      dlg = YourDialog()  
      obj = doc.SearchObject("Null")  #The object holding a boolean that tells the dialog whether it can be opened  
      
      #If the switch is off (default) then go ahead and open this dialog window   
      if obj[c4d.ID_USERDATA, 1]==0: dlg.Open(dlgtype= c4d.DLG_TYPE_ASYNC, xpos=600, ypos=500, defaultw=200, defaulth=200)
    

    Works good.
    But you need to set up your own object and UserData instead of using the built in preferences attributes like my first example.

    -ScottA


Log in to reply