DEADSOFTWARE

weapons: use TAnimState
[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 Invalidate;
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;
102 function IsInvalid (): Boolean;
103 function IsValid (): Boolean;
105 public
106 property played: Boolean read mPlayed;
107 property enabled: Boolean read mEnabled;
108 property isReverse: Boolean read mRevert;
109 property loop: Boolean read mLoop write mLoop;
110 property speed: Byte read mSpeed write mSpeed;
111 property minLength: Byte read mMinLength write mMinLength;
112 property currentFrame: Integer read mCurrentFrame write mCurrentFrame;
113 property currentCounter: Byte read mCounter write mCounter;
114 property counter: Byte read mCounter;
115 property length: Integer read mLength;
116 end;
118 implementation
120 uses
121 g_game, e_log, g_basic, g_console, wadreader,
122 g_language, utils, xstreams;
124 constructor TAnimationState.Create (aloop: Boolean; aspeed: Byte; len: Integer);
125 begin
126 assert(len >= 0);
127 mLength := len;
129 mMinLength := 0;
130 mLoop := aloop;
131 mSpeed := aspeed;
132 mEnabled := true;
133 mCurrentFrame := 0;
134 mPlayed := false;
135 end;
137 destructor TAnimationState.Destroy;
138 begin
139 inherited;
140 end;
142 procedure TAnimationState.update;
143 begin
144 if (not mEnabled) then exit;
146 mCounter += 1;
148 if (mCounter >= mSpeed) then
149 begin
150 // Îæèäàíèå ìåæäó êàäðàìè çàêîí÷èëîñü
151 // Îáðàòíûé ïîðÿäîê êàäðîâ?
152 if mRevert then
153 begin
154 // Äîøëè äî êîíöà àíèìàöèè. Âîçìîæíî, æäåì åùå
155 if (mCurrentFrame = 0) then
156 begin
157 if (mLength * mSpeed + mCounter < mMinLength) then exit;
158 end;
160 mCurrentFrame -= 1;
161 mPlayed := (mCurrentFrame < 0);
163 // Ïîâòîðÿòü ëè àíèìàöèþ ïî êðóãó?
164 if mPlayed then
165 begin
166 if mLoop then
167 mCurrentFrame := mLength - 1
168 else
169 mCurrentFrame += 1
170 end;
172 mCounter := 0;
173 end
174 else
175 begin
176 // Ïðÿìîé ïîðÿäîê êàäðîâ
177 // Äîøëè äî êîíöà àíèìàöèè. Âîçìîæíî, æäåì åùå
178 if (mCurrentFrame = mLength - 1) then
179 begin
180 if (mLength * mSpeed + mCounter < mMinLength) then exit;
181 end;
183 mCurrentFrame += 1;
184 mPlayed := (mCurrentFrame > mLength - 1);
186 // Ïîâòîðÿòü ëè àíèìàöèþ ïî êðóãó?
187 if mPlayed then
188 begin
189 if mLoop then mCurrentFrame := 0 else mCurrentFrame -= 1;
190 end;
192 mCounter := 0;
193 end;
194 end;
195 end;
197 procedure TAnimationState.reset;
198 begin
199 if mRevert then
200 mCurrentFrame := mLength - 1
201 else
202 mCurrentFrame := 0;
203 mCounter := 0;
204 mPlayed := false
205 end;
207 procedure TAnimationState.disable;
208 begin
209 mEnabled := false
210 end;
212 procedure TAnimationState.enable;
213 begin
214 mEnabled := true
215 end;
217 procedure TAnimationState.revert (r: Boolean);
218 begin
219 mRevert := r;
220 reset
221 end;
223 function TAnimationState.totalFrames (): Integer; inline;
224 begin
225 result := mLength
226 end;
228 procedure TAnimationState.saveState (st: TStream; mAlpha: Byte; mBlending: Boolean);
229 begin
230 if (st = nil) then exit;
232 utils.writeSign(st, 'ANIM');
233 utils.writeInt(st, Byte(0)); // version
234 // Ñ÷åò÷èê îæèäàíèÿ ìåæäó êàäðàìè
235 utils.writeInt(st, Byte(mCounter));
236 // Òåêóùèé êàäð
237 utils.writeInt(st, LongInt(mCurrentFrame));
238 // Ïðîèãðàíà ëè àíèìàöèÿ öåëèêîì
239 utils.writeBool(st, mPlayed);
240 // Alpha-êàíàë âñåé òåêñòóðû
241 utils.writeInt(st, Byte(mAlpha));
242 // Ðàçìûòèå òåêñòóðû
243 utils.writeInt(st, Byte(mBlending));
244 // Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè
245 utils.writeInt(st, Byte(mSpeed));
246 // Çàöèêëåíà ëè àíèìàöèÿ
247 utils.writeBool(st, mLoop);
248 // Âêëþ÷åíà ëè
249 utils.writeBool(st, mEnabled);
250 // Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ
251 utils.writeInt(st, Byte(mMinLength));
252 // Îáðàòíûé ëè ïîðÿäîê êàäðîâ
253 utils.writeBool(st, mRevert);
254 end;
257 procedure TAnimationState.loadState (st: TStream; out mAlpha: Byte; out mBlending: Boolean);
258 begin
259 if (st = nil) then exit;
261 if not utils.checkSign(st, 'ANIM') then raise XStreamError.Create('animation chunk expected');
262 if (utils.readByte(st) <> 0) then raise XStreamError.Create('invalid animation chunk version');
263 // Ñ÷åò÷èê îæèäàíèÿ ìåæäó êàäðàìè
264 mCounter := utils.readByte(st);
265 // Òåêóùèé êàäð
266 mCurrentFrame := utils.readLongInt(st);
267 // Ïðîèãðàíà ëè àíèìàöèÿ öåëèêîì
268 mPlayed := utils.readBool(st);
269 // Alpha-êàíàë âñåé òåêñòóðû
270 mAlpha := utils.readByte(st);
271 // Ðàçìûòèå òåêñòóðû
272 mBlending := utils.readBool(st);
273 // Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè
274 mSpeed := utils.readByte(st);
275 // Çàöèêëåíà ëè àíèìàöèÿ
276 mLoop := utils.readBool(st);
277 // Âêëþ÷åíà ëè
278 mEnabled := utils.readBool(st);
279 // Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ
280 mMinLength := utils.readByte(st);
281 // Îáðàòíûé ëè ïîðÿäîê êàäðîâ
282 mRevert := utils.readBool(st);
283 end;
286 (* ------------- *)
288 constructor TAnimState.Create (aloop: Boolean; aspeed: Byte; len: Integer);
289 begin
290 Self := Default(TAnimState);
292 assert(len >= 0);
293 mLength := len;
295 mMinLength := 0;
296 mLoop := aloop;
297 mSpeed := aspeed;
298 mEnabled := true;
299 mCurrentFrame := 0;
300 mPlayed := false;
301 end;
303 procedure TAnimState.Invalidate;
304 begin
305 Self := Default(TAnimState);
306 end;
308 procedure TAnimState.update;
309 begin
310 if (not mEnabled) then exit;
312 mCounter += 1;
314 if (mCounter >= mSpeed) then
315 begin
316 if mRevert then
317 begin
318 if (mCurrentFrame = 0) then
319 begin
320 if (mLength * mSpeed + mCounter < mMinLength) then exit;
321 end;
323 mCurrentFrame -= 1;
324 mPlayed := (mCurrentFrame < 0);
326 if mPlayed then
327 begin
328 if mLoop then
329 mCurrentFrame := mLength - 1
330 else
331 mCurrentFrame += 1
332 end;
334 mCounter := 0;
335 end
336 else
337 begin
338 if (mCurrentFrame = mLength - 1) then
339 begin
340 if (mLength * mSpeed + mCounter < mMinLength) then exit;
341 end;
343 mCurrentFrame += 1;
344 mPlayed := (mCurrentFrame > mLength - 1);
346 if mPlayed then
347 begin
348 if mLoop then mCurrentFrame := 0 else mCurrentFrame -= 1;
349 end;
351 mCounter := 0;
352 end;
353 end;
354 end;
356 procedure TAnimState.reset;
357 begin
358 if mRevert then
359 mCurrentFrame := mLength - 1
360 else
361 mCurrentFrame := 0;
362 mCounter := 0;
363 mPlayed := false
364 end;
366 procedure TAnimState.disable;
367 begin
368 mEnabled := false
369 end;
371 procedure TAnimState.enable;
372 begin
373 mEnabled := true
374 end;
376 procedure TAnimState.revert (r: Boolean);
377 begin
378 mRevert := r;
379 reset
380 end;
382 function TAnimState.totalFrames (): Integer; inline;
383 begin
384 result := mLength
385 end;
387 function TAnimState.IsInvalid (): Boolean;
388 begin
389 result := mLength <= 0
390 end;
392 function TAnimState.IsValid (): Boolean;
393 begin
394 result := mLength > 0
395 end;
397 procedure TAnimState.saveState (st: TStream; mAlpha: Byte; mBlending: Boolean);
398 begin
399 if (st = nil) then exit;
401 utils.writeSign(st, 'ANIM');
402 utils.writeInt(st, Byte(0)); // version
403 utils.writeInt(st, Byte(mCounter));
404 utils.writeInt(st, LongInt(mCurrentFrame));
405 utils.writeBool(st, mPlayed);
406 utils.writeInt(st, Byte(mAlpha));
407 utils.writeInt(st, Byte(mBlending));
408 utils.writeInt(st, Byte(mSpeed));
409 utils.writeBool(st, mLoop);
410 utils.writeBool(st, mEnabled);
411 utils.writeInt(st, Byte(mMinLength));
412 utils.writeBool(st, mRevert);
413 end;
416 procedure TAnimState.loadState (st: TStream; out mAlpha: Byte; out mBlending: Boolean);
417 begin
418 if (st = nil) then exit;
420 if not utils.checkSign(st, 'ANIM') then raise XStreamError.Create('animation chunk expected');
421 if (utils.readByte(st) <> 0) then raise XStreamError.Create('invalid animation chunk version');
422 mCounter := utils.readByte(st);
423 mCurrentFrame := utils.readLongInt(st);
424 mPlayed := utils.readBool(st);
425 mAlpha := utils.readByte(st);
426 mBlending := utils.readBool(st);
427 mSpeed := utils.readByte(st);
428 mLoop := utils.readBool(st);
429 mEnabled := utils.readBool(st);
430 mMinLength := utils.readByte(st);
431 mRevert := utils.readBool(st);
432 end;
435 end.