Recent

Author Topic: Flickering BGRABitmap when painting with mouse  (Read 232 times)

JasonLugg

  • Jr. Member
  • **
  • Posts: 67
Flickering BGRABitmap when painting with mouse
« on: April 28, 2019, 03:21:07 pm »
Hi All

I which to make a sort of tile editor. I am using a layered bitmap so that a grid can be viewed on one of the layers.

However, when I paint a 'cell' (rectangle) with the mouse I have to redraw it to see the changes. However this flickers. Is there a way around this?

My BGRABitmap is in its own class.

The flickering does not occur with a standard TImage. However I want the transparency offered by BGRABitmap.

Any help much appreciated.

//The Class
Code: Pascal  [Select]
  1. unit BGRATileEditor;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Graphics, BGRABitmap, BGRABitMapTypes, BGRALayers;
  9.  
  10. type
  11.  
  12.  
  13.   { BGRATileEditor }
  14.  
  15.   { tBGRATileEditor }
  16.  
  17.   tBGRATileEditor = class
  18.     //Variables, Procs, Funcs ONLY visible internally to this class
  19.     Private
  20.       //Is the Bitmap initialised?
  21.       bInit: boolean;
  22.       //The exploded view of the Tile where Editing Will Take Place
  23.       //will have layers so we can show/hide a grid
  24.       //tExplodedImg: TBGRALayeredBitmap;
  25.       tExplodedImg: TBGRABitMap;
  26.       tExpLayers: TBGRALayeredBitMap;
  27.  
  28.       //Structure
  29.       iSize: integer;         //Size of the window
  30.       iGridSize: integer;     //Size of the grid
  31.       tGridCol: TBGRAPixel;   //Colour for the grid
  32.       iCellSize: integer;     //How Big is Each Cell to Paint/Display
  33.       iDrawX, iDrawY: integer;//Where to Draw
  34.       aDrawToCanvas: tCanvas; //Were to Draw To
  35.  
  36.       //Editing Options
  37.       tPaintCol: TBGRAPixel;  //Which colour are we painting with?
  38.       tEraseCol: TBGRAPixel;  //Which colour is the Erase Color?
  39.  
  40.  
  41.       //Switches
  42.       bGridVisible: boolean;
  43.  
  44.     //Vars, Procs, Funcs visible Outside of this class
  45.     Public
  46.       constructor Create(iSizeOfEditor, iNumBigPixels, iDrawAtX, iDrawAtY: integer; tCanvasToDrawTo: TCanvas);
  47.       //Draw the TileEditor
  48.       procedure Draw();
  49.  
  50.       //Painting
  51.       procedure PaintCell(ixCell, iyCell: integer; tCol: TColor);
  52.       procedure EraseCell(ixCell, iyCell: integer);
  53.  
  54.  
  55.       //Grid Procs
  56.       procedure DrawGrid();    //CellSize  = Big Pixel Size
  57.       //Is the Grid to be Visible?
  58.       Property Grid_Visible: boolean read bGridVisible write bGridVisible;
  59.       //Change Grid Color
  60.       procedure SetGridColor(iRed, iGreen, iBlue, iAlpha: integer);
  61.  
  62.  
  63.       Property Size: integer read iSize;
  64.       Property xPos: integer read iDrawX write iDrawX;
  65.       property yPos: integer read iDrawY write iDrawY;
  66.       property CellSize: integer read iCellSize;
  67.  
  68.   end;
  69.  
  70.  
  71. implementation
  72.  
  73. const
  74.    LYRBACK = 0;
  75.    LYRPAINT= 1;
  76.    LYRGRID = 2;
  77.  
  78. { BGRATileEditor }
  79.  
  80. constructor tBGRATileEditor.Create(iSizeOfEditor, iNumBigPixels, iDrawAtX, iDrawAtY: integer; tCanvasToDrawTo: TCanvas);
  81. begin
  82.      //Set Init to false to start
  83.      bInit:=false;
  84.  
  85.      //Hold Draw Position
  86.      iDrawX:=iDrawAtX;
  87.      iDrawY:=iDrawAtY;
  88.      aDrawToCanvas:=tCanvasToDrawTo;
  89.  
  90.  
  91.      //Set an initial Grid Colour
  92.      tGridCol:=BGRA(0,255,0,255);
  93.      tEraseCol:=BGRA(255,255,255,0);
  94.  
  95.      //Create the Bitmap that we will draw our exploded view to
  96.      if (iSizeOfEditor < 64) or (iSizeOfEditor > 512) then
  97.         exit;
  98.  
  99.      iSize:=iSizeOfEditor;
  100.      tExplodedImg:=tBGRABitMap.Create(iSize, iSize, BGRAPixelTransparent );
  101.  
  102.      //Draw Transparent BackGround
  103.      tExplodedImg.DrawCheckers(rect(0,0,iSize, iSize), BGRA(100,100,100,255), BGRA(200,200,200,255));
  104.  
  105.      bInit:=true;
  106.      bGridVisible:=false;
  107.      iCellSize:=iSize div iNumBigPixels;
  108.  
  109.      //DEBUG - Trying Layers
  110.      tExpLayers:=TBGRALayeredBitMap.Create(20,20);
  111.      //a Checkered Background
  112.      tExpLayers.AddLayer('BackGrnd',TBGRABitMap.Create(iSize, iSize, BGRAPixelTransparent), 0);
  113.      tExpLayers.LayerBitmap[LYRBACK].DrawCheckers(rect(0,0,iSize, iSize), BGRA(225,228,234,255), BGRA(183,186,191,255));
  114.      //The Layer we paint To
  115.      tExpLayers.AddLayer('Paint',TBGRABitmap.Create(iSize, iSize, BGRAPixelTransparent), 0);
  116.      //The Grid Layer
  117.      tExpLayers.AddLayer('Grid',TBGRABitmap.Create(iSize, iSize, BGRAPixelTransparent), 0);
  118.  
  119.      //DEBUG - Test Layers
  120.      DrawGrid();
  121.      Draw();
  122.  
  123. end;
  124.  
  125. procedure tBGRATileEditor.Draw();
  126. begin
  127.      //Are we initialised?
  128.      if bInit = false then
  129.         //No Jump Out
  130.         exit;
  131.  
  132.      //tExplodedImg.Draw(CanvasToDrawTo, ixPos, iyPos, false);
  133.     if bGridVisible = true then
  134.         begin
  135.              tExpLayers.LayerBitmap[LYRBACK].Draw(aDrawToCanvas, iDrawX, iDrawY, false);
  136.              tExpLayers.LayerBitmap[LYRPAINT].Draw(aDrawToCanvas, iDrawX, iDrawY, false);
  137.              tExplayers.LayerBitmap[LYRGRID].Draw(aDrawToCanvas, iDrawX, iDrawY, false);
  138.         end
  139.      else
  140.          begin
  141.              tExpLayers.LayerBitmap[LYRBACK].Draw(aDrawToCanvas, iDrawX, iDrawY, false);
  142.              tExpLayers.LayerBitmap[LYRPAINT].Draw(aDrawToCanvas, iDrawX, iDrawY, false);
  143.          end;
  144.  
  145. end;
  146.  
  147. procedure tBGRATileEditor.PaintCell(ixCell, iyCell: integer; tCol: TColor); overload;
  148. var
  149.   pRect: TRect;
  150.   aPixel: TBGRAPixel;
  151. begin
  152.     //Are we intialised?
  153.     if (bInit = false) then
  154.        //No - Jump Out
  155.        exit;
  156.  
  157.     aPixel.red:=Red(tCol);
  158.     aPixel.green:=Green(tCol);
  159.     aPixel.blue:=Blue(tCol);
  160.     //DEBUG Set Alpha Here - Ideally Allow User to Change
  161.     aPixel.alpha:=255;
  162.  
  163.     pRect.Left:=ixCell * iCellSize;
  164.     pRect.Top:=iyCell * iCellSize;
  165.     pRect.Width:=iCellSize;
  166.     pREct.Height:=iCellSize;
  167.  
  168.     //Bounds Checking
  169.     if (pRect.Left >=0) and (pRect.Left+ pRect.Width <= iSize) and (pRect.Top >=0) and (pRect.Top+pRect.Height <= iSize) then
  170.        begin
  171.             tExpLayers.LayerBitmap[LYRPAINT].FillRect(pRect, aPixel, tDrawMode.dmDrawWithTransparency);
  172.             //tExpLayers.LayerBitmap[LYRPAINT].Canvas2d.fillStyle(aPixel);
  173.             //tExpLayers.LayerBitmap[LYRPAINT].Canvas2d.fillRect(pRect.Left, pRect.Top, iCellSize, iCellSize);
  174.  
  175.             Draw();
  176.        end;
  177.  
  178. end;
  179.  
  180. procedure tBGRATileEditor.EraseCell(ixCell, iyCell: integer); overload;
  181. var
  182.   pRect: TRect;
  183.   aPixel: TBGRAPixel;
  184. begin
  185.   pRect.Left:=ixCell * iCellSize;
  186.   pRect.Top:=iyCell * iCellSize;
  187.   pRect.Width:=iCellSize;
  188.   pREct.Height:=iCellSize;
  189.  
  190.   //Bounds Checking
  191.   if (pRect.Left >=0) and (pRect.Left+ pRect.Width <= iSize) and (pRect.Top >=0) and (pRect.Top+pRect.Height <= iSize) then
  192.      begin
  193.           tExpLayers.LayerBitmap[LYRPAINT].EraseRectAntialias(pRect.Left, pRect.Top, pRect.Right, pRect.Bottom,255);
  194.           Draw();
  195.      end;
  196. end;
  197.  
  198. procedure tBGRATileEditor.DrawGrid();
  199. var
  200.   iCount: integer;
  201.   ixPos, iyPos: integer;
  202.   iGridLayer: integer;
  203. begin
  204.      //Are we intialised?
  205.      if (bInit = false) then
  206.         //No - Jump Out
  207.         exit;
  208.  
  209.      ixPos:=0;
  210.      for iCount:=1 to tExpLayers.LayerBitmap[1].Width div iCellSize do
  211.          begin;
  212.                ixPos:=iCount * iCellSize;
  213.                tExpLayers.LayerBitmap[LYRGRID].DrawLine(ixPos,0,ixPos, tExplodedImg.Height, tGridCol, true, TDrawMode.dmDrawWithTransparency );
  214.          end;
  215.      //Draw Horizontals
  216.      iyPos:=0;
  217.      for iCount:=1 to tExplodedImg.Height div iCellSize do
  218.         begin
  219.              iyPos:=iCount*iCellSize;
  220.              tExpLayers.LayerBitmap[LYRGRID].DrawLine(0, iyPos, tExplodedImg.Width, iyPos, tGridCol, true, TDrawMode.dmDrawWithTransparency );
  221.         end;
  222.  
  223.  
  224. end;
  225.  
  226. procedure tBGRATileEditor.SetGridColor(iRed, iGreen, iBlue, iAlpha: integer);
  227. begin
  228.   tGridCol.red:=iRed;
  229.   tGridCol.green:=iGreen;
  230.   tGridCol.blue:=iBlue;
  231.   tGridCol.alpha:=iAlpha;
  232.   DrawGrid();
  233. end;
  234.  
  235.  
  236. end.
  237.  

