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
    • Login

    Strange behavior of UserArea docked with Timeline

    Cinema 4D SDK
    r21 s24 python windows
    2
    5
    797
    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.
    • K
      kng_ito
      last edited by

      Hi,

      I am trying to use UserArea to draw a simple 4x4 grid in a dialog, and docking it with the Timeline.
      The issue is when I click around the UserArea and the Timeline(which is built-in UserArea??), top and bottom edges of the UserArea behave strangely.
      And when I tweak the size of the dialog to redraw the UserArea, it returns to normal.

      video:
      https://drive.google.com/file/d/1arqRD-4y52WJfyI3QnlgN3oBpsuvfxcj/view?usp=sharing

      .pyp:

      import c4d
      import os
      
      PLUGIN_ID           = 9366042 # Random Number
      ID_UA               = 1000
      
      class TestUserArea(c4d.gui.GeUserArea):
          def DrawMsg(self, x1, y1, x2, y2, msg):
              self.OffScreenOn()
              self.SetClippingRegion(x1, y1, x2, y2)
      
              # Draw Background
              black = c4d.Vector(0)
              self.DrawSetPen(black)
              self.DrawRectangle(x1, y1, x2, y2)
      
              # Draw Grid
              white = c4d.Vector(1)
              self.DrawSetPen(white)
              w = self.GetWidth()
              h = self.GetHeight()
              for i in range(5):
                  xpos = int(i*0.25*w)
                  self.DrawLine(xpos, y1, xpos, y2)
                  ypos = int(i*0.25*h)
                  self.DrawLine(x1, ypos, x2, ypos)
      
      class TestDialog(c4d.gui.GeDialog):
          def CreateLayout(self):
              self.ua = TestUserArea()
              self.AddUserArea(ID_UA, c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT)
              self.AttachUserArea(self.ua, ID_UA)
              return True
      
      class TestData(c4d.plugins.CommandData):
          dialog = None
      
          def Execute(self, doc):
              if self.dialog is None:
                  self.dialog = TestDialog()
              return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=PLUGIN_ID)
      
          def RestoreLayout(self, sec_ref):
              if self.dialog is None:
                  self.dialog = TestDialog()
              return self.dialog.Restore(pluginid=PLUGIN_ID, secret=sec_ref)
      
      if __name__ == "__main__":
          path, file = os.path.split(__file__)
          bmp = c4d.bitmaps.BaseBitmap()
          bmp.InitWith(os.path.join(path, "res", "icon.tif"))
          c4d.plugins.RegisterCommandPlugin(id=PLUGIN_ID, str="TestUserArea", info=0,
                                            help="", dat=TestData(), icon=bmp)
      

      The same issue can be seen with the official plugin sample Py-MemoryViewer.
      In this one, Redraw() is called frequently, so it returns to normal display immediately.
      https://drive.google.com/file/d/1vGgoPJ3ierUFBNdD92hUl7UuaKjkcE--/view?usp=sharing

      I know that this issue is not that critical, but is there any solution? Thank you.

      1 Reply Last reply Reply Quote 0
      • ManuelM
        Manuel
        last edited by

        Hi,

        i tested your code with S24 and was unable to reproduce the behavior. Wath is the version that you are using?

        Cheers,
        Manuel

        MAXON SDK Specialist

        MAXON Registered Developer

        K 1 Reply Last reply Reply Quote 0
        • K
          kng_ito @Manuel
          last edited by kng_ito

          @m_magalhaes
          The versions I have checked are R21.207 and S24.037 on Windows.
          I also checked with S24 on Mac and there was no problem.

          The problem shows up when it is docked next to the timeline, especially in the lower left corner of the animation layout like this.

          1 Reply Last reply Reply Quote 0
          • ManuelM
            Manuel
            last edited by Manuel

            hi,

            I was able to reproduce it, after asking to @m_adam it's not a bug it's an optimisation.
            The screen redraw happens from top left to bottom right. So, the coordinates sent to the UserArea will only contain what really need to be redraw. In our example, we don't take that into account.

            a1ffbaf3-7bd6-4955-8d24-f589faa5eee2-image.png
            As you can see in this screenshot, the UserArea is sliced in two but align with the attribut manager menu. (because I've clicked there)
            The Draw function is called twice, one for the top part and one for the bottom part. That's why the grid is different and the memory appears various times.

            To fix that you can simply not redraw if the size sent to the DrawMsg function are not correct. To know if they are correct you can simply use the Sized function to retrieve the size of the UserArea and store it locally.

              def Sized(self, w, h):
                    self.h = h
                    self.w = w
            
                def DrawMsg(self, x1, y1, x2, y2, msg_ref):
                    """This Method is called automatically when Cinema 4D Draw the Gadget.
            
                    Args:
                        x1 (int): The upper left x coordinate.
                        y1 (int): The upper left y coordinate.
                        x2 (int): The lower right x coordinate.
                        y2 (int): The lower right y coordinate.
                        msg_ref (c4d.BaseContainer): The original mesage container.
                    
                    """
                    if x2-x1 < self.w:
                        return 
                    if y2-y1 < self.h:
                        return
            

            Or you can use the same technique than @m_adam in this thread
            Catch the draw message and call yourself the DrawMsg with the maximum size. (redraw everything)

            def Message(self, msg, result):
                    # Catch the draw message to cancel it (return True)
                    # and call ourself the DrawMsg with the dimension we expect
                    if msg.GetId() == c4d.BFM_DRAW:
                        self.DrawMsg(0, 0, self.width, self.height, c4d.BaseContainer())
            
                        return True
                
                    return c4d.gui.GeUserArea.Message(self, msg, result)
            
            

            Cheers,
            Manuel

            MAXON SDK Specialist

            MAXON Registered Developer

            1 Reply Last reply Reply Quote 1
            • K
              kng_ito
              last edited by

              Hi,

              It looks like the problem got solved by Sized function.
              Thanks a lot @m_magalhaes and @m_adam !!

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