Command in Tag Plugin [SOLVED]

  • On 07/10/2014 at 08:41, xxxxxxxx wrote:

    I have a custom tag with various sliders/buttons. There are functions for when a button is pressed, it sets the faders to custom values.

    How can I determine if a slider is changed?

    I tried:

    if tag[id]:

    in Message an the Execute. It runs the function continuously, and not at that specific moment.

    I just want to know when that specific slider is changed. Ideas?

  • On 07/10/2014 at 10:36, xxxxxxxx wrote:


  • On 07/10/2014 at 13:27, xxxxxxxx wrote:

    Still confused by that. I basically want to do what a command plugin would do in the command section.

    if id == 1001:
    print "it works"

    But instead of a button triggering it, i need a slider to do it.


  • On 09/10/2014 at 10:50, xxxxxxxx wrote:

    Anyone else have an idea on how I would get an action on when a slider changes in a tag plugin?

  • On 09/10/2014 at 12:22, xxxxxxxx wrote:

    This is how to create a slider gizmo with a .res file.
    And get it's value in the .pyp code.

    ### mytag.res ###    
    CONTAINER mytag   #This container Must! be set to the same name as your .h file  
     NAME mytag;  
         COLUMNS 1;  
         DEFAULT 1;             
    ### mytag.h ###  
    GROUP1    = 9000,   
    MY_SLIDER = 1001,  
    ### mtag.str ###  
    STRINGTABLE mytag  
      mytag      "My Tag plugin";  
      GROUP1     "My Group";  
      MY_SLIDER  "My Slider";  
    ### mtag.pyp ###  
      def Execute(self, tag, doc, op, bt, priority, flags) :  
          bc = tag.GetDataInstance()  
          getValue = bc.GetReal(c4d.MY_SLIDER)  
          print getValue


  • On 10/10/2014 at 07:27, xxxxxxxx wrote:

    Thanks for the reply. Unfortunately this doesn't answer my question. Perhaps I'm being unclear.

    I know how to make a slider and get the values from it. I have that working fine.

    What I need is to print the value whenever that slider changes. If you run your code, it prints whenever there is a C4DEVENTMESSAGE. Not what I need...

    How can I find out when the user changes that slider?

  • On 10/10/2014 at 08:06, xxxxxxxx wrote:

    If you're looking for a boolean result that the user has changed it. You'll have to create a "trigger" variable by hand. Using a class member variable to compare the variable with the value of the slider.
    Or set that variable to True when the MSG_DESCRIPTION_POSTSETPARAMETER message is received. Then re-set it to False again.

    There is also: op.GetDirty(c4d.DIRTYFLAGS_DATA) which will execute if a slider is changed.
    But again. This returns an incremental integer value every time it's executed. Not a True/False value.
    So you'd still need to use your own "trigger" variable to poll it for changes.


  • On 10/10/2014 at 12:20, xxxxxxxx wrote:

    That helps. To give you insight on what I'm making, I want a variable to be the value of the slider. But I don't always want it the same as the slider. I just want the variable to update when the slider changes.

    I think op.GetDirty will work.

    How would I implement it? I tried:

    def Execute(self, tag, doc, op, bt, priority, flags) :
    print op.GetDirty(1102) #the slider ID

    return True

    It just prints continuously... Thoughts?

  • On 10/10/2014 at 13:31, xxxxxxxx wrote:

    GetDirty requires a flag as the parameter:  op.GetDirty(c4d.DIRTYFLAGS_DATA)

    Any gizmo on your tag that the user changes will make the dirty value change.
    So it's probably better to poll the slider's value instead of polling the dirty value.
    That way you only poll the value for that specific gizmo.


  • On 10/10/2014 at 14:34, xxxxxxxx wrote:

    While polling the slider's value with a class member variable should work fine.
    I just remembered another way I delt with this kind of thing a long time ago in one of my C++ plugins.

    This will grab the gizmo's data from the tag while the LMB is being held down.
    The "break" will stop it from running when the LMB is not being pressed.

        def Message(self, op, type, data) :  
          doc = op.GetDocument()   
          msg = c4d.BaseContainer()  
          while c4d.gui.GetInputState(c4d.BFM_INPUT_MOUSE, c4d.BFM_INPUT_MOUSELEFT, msg) :  
              if msg[c4d.BFM_INPUT_VALUE] == 0: break    
              if msg[c4d.BFM_INPUT_VALUE] == 1:   
                  #This value can be sent to a class member variable for usage in the other overriden plugin methods  
                  print op[c4d.MY_SLIDER]   

    Probably overkill for your needs. But I thought I'd mention it.


  • On 10/10/2014 at 17:12, xxxxxxxx wrote:

    I follow you on the GetDirty method, however, I'm not having much luck getting it to work..

    I added the op.GetDirty(c4d.DIRTYFLAGS_DATA) to the Message function.

    How to I make it only poll a slider and not the entire plugin?

    If you could post a sample code of getting a sliders value change, that would be perfect. And thats for the LMB trick, that will come in handy in the future.

    Thanks again,

  • On 10/10/2014 at 17:29, xxxxxxxx wrote:

    Even if that works, I don't think it will achieve what I'm after. I have it working in a script. Can I email you that and see if you can translate it to a tag plugin?

    I don't know if it's possible in the way I need it to work.


  • On 10/10/2014 at 17:36, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    How to I make it only poll a slider and not the entire plugin?

    You can't. At least I don't know any way to do that.
    Dirty can only test if "any" of the object's tag was changed in some manner. It can't tell which specific gizmo was changed.

    Grabbing the slider's value and comparing it to a class member variable to see if they are the same is the most common way to tell if a specific gimzo was changed.


  • On 10/10/2014 at 18:01, xxxxxxxx wrote:

    import c4d
    from c4d import plugins, gui, bitmaps

    class ExampleDlg(gui.GeDialog) :

    def CreateLayout(self) :
            self.AddEditSlider(101, c4d.BFH_SCALEFIT, initw=50, inith=0)
            self.AddEditSlider(102, c4d.BFH_SCALEFIT, initw=50, inith=0)
            self.AddEditSlider(103, c4d.BFH_SCALEFIT, initw=50, inith=0)
            self.AddSeparatorH(2, c4d.BFH_SCALEFIT)
            self.AddEditSlider(104, c4d.BFH_SCALEFIT, initw=50, inith=0)
            return True

    def InitValues(self) :

    self.SetFloat(101, 1, min=0, max=1, step=.01, format=c4d.FORMAT_PERCENT)
            self.SetFloat(102, 1, min=0, max=1, step=.01, format=c4d.FORMAT_PERCENT)
            self.SetFloat(103, 1, min=0, max=1, step=.01, format=c4d.FORMAT_PERCENT)
            self.SetFloat(104, 1, min=0, max=1, step=.01, format=c4d.FORMAT_PERCENT)
            self.a = 1
            self.b = 1
            self.c = 1
            return True

    def Command(self, id, msg) :

    if id == 101:
                self.a = self.GetFloat(101)

    if id == 102:
                self.b = self.GetFloat(102)
            if id == 103:
                self.c = self.GetFloat(103)   
            if id == 104:
                changea =  1 / self.a
                changeb =  1 / self.b
                changec =  1 / self.c

    self.SetFloat(101, self.GetFloat(104) / changea, min=0, max=1, step=.01, format=c4d.FORMAT_PERCENT)
                self.SetFloat(102, self.GetFloat(104) / changeb, min=0, max=1, step=.01, format=c4d.FORMAT_PERCENT)
                self.SetFloat(103, self.GetFloat(104) / changec, min=0, max=1, step=.01, format=c4d.FORMAT_PERCENT)
            return True

    dialog = ExampleDlg()

    Mess around with this. It's basically what I need to do..

  • On 11/10/2014 at 03:42, xxxxxxxx wrote:


    in my Tag plugin I solved it like this:

      def Init(self, node) :  
          tag = node  
          data = tag.GetDataInstance()  
          data.SetReal(10007, 0.5) #the slider id and the initial value  
          self.a = data.GetReal(10007) #you can set it to your initial value, too like self.a = 0.5  
      def Message(self, node, type, data) :  
          tag = node  
          instance = tag.GetDataInstance()  
          if (type == c4d.MSG_DESCRIPTION_CHECKUPDATE) :  
              if self.a != instance.GetReal(10007) :  
                  print "slider has changed"  
                  self.a = instance.GetReal(10007)  
                  print self.a  

    Or have a look to this post


  • On 13/10/2014 at 04:44, xxxxxxxx wrote:


    did it work for you?

    Found out that the succestion from Niklas:

    is the fastest way to solve it.(it´s lighter no additional check for doc or draw like in checkupdate)
    But it seems that

    c4d.DescriptionPostSetValue()    (this should give you the desc id of the changed parameter)
    is not defined in Python and therefore you have to set a variable
    and compare for changes like in the script I´ve posted before.


  • On 13/10/2014 at 14:11, xxxxxxxx wrote:

    Hi. Unfortunately I realized that it is not possible what I want to do. Take that script i posted and run it in script manager. A master slider will change the values of "child" sliders. But that will still be recognized by the MSG_DESCRIPTION_POSTSETPARAMETER.

    I don't think its possible. Thanks though.

  • On 14/10/2014 at 00:54, xxxxxxxx wrote:


    it is possible.
    What you need is some more if clauses, to decide if the masterslider controll the values or an individual sliders does it, like:

      def Init(self, node) :  
          tag = node  
          data = tag.GetDataInstance()  
          data.SetReal(10200, 1)#the masterslider  
          data.SetReal(10201, 1)#slider_1  
          data.SetReal(10202, 1)#slider_2  
          data.SetReal(10203, 1)#slider_3  
          self.d = data.GetReal(10200)  
          self.a = data.GetReal(10201)  
          self.b = data.GetReal(10202)  
          self.c = data.GetReal(10203)  
      def Message(self, node, type, data) :  
          tag = node  
          instance = tag.GetDataInstance()  
          if (type == c4d.MSG_DESCRIPTION_POSTSETPARAMETER) :  
              if self.d != instance.GetReal(10200) :  
                  self.d = instance.GetReal(10200)  
                  changea =  self.d*self.a  
                  instance.SetReal(10201, changea)  
                  changeb =  self.d*self.b  
                  instance.SetReal(10202, changeb)  
                  changec =  self.d*self.c  
                  instance.SetReal(10203, changec)  
                  if self.a != instance.GetReal(10201) :  
                      self.a = instance.GetReal(10201)  
                  if self.b != instance.GetReal(10202) :          
                      self.b = instance.GetReal(10202)  
                  if self.c != instance.GetReal(10203) :  
                      self.c = instance.GetReal(10203)  
              print self.a, self.b, self.c, self.d, "final"  

    That´s what you want, I guess?
    (By the way, in the the script you´ve posted keep an eye on avoiding divisions by zero.)


  • On 15/10/2014 at 13:05, xxxxxxxx wrote:

    Okay. That worked! However, the console would display some errors saying that self.d didn't exist. So I put it in a try/except. Is that a safe way to fix it?

    	        if self.d != instance.GetReal(1201) :
    	            self.d = instance.GetReal(1201)
    	            changea =  self.d*self.a
    	            instance.SetReal(1012, changea)
    	            changeb =  self.d*self.b
    	            instance.SetReal(1013, changeb)
    	            changec =  self.d*self.c
    	            instance.SetReal(1015, changec)
    	            if self.a != instance.GetReal(1012) :
    	                self.a = instance.GetReal(1012)
    	            if self.b != instance.GetReal(1013) :        
    	                self.b = instance.GetReal(1013)
    	            if self.c != instance.GetReal(1015) :
    	                self.c = instance.GetReal(1015)

    Ignore the indents. Didn't copy correctly.

  • On 16/10/2014 at 00:09, xxxxxxxx wrote:


    I actually can´t see a reason why self.d didn´t exist, if the variables where initialized correctly.
    Please post the whole thing or send me a private message.

    In my plugin it works like a charme.


Log in to reply