bgraspriteanimation.pas 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  1. // SPDX-License-Identifier: LGPL-3.0-linking-exception
  2. {
  3. Created by BGRA Controls Team
  4. Dibo, Circular, lainz (007) and contributors.
  5. For detailed information see readme.txt
  6. Site: https://sourceforge.net/p/bgra-controls/
  7. Wiki: http://wiki.lazarus.freepascal.org/BGRAControls
  8. Forum: http://forum.lazarus.freepascal.org/index.php/board,46.0.html
  9. }
  10. {******************************* CONTRIBUTOR(S) ******************************
  11. - Edivando S. Santos Brasil | [email protected]
  12. (Compatibility with delphi VCL 11/2018)
  13. - FreeMan35
  14. ***************************** END CONTRIBUTOR(S) *****************************}
  15. unit BGRASpriteAnimation;
  16. {$I bgracontrols.inc}
  17. interface
  18. uses
  19. Types, Classes, Controls, Dialogs, ExtCtrls, Forms, Graphics,
  20. {$IFDEF FPC}
  21. LCLIntF, LResources,
  22. {$ELSE}
  23. BGRAGraphics, GraphType, FPImage,
  24. {$ENDIF}
  25. BCBaseCtrls, BGRABitmap, BGRABitmapTypes, BCTypes, BGRAAnimatedGif;
  26. type
  27. TBGRASpriteAnimation = class;
  28. { TSpriteBitmap }
  29. TSpriteBitmap = class(TBitmap)
  30. private
  31. FOwner: TBGRASpriteAnimation;
  32. protected
  33. procedure AssignTo(Dest: TPersistent); override;
  34. public
  35. constructor Create(AOwner: TBGRASpriteAnimation); overload;
  36. procedure Assign(Source: TPersistent); override;
  37. end;
  38. TFlipMode = (flNone, flHorizontal, flVertical, flBoth);
  39. TRotationMode = (rtNone, rtClockWise, rtCounterClockWise, rt180);
  40. { TBGRASpriteAnimation }
  41. TBGRASpriteAnimation = class(TBGRAGraphicCtrl)
  42. private
  43. { Private declarations }
  44. FAnimInvert: boolean;
  45. FAnimPosition: cardinal;
  46. FAnimRepeat: cardinal;
  47. FAnimRepeatLap: cardinal;
  48. FAnimSpeed: cardinal;
  49. FAnimStatic: boolean;
  50. FAnimTimer: TTimer;
  51. FCenter: boolean;
  52. FOnLapChanged: TNotifyEvent;
  53. FOnLapChanging: TNotifyEvent;
  54. FOnPositionChanged: TNotifyEvent;
  55. FOnPositionChanging: TNotifyEvent;
  56. FOnRedrawAfter: TBGRARedrawEvent;
  57. FOnRedrawBefore: TBGRARedrawEvent;
  58. FProportional: boolean;
  59. FSprite: TBitmap;
  60. FSpriteCount: cardinal;
  61. FSpriteFillOpacity: byte;
  62. FSpriteFlipMode: TFlipMode;
  63. FSpriteKeyColor: TColor;
  64. FSpriteResampleFilter: TResampleFilter;
  65. FSpriteResampleMode: TResampleMode;
  66. FSpriteRotation: TRotationMode;
  67. FStretch: boolean;
  68. FTile: boolean;
  69. function DoCalculateDestRect(AWidth, AHeight: integer): TRect;
  70. function DoCalculatePosition(AValue: integer): integer;
  71. function DoCalculateSize(AValue: cardinal): cardinal;
  72. procedure DoAnimTimerOnTimer({%H-}Sender: TObject);
  73. procedure DoSpriteDraw(ABitmap: TBGRABitmap);
  74. procedure DoSpriteFillOpacity(ABitmap: TBGRABitmap);
  75. procedure DoSpriteFlip(ABitmap: TBGRABitmap);
  76. procedure DoSpriteKeyColor(ABitmap: TBGRABitmap);
  77. procedure DoSpriteResampleFilter(ABitmap: TBGRABitmap);
  78. procedure SetFAnimInvert(const AValue: boolean);
  79. procedure SetFAnimPosition(const AValue: cardinal);
  80. procedure SetFAnimRepeat(const AValue: cardinal);
  81. procedure SetFAnimRepeatLap(const AValue: cardinal);
  82. procedure SetFAnimSpeed(const AValue: cardinal);
  83. procedure SetFAnimStatic(const AValue: boolean);
  84. procedure SetFCenter(const AValue: boolean);
  85. procedure SetFProportional(const AValue: boolean);
  86. procedure SetFSprite(const AValue: TBitmap);
  87. procedure SetFSpriteCount(const AValue: cardinal);
  88. procedure SetFSpriteFillOpacity(const AValue: byte);
  89. procedure SetFSpriteFlipMode(const AValue: TFlipMode);
  90. procedure SetFSpriteKeyColor(const AValue: TColor);
  91. procedure SetFSpriteResampleFilter(const AValue: TResampleFilter);
  92. procedure SetFSpriteResampleMode(const AValue: TResampleMode);
  93. procedure SetFSpriteRotation(const AValue: TRotationMode);
  94. procedure SetFStretch(const AValue: boolean);
  95. procedure SetFTile(const AValue: boolean);
  96. procedure SpriteChange(Sender: TObject);
  97. protected
  98. { Protected declarations }
  99. procedure Paint; override;
  100. procedure CalculatePreferredSize(var PreferredWidth, PreferredHeight: integer;
  101. {%H-}WithThemeSpace: Boolean); override;
  102. public
  103. { Public declarations }
  104. procedure GifImageToSprite(Gif: TBGRAAnimatedGif);
  105. procedure SpriteToGifImage(Gif: TBGRAAnimatedGif);
  106. procedure LoadFromResourceName(Instance: THandle; const ResName: string); overload;
  107. procedure LoadFromBitmapResource(const Resource: string); overload;
  108. {$IF BGRABitmapVersion > 11030100}
  109. procedure LoadFromBitmapStream(AStream: TStream);
  110. {$ENDIF}
  111. procedure LoadFromBGRABitmap(const BGRA: TBGRABitmap);
  112. procedure SpriteToAnimatedGif(Filename: string);
  113. procedure AnimatedGifToSprite(Filename: string);
  114. constructor Create(AOwner: TComponent); override;
  115. destructor Destroy; override;
  116. published
  117. { Published declarations }
  118. property AnimInvert: boolean read FAnimInvert write SetFAnimInvert;
  119. property AnimPosition: cardinal read FAnimPosition write SetFAnimPosition;
  120. property AnimRepeat: cardinal read FAnimRepeat write SetFAnimRepeat;
  121. property AnimRepeatLap: cardinal read FAnimRepeatLap write SetFAnimRepeatLap;
  122. property AnimSpeed: cardinal read FAnimSpeed write SetFAnimSpeed;
  123. property AnimStatic: boolean read FAnimStatic write SetFAnimStatic;
  124. property Center: boolean read FCenter write SetFCenter;
  125. property Proportional: boolean read FProportional write SetFProportional;
  126. property Sprite: TBitmap read FSprite write SetFSprite;
  127. property SpriteCount: cardinal read FSpriteCount write SetFSpriteCount;
  128. property SpriteFillOpacity: byte read FSpriteFillOpacity write SetFSpriteFillOpacity;
  129. property SpriteFlipMode: TFlipMode read FSpriteFlipMode write SetFSpriteFlipMode;
  130. property SpriteKeyColor: TColor read FSpriteKeyColor write SetFSpriteKeyColor;
  131. property SpriteResampleFilter: TResampleFilter
  132. read FSpriteResampleFilter write SetFSpriteResampleFilter;
  133. property SpriteResampleMode: TResampleMode
  134. read FSpriteResampleMode write SetFSpriteResampleMode;
  135. property SpriteRotation: TRotationMode read FSpriteRotation write SetFSpriteRotation;
  136. property Stretch: boolean read FStretch write SetFStretch;
  137. property Tile: boolean read FTile write SetFTile;
  138. published
  139. property Align;
  140. property Anchors;
  141. property AutoSize;
  142. property Caption;
  143. property Color;
  144. property Enabled;
  145. property OnClick;
  146. property OnDblClick;
  147. property OnLapChanged: TNotifyEvent read FOnLapChanged write FOnLapChanged;
  148. property OnLapChanging: TNotifyEvent read FOnLapChanging write FOnLapChanging;
  149. property OnMouseDown;
  150. property OnMouseEnter;
  151. property OnMouseLeave;
  152. property OnMouseMove;
  153. property OnMouseUp;
  154. property OnPositionChanged: TNotifyEvent
  155. read FOnPositionChanged write FOnPositionChanged;
  156. property OnPositionChanging: TNotifyEvent
  157. read FOnPositionChanging write FOnPositionChanging;
  158. property OnRedrawAfter: TBGRARedrawEvent read FOnRedrawAfter write FOnRedrawAfter;
  159. property OnRedrawBefore: TBGRARedrawEvent read FOnRedrawBefore write FOnRedrawBefore;
  160. property PopupMenu;
  161. property Visible;
  162. end;
  163. {$IFDEF FPC}procedure Register;{$ENDIF}
  164. implementation
  165. {$IFDEF FPC}
  166. procedure Register;
  167. begin
  168. RegisterComponents('BGRA Controls', [TBGRASpriteAnimation]);
  169. end;
  170. { TSpriteBitmap }
  171. procedure TSpriteBitmap.AssignTo(Dest: TPersistent);
  172. begin
  173. if Dest is TBGRAAnimatedGif then
  174. FOwner.SpriteToGifImage(TBGRAAnimatedGif(Dest));
  175. inherited AssignTo(Dest);
  176. end;
  177. constructor TSpriteBitmap.Create(AOwner: TBGRASpriteAnimation);
  178. begin
  179. inherited Create;
  180. FOwner := AOwner;
  181. end;
  182. procedure TSpriteBitmap.Assign(Source: TPersistent);
  183. begin
  184. if Source is TBGRAAnimatedGif then
  185. FOwner.GifImageToSprite(TBGRAAnimatedGif(Source))
  186. else
  187. inherited Assign(Source);
  188. end;
  189. {$ENDIF}
  190. { TBGRASpriteAnimation }
  191. { Animation Variables }
  192. procedure TBGRASpriteAnimation.SetFAnimInvert(const AValue: boolean);
  193. begin
  194. if FAnimInvert = AValue then
  195. Exit;
  196. FAnimInvert := AValue;
  197. if csDesigning in ComponentState then
  198. Invalidate;
  199. end;
  200. procedure TBGRASpriteAnimation.SetFAnimPosition(const AValue: cardinal);
  201. begin
  202. if FAnimPosition = AValue then
  203. Exit;
  204. if (AValue < 1) or (AValue > FSpriteCount) then
  205. FAnimPosition := 1
  206. else
  207. FAnimPosition := AValue;
  208. if Assigned(FOnPositionChanged) then
  209. FOnPositionChanged(Self);
  210. if csDesigning in ComponentState then
  211. Invalidate;
  212. end;
  213. procedure TBGRASpriteAnimation.SetFAnimRepeat(const AValue: cardinal);
  214. begin
  215. if FAnimRepeat = AValue then
  216. Exit;
  217. FAnimRepeat := AValue;
  218. end;
  219. procedure TBGRASpriteAnimation.SetFAnimRepeatLap(const AValue: cardinal);
  220. begin
  221. if (FAnimRepeatLap = AValue) then
  222. Exit;
  223. FAnimRepeatLap := AValue;
  224. if (AValue = FAnimRepeat) and (AValue <> 0) then
  225. begin
  226. if csDesigning in ComponentState then
  227. Exit;
  228. SetFAnimStatic(True);
  229. end;
  230. if Assigned(FOnLapChanged) then
  231. FOnLapChanged(Self);
  232. end;
  233. procedure TBGRASpriteAnimation.SetFAnimSpeed(const AValue: cardinal);
  234. begin
  235. if FAnimSpeed = AValue then
  236. Exit;
  237. FAnimSpeed := AValue;
  238. FAnimTimer.Interval := AValue;
  239. end;
  240. procedure TBGRASpriteAnimation.SetFAnimStatic(const AValue: boolean);
  241. begin
  242. if FAnimStatic = AValue then
  243. Exit;
  244. FAnimStatic := AValue;
  245. if csDesigning in ComponentState then
  246. Exit;
  247. FAnimTimer.Enabled := not AValue;
  248. end;
  249. { Sprite Variables }
  250. procedure TBGRASpriteAnimation.SetFSprite(const AValue: TBitmap);
  251. begin
  252. if (FSprite = AValue) or (AValue = nil) then
  253. Exit;
  254. FSprite.Assign(AValue);
  255. end;
  256. procedure TBGRASpriteAnimation.SetFSpriteCount(const AValue: cardinal);
  257. begin
  258. if (FSpriteCount = AValue) or (FSprite = nil) then
  259. Exit;
  260. if (AValue < 1) or (AValue > cardinal(FSprite.Width)) then
  261. FSpriteCount := 1
  262. else
  263. FSpriteCount := AValue;
  264. if AnimPosition > AValue then
  265. SetFAnimPosition(1);
  266. Invalidate;
  267. InvalidatePreferredSize;
  268. AdjustSize;
  269. end;
  270. procedure TBGRASpriteAnimation.SetFSpriteFillOpacity(const AValue: byte);
  271. begin
  272. if FSpriteFillOpacity = AValue then
  273. Exit;
  274. FSpriteFillOpacity := AValue;
  275. if csDesigning in ComponentState then
  276. Invalidate;
  277. end;
  278. procedure TBGRASpriteAnimation.SetFSpriteFlipMode(const AValue: TFlipMode);
  279. begin
  280. if FSpriteFlipMode = AValue then
  281. Exit;
  282. FSpriteFlipMode := AValue;
  283. if csDesigning in ComponentState then
  284. Invalidate;
  285. end;
  286. procedure TBGRASpriteAnimation.SetFSpriteKeyColor(const AValue: TColor);
  287. begin
  288. if FSpriteKeyColor = AValue then
  289. Exit;
  290. FSpriteKeyColor := AValue;
  291. if csDesigning in ComponentState then
  292. Invalidate;
  293. end;
  294. procedure TBGRASpriteAnimation.SetFSpriteResampleFilter(const AValue: TResampleFilter);
  295. begin
  296. if FSpriteResampleFilter = AValue then
  297. Exit;
  298. FSpriteResampleFilter := AValue;
  299. if csDesigning in ComponentState then
  300. Invalidate;
  301. end;
  302. procedure TBGRASpriteAnimation.SetFSpriteResampleMode(const AValue: TResampleMode);
  303. begin
  304. if FSpriteResampleMode = AValue then
  305. Exit;
  306. FSpriteResampleMode := AValue;
  307. if csDesigning in ComponentState then
  308. Invalidate;
  309. end;
  310. procedure TBGRASpriteAnimation.SetFSpriteRotation(const AValue: TRotationMode);
  311. begin
  312. if FSpriteRotation = AValue then
  313. Exit;
  314. FSpriteRotation := AValue;
  315. if csDesigning in ComponentState then
  316. Invalidate;
  317. InvalidatePreferredSize;
  318. AdjustSize;
  319. end;
  320. { General Variables }
  321. procedure TBGRASpriteAnimation.SetFCenter(const AValue: boolean);
  322. begin
  323. if FCenter = AValue then
  324. Exit;
  325. FCenter := AValue;
  326. if csDesigning in ComponentState then
  327. Invalidate;
  328. end;
  329. procedure TBGRASpriteAnimation.SetFProportional(const AValue: boolean);
  330. begin
  331. if FProportional = AValue then
  332. Exit;
  333. FProportional := AValue;
  334. if csDesigning in ComponentState then
  335. Invalidate;
  336. end;
  337. procedure TBGRASpriteAnimation.SetFStretch(const AValue: boolean);
  338. begin
  339. if FStretch = AValue then
  340. Exit;
  341. FStretch := AValue;
  342. if csDesigning in ComponentState then
  343. Invalidate;
  344. end;
  345. procedure TBGRASpriteAnimation.SetFTile(const AValue: boolean);
  346. begin
  347. if FTile = AValue then
  348. Exit;
  349. FTile := AValue;
  350. if csDesigning in ComponentState then
  351. Invalidate;
  352. end;
  353. procedure TBGRASpriteAnimation.SpriteChange(Sender: TObject);
  354. begin
  355. Invalidate;
  356. InvalidatePreferredSize;
  357. AdjustSize;
  358. end;
  359. { Utils }
  360. function TBGRASpriteAnimation.DoCalculateDestRect(AWidth, AHeight: integer): TRect;
  361. var
  362. PicWidth: integer;
  363. PicHeight: integer;
  364. ImgWidth: integer;
  365. ImgHeight: integer;
  366. w: integer;
  367. h: integer;
  368. begin
  369. PicWidth := AWidth;
  370. PicHeight := AHeight;
  371. ImgWidth := ClientWidth;
  372. ImgHeight := ClientHeight;
  373. if Stretch or (Proportional and ((PicWidth > ImgWidth) or
  374. (PicHeight > ImgHeight))) then
  375. begin
  376. if Proportional and (PicWidth > 0) and (PicHeight > 0) then
  377. begin
  378. w := ImgWidth;
  379. h := (PicHeight * w) div PicWidth;
  380. if h > ImgHeight then
  381. begin
  382. h := ImgHeight;
  383. w := (PicWidth * h) div PicHeight;
  384. end;
  385. PicWidth := w;
  386. PicHeight := h;
  387. end
  388. else
  389. begin
  390. PicWidth := ImgWidth;
  391. PicHeight := ImgHeight;
  392. end;
  393. end;
  394. Result := Rect(0, 0, PicWidth, PicHeight);
  395. if Center then
  396. Types.OffsetRect(Result, (ImgWidth - PicWidth) div 2, (ImgHeight - PicHeight) div 2);
  397. end;
  398. function TBGRASpriteAnimation.DoCalculatePosition(AValue: integer): integer;
  399. begin
  400. if FAnimInvert then
  401. Result := -AValue * (FSpriteCount - FAnimPosition)
  402. else
  403. Result := -AValue * (FAnimPosition - 1);
  404. end;
  405. function TBGRASpriteAnimation.DoCalculateSize(AValue: cardinal): cardinal;
  406. begin
  407. Result := AValue div FSpriteCount;
  408. end;
  409. procedure TBGRASpriteAnimation.DoSpriteResampleFilter(ABitmap: TBGRABitmap);
  410. begin
  411. ABitmap.ResampleFilter := FSpriteResampleFilter;
  412. end;
  413. procedure TBGRASpriteAnimation.DoSpriteFillOpacity(ABitmap: TBGRABitmap);
  414. begin
  415. if FSpriteFillOpacity <> 255 then
  416. ABitmap.ApplyGlobalOpacity(FSpriteFillOpacity);
  417. end;
  418. procedure TBGRASpriteAnimation.DoSpriteFlip(ABitmap: TBGRABitmap);
  419. begin
  420. case FSpriteFlipMode of
  421. flNone: Exit;
  422. flHorizontal: ABitmap.HorizontalFlip;
  423. flVertical: ABitmap.VerticalFlip;
  424. flBoth:
  425. begin
  426. ABitmap.HorizontalFlip;
  427. ABitmap.VerticalFlip;
  428. end;
  429. end;
  430. end;
  431. procedure TBGRASpriteAnimation.DoSpriteKeyColor(ABitmap: TBGRABitmap);
  432. begin
  433. if FSpriteKeyColor <> clNone then
  434. ABitmap.ReplaceColor(ColorToBGRA(ColorToRGB(FSpriteKeyColor), 255),
  435. BGRAPixelTransparent);
  436. end;
  437. { Main }
  438. procedure TBGRASpriteAnimation.Paint;
  439. procedure DrawFrame;
  440. begin
  441. with inherited Canvas do
  442. begin
  443. Pen.Color := clBlack;
  444. Pen.Style := graphics.psDash;
  445. MoveTo(0, 0);
  446. LineTo(Self.Width - 1, 0);
  447. LineTo(Self.Width - 1, Self.Height - 1);
  448. LineTo(0, Self.Height - 1);
  449. LineTo(0, 0);
  450. end;
  451. end;
  452. var
  453. TempSprite, TempSpriteBGRA: TBGRABitmap;
  454. TempSpriteWidth, TempSpriteHeight, TempSpritePosition: integer;
  455. begin
  456. if (Color <> clNone) and (Color <> clDefault) then
  457. begin
  458. Canvas.Brush.Color := Color;
  459. Canvas.Brush.Style := bsSolid;
  460. Canvas.FillRect(ClientRect);
  461. end;
  462. if csDesigning in ComponentState then
  463. DrawFrame;
  464. if FSprite = nil then
  465. Exit;
  466. if (Width > 0) and (Height > 0) then
  467. begin
  468. TempSpriteWidth := DoCalculateSize(FSprite.Width);
  469. TempSpriteHeight := FSprite.Height;
  470. TempSpritePosition := DoCalculatePosition(TempSpriteWidth);
  471. TempSpriteBGRA := TBGRABitmap.Create(FSprite);
  472. TempSprite := TBGRABitmap.Create(TempSpriteWidth, TempSpriteHeight);
  473. TempSprite.BlendImage(TempSpritePosition, 0, TempSpriteBGRA, boLinearBlend);
  474. TempSpriteBGRA.Free;
  475. if Assigned(FOnRedrawBefore) then
  476. FOnRedrawBefore(Self, TempSprite);
  477. DoSpriteDraw(TempSprite);
  478. end;
  479. end;
  480. procedure TBGRASpriteAnimation.CalculatePreferredSize(var PreferredWidth,
  481. PreferredHeight: integer; WithThemeSpace: Boolean);
  482. begin
  483. if SpriteRotation in [rtClockWise,rtCounterClockWise] then
  484. begin
  485. PreferredWidth := Sprite.Height;
  486. PreferredHeight := Sprite.Width div SpriteCount;
  487. end else
  488. begin
  489. PreferredWidth := Sprite.Width div SpriteCount;
  490. PreferredHeight := Sprite.Height;
  491. end;
  492. end;
  493. procedure TBGRASpriteAnimation.GifImageToSprite(Gif: TBGRAAnimatedGif);
  494. {$IF BGRABitmapVersion > 11030100}
  495. var
  496. TempBitmap: TBGRABitmap;
  497. n: integer;
  498. begin
  499. if Gif.Count = 0 then exit;
  500. TempBitmap := TBGRABitmap.Create(Gif.Width * Gif.Count, Gif.Height);
  501. try
  502. for n := 0 to Gif.Count-1 do
  503. begin
  504. Gif.CurrentImage := n;
  505. TempBitmap.PutImage(Gif.Width * n, 0, Gif.MemBitmap, dmSet);
  506. end;
  507. TempBitmap.AssignToBitmap(FSprite);
  508. SpriteCount := Gif.Count;
  509. AnimSpeed := Gif.TotalAnimationTimeMs div Gif.Count;
  510. finally
  511. TempBitmap.Free;
  512. end;
  513. {$ELSE}
  514. var
  515. TempBitmap: TBGRABitmap;
  516. n: integer;
  517. begin
  518. if Gif.Count = 0 then exit;
  519. TempBitmap := TBGRABitmap.Create(Gif.Width * Gif.Count, Gif.Height);
  520. for n := 0 to Gif.Count do
  521. begin
  522. Gif.CurrentImage := n;
  523. TempBitmap.BlendImage(Gif.Width * n, 0, Gif.MemBitmap, boLinearBlend);
  524. end;
  525. AnimSpeed := Gif.TotalAnimationTimeMs div Gif.Count;
  526. FSpriteCount := Gif.Count;
  527. FSprite.Width := Gif.Width * Gif.Count;
  528. FSprite.Height := Gif.Height;
  529. FSprite.Canvas.Brush.Color := SpriteKeyColor;
  530. FSprite.Canvas.FillRect(Rect(0, 0, FSprite.Width, FSprite.Height));
  531. FSprite.Canvas.Draw(0, 0, TempBitmap.Bitmap);
  532. TempBitmap.Free;
  533. {$ENDIF}
  534. end;
  535. procedure TBGRASpriteAnimation.SpriteToGifImage(Gif: TBGRAAnimatedGif);
  536. var
  537. i: integer;
  538. TempSpriteWidth: Integer;
  539. TempSpritePosition: Integer;
  540. TempSpriteBGRA, TempSprite: TBGRABitmap;
  541. begin
  542. gif.Clear;
  543. if AnimRepeat > high(Word) then
  544. gif.LoopCount := 0
  545. else
  546. gif.LoopCount := AnimRepeat;
  547. TempSpriteBGRA := TBGRABitmap.Create(FSprite);
  548. TempSpriteWidth := TempSpriteBGRA.Width div FSpriteCount;
  549. gif.SetSize(TempSpriteWidth, TempSpriteBGRA.Height);
  550. for i:=0 to FSpriteCount-1 do
  551. begin
  552. TempSpritePosition := -TempSpriteWidth * i;
  553. TempSprite := TBGRABitmap.Create(TempSpriteWidth, TempSpriteBGRA.Height);
  554. TempSprite.BlendImage(TempSpritePosition, 0, TempSpriteBGRA, boLinearBlend);
  555. gif.AddFullFrame(TempSprite, FAnimSpeed);
  556. TempSprite.Free;
  557. end;
  558. TempSpriteBGRA.Free;
  559. end;
  560. procedure TBGRASpriteAnimation.LoadFromResourceName(Instance: THandle;
  561. const ResName: string);
  562. var
  563. TempGif: TBGRAAnimatedGif;
  564. begin
  565. TempGif := TBGRAAnimatedGif.Create;
  566. {$IFDEF FPC}//#
  567. TempGif.LoadFromResourceName(Instance, ResName);
  568. {$ENDIF}
  569. GifImageToSprite(TempGif);
  570. TempGif.Free;
  571. end;
  572. procedure TBGRASpriteAnimation.LoadFromBitmapResource(const Resource: string);
  573. {$IF BGRABitmapVersion > 11030100}
  574. var
  575. stream: TStream;
  576. begin
  577. stream := BGRAResource.GetResourceStream(Resource);
  578. try
  579. LoadFromBitmapStream(stream);
  580. finally
  581. stream.Free;
  582. end;
  583. {$ELSE}
  584. var
  585. tempGif: TBGRAAnimatedGif;
  586. begin
  587. tempGif := TBGRAAnimatedGif.Create;
  588. try
  589. tempGif.LoadFromResource(Resource);
  590. GifImageToSprite(tempGif);
  591. finally
  592. tempGif.Free;
  593. end;
  594. {$ENDIF}
  595. end;
  596. {$IF BGRABitmapVersion > 11030100}
  597. procedure TBGRASpriteAnimation.LoadFromBitmapStream(AStream: TStream);
  598. var
  599. tempGif: TBGRAAnimatedGif;
  600. tempBGRA: TBGRABitmap;
  601. begin
  602. if DetectFileFormat(AStream) = ifGif then
  603. begin
  604. tempGif := TBGRAAnimatedGif.Create;
  605. try
  606. tempGif.LoadFromStream(AStream);
  607. GifImageToSprite(tempGif);
  608. finally
  609. tempGif.Free;
  610. end;
  611. end else
  612. begin
  613. tempBGRA := TBGRABitmap.Create;
  614. try
  615. tempBGRA.LoadFromStream(AStream);
  616. tempBGRA.AssignToBitmap(FSprite);
  617. finally
  618. tempBGRA.FRee;
  619. end;
  620. end;
  621. end;
  622. {$ENDIF}
  623. procedure TBGRASpriteAnimation.LoadFromBGRABitmap(const BGRA: TBGRABitmap);
  624. begin
  625. {$IF BGRABitmapVersion > 11030100}
  626. BGRA.AssignToBitmap(FSprite);
  627. {$ELSE}
  628. FSprite.Width := BGRA.Width;
  629. FSprite.Height := BGRA.Height;
  630. BGRA.Draw(FSprite.Canvas, 0, 0, False);
  631. {$ENDIF}
  632. end;
  633. procedure TBGRASpriteAnimation.SpriteToAnimatedGif(Filename: string);
  634. var
  635. gif : TBGRAAnimatedGif;
  636. begin
  637. gif := TBGRAAnimatedGif.Create;
  638. SpriteToGifImage(Gif);
  639. gif.SaveToFile(Filename);
  640. gif.Free;
  641. end;
  642. procedure TBGRASpriteAnimation.AnimatedGifToSprite(Filename: string);
  643. var
  644. TempGif: TBGRAAnimatedGif;
  645. begin
  646. TempGif := TBGRAAnimatedGif.Create(Filename);
  647. try
  648. GifImageToSprite(TempGif);
  649. finally
  650. TempGif.Free;
  651. end;
  652. end;
  653. procedure TBGRASpriteAnimation.DoSpriteDraw(ABitmap: TBGRABitmap);
  654. var
  655. TempRect: TRect;
  656. begin
  657. DoSpriteResampleFilter(ABitmap);
  658. DoSpriteKeyColor(ABitmap);
  659. DoSpriteFillOpacity(ABitmap);
  660. DoSpriteFlip(ABitmap);
  661. case FSpriteRotation of
  662. rtClockWise: BGRAReplace(ABitmap, ABitmap.RotateCW);
  663. rtCounterClockWise: BGRAReplace(ABitmap, ABitmap.RotateCCW);
  664. rt180: ABitmap.RotateUDInplace;
  665. end;
  666. { TODO -oLainz : If there is no Sprite loaded and you set 'Tile' to true a division by cero error is shown }
  667. if Tile then
  668. BGRAReplace(ABitmap, ABitmap.GetPart(rect(0, 0, Width, Height)));
  669. TempRect := DoCalculateDestRect(ABitmap.Width, ABitmap.Height);
  670. if Assigned(FOnRedrawAfter) then
  671. FOnRedrawAfter(Self, ABitmap);
  672. if Stretch and (FSpriteResampleMode = rmFineResample) then
  673. BGRAReplace(ABitmap, ABitmap.Resample(Width, Height, FSpriteResampleMode));
  674. ABitmap.Draw(Canvas, TempRect, False);
  675. ABitmap.Free;
  676. end;
  677. procedure TBGRASpriteAnimation.DoAnimTimerOnTimer(Sender: TObject);
  678. begin
  679. Invalidate;
  680. if Assigned(FOnPositionChanging) then
  681. FOnPositionChanging(Self);
  682. SetFAnimPosition(FAnimPosition + 1);
  683. if FAnimPosition = FSpriteCount then
  684. begin
  685. if Assigned(FOnLapChanging) then
  686. FOnLapChanging(Self);
  687. SetFAnimRepeatLap(FAnimRepeatLap + 1);
  688. end;
  689. end;
  690. { Create / Destroy }
  691. constructor TBGRASpriteAnimation.Create(AOwner: TComponent);
  692. begin
  693. inherited Create(AOwner);
  694. with GetControlClassDefaultSize do
  695. SetInitialBounds(0, 0, CX, CY);
  696. FAnimInvert := False;
  697. FAnimPosition := 1;
  698. FAnimRepeat := 0;
  699. FAnimRepeatLap := 0;
  700. FAnimSpeed := 1000;
  701. FAnimStatic := False;
  702. FAnimTimer := TTimer.Create(Self);
  703. FAnimTimer.Interval := FAnimSpeed;
  704. FAnimTimer.OnTimer := DoAnimTimerOnTimer;
  705. FCenter := True;
  706. FProportional := True;
  707. FStretch := True;
  708. FSprite := TSpriteBitmap.Create(self);
  709. FSprite.OnChange:=SpriteChange;
  710. FSpriteCount := 1;
  711. FSpriteFillOpacity := 255;
  712. FSpriteFlipMode := flNone;
  713. FSpriteKeyColor := clNone;
  714. FSpriteResampleFilter := rfLinear;
  715. FSpriteResampleMode := rmSimpleStretch;
  716. FSpriteRotation := rtNone;
  717. FTile := False;
  718. if csDesigning in ComponentState then
  719. FAnimTimer.Enabled := False;
  720. end;
  721. destructor TBGRASpriteAnimation.Destroy;
  722. begin
  723. FAnimTimer.Enabled := False;
  724. FAnimTimer.OnTimer := nil;
  725. FAnimTimer.Free;
  726. FSprite.Free;
  727. inherited Destroy;
  728. end;
  729. end.