1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
|
{
fpGUI - Free Pascal GUI Toolkit
Copyright (C) 2006 - 2008 See the file AUTHORS.txt, included in this
distribution, for details of the copyright.
See the file COPYING.modifiedLGPL, included in this distribution,
for details about redistributing fpGUI.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Description:
It's a simple little component that animates an image that contains
multiple frames (in a horizontal direction). See the Animation
demo for image examples.
}
unit gui_animation;
{$mode objfpc}{$H+}
interface
uses
Classes,
gfx_widget,
gfxbase,
fpgfx;
type
TfpgBaseImgAnim = class(TfpgWidget)
private
FFrameCount: integer;
FImageFilename: TfpgString;
FImage: TfpgImage;
FInterval: integer;
FTimer: TfpgTimer;
FPos: integer;
FImageWidth: TfpgCoord;
FTransparent: Boolean;
procedure InternalTimerFired(Sender: TObject);
procedure SetAnimPosition(const AValue: integer);
procedure SetInterval(const AValue: integer);
procedure RecalcImageWidth;
protected
procedure HandlePaint; override;
procedure SetEnabled(const AValue: boolean); override;
procedure SetImageFilename(const AValue: TfpgString); virtual;
//
property Interval: integer read FInterval write SetInterval default 50;
property ImageFileName: TfpgString read FImageFilename write SetImageFilename;
property IsTransparent: Boolean read FTransparent write FTransparent default True;
property FrameCount: integer read FFrameCount write FFrameCount default 4;
property Position: integer read FPos write SetAnimPosition default 0;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
TfpgImgAnim = class(TfpgBaseImgAnim)
public
property Position;
published
property Enabled;
property Interval;
property ImageFileName;
property IsTransparent;
property FrameCount;
end;
implementation
uses
SysUtils,
gfx_imgfmt_bmp,
gfx_utils;
{ TfpgBaseImgAnim }
procedure TfpgBaseImgAnim.InternalTimerFired(Sender: TObject);
begin
Repaint;
inc(FPos);
if FPos > FrameCount-1 then
FPos := 0;
end;
procedure TfpgBaseImgAnim.SetAnimPosition(const AValue: integer);
begin
if FTimer.Enabled then
Exit; // ignore position because animation is running
if AValue < 0 then
FPos := 0
else
FPos := AValue;
Repaint;
end;
procedure TfpgBaseImgAnim.SetInterval(const AValue: integer);
begin
if FInterval = AValue then
Exit; //==>
FInterval := AValue;
FTimer.Interval := FInterval;
RecalcImageWidth;
end;
procedure TfpgBaseImgAnim.RecalcImageWidth;
begin
FImageWidth := FImage.Width div FrameCount;
FPos := 0;
end;
procedure TfpgBaseImgAnim.HandlePaint;
begin
if (FImageFilename = '') or (FImage = nil) then
Exit; //==>
Canvas.BeginDraw;
Canvas.Clear(clWindowBackground);
Canvas.DrawImagePart(0, 0, FImage, (FImageWidth * FPos), 0, FImageWidth, FImage.Height);
Canvas.EndDraw;
end;
procedure TfpgBaseImgAnim.SetEnabled(const AValue: boolean);
begin
inherited SetEnabled(AValue);
FTimer.Enabled := FEnabled;
end;
procedure TfpgBaseImgAnim.SetImageFilename(const AValue: TfpgString);
begin
if FImageFilename = AValue then
Exit; //==>
if Trim(AValue) = '' then
Exit; //==>
if not fpgFileExists(AValue) then
raise Exception.CreateFmt('The file <%s> does not exist.', [AValue])
else
FImageFilename := AValue;
FTimer.Enabled := False;
FImage.Free;
FImage := LoadImage_BMP(FImageFilename);
if FTransparent then
begin
FImage.CreateMaskFromSample(0, 0);
FImage.UpdateImage;
end;
RecalcImageWidth;
Repaint;
end;
constructor TfpgBaseImgAnim.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FPos := 0;
FFrameCount := 4;
FInterval := 50;
FImage := nil;
FEnabled := False;
FTransparent := True;
FTimer := TfpgTimer.Create(FInterval);
FTimer.OnTimer := @InternalTimerFired;
end;
destructor TfpgBaseImgAnim.Destroy;
begin
FTimer.Enabled := False;
FTimer.Free;
FImage.Free;
inherited Destroy;
end;
end.
|