bgraspriteanimation.pas 22 KB

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