1 (* Copyright (C) Doom 2D: Forever Developers
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.
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.
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/>.
15 {$INCLUDE ../shared/a_modes.inc}
22 {$IFDEF USE_MEMPOOL}mempool
,{$ENDIF}
23 g_base
, r_graphics
, MAPDEF
, ImagingTypes
, Imaging
, ImagingUtility
;
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;
32 TLevelTextureArray
= array of TLevelTexture
;
34 TAnimationState
= class{$IFDEF USE_MEMPOOL}(TPoolObject
){$ENDIF}
38 mCounter
: Byte; // Ñ÷åò÷èê îæèäàíèÿ ìåæäó êàäðàìè
39 mSpeed
: Byte; // Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè
40 mCurrentFrame
: Integer; // Òåêóùèé êàäð (íà÷èíàÿ ñ 0)
41 mLoop
: Boolean; // Ïåðåõîäèòü íà ïåðâûé êàäð ïîñëå ïîñëåäíåãî?
42 mEnabled
: Boolean; // Ðàáîòà ðàçðåøåíà?
43 mPlayed
: Boolean; // Ïðîèãðàíà âñÿ õîòÿ áû ðàç?
44 mMinLength
: Byte; // Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ
45 mRevert
: Boolean; // Ñìåíà êàäðîâ îáðàòíàÿ?
50 constructor Create (aloop
: Boolean; aspeed
: Byte; len
: Integer);
51 destructor Destroy (); override;
57 procedure revert (r
: Boolean);
59 procedure saveState (st
: TStream
);
60 procedure loadState (st
: TStream
);
62 function totalFrames (): Integer; inline;
65 property played
: Boolean read mPlayed
;
66 property enabled
: Boolean read mEnabled
;
67 property isReverse
: Boolean read mRevert
;
68 property loop
: Boolean read mLoop write mLoop
;
69 property speed
: Byte read mSpeed write mSpeed
;
70 property minLength
: Byte read mMinLength write mMinLength
;
71 property currentFrame
: Integer read mCurrentFrame write mCurrentFrame
;
72 property currentCounter
: Byte read mCounter write mCounter
;
73 property counter
: Byte read mCounter
;
74 property blending
: Boolean read mBlending write mBlending
;
75 property alpha
: Byte read mAlpha write mAlpha
;
76 property length
: Integer read mLength
;
79 TAnimation
= class{$IFDEF USE_MEMPOOL}(TPoolObject
){$ENDIF}
84 mCounter
: Byte; // Ñ÷åò÷èê îæèäàíèÿ ìåæäó êàäðàìè
85 mSpeed
: Byte; // Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè
86 mCurrentFrame
: Integer; // Òåêóùèé êàäð (íà÷èíàÿ ñ 0)
87 mLoop
: Boolean; // Ïåðåõîäèòü íà ïåðâûé êàäð ïîñëå ïîñëåäíåãî?
88 mEnabled
: Boolean; // Ðàáîòà ðàçðåøåíà?
89 mPlayed
: Boolean; // Ïðîèãðàíà âñÿ õîòÿ áû ðàç?
92 mMinLength
: Byte; // Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ
93 mRevert
: Boolean; // Ñìåíà êàäðîâ îáðàòíàÿ?
96 constructor Create (aframesID
: LongWord; aloop
: Boolean; aspeed
: Byte);
97 destructor Destroy (); override;
102 procedure disable ();
103 procedure revert (r
: Boolean);
105 procedure saveState (st
: TStream
);
106 procedure loadState (st
: TStream
);
108 function totalFrames (): Integer; inline;
111 property played
: Boolean read mPlayed
;
112 property enabled
: Boolean read mEnabled
;
113 property isReverse
: Boolean read mRevert
;
114 property loop
: Boolean read mLoop write mLoop
;
115 property speed
: Byte read mSpeed write mSpeed
;
116 property minLength
: Byte read mMinLength write mMinLength
;
117 property currentFrame
: Integer read mCurrentFrame write mCurrentFrame
;
118 property currentCounter
: Byte read mCounter write mCounter
;
119 property counter
: Byte read mCounter
;
120 property blending
: Boolean read mBlending write mBlending
;
121 property alpha
: Byte read mAlpha write mAlpha
;
122 property framesId
: LongWord read mId
;
123 property width
: Word read mWidth
;
124 property height
: Word read mHeight
;
126 property id
: LongWord read mId
;
132 g_game
, e_log
, g_basic
, g_console
, wadreader
, r_animations
,
133 g_language
, utils
, xstreams
;
138 constructor TAnimationState
.Create (aloop
: Boolean; aspeed
: Byte; len
: Integer);
152 destructor TAnimationState
.Destroy
;
157 procedure TAnimationState
.update
;
159 if (not mEnabled
) then exit
;
163 if (mCounter
>= mSpeed
) then
165 // Îæèäàíèå ìåæäó êàäðàìè çàêîí÷èëîñü
166 // Îáðàòíûé ïîðÿäîê êàäðîâ?
169 // Äîøëè äî êîíöà àíèìàöèè. Âîçìîæíî, æäåì åùå
170 if (mCurrentFrame
= 0) then
172 if (mLength
* mSpeed
+ mCounter
< mMinLength
) then exit
;
176 mPlayed
:= (mCurrentFrame
< 0);
178 // Ïîâòîðÿòü ëè àíèìàöèþ ïî êðóãó?
182 mCurrentFrame
:= mLength
- 1
191 // Ïðÿìîé ïîðÿäîê êàäðîâ
192 // Äîøëè äî êîíöà àíèìàöèè. Âîçìîæíî, æäåì åùå
193 if (mCurrentFrame
= mLength
- 1) then
195 if (mLength
* mSpeed
+ mCounter
< mMinLength
) then exit
;
199 mPlayed
:= (mCurrentFrame
> mLength
- 1);
201 // Ïîâòîðÿòü ëè àíèìàöèþ ïî êðóãó?
204 if mLoop
then mCurrentFrame
:= 0 else mCurrentFrame
-= 1;
212 procedure TAnimationState
.reset
;
215 mCurrentFrame
:= mLength
- 1
222 procedure TAnimationState
.disable
;
227 procedure TAnimationState
.enable
;
232 procedure TAnimationState
.revert (r
: Boolean);
238 function TAnimationState
.totalFrames (): Integer; inline;
243 procedure TAnimationState
.saveState (st
: TStream
);
245 if (st
= nil) then exit
;
247 utils
.writeSign(st
, 'ANIM');
248 utils
.writeInt(st
, Byte(0)); // version
249 // Ñ÷åò÷èê îæèäàíèÿ ìåæäó êàäðàìè
250 utils
.writeInt(st
, Byte(mCounter
));
252 utils
.writeInt(st
, LongInt(mCurrentFrame
));
253 // Ïðîèãðàíà ëè àíèìàöèÿ öåëèêîì
254 utils
.writeBool(st
, mPlayed
);
255 // Alpha-êàíàë âñåé òåêñòóðû
256 utils
.writeInt(st
, Byte(mAlpha
));
258 utils
.writeInt(st
, Byte(mBlending
));
259 // Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè
260 utils
.writeInt(st
, Byte(mSpeed
));
261 // Çàöèêëåíà ëè àíèìàöèÿ
262 utils
.writeBool(st
, mLoop
);
264 utils
.writeBool(st
, mEnabled
);
265 // Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ
266 utils
.writeInt(st
, Byte(mMinLength
));
267 // Îáðàòíûé ëè ïîðÿäîê êàäðîâ
268 utils
.writeBool(st
, mRevert
);
272 procedure TAnimationState
.loadState (st
: TStream
);
274 if (st
= nil) then exit
;
276 if not utils
.checkSign(st
, 'ANIM') then raise XStreamError
.Create('animation chunk expected');
277 if (utils
.readByte(st
) <> 0) then raise XStreamError
.Create('invalid animation chunk version');
278 // Ñ÷åò÷èê îæèäàíèÿ ìåæäó êàäðàìè
279 mCounter
:= utils
.readByte(st
);
281 mCurrentFrame
:= utils
.readLongInt(st
);
282 // Ïðîèãðàíà ëè àíèìàöèÿ öåëèêîì
283 mPlayed
:= utils
.readBool(st
);
284 // Alpha-êàíàë âñåé òåêñòóðû
285 mAlpha
:= utils
.readByte(st
);
287 mBlending
:= utils
.readBool(st
);
288 // Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè
289 mSpeed
:= utils
.readByte(st
);
290 // Çàöèêëåíà ëè àíèìàöèÿ
291 mLoop
:= utils
.readBool(st
);
293 mEnabled
:= utils
.readBool(st
);
294 // Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ
295 mMinLength
:= utils
.readByte(st
);
296 // Îáðàòíûé ëè ïîðÿäîê êàäðîâ
297 mRevert
:= utils
.readBool(st
);
305 constructor TAnimation
.Create (aframesID
: LongWord; aloop
: Boolean; aspeed
: Byte);
307 if (aframesID
>= Length(framesArray
)) then
309 //raise Exception.Create('trying to create inexisting frame: something is very wrong here');
310 e_LogWritefln('trying to create inexisting frame %u of %u: something is very wrong here', [aframesID
, LongWord(Length(framesArray
))], TMsgType
.Warning
);
312 if (Length(framesArray
) = 0) then raise Exception
.Create('trying to create inexisting frame: something is very wrong here');
322 mWidth
:= framesArray
[mId
].FrameWidth
;
323 mHeight
:= framesArray
[mId
].FrameHeight
;
327 destructor TAnimation
.Destroy ();
333 procedure TAnimation
.update ();
335 if (not mEnabled
) then exit
;
339 if (mCounter
>= mSpeed
) then
341 // Îæèäàíèå ìåæäó êàäðàìè çàêîí÷èëîñü
342 // Îáðàòíûé ïîðÿäîê êàäðîâ?
345 // Äîøëè äî êîíöà àíèìàöèè. Âîçìîæíî, æäåì åùå
346 if (mCurrentFrame
= 0) then
348 if (Length(framesArray
[mId
].TexturesID
)*mSpeed
+mCounter
< mMinLength
) then exit
;
352 mPlayed
:= (mCurrentFrame
< 0);
354 // Ïîâòîðÿòü ëè àíèìàöèþ ïî êðóãó?
357 if mLoop
then mCurrentFrame
:= High(framesArray
[mId
].TexturesID
) else mCurrentFrame
+= 1;
364 // Ïðÿìîé ïîðÿäîê êàäðîâ
365 // Äîøëè äî êîíöà àíèìàöèè. Âîçìîæíî, æäåì åùå
366 if (mCurrentFrame
= High(framesArray
[mId
].TexturesID
)) then
368 if (Length(framesArray
[mId
].TexturesID
)*mSpeed
+mCounter
< mMinLength
) then exit
;
372 mPlayed
:= (mCurrentFrame
> High(framesArray
[mId
].TexturesID
));
374 // Ïîâòîðÿòü ëè àíèìàöèþ ïî êðóãó?
377 if mLoop
then mCurrentFrame
:= 0 else mCurrentFrame
-= 1;
386 procedure TAnimation
.reset ();
388 if mRevert
then mCurrentFrame
:= High(framesArray
[mId
].TexturesID
) else mCurrentFrame
:= 0;
394 procedure TAnimation
.disable (); begin mEnabled
:= false; end;
395 procedure TAnimation
.enable (); begin mEnabled
:= true; end;
398 function TAnimation
.totalFrames (): Integer; inline; begin result
:= Length(framesArray
[mId
].TexturesID
); end;
401 procedure TAnimation
.revert (r
: Boolean);
408 procedure TAnimation
.saveState (st
: TStream
);
410 if (st
= nil) then exit
;
412 utils
.writeSign(st
, 'ANIM');
413 utils
.writeInt(st
, Byte(0)); // version
414 // Ñ÷åò÷èê îæèäàíèÿ ìåæäó êàäðàìè
415 utils
.writeInt(st
, Byte(mCounter
));
417 utils
.writeInt(st
, LongInt(mCurrentFrame
));
418 // Ïðîèãðàíà ëè àíèìàöèÿ öåëèêîì
419 utils
.writeBool(st
, mPlayed
);
420 // Alpha-êàíàë âñåé òåêñòóðû
421 utils
.writeInt(st
, Byte(mAlpha
));
423 utils
.writeInt(st
, Byte(mBlending
));
424 // Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè
425 utils
.writeInt(st
, Byte(mSpeed
));
426 // Çàöèêëåíà ëè àíèìàöèÿ
427 utils
.writeBool(st
, mLoop
);
429 utils
.writeBool(st
, mEnabled
);
430 // Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ
431 utils
.writeInt(st
, Byte(mMinLength
));
432 // Îáðàòíûé ëè ïîðÿäîê êàäðîâ
433 utils
.writeBool(st
, mRevert
);
437 procedure TAnimation
.loadState (st
: TStream
);
439 if (st
= nil) then exit
;
441 if not utils
.checkSign(st
, 'ANIM') then raise XStreamError
.Create('animation chunk expected');
442 if (utils
.readByte(st
) <> 0) then raise XStreamError
.Create('invalid animation chunk version');
443 // Ñ÷åò÷èê îæèäàíèÿ ìåæäó êàäðàìè
444 mCounter
:= utils
.readByte(st
);
446 mCurrentFrame
:= utils
.readLongInt(st
);
447 // Ïðîèãðàíà ëè àíèìàöèÿ öåëèêîì
448 mPlayed
:= utils
.readBool(st
);
449 // Alpha-êàíàë âñåé òåêñòóðû
450 mAlpha
:= utils
.readByte(st
);
452 mBlending
:= utils
.readBool(st
);
453 // Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè
454 mSpeed
:= utils
.readByte(st
);
455 // Çàöèêëåíà ëè àíèìàöèÿ
456 mLoop
:= utils
.readBool(st
);
458 mEnabled
:= utils
.readBool(st
);
459 // Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ
460 mMinLength
:= utils
.readByte(st
);
461 // Îáðàòíûé ëè ïîðÿäîê êàäðîâ
462 mRevert
:= utils
.readBool(st
);