DEADSOFTWARE

d12a9a24e4ba74789cfbe74fbaa0713e4b0c376f
[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;
28 width, height: Word;
29 case anim: Boolean of
30 false: (textureID: LongWord);
31 true: (framesID: LongWord; framesCount: Byte; speed: Byte);
32 end;
34 TLevelTextureArray = array of TLevelTexture;
36 TAnimation = class{$IFDEF USE_MEMPOOL}(TPoolObject){$ENDIF}
37 private
38 mId: LongWord;
39 mAlpha: Byte;
40 mBlending: Boolean;
41 mCounter: Byte; // Ñ÷åò÷èê îæèäàíèÿ ìåæäó êàäðàìè
42 mSpeed: Byte; // Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè
43 mCurrentFrame: Integer; // Òåêóùèé êàäð (íà÷èíàÿ ñ 0)
44 mLoop: Boolean; // Ïåðåõîäèòü íà ïåðâûé êàäð ïîñëå ïîñëåäíåãî?
45 mEnabled: Boolean; // Ðàáîòà ðàçðåøåíà?
46 mPlayed: Boolean; // Ïðîèãðàíà âñÿ õîòÿ áû ðàç?
47 mHeight: Word;
48 mWidth: Word;
49 mMinLength: Byte; // Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ
50 mRevert: Boolean; // Ñìåíà êàäðîâ îáðàòíàÿ?
52 public
53 constructor Create (aframesID: LongWord; aloop: Boolean; aspeed: Byte);
54 destructor Destroy (); override;
56 procedure reset ();
57 procedure update ();
58 procedure enable ();
59 procedure disable ();
60 procedure revert (r: Boolean);
62 procedure saveState (st: TStream);
63 procedure loadState (st: TStream);
65 function totalFrames (): Integer; inline;
67 public
68 property played: Boolean read mPlayed;
69 property enabled: Boolean read mEnabled;
70 property isReverse: Boolean read mRevert;
71 property loop: Boolean read mLoop write mLoop;
72 property speed: Byte read mSpeed write mSpeed;
73 property minLength: Byte read mMinLength write mMinLength;
74 property currentFrame: Integer read mCurrentFrame write mCurrentFrame;
75 property currentCounter: Byte read mCounter write mCounter;
76 property counter: Byte read mCounter;
77 property blending: Boolean read mBlending write mBlending;
78 property alpha: Byte read mAlpha write mAlpha;
79 property framesId: LongWord read mId;
80 property width: Word read mWidth;
81 property height: Word read mHeight;
83 property id: LongWord read mId;
84 end;
86 implementation
88 uses
89 g_game, e_log, g_basic, g_console, wadreader, r_animations,
90 g_language, utils, xstreams;
92 constructor TAnimation.Create (aframesID: LongWord; aloop: Boolean; aspeed: Byte);
93 begin
94 if (aframesID >= Length(framesArray)) then
95 begin
96 //raise Exception.Create('trying to create inexisting frame: something is very wrong here');
97 e_LogWritefln('trying to create inexisting frame %u of %u: something is very wrong here', [aframesID, LongWord(Length(framesArray))], TMsgType.Warning);
98 aframesID := 0;
99 if (Length(framesArray) = 0) then raise Exception.Create('trying to create inexisting frame: something is very wrong here');
100 end;
101 mId := aframesID;
102 mMinLength := 0;
103 mLoop := aloop;
104 mSpeed := aspeed;
105 mEnabled := true;
106 mCurrentFrame := 0;
107 mPlayed := false;
108 mAlpha := 0;
109 mWidth := framesArray[mId].FrameWidth;
110 mHeight := framesArray[mId].FrameHeight;
111 end;
114 destructor TAnimation.Destroy ();
115 begin
116 inherited;
117 end;
120 procedure TAnimation.update ();
121 begin
122 if (not mEnabled) then exit;
124 mCounter += 1;
126 if (mCounter >= mSpeed) then
127 begin
128 // Îæèäàíèå ìåæäó êàäðàìè çàêîí÷èëîñü
129 // Îáðàòíûé ïîðÿäîê êàäðîâ?
130 if mRevert then
131 begin
132 // Äîøëè äî êîíöà àíèìàöèè. Âîçìîæíî, æäåì åùå
133 if (mCurrentFrame = 0) then
134 begin
135 if (Length(framesArray[mId].TexturesID)*mSpeed+mCounter < mMinLength) then exit;
136 end;
138 mCurrentFrame -= 1;
139 mPlayed := (mCurrentFrame < 0);
141 // Ïîâòîðÿòü ëè àíèìàöèþ ïî êðóãó?
142 if mPlayed then
143 begin
144 if mLoop then mCurrentFrame := High(framesArray[mId].TexturesID) else mCurrentFrame += 1;
145 end;
147 mCounter := 0;
148 end
149 else
150 begin
151 // Ïðÿìîé ïîðÿäîê êàäðîâ
152 // Äîøëè äî êîíöà àíèìàöèè. Âîçìîæíî, æäåì åùå
153 if (mCurrentFrame = High(framesArray[mId].TexturesID)) then
154 begin
155 if (Length(framesArray[mId].TexturesID)*mSpeed+mCounter < mMinLength) then exit;
156 end;
158 mCurrentFrame += 1;
159 mPlayed := (mCurrentFrame > High(framesArray[mId].TexturesID));
161 // Ïîâòîðÿòü ëè àíèìàöèþ ïî êðóãó?
162 if mPlayed then
163 begin
164 if mLoop then mCurrentFrame := 0 else mCurrentFrame -= 1;
165 end;
167 mCounter := 0;
168 end;
169 end;
170 end;
173 procedure TAnimation.reset ();
174 begin
175 if mRevert then mCurrentFrame := High(framesArray[mId].TexturesID) else mCurrentFrame := 0;
176 mCounter := 0;
177 mPlayed := false;
178 end;
181 procedure TAnimation.disable (); begin mEnabled := false; end;
182 procedure TAnimation.enable (); begin mEnabled := true; end;
185 function TAnimation.totalFrames (): Integer; inline; begin result := Length(framesArray[mId].TexturesID); end;
188 procedure TAnimation.revert (r: Boolean);
189 begin
190 mRevert := r;
191 reset();
192 end;
195 procedure TAnimation.saveState (st: TStream);
196 begin
197 if (st = nil) then exit;
199 utils.writeSign(st, 'ANIM');
200 utils.writeInt(st, Byte(0)); // version
201 // Ñ÷åò÷èê îæèäàíèÿ ìåæäó êàäðàìè
202 utils.writeInt(st, Byte(mCounter));
203 // Òåêóùèé êàäð
204 utils.writeInt(st, LongInt(mCurrentFrame));
205 // Ïðîèãðàíà ëè àíèìàöèÿ öåëèêîì
206 utils.writeBool(st, mPlayed);
207 // Alpha-êàíàë âñåé òåêñòóðû
208 utils.writeInt(st, Byte(mAlpha));
209 // Ðàçìûòèå òåêñòóðû
210 utils.writeInt(st, Byte(mBlending));
211 // Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè
212 utils.writeInt(st, Byte(mSpeed));
213 // Çàöèêëåíà ëè àíèìàöèÿ
214 utils.writeBool(st, mLoop);
215 // Âêëþ÷åíà ëè
216 utils.writeBool(st, mEnabled);
217 // Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ
218 utils.writeInt(st, Byte(mMinLength));
219 // Îáðàòíûé ëè ïîðÿäîê êàäðîâ
220 utils.writeBool(st, mRevert);
221 end;
224 procedure TAnimation.loadState (st: TStream);
225 begin
226 if (st = nil) then exit;
228 if not utils.checkSign(st, 'ANIM') then raise XStreamError.Create('animation chunk expected');
229 if (utils.readByte(st) <> 0) then raise XStreamError.Create('invalid animation chunk version');
230 // Ñ÷åò÷èê îæèäàíèÿ ìåæäó êàäðàìè
231 mCounter := utils.readByte(st);
232 // Òåêóùèé êàäð
233 mCurrentFrame := utils.readLongInt(st);
234 // Ïðîèãðàíà ëè àíèìàöèÿ öåëèêîì
235 mPlayed := utils.readBool(st);
236 // Alpha-êàíàë âñåé òåêñòóðû
237 mAlpha := utils.readByte(st);
238 // Ðàçìûòèå òåêñòóðû
239 mBlending := utils.readBool(st);
240 // Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè
241 mSpeed := utils.readByte(st);
242 // Çàöèêëåíà ëè àíèìàöèÿ
243 mLoop := utils.readBool(st);
244 // Âêëþ÷åíà ëè
245 mEnabled := utils.readBool(st);
246 // Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ
247 mMinLength := utils.readByte(st);
248 // Îáðàòíûé ëè ïîðÿäîê êàäðîâ
249 mRevert := utils.readBool(st);
250 end;
252 end.