DEADSOFTWARE

render: hide panel textures into render
[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, r_graphics, MAPDEF, ImagingTypes, Imaging, ImagingUtility;
25 type
26 TLevelTexture = record
27 TextureName: AnsiString; // as stored in wad
28 FullName: AnsiString; // full path to texture // !!! merge it with TextureName
29 case anim: Boolean of
30 true: (framesCount: Byte; speed: Byte);
31 end;
33 TLevelTextureArray = array of TLevelTexture;
35 TAnimationState = class{$IFDEF USE_MEMPOOL}(TPoolObject){$ENDIF}
36 private
37 mAlpha: Byte;
38 mBlending: Boolean;
39 mCounter: Byte; // Ñ÷åò÷èê îæèäàíèÿ ìåæäó êàäðàìè
40 mSpeed: Byte; // Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè
41 mCurrentFrame: Integer; // Òåêóùèé êàäð (íà÷èíàÿ ñ 0)
42 mLoop: Boolean; // Ïåðåõîäèòü íà ïåðâûé êàäð ïîñëå ïîñëåäíåãî?
43 mEnabled: Boolean; // Ðàáîòà ðàçðåøåíà?
44 mPlayed: Boolean; // Ïðîèãðàíà âñÿ õîòÿ áû ðàç?
45 mMinLength: Byte; // Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ
46 mRevert: Boolean; // Ñìåíà êàäðîâ îáðàòíàÿ?
48 mLength: Integer;
50 public
51 constructor Create (aloop: Boolean; aspeed: Byte; len: Integer);
52 destructor Destroy (); override;
54 procedure reset ();
55 procedure update ();
56 procedure enable ();
57 procedure disable ();
58 procedure revert (r: Boolean);
60 procedure saveState (st: TStream);
61 procedure loadState (st: TStream);
63 function totalFrames (): Integer; inline;
65 public
66 property played: Boolean read mPlayed;
67 property enabled: Boolean read mEnabled;
68 property isReverse: Boolean read mRevert;
69 property loop: Boolean read mLoop write mLoop;
70 property speed: Byte read mSpeed write mSpeed;
71 property minLength: Byte read mMinLength write mMinLength;
72 property currentFrame: Integer read mCurrentFrame write mCurrentFrame;
73 property currentCounter: Byte read mCounter write mCounter;
74 property counter: Byte read mCounter;
75 property blending: Boolean read mBlending write mBlending;
76 property alpha: Byte read mAlpha write mAlpha;
77 end;
79 TAnimation = class{$IFDEF USE_MEMPOOL}(TPoolObject){$ENDIF}
80 private
81 mId: LongWord;
82 mAlpha: Byte;
83 mBlending: Boolean;
84 mCounter: Byte; // Ñ÷åò÷èê îæèäàíèÿ ìåæäó êàäðàìè
85 mSpeed: Byte; // Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè
86 mCurrentFrame: Integer; // Òåêóùèé êàäð (íà÷èíàÿ ñ 0)
87 mLoop: Boolean; // Ïåðåõîäèòü íà ïåðâûé êàäð ïîñëå ïîñëåäíåãî?
88 mEnabled: Boolean; // Ðàáîòà ðàçðåøåíà?
89 mPlayed: Boolean; // Ïðîèãðàíà âñÿ õîòÿ áû ðàç?
90 mHeight: Word;
91 mWidth: Word;
92 mMinLength: Byte; // Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ
93 mRevert: Boolean; // Ñìåíà êàäðîâ îáðàòíàÿ?
95 public
96 constructor Create (aframesID: LongWord; aloop: Boolean; aspeed: Byte);
97 destructor Destroy (); override;
99 procedure reset ();
100 procedure update ();
101 procedure enable ();
102 procedure disable ();
103 procedure revert (r: Boolean);
105 procedure saveState (st: TStream);
106 procedure loadState (st: TStream);
108 function totalFrames (): Integer; inline;
110 public
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;
127 end;
129 implementation
131 uses
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);
139 begin
140 assert(len >= 0);
141 mLength := len;
143 mMinLength := 0;
144 mLoop := aloop;
145 mSpeed := aspeed;
146 mEnabled := true;
147 mCurrentFrame := 0;
148 mAlpha := 0;
149 mPlayed := false;
150 end;
152 destructor TAnimationState.Destroy;
153 begin
154 inherited;
155 end;
157 procedure TAnimationState.update;
158 begin
159 if (not mEnabled) then exit;
161 mCounter += 1;
163 if (mCounter >= mSpeed) then
164 begin
165 // Îæèäàíèå ìåæäó êàäðàìè çàêîí÷èëîñü
166 // Îáðàòíûé ïîðÿäîê êàäðîâ?
167 if mRevert then
168 begin
169 // Äîøëè äî êîíöà àíèìàöèè. Âîçìîæíî, æäåì åùå
170 if (mCurrentFrame = 0) then
171 begin
172 if (mLength * mSpeed + mCounter < mMinLength) then exit;
173 end;
175 mCurrentFrame -= 1;
176 mPlayed := (mCurrentFrame < 0);
178 // Ïîâòîðÿòü ëè àíèìàöèþ ïî êðóãó?
179 if mPlayed then
180 begin
181 if mLoop then
182 mCurrentFrame := mLength - 1
183 else
184 mCurrentFrame += 1
185 end;
187 mCounter := 0;
188 end
189 else
190 begin
191 // Ïðÿìîé ïîðÿäîê êàäðîâ
192 // Äîøëè äî êîíöà àíèìàöèè. Âîçìîæíî, æäåì åùå
193 if (mCurrentFrame = mLength - 1) then
194 begin
195 if (mLength * mSpeed + mCounter < mMinLength) then exit;
196 end;
198 mCurrentFrame += 1;
199 mPlayed := (mCurrentFrame > mLength - 1);
201 // Ïîâòîðÿòü ëè àíèìàöèþ ïî êðóãó?
202 if mPlayed then
203 begin
204 if mLoop then mCurrentFrame := 0 else mCurrentFrame -= 1;
205 end;
207 mCounter := 0;
208 end;
209 end;
210 end;
212 procedure TAnimationState.reset;
213 begin
214 if mRevert then
215 mCurrentFrame := mLength - 1
216 else
217 mCurrentFrame := 0;
218 mCounter := 0;
219 mPlayed := false
220 end;
222 procedure TAnimationState.disable;
223 begin
224 mEnabled := false
225 end;
227 procedure TAnimationState.enable;
228 begin
229 mEnabled := true
230 end;
232 procedure TAnimationState.revert (r: Boolean);
233 begin
234 mRevert := r;
235 reset
236 end;
238 function TAnimationState.totalFrames (): Integer; inline;
239 begin
240 result := mLength
241 end;
243 procedure TAnimationState.saveState (st: TStream);
244 begin
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));
251 // Òåêóùèé êàäð
252 utils.writeInt(st, LongInt(mCurrentFrame));
253 // Ïðîèãðàíà ëè àíèìàöèÿ öåëèêîì
254 utils.writeBool(st, mPlayed);
255 // Alpha-êàíàë âñåé òåêñòóðû
256 utils.writeInt(st, Byte(mAlpha));
257 // Ðàçìûòèå òåêñòóðû
258 utils.writeInt(st, Byte(mBlending));
259 // Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè
260 utils.writeInt(st, Byte(mSpeed));
261 // Çàöèêëåíà ëè àíèìàöèÿ
262 utils.writeBool(st, mLoop);
263 // Âêëþ÷åíà ëè
264 utils.writeBool(st, mEnabled);
265 // Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ
266 utils.writeInt(st, Byte(mMinLength));
267 // Îáðàòíûé ëè ïîðÿäîê êàäðîâ
268 utils.writeBool(st, mRevert);
269 end;
272 procedure TAnimationState.loadState (st: TStream);
273 begin
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);
280 // Òåêóùèé êàäð
281 mCurrentFrame := utils.readLongInt(st);
282 // Ïðîèãðàíà ëè àíèìàöèÿ öåëèêîì
283 mPlayed := utils.readBool(st);
284 // Alpha-êàíàë âñåé òåêñòóðû
285 mAlpha := utils.readByte(st);
286 // Ðàçìûòèå òåêñòóðû
287 mBlending := utils.readBool(st);
288 // Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè
289 mSpeed := utils.readByte(st);
290 // Çàöèêëåíà ëè àíèìàöèÿ
291 mLoop := utils.readBool(st);
292 // Âêëþ÷åíà ëè
293 mEnabled := utils.readBool(st);
294 // Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ
295 mMinLength := utils.readByte(st);
296 // Îáðàòíûé ëè ïîðÿäîê êàäðîâ
297 mRevert := utils.readBool(st);
298 end;
305 constructor TAnimation.Create (aframesID: LongWord; aloop: Boolean; aspeed: Byte);
306 begin
307 if (aframesID >= Length(framesArray)) then
308 begin
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);
311 aframesID := 0;
312 if (Length(framesArray) = 0) then raise Exception.Create('trying to create inexisting frame: something is very wrong here');
313 end;
314 mId := aframesID;
315 mMinLength := 0;
316 mLoop := aloop;
317 mSpeed := aspeed;
318 mEnabled := true;
319 mCurrentFrame := 0;
320 mPlayed := false;
321 mAlpha := 0;
322 mWidth := framesArray[mId].FrameWidth;
323 mHeight := framesArray[mId].FrameHeight;
324 end;
327 destructor TAnimation.Destroy ();
328 begin
329 inherited;
330 end;
333 procedure TAnimation.update ();
334 begin
335 if (not mEnabled) then exit;
337 mCounter += 1;
339 if (mCounter >= mSpeed) then
340 begin
341 // Îæèäàíèå ìåæäó êàäðàìè çàêîí÷èëîñü
342 // Îáðàòíûé ïîðÿäîê êàäðîâ?
343 if mRevert then
344 begin
345 // Äîøëè äî êîíöà àíèìàöèè. Âîçìîæíî, æäåì åùå
346 if (mCurrentFrame = 0) then
347 begin
348 if (Length(framesArray[mId].TexturesID)*mSpeed+mCounter < mMinLength) then exit;
349 end;
351 mCurrentFrame -= 1;
352 mPlayed := (mCurrentFrame < 0);
354 // Ïîâòîðÿòü ëè àíèìàöèþ ïî êðóãó?
355 if mPlayed then
356 begin
357 if mLoop then mCurrentFrame := High(framesArray[mId].TexturesID) else mCurrentFrame += 1;
358 end;
360 mCounter := 0;
361 end
362 else
363 begin
364 // Ïðÿìîé ïîðÿäîê êàäðîâ
365 // Äîøëè äî êîíöà àíèìàöèè. Âîçìîæíî, æäåì åùå
366 if (mCurrentFrame = High(framesArray[mId].TexturesID)) then
367 begin
368 if (Length(framesArray[mId].TexturesID)*mSpeed+mCounter < mMinLength) then exit;
369 end;
371 mCurrentFrame += 1;
372 mPlayed := (mCurrentFrame > High(framesArray[mId].TexturesID));
374 // Ïîâòîðÿòü ëè àíèìàöèþ ïî êðóãó?
375 if mPlayed then
376 begin
377 if mLoop then mCurrentFrame := 0 else mCurrentFrame -= 1;
378 end;
380 mCounter := 0;
381 end;
382 end;
383 end;
386 procedure TAnimation.reset ();
387 begin
388 if mRevert then mCurrentFrame := High(framesArray[mId].TexturesID) else mCurrentFrame := 0;
389 mCounter := 0;
390 mPlayed := false;
391 end;
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);
402 begin
403 mRevert := r;
404 reset();
405 end;
408 procedure TAnimation.saveState (st: TStream);
409 begin
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));
416 // Òåêóùèé êàäð
417 utils.writeInt(st, LongInt(mCurrentFrame));
418 // Ïðîèãðàíà ëè àíèìàöèÿ öåëèêîì
419 utils.writeBool(st, mPlayed);
420 // Alpha-êàíàë âñåé òåêñòóðû
421 utils.writeInt(st, Byte(mAlpha));
422 // Ðàçìûòèå òåêñòóðû
423 utils.writeInt(st, Byte(mBlending));
424 // Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè
425 utils.writeInt(st, Byte(mSpeed));
426 // Çàöèêëåíà ëè àíèìàöèÿ
427 utils.writeBool(st, mLoop);
428 // Âêëþ÷åíà ëè
429 utils.writeBool(st, mEnabled);
430 // Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ
431 utils.writeInt(st, Byte(mMinLength));
432 // Îáðàòíûé ëè ïîðÿäîê êàäðîâ
433 utils.writeBool(st, mRevert);
434 end;
437 procedure TAnimation.loadState (st: TStream);
438 begin
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);
445 // Òåêóùèé êàäð
446 mCurrentFrame := utils.readLongInt(st);
447 // Ïðîèãðàíà ëè àíèìàöèÿ öåëèêîì
448 mPlayed := utils.readBool(st);
449 // Alpha-êàíàë âñåé òåêñòóðû
450 mAlpha := utils.readByte(st);
451 // Ðàçìûòèå òåêñòóðû
452 mBlending := utils.readBool(st);
453 // Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè
454 mSpeed := utils.readByte(st);
455 // Çàöèêëåíà ëè àíèìàöèÿ
456 mLoop := utils.readBool(st);
457 // Âêëþ÷åíà ëè
458 mEnabled := utils.readBool(st);
459 // Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ
460 mMinLength := utils.readByte(st);
461 // Îáðàòíûé ëè ïîðÿäîê êàäðîâ
462 mRevert := utils.readBool(st);
463 end;
465 end.