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

    ReferenceError when trying to Cache a GeClipMap

    Cinema 4D SDK
    python windows r23
    2
    3
    334
    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.
    • ?
      A Former User
      last edited by

      Hello,
      I'm trying to create a crude example of caching the Bitmaps/GeClipMaps and I'm running into an error I can't seem to solve. In the code below, self.UpdateBackgroundCache() works, but self.UpdateBoxCache() does not. In this function, I'm creating a GeClipMap, initializing it, drawing a rectangle, and storing the clipmap's BaseBitmap as a property of the GeUserArea. I keep getting the error:

      ReferenceError: the object 'c4d.bitmaps.BaseBitmap' is not alive
      

      Can anyone help me understand what is going wrong? Thank you!

      import c4d
      from c4d import gui,bitmaps
      
      GADGET_ID_GEUSERAREA = 10000
      
      def drawColorBitmap(w,h,r,g,b):
          r = int(r * 255)
          g = int(g * 255)
          b = int(b * 255)
          bmp = bitmaps.BaseBitmap()
          bmp.Init(w, h, 24)
          for wPixel in range(w):
              for hPixel in range(h):
                  bmp.SetPixel(wPixel, hPixel, r, g, b)
          return bmp
      
      class MyUserArea(c4d.gui.GeUserArea):
          def __init__(self):
              self.boxX = 50
              self.boxY = 50
              self.boxWidth = 50
              self.boxHeight = 50
              self.boxAngle = 0
              self.boxOpacity = 1.0
              self.bgCache = None
              self.boxCache = None
      
          def UpdateBackgroundCache(self,x2,y2):
              self.bgCache = drawColorBitmap(x2,y2,0.35,0.35,0.35)
      
          def UpdateBoxCache(self):
              rMap = c4d.bitmaps.GeClipMap()
              rMap.Init(self.boxWidth, self.boxHeight)
              rMap.BeginDraw()
              rMap.SetDrawMode(c4d.GE_CM_DRAWMODE_BLEND,
                  c4d.GE_CM_SRC_MAX_OPACITY)
              rMap.SetColor(255,0,0,255)
              rMap.FillRect(0,0,50,self.boxHeight)
              rMap.EndDraw()
              self.boxCache = rMap.GetBitmap()        
      
          def GetMinSize(self):
              return 300,150
      
          def UpdateCache(self):
              #Cache Background
              if self.bgCache == None:
                  self.UpdateBackgroundCache(self.GetWidth(),self.GetHeight())
      
              #Cache Red Box
              if self.boxCache == None:
                  self.UpdateBoxCache()
      
              #Blit Red Box with Background
              clipMap = bitmaps.GeClipMap()
              clipMap.InitWithBitmap(self.bgCache, None)
              clipMap.BeginDraw()
              clipMap.SetDrawMode(c4d.GE_CM_DRAWMODE_BLEND,
                  c4d.GE_CM_SRC_MAX_OPACITY)
      
              rectMap = bitmaps.GeClipMap()
              rectMap.InitWithBitmap(self.boxCache, None)
      
              clipMap.Blit(self.boxX, self.boxY,
                  rectMap, 0, 0, self.boxWidth, self.boxHeight,
                  rop = c4d.GE_CM_BLIT_COL)
      
              clipMap.EndDraw()
              bmp = clipMap.GetBitmap()
              return bmp
      
          def DrawMsg(self, x1, y1, x2, y2, msg):
              cache = self.UpdateCache()
              self.DrawBitmap(cache, x1, y1, x2, y2, 0, 0, 300, 150, c4d.BMP_NORMAL | c4d.BMP_ALLOWALPHA)
      
      class ExampleDialog(c4d.gui.GeDialog):
          geUserArea = MyUserArea()
      
          def CreateLayout(self):
              self.SetTitle("ClipMap")
              self.AddUserArea(GADGET_ID_GEUSERAREA, c4d.BFH_CENTER | c4d.BFH_SCALE | c4d.BFV_CENTER | c4d.BFV_SCALE, 300, 150)
              self.AttachUserArea(self.geUserArea, GADGET_ID_GEUSERAREA)
              return True
      
      def main():
          global dlg
          dlg = ExampleDialog()
          dlg.Open(c4d.DLG_TYPE_ASYNC, defaultw=400, defaulth=250, xpos=-2, ypos=-2)
      
      if __name__=='__main__':
          main()
      
      1 Reply Last reply Reply Quote 0
      • ferdinandF
        ferdinand
        last edited by ferdinand

        Hi @blastframe,

        thank you for reaching out to us. The error ReferenceError: the object 'xyz' is not alive means that something has deallocated the object you are trying to reference. This happens because you have two competing memory management systems, one provided by Python, its gc, and one provided by Cinema's C++ API. In this case the method GeClipMap.GetBitmap() (Link to C++ Doc) only does return a pointer, i.e. an object that is owned by the GeClipMap. To avoid the error, you have either to avoid the GeClipMap being garbage collected or clone the bitmap so that you have full ownership. I "fixed" your code by just plastering in two .GetClone().

        Cheers,
        Ferdinand

        import c4d
        from c4d import gui,bitmaps
        
        GADGET_ID_GEUSERAREA = 10000
        FOO = None
        def drawColorBitmap(w,h,r,g,b):
            r = int(r * 255)
            g = int(g * 255)
            b = int(b * 255)
            bmp = bitmaps.BaseBitmap()
            bmp.Init(w, h, 24)
            for wPixel in range(w):
                for hPixel in range(h):
                    bmp.SetPixel(wPixel, hPixel, r, g, b)
            return bmp
        
        class MyUserArea(c4d.gui.GeUserArea):
            def __init__(self):
                self.boxX = 50
                self.boxY = 50
                self.boxWidth = 50
                self.boxHeight = 50
                self.boxAngle = 0
                self.boxOpacity = 1.0
                self.bgCache = None
                self.boxCache = None
        
            def UpdateBackgroundCache(self,x2,y2):
                self.bgCache = drawColorBitmap(x2,y2,0.35,0.35,0.35)
        
            def UpdateBoxCache(self):
                rMap = c4d.bitmaps.GeClipMap()
                rMap.Init(self.boxWidth, self.boxHeight)
                rMap.BeginDraw()
                rMap.SetDrawMode(c4d.GE_CM_DRAWMODE_BLEND,
                    c4d.GE_CM_SRC_MAX_OPACITY)
                rMap.SetColor(255,0,0,255)
                rMap.FillRect(0,0,50,self.boxHeight)
                rMap.EndDraw()
                # The bitmap returned by GeClipMap.GetBitmap() is owned by the 
                # GeClipMap. Leaving the scope of this function will free the
                # GeClipMap and with it the attached BaseBitmap.
                bitmap = rMap.GetBitmap()
                # Either clone the bitmap or also reference the GeClipMap so that
                # it won't be deallocated on exit.
                self.boxCache = bitmap.GetClone()
        
            def GetMinSize(self):
                return 300,150
        
            def UpdateCache(self):
                #Cache Background
                if self.bgCache == None:
                    self.UpdateBackgroundCache(self.GetWidth(),self.GetHeight())
        
                #Cache Red Box
                if self.boxCache == None:
                    self.UpdateBoxCache()
        
                #Blit Red Box with Background
                clipMap = bitmaps.GeClipMap()
                clipMap.InitWithBitmap(self.bgCache, None)
                clipMap.BeginDraw()
                clipMap.SetDrawMode(c4d.GE_CM_DRAWMODE_BLEND,
                    c4d.GE_CM_SRC_MAX_OPACITY)
        
                rectMap = bitmaps.GeClipMap()
                rectMap.InitWithBitmap(self.boxCache, None)
        
                clipMap.Blit(self.boxX, self.boxY,
                    rectMap, 0, 0, self.boxWidth, self.boxHeight,
                    rop = c4d.GE_CM_BLIT_COL)
        
                clipMap.EndDraw()
                # The same thing applies here.
                bmp = clipMap.GetBitmap()
                return bmp.GetClone()
        
            def DrawMsg(self, x1, y1, x2, y2, msg):
                cache = self.UpdateCache()
                self.DrawBitmap(cache, x1, y1, x2, y2, 0, 0, 300, 150, c4d.BMP_NORMAL | c4d.BMP_ALLOWALPHA)
        
        class ExampleDialog(c4d.gui.GeDialog):
            geUserArea = MyUserArea()
        
            def CreateLayout(self):
                self.SetTitle("ClipMap")
                self.AddUserArea(GADGET_ID_GEUSERAREA, c4d.BFH_CENTER | c4d.BFH_SCALE | c4d.BFV_CENTER | c4d.BFV_SCALE, 300, 150)
                self.AttachUserArea(self.geUserArea, GADGET_ID_GEUSERAREA)
                return True
        
        def main():
            global dlg
            dlg = ExampleDialog()
            dlg.Open(c4d.DLG_TYPE_ASYNC, defaultw=400, defaulth=250, xpos=-2, ypos=-2)
        
        if __name__=='__main__':
            main()
        

        MAXON SDK Specialist
        developers.maxon.net

        ? 1 Reply Last reply Reply Quote 0
        • ?
          A Former User @ferdinand
          last edited by

          @zipit Thank you very much, Ferdinand. This helped me a lot!

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