DEADSOFTWARE

anim: add static variant of TAnimationState
[d2df-sdl.git] / src / game / g_textures.pas
1 (* Copyright (C) Doom 2D: Forever Developers
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, version 3 of the License ONLY.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 *)
15 {$INCLUDE ../shared/a_modes.inc}
16 unit g_textures;
18 interface
20 uses
21 SysUtils, Classes,
22 {$IFDEF USE_MEMPOOL}mempool,{$ENDIF}
23 g_base, MAPDEF;
25 type
26 TLevelTexture = record
27 TextureName: AnsiString; // as stored in wad
28 FullName: AnsiString; // full path to texture // !!! merge it with TextureName
29 framesCount, speed: Byte;
30 end;
32 TLevelTextureArray = array of TLevelTexture;
34 TAnimationState = class{$IFDEF USE_MEMPOOL}(TPoolObject){$ENDIF}
35 private
36 mCounter: Byte; // Ñ÷åò÷èê îæèäàíèÿ ìåæäó êàäðàìè
37 mSpeed: Byte; // Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè
38 mCurrentFrame: Integer; // Òåêóùèé êàäð (íà÷èíàÿ ñ 0)
39 mLoop: Boolean; // Ïåðåõîäèòü íà ïåðâûé êàäð ïîñëå ïîñëåäíåãî?
40 mEnabled: Boolean; // Ðàáîòà ðàçðåøåíà?
41 mPlayed: Boolean; // Ïðîèãðàíà âñÿ õîòÿ áû ðàç?
42 mMinLength: Byte; // Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ
43 mRevert: Boolean; // Ñìåíà êàäðîâ îáðàòíàÿ?
45 mLength: Integer;
47 public
48 constructor Create (aloop: Boolean; aspeed: Byte; len: Integer);
49 destructor Destroy (); override;
51 procedure reset ();
52 procedure update ();
53 procedure enable ();
54 procedure disable ();
55 procedure revert (r: Boolean);
57 procedure saveState (st: TStream; mAlpha: Byte; mBlending: Boolean);
58 procedure loadState (st: TStream; out mAlpha: Byte; out mBlending: Boolean);
60 function totalFrames (): Integer; inline;
62 public
63 property played: Boolean read mPlayed;
64 property enabled: Boolean read mEnabled;
65 property isReverse: Boolean read mRevert;
66 property loop: Boolean read mLoop write mLoop;
67 property speed: Byte read mSpeed write mSpeed;
68 property minLength: Byte read mMinLength write mMinLength;
69 property currentFrame: Integer read mCurrentFrame write mCurrentFrame;
70 property currentCounter: Byte read mCounter write mCounter;
71 property counter: Byte read mCounter;
72 property length: Integer read mLength;
73 end;
75 TAnimState = record
76 private
77 mCounter: Byte; // Ñ÷åò÷èê îæèäàíèÿ ìåæäó êàäðàìè
78 mSpeed: Byte; // Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè
79 mCurrentFrame: Integer; // Òåêóùèé êàäð (íà÷èíàÿ ñ 0)
80 mLoop: Boolean; // Ïåðåõîäèòü íà ïåðâûé êàäð ïîñëå ïîñëåäíåãî?
81 mEnabled: Boolean; // Ðàáîòà ðàçðåøåíà?
82 mPlayed: Boolean; // Ïðîèãðàíà âñÿ õîòÿ áû ðàç?
83 mMinLength: Byte; // Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ
84 mRevert: Boolean; // Ñìåíà êàäðîâ îáðàòíàÿ?
86 mLength: Integer;
88 public
89 constructor Create (aloop: Boolean; aspeed: Byte; len: Integer);
90 procedure Destroy;
92 procedure reset ();
93 procedure update ();
94 procedure enable ();
95 procedure disable ();
96 procedure revert (r: Boolean);
98 procedure saveState (st: TStream; mAlpha: Byte; mBlending: Boolean);
99 procedure loadState (st: TStream; out mAlpha: Byte; out mBlending: Boolean);
101 function totalFrames (): Integer; inline;
103 public
104 property played: Boolean read mPlayed;
105 property enabled: Boolean read mEnabled;
106 property isReverse: Boolean read mRevert;
107 property loop: Boolean read mLoop write mLoop;
108 property speed: Byte read mSpeed write mSpeed;
109 property minLength: Byte read mMinLength write mMinLength;
110 property currentFrame: Integer read mCurrentFrame write mCurrentFrame;
111 property currentCounter: Byte read mCounter write mCounter;
112 property counter: Byte read mCounter;
113 property length: Integer read mLength;
114 end;
116 implementation
118 uses
119 g_game, e_log, g_basic, g_console, wadreader,
120 g_language, utils, xstreams;
122 constructor TAnimationState.Create (aloop: Boolean; aspeed: Byte; len: Integer);
123 begin
124 assert(len >= 0);
125 mLength := len;
127 mMinLength := 0;
128 mLoop := aloop;
129 mSpeed := aspeed;
130 mEnabled := true;
131 mCurrentFrame := 0;
132 mPlayed := false;
133 end;
135 destructor TAnimationState.Destroy;
136 begin
137 inherited;
138 end;
140 procedure TAnimationState.update;
141 begin
142 if (not mEnabled) then exit;
144 mCounter += 1;
146 if (mCounter >= mSpeed) then
147 begin
148 // Îæèäàíèå ìåæäó êàäðàìè çàêîí÷èëîñü
149 // Îáðàòíûé ïîðÿäîê êàäðîâ?
150 if mRevert then
151 begin
152 // Äîøëè äî êîíöà àíèìàöèè. Âîçìîæíî, æäåì åùå
153 if (mCurrentFrame = 0) then
154 begin
155 if (mLength * mSpeed + mCounter < mMinLength) then exit;
156 end;
158 mCurrentFrame -= 1;
159 mPlayed := (mCurrentFrame < 0);
161 // Ïîâòîðÿòü ëè àíèìàöèþ ïî êðóãó?
162 if mPlayed then
163 begin
164 if mLoop then
165 mCurrentFrame := mLength - 1
166 else
167 mCurrentFrame += 1
168 end;
170 mCounter := 0;
171 end
172 else
173 begin
174 // Ïðÿìîé ïîðÿäîê êàäðîâ
175 // Äîøëè äî êîíöà àíèìàöèè. Âîçìîæíî, æäåì åùå
176 if (mCurrentFrame = mLength - 1) then
177 begin
178 if (mLength * mSpeed + mCounter < mMinLength) then exit;
179 end;
181 mCurrentFrame += 1;
182 mPlayed := (mCurrentFrame > mLength - 1);
184 // Ïîâòîðÿòü ëè àíèìàöèþ ïî êðóãó?
185 if mPlayed then
186 begin
187 if mLoop then mCurrentFrame := 0 else mCurrentFrame -= 1;
188 end;
190 mCounter := 0;
191 end;
192 end;
193 end;
195 procedure TAnimationState.reset;
196 begin
197 if mRevert then
198 mCurrentFrame := mLength - 1
199 else
200 mCurrentFrame := 0;
201 mCounter := 0;
202 mPlayed := false
203 end;
205 procedure TAnimationState.disable;
206 begin
207 mEnabled := false
208 end;
210 procedure TAnimationState.enable;
211 begin
212 mEnabled := true
213 end;
215 procedure TAnimationState.revert (r: Boolean);
216 begin
217 mRevert := r;
218 reset
219 end;
221 function TAnimationState.totalFrames (): Integer; inline;
222 begin
223 result := mLength
224 end;
226 procedure TAnimationState.saveState (st: TStream; mAlpha: Byte; mBlending: Boolean);
227 begin
228 if (st = nil) then exit;
230 utils.writeSign(st, 'ANIM');
231 utils.writeInt(st, Byte(0)); // version
232 // Ñ÷åò÷èê îæèäàíèÿ ìåæäó êàäðàìè
233 utils.writeInt(st, Byte(mCounter));
234 // Òåêóùèé êàäð
235 utils.writeInt(st, LongInt(mCurrentFrame));
236 // Ïðîèãðàíà ëè àíèìàöèÿ öåëèêîì
237 utils.writeBool(st, mPlayed);
238 // Alpha-êàíàë âñåé òåêñòóðû
239 utils.writeInt(st, Byte(mAlpha));
240 // Ðàçìûòèå òåêñòóðû
241 utils.writeInt(st, Byte(mBlending));
242 // Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè
243 utils.writeInt(st, Byte(mSpeed));
244 // Çàöèêëåíà ëè àíèìàöèÿ
245 utils.writeBool(st, mLoop);
246 // Âêëþ÷åíà ëè
247 utils.writeBool(st, mEnabled);
248 // Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ
249 utils.writeInt(st, Byte(mMinLength));
250 // Îáðàòíûé ëè ïîðÿäîê êàäðîâ
251 utils.writeBool(st, mRevert);
252 end;
255 procedure TAnimationState.loadState (st: TStream; out mAlpha: Byte; out mBlending: Boolean);
256 begin
257 if (st = nil) then exit;
259 if not utils.checkSign(st, 'ANIM') then raise XStreamError.Create('animation chunk expected');
260 if (utils.readByte(st) <> 0) then raise XStreamError.Create('invalid animation chunk version');
261 // Ñ÷åò÷èê îæèäàíèÿ ìåæäó êàäðàìè
262 mCounter := utils.readByte(st);
263 // Òåêóùèé êàäð
264 mCurrentFrame := utils.readLongInt(st);
265 // Ïðîèãðàíà ëè àíèìàöèÿ öåëèêîì
266 mPlayed := utils.readBool(st);
267 // Alpha-êàíàë âñåé òåêñòóðû
268 mAlpha := utils.readByte(st);
269 // Ðàçìûòèå òåêñòóðû
270 mBlending := utils.readBool(st);
271 // Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè
272 mSpeed := utils.readByte(st);
273 // Çàöèêëåíà ëè àíèìàöèÿ
274 mLoop := utils.readBool(st);
275 // Âêëþ÷åíà ëè
276 mEnabled := utils.readBool(st);
277 // Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ
278 mMinLength := utils.readByte(st);
279 // Îáðàòíûé ëè ïîðÿäîê êàäðîâ
280 mRevert := utils.readBool(st);
281 end;
284 (* ------------- *)
286 constructor TAnimState.Create (aloop: Boolean; aspeed: Byte; len: Integer);
287 begin
288 assert(len >= 0);
289 mLength := len;
291 mMinLength := 0;
292 mLoop := aloop;
293 mSpeed := aspeed;
294 mEnabled := true;
295 mCurrentFrame := 0;
296 mPlayed := false;
297 end;
299 procedure TAnimState.Destroy;
300 begin
301 Self := Default(TAnimState);
302 end;
304 procedure TAnimState.update;
305 begin
306 if (not mEnabled) then exit;
308 mCounter += 1;
310 if (mCounter >= mSpeed) then
311 begin
312 if mRevert then
313 begin
314 if (mCurrentFrame = 0) then
315 begin
316 if (mLength * mSpeed + mCounter < mMinLength) then exit;
317 end;
319 mCurrentFrame -= 1;
320 mPlayed := (mCurrentFrame < 0);
322 if mPlayed then
323 begin
324 if mLoop then
325 mCurrentFrame := mLength - 1
326 else
327 mCurrentFrame += 1
328 end;
330 mCounter := 0;
331 end
332 else
333 begin
334 if (mCurrentFrame = mLength - 1) then
335 begin
336 if (mLength * mSpeed + mCounter < mMinLength) then exit;
337 end;
339 mCurrentFrame += 1;
340 mPlayed := (mCurrentFrame > mLength - 1);
342 if mPlayed then
343 begin
344 if mLoop then mCurrentFrame := 0 else mCurrentFrame -= 1;
345 end;
347 mCounter := 0;
348 end;
349 end;
350 end;
352 procedure TAnimState.reset;
353 begin
354 if mRevert then
355 mCurrentFrame := mLength - 1
356 else
357 mCurrentFrame := 0;
358 mCounter := 0;
359 mPlayed := false
360 end;
362 procedure TAnimState.disable;
363 begin
364 mEnabled := false
365 end;
367 procedure TAnimState.enable;
368 begin
369 mEnabled := true
370 end;
372 procedure TAnimState.revert (r: Boolean);
373 begin
374 mRevert := r;
375 reset
376 end;
378 function TAnimState.totalFrames (): Integer; inline;
379 begin
380 result := mLength
381 end;
383 procedure TAnimState.saveState (st: TStream; mAlpha: Byte; mBlending: Boolean);
384 begin
385 if (st = nil) then exit;
387 utils.writeSign(st, 'ANIM');
388 utils.writeInt(st, Byte(0)); // version
389 utils.writeInt(st, Byte(mCounter));
390 utils.writeInt(st, LongInt(mCurrentFrame));
391 utils.writeBool(st, mPlayed);
392 utils.writeInt(st, Byte(mAlpha));
393 utils.writeInt(st, Byte(mBlending));
394 utils.writeInt(st, Byte(mSpeed));
395 utils.writeBool(st, mLoop);
396 utils.writeBool(st, mEnabled);
397 utils.writeInt(st, Byte(mMinLength));
398 utils.writeBool(st, mRevert);
399 end;
402 procedure TAnimState.loadState (st: TStream; out mAlpha: Byte; out mBlending: Boolean);
403 begin
404 if (st = nil) then exit;
406 if not utils.checkSign(st, 'ANIM') then raise XStreamError.Create('animation chunk expected');
407 if (utils.readByte(st) <> 0) then raise XStreamError.Create('invalid animation chunk version');
408 mCounter := utils.readByte(st);
409 mCurrentFrame := utils.readLongInt(st);
410 mPlayed := utils.readBool(st);
411 mAlpha := utils.readByte(st);
412 mBlending := utils.readBool(st);
413 mSpeed := utils.readByte(st);
414 mLoop := utils.readBool(st);
415 mEnabled := utils.readBool(st);
416 mMinLength := utils.readByte(st);
417 mRevert := utils.readBool(st);
418 end;
421 end.