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

    Scroll area in UA

    Scheduled Pinned Locked Moved PYTHON Development
    5 Posts 0 Posters 1.4k 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 12/07/2018 at 07:46, xxxxxxxx wrote:

      I have a User Area with multiple (vertical) images in it.
      Now I want to add a vertical scroll bar to scroll through the images.
      But I do not understand fully, the relation between the ua size and the visible area size?

      What is the best place to define the visible area?
      How do I use SetVisibleArea() when the user area is resized?

      A little example would help me for certain!

      Here the code.

      import c4d
      from c4d import bitmaps, gui, plugins, utils, documents
      import collections, os, sys
        
      PLUGIN_ID = 10000010 #TestID only!!!!!!!!!!!!
      scrollGroup = 1001
        
      class Area(gui.GeUserArea) :
        
          def __init__(self) :
              self.bmp = c4d.bitmaps.BaseBitmap()
        
          def Sized(self, w, h) :
              print "Sized: ", w,h
              return     
        
          def DrawMsg(self, x1, y1, x2, y2, msg) :
          
              self.DrawRectangle(x1, y1, x2, y2)                                #Draws the UA rectangle area
              
              path = os.path.join(os.path.dirname(__file__), "Library", "Airbus_A380.jpg")
              result, ismovie = self.bmp.InitWith(path)
              
              x1 = 10
              if result == c4d.IMAGERESULT_OK:
                  y1 = 10
                  self.DrawBitmap(self.bmp, x1, y1, 200, 200, 0, 0, 200, 200, c4d.BMP_NORMAL)    #first        
                  y1 = 220
                  self.DrawBitmap(self.bmp, x1, y1, 200, 200, 0, 0, 200, 200, c4d.BMP_NORMAL)    #second     
                  y1 = 430
                  self.DrawBitmap(self.bmp, x1, y1, 200, 200, 0, 0, 200, 200, c4d.BMP_NORMAL)    #third
          
      class MyDialog(gui.GeDialog) :
        
          def __init__(self, area) :
              self.area = area
              
          def CreateLayout(self) :
              self.ScrollGroupBegin(scrollGroup, c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT, c4d.SCROLLGROUP_VERT)
              
              self.GroupBegin(1003, c4d.BFH_CENTER | c4d.BFV_CENTER, cols=1)
              self.GroupBorderNoTitle(c4d.BORDER_NONE)
              self.GroupBorderSpace(0, 0, 0, 20)
              self.AddUserArea(1, c4d.BFH_LEFT | c4d.BFV_TOP) 
              self.AttachUserArea(self.area, 1)
              self.GroupEnd() #end UA group
              
              self.GroupEnd() #end scrollgroup
        
              self.GroupBegin(0, flags=c4d.BFH_FIT, cols=1)
              self.AddButton(1027, flags=c4d.BFH_LEFT, initw=100, name="Test")  #Test button
              self.GroupEnd()
        
              return True
                      
          def Command(self, id, msg) :
        
              if (id == 1027) :
                  print self.GetVisibleArea(scrollGroup)   
                  self.SetVisibleArea(scrollGroup, 0,0,250,250)
        
                  self.area.Redraw()
                  return True
                  
              return True
              
      class MBLibrary(plugins.CommandData) :
          
          area = Area()
          dialog = None
        
          def Execute(self, doc) :
              if self.dialog is None: self.dialog = MyDialog(self.area)
              return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=PLUGIN_ID, defaultw=500, defaulth=120)
          def RestoreLayout(self, sec_ref) :
              if self.dialog is None: self.dialog = MyDialog(self.area)
              return self.dialog.Restore(pluginid=PLUGIN_ID, secret=sec_ref)
        
      if __name__ == "__main__":
        
          pluginString = "MB Library V01"
         
          bmp = bitmaps.BaseBitmap()
          dir, f = os.path.split(__file__)
          fn = os.path.join(dir, "res", "icon.tif")
          bmp.InitWith(fn)
          okyn = plugins.RegisterCommandPlugin(id=PLUGIN_ID, str=pluginString, info=0, help=pluginString, dat=MBLibrary(), icon=bmp)
                                        
          if (okyn) : 
              print pluginString + " initialized."
          else: print "Error initializing " + pluginString
        
      
      
      1 Reply Last reply Reply Quote 0
      • H Offline
        Helper
        last edited by

        On 16/07/2018 at 07:48, xxxxxxxx wrote:

        Hi Pim,

        The ua size is the total size of the GeUserArea, without any scrolling, so it's the full GeUserArea size, which can be bigger than the screen of course.
        The visible area is the part which is currently visible in this GeUserArea.

        Let' take an example, I get a ua of a 2000 pixels height, but my dialog is only 500 pixels height. So the Visible area will only be 500 pixels, but from the 2000 pixels, displayed pixels can be from 0 to 500 or either 1000 to 1500.

        But looking at your code there is few adjustments to make. For example, you initialize the parent group to BFH/BFV_CENTER, so by default a GeUserArea it will be a square of 4,4 pixels since there is nothing inside, please use BFH/BFV_SCALEFIT instead, it will then automatically scale according to the size you define in GetMinSize function.

        On a side note since you are going to draw more than it's allowed (by that I mean you will draw from pixel 0 to 2000 and then crop it using a scrollGroup in order to allow custom display size) so make sure to call SetClippingRegion in the DrawMsg function.

        Here is your example fixed

        import c4d
        from c4d import bitmaps, gui, plugins, utils, documents
        import collections, os, sys
          
        PLUGIN_ID = 10000010 #TestID only!!!!!!!!!!!!
        scrollGroup = 1001
          
        class Area(gui.GeUserArea) :
          
            def __init__(self) :
                self.bmp = c4d.bitmaps.BaseBitmap()
          
            def Sized(self, w, h) :
                print "Sized: ", w,h
                return
          
            def GetMinSize(self) :
              #do a calculation here
              return 400, 430 + 200
          
            def DrawMsg(self, x1, y1, x2, y2, msg) :
                self.DrawSetPen(c4d.COLOR_BG_HIGHLIGHT)
                self.SetClippingRegion(x1, y1, x2, y2)
                self.DrawRectangle(x1, y1, x2, y2)                                #Draws the UA rectangle area
                
                path = os.path.join(os.path.dirname(__file__), "Library", "Airbus_A380.jpg")
                result, ismovie = self.bmp.InitWith(path)
                
                x1 = 10
                if result == c4d.IMAGERESULT_OK:
                    y1 = 10
                    self.DrawBitmap(self.bmp, x1, y1, 200, 200, 0, 0, 200, 200, c4d.BMP_NORMAL)    #first        
                    y1 = 220
                    self.DrawBitmap(self.bmp, x1, y1, 200, 200, 0, 0, 200, 200, c4d.BMP_NORMAL)    #second     
                    y1 = 430
                    self.DrawBitmap(self.bmp, x1, y1, 200, 200, 0, 0, 200, 200, c4d.BMP_NORMAL)    #third
            
        class MyDialog(gui.GeDialog) :
          
            def __init__(self, area) :
                self.area = area
                
            def CreateLayout(self) :
                self.ScrollGroupBegin(scrollGroup, c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT, c4d.SCROLLGROUP_VERT)
                
                self.GroupBegin(1003, c4d.BFH_SCALEFIT|c4d.BFH_SCALEFIT, cols=1)
                self.GroupBorderSpace(0, 0, 0, 20)
                self.AddUserArea(1005, c4d.BFH_SCALEFIT|c4d.BFH_SCALEFIT)
                self.AttachUserArea(self.area, 1005)
                self.GroupEnd() #end UA group
                
                self.GroupEnd() #end scrollgroup
          
                self.GroupBegin(0, flags=c4d.BFH_FIT, cols=1)
                self.AddButton(1027, flags=c4d.BFH_LEFT, initw=100, name="Test")  #Test button
                self.GroupEnd()
          
                return True
                        
            def Command(self, id, msg) :
          
                if (id == 1027) :
                    sizes = self.GetVisibleArea(scrollGroup)
                    ySize = sizes["y2"] - sizes["y1"] # Get the current size displayed
                    #Jump to the 2nd picture
                    print self.area.GetHeight()
                    self.SetVisibleArea(scrollGroup, 0,220, 0, 220 + ySize)
          
                    #self.area.Redraw()
                    return True
                    
                return True
          
                
        class MBLibrary(plugins.CommandData) :
            
            area = Area()
            dialog = None
          
            def Execute(self, doc) :
                if self.dialog is None: self.dialog = MyDialog(self.area)
                return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=PLUGIN_ID, defaultw=500, defaulth=120)
            def RestoreLayout(self, sec_ref) :
                if self.dialog is None: self.dialog = MyDialog(self.area)
                return self.dialog.Restore(pluginid=PLUGIN_ID, secret=sec_ref)
          
        if __name__ == "__main__":
          
            pluginString = "MB Library V01"
           
            bmp = bitmaps.BaseBitmap()
            dir, f = os.path.split(__file__)
            fn = os.path.join(dir, "res", "icon.tif")
            bmp.InitWith(fn)
            okyn = plugins.RegisterCommandPlugin(id=PLUGIN_ID, str=pluginString, info=0, help=pluginString, dat=MBLibrary(), icon=bmp)
                                          
            if (okyn) :
                print pluginString + " initialized."
            else: print "Error initializing " + pluginString
        

        If you have any questions please let me know,
        Cheers,
        Maxime

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

          On 17/07/2018 at 03:30, xxxxxxxx wrote:

          Great explanation!
          Thanks, Pim

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

            On 18/07/2018 at 08:38, xxxxxxxx wrote:

            Sorry, more questions on scrolling UA.

            Next step is to size the images / thumbnails to be displayed.

            For example, when I click the test button, the size of the thumbnail is decreased from 200 to 20.
            Displaying the sized thumbnails is no problem, but how to size the vertical scroll bar, thus that it indicates the new size?

            Do I use GetMinSize() or SetVisibleArea().
            If so, where and when do I call GetMinSize()?

                    if (id == 1027) :
                        newSize = 20
                        self.area.GetMinSize()
                        print "SetVisibleArea: ", self.SetVisibleArea(scrollGroup, 0, 0, 400, 3*(newSize+10))
                        self.area.Redraw()
            
            1 Reply Last reply Reply Quote 0
            • H Offline
              Helper
              last edited by

              On 18/07/2018 at 09:39, xxxxxxxx wrote:

              Hi Scott,

              You don't have to call GetMinSize, it's called automatically when the parent(owner of the GeUserArea) is drawn/sized, in your case, group 1003 which is owned by your ScrollGroup.
              So in order to support what's, you want I've made few adjustments.

              class Area(gui.GeUserArea) :
                  size = 300
                  pictureCnt = 3
                
                  def GetMinSize(self) :
                      return 400, self.pictureCnt * self.size
                
                  def DrawMsg(self, x1, y1, x2, y2, msg) :
                      self.DrawSetPen(c4d.COLOR_BG_HIGHLIGHT)
                      self.SetClippingRegion(x1, y1, x2, y2)
                      self.DrawRectangle(x1, y1, x2, y2)  # Draws the UA rectangle area
                
                      path = os.path.join(os.path.dirname(__file__), "Library", "Airbus_A380.jpg")
                      result, ismovie = self.bmp.InitWith(path)
                
                      x1 = 10
                      if result == c4d.IMAGERESULT_OK:
                          for i in xrange(0, self.pictureCnt) :
                              y1 = self.size * i
                              self.DrawBitmap(self.bmp, x1, y1, self.size, self.size, 0, 0, self.size, self.size, c4d.BMP_NORMAL)
              

              and in the GeDialog

              if (id == 1027) :
              	self.area.size = 400
              	self.LayoutChanged(scrollGroup)
              	sizes = self.GetVisibleArea(scrollGroup)
              	ySize = sizes["y2"] - sizes["y1"]  # Get the current size displayed
              	pictureId = 1 # ID start from 0
              	self.SetVisibleArea(scrollGroup, 0, self.area.size * pictureId, 0, self.area.size * pictureId + ySize)
              	return True
              

              So we define the new size of the picture then we call self.LayoutChanged(scrollGroup) which will call DrawMsg and also GetMinSize in order to know the size of the UserArea then finally our scrollGroup is drawn according to these data. Then after is up to us to scroll where we want.

              Maybe off topic, but I did a library with thumbnail on my personal time some time ago, it's available in here you may found some interesting stuff in it.

              Again if you have any question, let me know! 🙂
              Cheers,
              Maxime

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