Code: Pascal  [Select]
  1. procedure TForm1.FormCreate(Sender: TObject);
  2. begin
  3.      TileEditor:=tBGRATileEditor.Create(480, 8, 100,100, Form1.Canvas);
  4. end;
  5.  
  6. procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  7.   Y: Integer);
  8. begin
  9.   Mx:=X;
  10.   My:=Y;
  11.   Edit1.Text:='Mouse: '+InttoStr(Mx)+','+InttoStr(My);
  12.  
  13.   //Is Mouse over Editor Area?
  14.   if (Mx >= TileEditor.xPos) and (Mx <= TileEditor.xPos + tileEditor.Size) and (My >=TileEditor.yPos) and (My <= TileEditor.xPos + TileEditor.Size) then
  15.      begin
  16.           //Flag we are over it
  17.           bOverEditor:=true;
  18.           //ListBox1.Items.Add('bOverEditor:=true');
  19.           //Calculate Cell we are over
  20.           iCellX:=(X-TileEditor.xPos) div TileEditor.CellSize;
  21.           iCellY:=(Y-TileEditor.yPos) div TileEditor.CellSize;
  22.           //ListBox1.Items.Add('Cell: '+InttoStr(iCellX)+','+IntTostr(iCellY) );
  23.           if bLeftMBtn = true then
  24.              begin
  25.                   TileEditor.PaintCell(iCellX, iCellY, clBlue);
  26.              end;
  27.           if bRightMBtn = true then
  28.              begin
  29.                   TileEditor.EraseCell(iCellX, iCellY);
  30.              end;
  31.      end;
  32. end;
  33. procedure TForm1.FormPaint(Sender: TObject);
  34. begin
  35.  
  36.   TileEditor.Draw();
  37. end;  
  38.  
  39.  


lainz

  • Hero Member
  • *****
  • Posts: 3139
    • Lainz
Re: Flickering BGRABitmap when painting with mouse
« Reply #1 on: April 28, 2019, 05:23:34 pm »
Can you attach the program, I copy-paste everything as is and is not working, nothing is drawn... only the checkers