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

    Dialog Freezes when checking for Message()

    Cinema 4D SDK
    r21 python
    4
    12
    1.2k
    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

      Hi,

      I'm trying to create a separate slider for my finger controls.
      The slider is at default 0. Then if you move it, the change will be applied to the finger control. Then the slider will be set again to 0.

      However, I'm having a problem as it freezes when checking for c4d.MSG_CHANGE.

      You can see the problem here:
      https://www.dropbox.com/s/88vmuzivqylbh1x/c4d207_dialog_freezes_when_checking_for_msg.mp4?dl=0

      You can check the working code here:

      # For the Add Edit Slider reset to Zero
      import c4d
      from c4d import bitmaps, documents, gui, plugins, threading, utils
      
      
      class MyDialog(c4d.gui.GeDialog):
          
          def __init__(self):
              self.finger_B_01_L_con = doc.SearchObject('finger_B_01_L_con')
              
          def CreateLayout(self):
              self.AddEditSlider(id=303030, flags=c4d.BFH_SCALEFIT, initw=80, inith=0)
              return True
      
          def InitValues(self):
              self.SetDegree(303030, 0.0, min=-45, max=45, step=0.01, min2=0.0, max2=0.0)
              return True
      
          def Message(self, msg, result):
      
              if msg.GetId() == c4d.MSG_CHANGE:
                  if self.AddEditSlider.GetFloat(303030) != 0: 
                      rotation_current = self.finger_B_01_L_con.GetRelPos()
                      rotation_modify = self.GetFloat(303030)
                      rotation_new = rotation_current + rotation_modify
                      self.finger_B_01_L_con.SetRelPos(rotation_new)
      
                      # Set the AddEditSlider Back to Zero
                      self.InitValues()
              
              return True
      
      if __name__ == "__main__":
          dlg = MyDialog()
          dlg.Open(dlgtype=c4d.DLG_TYPE_ASYNC)
      
      1 Reply Last reply Reply Quote 0
      • CairynC
        Cairyn
        last edited by

        Without explicitly testing: You are changing the slider (InitValues) while you are still checking the message. Which probably generates a new message, which calls Message again, etc.

        The least thing you can do is NOT call InitValues if the slider is already at 0.0.

        I'm not sure anyway whether the code will do what you want, as any tiny movement of the slider will accumulate into a finger rotation (even while the user is still dragging the slider). I bet it would just start spinning out of control, or become unresponsive...

        1 Reply Last reply Reply Quote 1
        • ferdinandF
          ferdinand
          last edited by

          Hi,

          I might be overlooking something here, but shouldn't raise self.AddEditSlider.GetFloat(303030) in the conditional statement an AttributeError since the method type has no attribute called GetFloat.

          Cheers
          zipit

          MAXON SDK Specialist
          developers.maxon.net

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

            Thanks for the response

            @Cairyn

            Oh you mean loop? I didn't think of that.
            But it should already do this: "NOT call InitValues if the slider is already at 0.0."
            since if I have a if self.AddEditSlider.GetFloat(303030) != 0: line.
            If its already at zero, the InitValues shouldn't be called.

            @zipit

            That might be so but for some reason, it does not give an error to the console. It just freezes.

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

              Hi @bentraje
              First, you should always call re-route the message to the parent (as it's written in the doc) GeDialog.Message. In some situation you may want to kill the event but they are very very limited and you should call GeDialog.KillEvents and return True, but this is really really rare. Since pretty much everything is handled by the parent (ask for close, ask for movement, ask for change, etc....) So if you don't re-route it freezes.

              Secondly, there is an issue in SetDegree since there is no min2 or max2 parameter see GeDialog.SetDegree.

              Moreover, I'm not sure which event you are trying to catch with MSG_CHANGE, since it sent to objects when they have changed not Dialog.

              Cheers,
              Maxime.

              MAXON SDK Specialist

              Development Blog, MAXON Registered Developer

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

                @m_adam

                Thanks for the response.

                RE: always call re-route the message to the parent
                By that, do you mean changing the
                return True
                to
                return GeDialog.Message(self, msg, result)
                ?

                RE: GeDialog.KillEvents
                Ok Added.

                RE: there is an issue in SetDegree since there is no min2 or max2 parameter
                Ok. Changed to SetFloat instead. By the way, in the documentation, there is GetFloat but no GetDegree. Is this normal?

                RE: I'm not sure which event you are trying to catch
                I'm trying to catch the dragging of the slider and release. So the slider changing values.

                Here is the revised code. It no longer freezes but it doesn't catch the event:

                # For the Add Edit Slider reset to Zero
                import c4d
                from c4d import bitmaps, documents, gui, plugins, threading, utils
                
                
                class MyDialog(c4d.gui.GeDialog):
                    
                    def __init__(self):
                        self.finger_B_01_L_con = doc.SearchObject('finger_B_01_L_con')
                        
                    def CreateLayout(self):
                        self.AddEditSlider(id=303030, flags=c4d.BFH_SCALEFIT, initw=80, inith=0)
                        return True
                
                    def InitValues(self):
                        self.SetFloat(303030, 0.0, min=-45, max=45, step=0.01, min2=0.0, max2=0.0)
                        return True
                
                    def Message(self, msg, result):
                
                        if msg.GetId() == c4d.MSG_CHANGE:
                            if self.AddEditSlider.GetFloat(303030) != 0: 
                                rotation_current = self.finger_B_01_L_con.GetRelPos()
                                rotation_modify = self.GetFloat(303030)
                                rotation_new = rotation_current + rotation_modify
                                self.finger_B_01_L_con.SetRelPos(rotation_new)
                
                                # Set the AddEditSlider Back to Zero
                                self.InitValues()
                                self.KillEvents() 
                        
                        return c4d.gui.GeDialog.Message(self, msg, result)
                
                if __name__ == "__main__":
                    dlg = MyDialog()
                    dlg.Open(dlgtype=c4d.DLG_TYPE_ASYNC)
                
                CairynC 1 Reply Last reply Reply Quote 0
                • M
                  m_adam
                  last edited by m_adam

                  @bentraje said in Dialog Freezes when checking for Message():

                  RE: always call re-route the message to the parent
                  By that, do you mean changing the
                  return True
                  to
                  return c4d.gui.GeDialog.Message(self, msg, result)
                  ?

                  Yes

                  @bentraje said in Dialog Freezes when checking for Message():

                  RE: GeDialog.KillEvents
                  Ok Added.

                  I guess you didn't understand what I said previously. There are two cases.

                  1. you don't want the message to be processed by others (e.g. disable default functions such as disabling the right-click or even value change, by removing the dispatch to the Command method so you have to call KillEvents and return True).
                  2. You want the default behavior, so when you change a value, the value will be changed, etc...
                    In your case do you want to remove default functionality for the Dialog? No, you just want to react to some change, but you want to be transparent, not avoid any change, so don't call KillEvents and return True.

                  @bentraje said in Dialog Freezes when checking for Message():

                  RE: there is an issue in SetDegree since there is no min2 or max2 parameter
                  Ok. Changed to SetFloat instead. By the way, in the documentation, there is GetFloat but no GetDegree. Is this normal?

                  Yes because SetDegree only changes how the internal float value is represented in the Dialog it's written in the documentation of GeDialog.SetDegree.

                  @bentraje said in Dialog Freezes when checking for Message():

                  RE: I'm not sure which event you are trying to catch
                  I'm trying to catch the dragging of the slider and release. So the slider changing values.

                  Command method will be called in both cases so I don't really know why you want to deal with Message.
                  However, if you want more precise control, then I agree that Message should be used, but you should listen for either
                  BFM_INTERACTSTART: (Sent when the user interaction start)
                  BFM_INTERACTEND: (Sent when user interaction ends.)

                  Or BFM_ACTION to get value while the dragging occurs.

                  For more information, look at the C++ GeDialog Gadget Interaction Manual.

                  And as @zipit already pointed you, there is no
                  self.AddEditSlider.GetFloat(303030). GetFloat is a method from GeDialog not for the gadget.

                  Cheers,
                  Maxime.

                  MAXON SDK Specialist

                  Development Blog, MAXON Registered Developer

                  1 Reply Last reply Reply Quote 1
                  • CairynC
                    Cairyn @bentraje
                    last edited by

                    @bentraje Try the BFM_xxx messages for gadget interaction, not MSG_CHANGE.

                    (and no KillEvents in your case)

                    1 Reply Last reply Reply Quote 1
                    • CairynC
                      Cairyn
                      last edited by

                      Duh, I need to type faster.

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

                        @m_adam @Cairyn

                        Thanks for the inputs and explanation.
                        The code functions but even if I use the BFM_ACTION where it gets updated for every dragging, the controller is only updated at the release of slider. Compared to the Attribute Manager where the changes are interactive.

                        I also tried the BFM_ACTION_INDRAG and BFM_ACTION_VALCHG but I get the same result.

                        You can see the problem here:
                        https://www.dropbox.com/s/05tq12uozc1acjj/c4d207_dialog_freezes_when_checking_for_msg02.mp4?dl=0

                        Apologies for the trouble.

                        Here is the working code:

                        # For the Add Edit Slider reset to Zero
                        import c4d
                        from c4d import bitmaps, documents, gui, plugins, threading, utils
                        
                        
                        class MyDialog(c4d.gui.GeDialog):
                        
                            def __init__(self):
                                doc = c4d.documents.GetActiveDocument()
                                self.finger_B_01_L_con = doc.SearchObject('finger_B_01_L_con')
                        
                            def CreateLayout(self):
                                self.AddEditSlider(id=303030, flags=c4d.BFH_SCALEFIT, initw=80, inith=0)
                                return True
                        
                            def InitValues(self):
                                self.SetFloat(303030, 0.0, min=-45, max=45, step=0.01, min2=0.0, max2=0.0)
                                return True
                        
                        
                            def Message(self, msg, result):
                        
                                if msg.GetId() == c4d.BFM_ACTION:
                                    if self.GetFloat(303030) != 0:    
                                        rotation_current = self.finger_B_01_L_con.GetRelRot()[2]
                                        rotation_modify = c4d.utils.DegToRad(self.GetFloat(303030))
                                        rotation_new = rotation_current + rotation_modify
                                                      
                                        self.finger_B_01_L_con[c4d.ID_BASEOBJECT_REL_ROTATION,c4d.VECTOR_Z] = rotation_new
                                        
                                        c4d.EventAdd()
                                    
                                    # Set the AddEditSlider Back to Zero
                        
                                if msg.GetId() == c4d.BFM_INTERACTEND:
                                 
                                    self.InitValues()
                                    return True
                        
                                return c4d.gui.GeDialog.Message(self, msg, result)
                        
                            def Command (self, id, msg):
                                
                                return True
                            
                        if __name__ == "__main__":
                            dlg = MyDialog()
                            dlg.Open(dlgtype=c4d.DLG_TYPE_ASYNC)
                        
                        1 Reply Last reply Reply Quote 0
                        • M
                          m_adam
                          last edited by m_adam

                          Cause in your BFM_ACTION you call EventAdd, instead call
                          c4d.DrawViews(c4d.DRAWFLAGS_ONLY_ACTIVE_VIEW | c4d.DRAWFLAGS_NO_THREAD | c4d.DRAWFLAGS_NO_REDUCTION | c4d.DRAWFLAGS_STATICBREAK)

                          The main issue is that EventAdd, as its name suggests adds an update event to the event stack, this will be processed when it got the time (meaning when the main thread is free) but since you are in a drag operation, the main thread is occupied by this drag operation.

                          While DrawViews, will as the name said, draw the view right now (take care it's pretty heavy since it implies a call to ExecutePass) so regarding the scene, it may be slow.

                          Cheers,
                          Maxime.

                          MAXON SDK Specialist

                          Development Blog, MAXON Registered Developer

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

                            Thanks @m_adam.
                            First time using the c4d.DrawViews().
                            It works as expected. Thanks for the introduction.

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