GeUserArea.DrawBitmap
-
On 07/12/2017 at 12:06, xxxxxxxx wrote:
User Information:
Cinema 4D Version: R19
Platform: Mac OSX ;
Language(s) : PYTHON ;---------
Hi,there seems to be an issue with GeUserArea.DrawBitmap().
Not only that BMP_DiMIMAGE is listed twice in the docs, but also the attribute of the function "mode" ,except BMP_NORMAL, can´t be assigned.
Especially BMP_ALLOWALPHA is really needed.cheers
Martin -
On 08/12/2017 at 08:09, xxxxxxxx wrote:
Hi Martin,
instead of drawing into the GeUserArea directly, we recommend to do all drawing (especially with alpha channels) into a GeClipMap. And then in the end only use DrawBitmap() with BMP_NORMAL and BMP_ALLOWALPHA to draw the GeClipMap (or rather the BaseBitrmap retrieved from the GeClipMap) into the GeUserArea. In this way BMP_ALLOWALPHA works for me as expected.
I borrowed some of Niklas' code from this thread:
import c4d import c4d.gui as gui import c4d.bitmaps as bitmaps class Area(gui.GeUserArea) : def __init__(self, w = 20, h = 20, r = 1, g = 1, b = 1) : self.bmp = bitmaps.GeClipMap() self.bmp.Init(w, h) self.bmp.BeginDraw() self.w = w self.h = h r = int(r * 255) g = int(g * 255) b = int(b * 255) for x in xrange(w) : for y in xrange(h) : a = (x * 4 / float(w))**(y / float(h)) try: a = 1 / (x**2 / float(w)**2) * a except: a = 0 a = int(a * 255) self.bmp.SetPixelRGBA(x, y, r, g, b, a) self.bmp.EndDraw() def DrawMsg(self, x1, y1, x2, y2, msg) : #self.DrawSetPen(c4d.Vector(0, 0, 0)) # changes bg color seen through alpha w, h = self.w, self.h self.DrawBitmap(self.bmp.GetBitmap(), 0, 0, w, h, 0, 0, w, h, c4d.BMP_NORMAL | c4d.BMP_ALLOWALPHA) def GetMinSize(self) : return self.w, self.h class Dialog(gui.GeDialog) : def __init__(self, area) : self.area = area def CreateLayout(self) : self.AddUserArea(1000, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT) self.AttachUserArea(self.area, 1000) return True def main() : area = Area(200, 200, 1.0, 0.66, 0.24) dlg = Dialog(area) dlg.Open(c4d.DLG_TYPE_MODAL) if __name__ == "__main__": main()
The double entry in the Python documentation will be fixed.
For now, I have moved this thread into the Python sub-forum. If you still feel BMP_ALLOWALPHA is buggy, please provide us with some more detail.
-
On 08/12/2017 at 11:39, xxxxxxxx wrote:
Hi Andreas,
I used GeClipMap() before, but no luck.
Confident through Niklas example I investigated further and the error occurred because a negative value was set to ww and wh attribute of the function.
In this special case BMP_NORMAL is valid, while the other modes are not, confusing...
An abs() function or an exception raise would be nice in GeUserArea.DrawBitmap().thanks,
Martin -
On 11/12/2017 at 01:08, xxxxxxxx wrote:
Hi Andreas,
thanks for your help,
some additional notes and a working example:
- drawing everything into one clipmap and at the end draw this clipmap to the userarea,
seems to be the only working way of layering several alpha bitmaps on top of each other.- it is important to set to c4d.GE_CM_DRAWMODE_BLEND in GeClipMap.SetDrawMode(),
otherwise the alpha channel is not being used.- it is important to overwrite GeUserArea.Sized() ,
otherwise the clipmap won't show upIf you feel like it´s ok, you can mark this thread as solved.
import c4d from c4d import bitmaps OK = 1003 SHOW = 1005 USERAREA = 1004 class Canvas(c4d.gui.GeUserArea) : def __init__(self) : self.w = self.GetWidth() self.h = self.GetHeight() self.rectangle=[-1,-1,-1,-1] self.drawMap = bitmaps.GeClipMap() ########################### #UserArea Functions def DrawMsg(self, x1, y1, x2, y2, msg) : self.OffScreenOn() #draw everything in one clip map self.drawMap.BeginDraw() #draw background self.drawMap.SetColor(51, 51, 51) self.drawMap.FillRect(x1, y1, x2, y2) #ensure that there is an object to draw the icon from obj=doc.GetFirstObject() if not obj: print "no item" self.drawMap.SetColor(255,170, 24) self.drawMap.TextAt(3,3,"Please, insert an object into the scene for testing!") self.drawMap.EndDraw() self.DrawBitmap(self.drawMap.GetBitmap(), 0, 0, self.GetWidth(), self.GetHeight(), 0, 0, self.GetWidth(), self.GetHeight(), c4d.BMP_NORMAL) return #draw text self.drawMap.SetColor(255,170, 24) self.drawMap.TextAt(3,3,str(50000000)) #draw a rectangle self.drawMap.SetColor(100, 100, 100, 255) self.drawMap.FillRect(150, 0, 250, 50) #needs to be set to draw alpha maps--------------------# self.drawMap.SetDrawMode(c4d.GE_CM_DRAWMODE_BLEND, 255) #------------------------------------------------------# #draw icon with alpha objicon = obj.GetIcon() bmp = objicon['bmp'] wbmp = objicon['w'] hbmp = objicon['h'] xbmp = objicon['x'] ybmp = objicon['y'] icon = bitmaps.BaseBitmap() icon.Init(wbmp,hbmp,depth=24) bmp.CopyPartTo(icon, xbmp, ybmp, wbmp, hbmp) alphaicon =icon.GetInternalChannel() iconclip = bitmaps.GeClipMap() iconclip.InitWithBitmap(icon,alphaicon) self.drawMap.Blit( 50,50, iconclip, 0, 0, wbmp, hbmp, rop = c4d.GE_CM_BLIT_COL) #draw drag self.drawMap.SetColor(200, 200, 255, 100) xdr,ydr,x2dr,y2dr = self.toolDragSortEx() self.drawMap.FillRect(xdr,ydr,x2dr,y2dr) self.drawMap.SetColor(255, 255, 255, 255) self.drawMap.Rect(xdr,ydr,x2dr,y2dr) self.drawMap.EndDraw() self.DrawBitmap(self.drawMap.GetBitmap(), 0, 0, self.GetWidth(), self.GetHeight(), 0, 0, self.GetWidth(), self.GetHeight(), c4d.BMP_NORMAL) return def Sized(self, w, h) : self.w=w self.h=h #needs to be set---------------------------------------# self.drawMap.Destroy() self.drawMap.Init(self.w, self.h) #------------------------------------------------------# return def GetMinSize(self) : return self.w, self.h def InputEvent(self, msg) : dev = msg.GetLong(c4d.BFM_INPUT_DEVICE) if dev == c4d.BFM_INPUT_MOUSE: return self.HandleMouseEvents(msg) return False def HandleMouseEvents(self, msg) : #init values mousex = msg.GetLong(c4d.BFM_INPUT_X) mousey = msg.GetLong(c4d.BFM_INPUT_Y) start_x = mx = mousex - self.Local2Global()['x'] start_y = my = mousey - self.Local2Global()['y'] #drag interaction state = c4d.BaseContainer() self.MouseDragStart(c4d.KEY_MLEFT,start_x, start_y, c4d.MOUSEDRAGFLAGS_DONTHIDEMOUSE| c4d.MOUSEDRAGFLAGS_NOMOVE ) while True: result, dx, dy, channels = self.MouseDrag() #end of Drag if result == c4d.MOUSEDRAGRESULT_ESCAPE: break if not self.GetInputState(c4d.BFM_INPUT_MOUSE, c4d.BFM_INPUT_MOUSELEFT, state) : print "mouse right etc" break if state[c4d.BFM_INPUT_VALUE] == 0: #mouse release self.rectangle = [-1,-1,-1,-1] self.Redraw() break #not moving, continue if dx == 0 and dy == 0: continue #draging mx -= dx my -= dy #start drag with rectangle self.rectangle = [start_x,start_y,mx,my] self.Redraw() return True def toolDragSortEx(self) : if self.rectangle[0]<self.rectangle[2]: x1,x2 = self.rectangle[0],self.rectangle[2] else: x1,x2 = self.rectangle[2],self.rectangle[0] if self.rectangle[1]<self.rectangle[3]: y1,y2 = self.rectangle[1],self.rectangle[3] else: y1,y2 = self.rectangle[3],self.rectangle[1] return x1,y1,x2,y2 class AreaDialog(c4d.gui.GeDialog) : def __init__(self,userarea) : self.userarea = userarea def CreateLayout(self) : self.SetTitle("USERAREATEST") self.AddUserArea(USERAREA, c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT) self.AttachUserArea(self.userarea, USERAREA) self.AddButton(OK, c4d.BFH_LEFT, name="OK") self.AddButton(SHOW, c4d.BFH_LEFT, name="Show bitmap") return True def Command(self, id, msg) : if id==OK: self.Close() return True if id==SHOW: bitmaps.ShowBitmap(self.userarea.drawMap.GetBitmap()) return True def main() : userarea = Canvas() dialog = None dialog = AreaDialog(userarea) dialog.Open(dlgtype=c4d.DLG_TYPE_MODAL_RESIZEABLE, xpos=100, ypos=100, defaultw=350, defaulth=500) if __name__=='__main__': main()
cheers,
Martin -
On 11/12/2017 at 09:52, xxxxxxxx wrote:
Hi Martin,
thanks for your detailed final conclusion.
Just a note on GeUserArea.Sized() : This function should actually always be implemented for a GeUserArea to properly react to resizing requests (well, if you have elements that need adaption like your bitmap for example).
-
On 12/12/2017 at 04:33, xxxxxxxx wrote:
Hi Andreas,
thanks for the advice.
A last aesthetical kind of question on this subject.
How should this clipmap draw solution draw sharp alphas and typo into the userarea?
The clipmap is always blown up to screen pixels after DrawBitmap .
Is there any solution?cheers,
Martin -
On 13/12/2017 at 10:16, xxxxxxxx wrote:
Hi Martin,
I'm not sure I understand. Are you saying the GeClipmap gets modified/scaled by DrawBitmap()?
Looking at your DrawBitmap() call in the code above, you are passing the same GeUserArea width and height into "both" parameters of DrawBitmap(), while actually the second width and height should be the size of your bitmap. Could that be part of the problem? -
On 13/12/2017 at 12:42, xxxxxxxx wrote:
Hi Andreas,
the clipmap was initialized with the width and height of the userarea. That´s why it makes no difference if I use .Getwidth() from the userarea or .GetBw() from the clipmap.
The example code shows the loss of quality/sharpness comparing drawing text with GeUserArea.DrawText and drawing text on the clipmap and afterwards draw the bitmap from the clipmap.You can simply replace the following DrawMsg function in my code above, to give it a try.
Thanks in advance!
Martindef DrawMsg(self, x1, y1, x2, y2, msg) : self.OffScreenOn() #draw everything in one clip map self.drawMap.BeginDraw() #draw background self.drawMap.SetColor(51, 51, 51) self.drawMap.FillRect(x1, y1, x2, y2) #draw text self.drawMap.SetColor(255,170, 24) self.drawMap.TextAt(3,10,"Motion-Tracker-Tracks können jetzt auch runde Suchmuster verwenden. ") self.drawMap.EndDraw() self.DrawBitmap(self.drawMap.GetBitmap(), 0, 0, self.w, self.h, 0, 0, self.drawMap.GetBw(),self.drawMap.GetBh(), c4d.BMP_NORMAL) #draw with usual textdraw self.DrawSetTextCol(c4d.COLOR_TEXT_SELECTED_DARK, c4d.COLOR_TRANS) self.DrawText("Motion-Tracker-Tracks können jetzt auch runde Suchmuster verwenden.", 3, 30) return
-
On 15/12/2017 at 02:53, xxxxxxxx wrote:
Hi Martin,
GeClipmap.TextAt() and GeUserArea.DrawText() doesn't give the same result because they use different means to draw text from different contexts.
GeClipmap.TextAt() draws into a bitmap whereas GeUserArea.DrawText() directly draws into the GUI.(I answered as Andreas left for vacation.)
-
On 19/12/2017 at 01:06, xxxxxxxx wrote:
Hi Yannick,
I see, could you please confirm than that there is either a sup-pixel sampling in drawBitmap or a working alpha draw method missing while drawing several alphas over elements in the user area draw function?
I can´t reach the quality/result I´m aiming for…cheers martin
-
On 22/12/2017 at 06:41, xxxxxxxx wrote:
Hi Martin,
I'm afraid I can't disclose internal implementation details.