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
    • Recent
    • Tags
    • Users
    • Login

    Threading for modelling tools

    Scheduled Pinned Locked Moved PYTHON Development
    7 Posts 0 Posters 637 Views
    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.
    • H Offline
      Helper
      last edited by

      On 18/05/2013 at 11:26, xxxxxxxx wrote:

      Hi,

      I have a pretty diffuse question again. I have a ToolData plugin which modifies the point data of 
      a polygon object attached to the active document. The plugin has a GeDialog gui and also allows
      modifying the main value by dragging in the editor window. The plugin is working technically 
      working fine, but there is still the problem that when I drag a gui slider or live drag in the editor
      window, that update method is not executed until i do release the mouse button. I guess the
      the reason is that i do all calculations from the main thread.

      So are there any resources on how to implement threading for such a task (i have to admit
      that i have generally avoided threading until now).

      here a visual help, if it was difficult to understand  my description of the problem :

      Start:

      While dragging (without update) :

      Update after releasing the mouse button:

      Thanks for reading,
      Happy rendering,
      Ferdinand

      1 Reply Last reply Reply Quote 0
      • H Offline
        Helper
        last edited by

        On 19/05/2013 at 07:57, xxxxxxxx wrote:

        Is something unclear about my question ? It seems to be rather common problem for me. At
        least in python I am not sure if ToolDescriptionData behaves differently in cpp. What I do
        really not understand is why there is no update at all while I am dragging, instead of a
        sluggish GUI/update behaviour because I do run everything from one thread.

        If some code helps for giving me an answer, I will try to show the update cycle on the
        example of an editor view mouse drag. The tool is working with a cache of the objects
        point and polygon data, so you can drag the sliders back and forth and they will always
        relate to the state when the tool has been raised.

            # --- Implements value mouse/editor manipulation and cursor change while drag event. 
            # -----------------------------------------------------------------------------------------------
            def MouseInput(self, doc, data, bd, win, msg) :
                startbc, currentbc, ox, dv = c4d.BaseContainer(), c4d.BaseContainer(), None, None
                # starting mouse state
                isok = gui.GetInputState(c4d.BFM_INPUT_MOUSE, c4d.BFM_INPUT_MOUSELEFT, startbc)
                # start drag
                if isok and startbc[c4d.BFM_INPUT_VALUE]:
                    sx = startbc.GetLong(c4d.BFM_INPUT_X)
                    # loop while mouse drag
                    while gui.GetInputState(c4d.BFM_INPUT_MOUSE, c4d.BFM_INPUT_MOUSELEFT, currentbc) :
                        if currentbc.GetLong(c4d.BFM_INPUT_VALUE) == 0: break
                        gui.SetMousePointer(c4d.MOUSE_ARROW_H)
                        x = currentbc.GetLong(c4d.BFM_INPUT_X)
                        # change dialog values when x != ox
                        if self.Dialog and x != ox:
                            # reset sx if drag vector changed
                            if dv != None and (dv>0) != (x-ox > 0) : sx = x
                            # check for shift qualifier and adjust dragscale
                            if currentbc[c4d.BFM_INPUT_QUALIFIER] == c4d.QSHIFT: 
                                scale = fhPolyTools.ID_MOUSE_DRAGSMALL
                            else : scale = fhPolyTools.ID_MOUSE_DRAGBIG
                            # edit the dialog value with the mouse data
                            dialogvalue = self.Dialog.GetReal(fhPolyTools.IDC_STRAIGHTEN_STRENGHT_EDT)
                            value  = round(c4d.utils.Clamp(0.001, 1, dialogvalue + ((x - sx) * 0.01) * scale), 4)
                            self.Dialog.SetPercent(id = fhPolyTools.IDC_STRAIGHTEN_STRENGHT_EDT, value = value, 
                                                   min = 0.0, max = 100.0, step = 0.01, tristate = False)
                            self.Dialog.Update()
                            # set dragvector and last pos
                            if ox: dv = x - ox
                            ox = x
                    # set cursor back
                    gui.SetMousePointer(c4d.MOUSE_NORMAL)
                return isok
        

        the orange line calls GeDialog.Update() in my tools dialog, which then simply calls back to the 
        tool itself:

            def Update(self) :
                return self.Host.Update(strenght     = self.GetReal(fhPolyTools.IDC_STRAIGHTEN_STRENGHT_EDT), 
                                        relax        = self.GetReal(fhPolyTools.IDC_STRAIGHTEN_RELAX_EDT), 
                                        distribution = self.GetReal(fhPolyTools.IDC_STRAIGHTEN_UNIFORM_CHK))
        

        the ToolData.Update() method loops through some earlier processed ordered point data to 
        apply the transform method ToolData.straightenEdge() which then updates the  point array 
        of the object which is then written into the object. undos are currently implemented in 
        other methods.

            # --- Update method called by the dialog and mouse input
            # --> Bool
            # -----------------------------------------------------------------------------------------------
            def Update(self, strenght, relax, distribution) :
                doc = documents.GetActiveDocument()
                if self.GetData(doc) :
                    # copy cache
                    data = self.PointCache[:]
                    for pointgroup in self.PointGroups.PointGroups:
                        data = self.straightenEdge(data, pointgroup, strenght, True)
                        if not data: return False
                    # update object
                    self.Object.SetAllPoints(data)
                    self.Object.Message(c4d.MSG_CHANGE)
                    c4d.EventAdd()
                    return True
                return False
        

        so which part do i have to put into a thread ?

        1 Reply Last reply Reply Quote 0
        • H Offline
          Helper
          last edited by

          On 19/05/2013 at 09:44, xxxxxxxx wrote:

          Hi littledevil,

          you say the mesh doesn't update while dragging a slider, did I get this straight?
          From the code you have posted, I only see you are doing the operations in MousInput().
          This method is not called while you are dragging a slider in the dialog, you need to
          override the Command() method of the dialog in this case.

          Best,
          -Niklas

          1 Reply Last reply Reply Quote 0
          • H Offline
            Helper
            last edited by

            On 19/05/2013 at 10:01, xxxxxxxx wrote:

            the example posted above is for ToolData.MouseInput(). The example shows the
            case where you chanage the 'main' value (the tools strength) by draginng with 
            the mouse pointer into a editor view. Just like you can do it for the extrude tool for 
            example.

            I have of course also overwritten GeDialog.Command() to register changes made
            in the GeDialog gui. The update behaviour for that is the same.

            # ----------------------------------------------------------------------------------------------- def Command(self, cid, msg) : # Endable/disable apply button if cid == fhPolyTools.IDC_TOOL_REALTIME_CHK: self.Realtime = self.GetBool(fhPolyTools.IDC_TOOL_REALTIME_CHK) self.Enable(fhPolyTools.IDC_TOOL_APPLY_BTN, not self.Realtime) # Apply update if cid == fhPolyTools.IDC_TOOL_APPLY_BTN: self.Update() # Reset values if cid == fhPolyTools.IDC_TOOL_RESET_BTN: self.InitValues() # Invoke update if realtime if self.Realtime: self.Update() return True
            
            1 Reply Last reply Reply Quote 0
            • H Offline
              Helper
              last edited by

              On 19/05/2013 at 10:14, xxxxxxxx wrote:

              I see. Try DrawViews() instead/in addition to EventAdd(). Threading
              wouldn't help at all.

              Best,
              -Nik

              1 Reply Last reply Reply Quote 0
              • H Offline
                Helper
                last edited by

                On 19/05/2013 at 10:28, xxxxxxxx wrote:

                three things :

                1. when dragging in the editor window with the mouse the GeDialog slider is actually
                updatetd properly while dragging

                2. i also tried calling c4d.StopAllThreads() before updating the object, but it had no effect

                3. i already wrote it earlier, what bugs me most, is that the problem is not that everything 
                is very slow, as i am doing verything from one thread, but that it runs smoothly, only that
                the result of the modification is not shown until i release the left mouse button (both for
                the editor and the dialog slider).

                so it feels somehow that c4d limits the update of obejcts while some mouse interaction
                is going on. but i am not sure how for example the extrude tool is avoiding that problem.
                is the object shown by those tools in the editor maybe actually not the object attached 
                to the document, but only a reflection of the tools data cache drawn with the tools Draw()
                method ?

                1 Reply Last reply Reply Quote 0
                • H Offline
                  Helper
                  last edited by

                  On 19/05/2013 at 10:31, xxxxxxxx wrote:

                  Originally posted by xxxxxxxx

                  I see. Try DrawViews() instead/in addition to EventAdd(). Threading
                  wouldn't help at all.

                  Best,
                  -Nik

                  that did the trick, god and i saw myself already sunken into some nasty threading geek stuff.

                  👏

                  happy rendering,
                  ferdinand

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