DEADSOFTWARE

put "{$MODE ...}" directive in each source file; removed trailing spaces, and convert...
[d2df-sdl.git] / src / game / g_panel.pas
1 {$MODE DELPHI}
2 unit g_panel;
4 interface
6 uses
7 MAPSTRUCT, BinEditor, g_textures;
9 type
10 TAddTextureArray = Array of
11 record
12 Texture: Cardinal;
13 Anim: Boolean;
14 end;
16 TPanel = Class (TObject)
17 private
18 FTextureWidth: Word;
19 FTextureHeight: Word;
20 FAlpha: Byte;
21 FBlending: Boolean;
22 FTextureIDs: Array of
23 record
24 case Anim: Boolean of
25 False: (Tex: Cardinal);
26 True: (AnTex: TAnimation);
27 end;
29 public
30 FCurTexture: Integer; // Íîìåð òåêóùåé òåêñòóðû
31 FCurFrame: Integer;
32 FCurFrameCount: Byte;
33 X, Y: Integer;
34 Width, Height: Word;
35 PanelType: Word;
36 SaveIt: Boolean; // Ñîõðàíÿòü ïðè SaveState?
37 Enabled: Boolean;
38 Door: Boolean;
39 LiftType: Byte;
40 LastAnimLoop: Byte;
42 constructor Create(PanelRec: TPanelRec_1;
43 AddTextures: TAddTextureArray;
44 CurTex: Integer;
45 var Textures: TLevelTextureArray);
46 destructor Destroy(); override;
48 procedure Draw();
49 procedure Update();
50 procedure SetFrame(Frame: Integer; Count: Byte);
51 procedure NextTexture(AnimLoop: Byte = 0);
52 procedure SetTexture(ID: Integer; AnimLoop: Byte = 0);
53 function GetTextureID(): Cardinal;
54 function GetTextureCount(): Integer;
56 procedure SaveState(var Mem: TBinMemoryWriter);
57 procedure LoadState(var Mem: TBinMemoryReader);
58 end;
60 TPanelArray = Array of TPanel;
62 implementation
64 uses
65 SysUtils, g_basic, g_map, MAPDEF, g_game, e_graphics,
66 g_console, g_language, e_log;
68 const
69 PANEL_SIGNATURE = $4C4E4150; // 'PANL'
71 { T P a n e l : }
73 constructor TPanel.Create(PanelRec: TPanelRec_1;
74 AddTextures: TAddTextureArray;
75 CurTex: Integer;
76 var Textures: TLevelTextureArray);
77 var
78 i: Integer;
79 begin
80 X := PanelRec.X;
81 Y := PanelRec.Y;
82 Width := PanelRec.Width;
83 Height := PanelRec.Height;
84 FAlpha := 0;
85 FBlending := False;
86 FCurFrame := 0;
87 FCurFrameCount := 0;
88 LastAnimLoop := 0;
90 // Òèï ïàíåëè:
91 PanelType := PanelRec.PanelType;
92 Enabled := True;
93 Door := False;
94 LiftType := 0;
95 SaveIt := False;
97 case PanelType of
98 PANEL_OPENDOOR:
99 begin
100 Enabled := False;
101 Door := True;
102 SaveIt := True;
103 end;
104 PANEL_CLOSEDOOR:
105 begin
106 Door := True;
107 SaveIt := True;
108 end;
109 PANEL_LIFTUP:
110 SaveIt := True;
111 PANEL_LIFTDOWN:
112 begin
113 LiftType := 1;
114 SaveIt := True;
115 end;
116 PANEL_LIFTLEFT:
117 begin
118 LiftType := 2;
119 SaveIt := True;
120 end;
121 PANEL_LIFTRIGHT:
122 begin
123 LiftType := 3;
124 SaveIt := True;
125 end;
126 end;
128 // Íåâèäèìàÿ:
129 if ByteBool(PanelRec.Flags and PANEL_FLAG_HIDE) then
130 begin
131 SetLength(FTextureIDs, 0);
132 FCurTexture := -1;
133 Exit;
134 end;
135 // Ïàíåëè, íå èñïîëüçóþùèå òåêñòóðû:
136 if ByteBool(PanelType and
137 (PANEL_LIFTUP or
138 PANEL_LIFTDOWN or
139 PANEL_LIFTLEFT or
140 PANEL_LIFTRIGHT or
141 PANEL_BLOCKMON)) then
142 begin
143 SetLength(FTextureIDs, 0);
144 FCurTexture := -1;
145 Exit;
146 end;
148 // Åñëè ýòî æèäêîñòü áåç òåêñòóðû - ñïåöòåêñòóðó:
149 if WordBool(PanelType and (PANEL_WATER or PANEL_ACID1 or PANEL_ACID2)) and
150 (not ByteBool(PanelRec.Flags and PANEL_FLAG_WATERTEXTURES)) then
151 begin
152 SetLength(FTextureIDs, 1);
153 FTextureIDs[0].Anim := False;
155 case PanelRec.PanelType of
156 PANEL_WATER:
157 FTextureIDs[0].Tex := TEXTURE_SPECIAL_WATER;
158 PANEL_ACID1:
159 FTextureIDs[0].Tex := TEXTURE_SPECIAL_ACID1;
160 PANEL_ACID2:
161 FTextureIDs[0].Tex := TEXTURE_SPECIAL_ACID2;
162 end;
164 FCurTexture := 0;
165 Exit;
166 end;
168 SetLength(FTextureIDs, Length(AddTextures));
170 if CurTex < 0 then
171 FCurTexture := -1
172 else
173 if CurTex >= Length(FTextureIDs) then
174 FCurTexture := Length(FTextureIDs) - 1
175 else
176 FCurTexture := CurTex;
178 for i := 0 to Length(FTextureIDs)-1 do
179 begin
180 FTextureIDs[i].Anim := AddTextures[i].Anim;
181 if FTextureIDs[i].Anim then
182 begin // Àíèìèðîâàííàÿ òåêñòóðà
183 FTextureIDs[i].AnTex :=
184 TAnimation.Create(Textures[AddTextures[i].Texture].FramesID,
185 True, Textures[AddTextures[i].Texture].Speed);
186 FTextureIDs[i].AnTex.Blending := ByteBool(PanelRec.Flags and PANEL_FLAG_BLENDING);
187 FTextureIDs[i].AnTex.Alpha := PanelRec.Alpha;
188 SaveIt := True;
189 end
190 else
191 begin // Îáû÷íàÿ òåêñòóðà
192 FTextureIDs[i].Tex := Textures[AddTextures[i].Texture].TextureID;
193 end;
194 end;
196 // Òåêñòóð íåñêîëüêî - íóæíî ñîõðàíÿòü òåêóùóþ:
197 if Length(FTextureIDs) > 1 then
198 SaveIt := True;
200 // Åñëè íå ñïåöòåêñòóðà, òî çàäàåì ðàçìåðû:
201 if PanelRec.TextureNum > High(Textures) then
202 begin
203 e_WriteLog(Format('WTF?! PanelRec.TextureNum is out of limits! (%d : %d)', [PanelRec.TextureNum, High(Textures)]), MSG_FATALERROR);
204 FTextureWidth := 2;
205 FTextureHeight := 2;
206 FAlpha := 0;
207 FBlending := ByteBool(0);
208 end
209 else if not g_Map_IsSpecialTexture(Textures[PanelRec.TextureNum].TextureName) then
210 begin
211 FTextureWidth := Textures[PanelRec.TextureNum].Width;
212 FTextureHeight := Textures[PanelRec.TextureNum].Height;
213 FAlpha := PanelRec.Alpha;
214 FBlending := ByteBool(PanelRec.Flags and PANEL_FLAG_BLENDING);
215 end;
216 end;
218 destructor TPanel.Destroy();
219 var
220 i: Integer;
221 begin
222 for i := 0 to High(FTextureIDs) do
223 if FTextureIDs[i].Anim then
224 FTextureIDs[i].AnTex.Free();
225 SetLength(FTextureIDs, 0);
227 Inherited;
228 end;
230 procedure TPanel.Draw();
231 var
232 xx, yy: Integer;
233 NoTextureID: DWORD;
234 NW, NH: Word;
235 begin
236 if Enabled and (FCurTexture >= 0) and
237 (Width > 0) and (Height > 0) and (FAlpha < 255) and
238 g_Collide(X, Y, Width, Height,
239 sX, sY, sWidth, sHeight) then
240 begin
241 if FTextureIDs[FCurTexture].Anim then
242 begin // Àíèìèðîâàííàÿ òåêñòóðà
243 if FTextureIDs[FCurTexture].AnTex = nil then
244 Exit;
246 for xx := 0 to (Width div FTextureWidth)-1 do
247 for yy := 0 to (Height div FTextureHeight)-1 do
248 FTextureIDs[FCurTexture].AnTex.Draw(
249 X + xx*FTextureWidth,
250 Y + yy*FTextureHeight, M_NONE);
251 end
252 else
253 begin // Îáû÷íàÿ òåêñòóðà
254 case FTextureIDs[FCurTexture].Tex of
255 TEXTURE_SPECIAL_WATER:
256 e_DrawFillQuad(X, Y, X+Width-1, Y+Height-1,
257 0, 0, 255, 0, B_FILTER);
258 TEXTURE_SPECIAL_ACID1:
259 e_DrawFillQuad(X, Y, X+Width-1, Y+Height-1,
260 0, 128, 0, 0, B_FILTER);
261 TEXTURE_SPECIAL_ACID2:
262 e_DrawFillQuad(X, Y, X+Width-1, Y+Height-1,
263 128, 0, 0, 0, B_FILTER);
264 TEXTURE_NONE:
265 if g_Texture_Get('NOTEXTURE', NoTextureID) then
266 begin
267 e_GetTextureSize(NoTextureID, @NW, @NH);
268 e_DrawFill(NoTextureID, X, Y, Width div NW, Height div NH,
269 0, False, False);
270 end else
271 begin
272 xx := X + (Width div 2);
273 yy := Y + (Height div 2);
274 e_DrawFillQuad(X, Y, xx, yy,
275 255, 0, 255, 0);
276 e_DrawFillQuad(xx, Y, X+Width-1, yy,
277 255, 255, 0, 0);
278 e_DrawFillQuad(X, yy, xx, Y+Height-1,
279 255, 255, 0, 0);
280 e_DrawFillQuad(xx, yy, X+Width-1, Y+Height-1,
281 255, 0, 255, 0);
282 end;
284 else
285 e_DrawFill(FTextureIDs[FCurTexture].Tex, X, Y,
286 Width div FTextureWidth,
287 Height div FTextureHeight,
288 FAlpha, True, FBlending);
289 end;
290 end;
291 end;
292 end;
294 procedure TPanel.Update();
295 begin
296 if Enabled and (FCurTexture >= 0) and
297 (FTextureIDs[FCurTexture].Anim) and
298 (FTextureIDs[FCurTexture].AnTex <> nil) and
299 (Width > 0) and (Height > 0) and (FAlpha < 255) then
300 begin
301 FTextureIDs[FCurTexture].AnTex.Update();
302 FCurFrame := FTextureIDs[FCurTexture].AnTex.CurrentFrame;
303 FCurFrameCount := FTextureIDs[FCurTexture].AnTex.CurrentCounter;
304 end;
305 end;
307 procedure TPanel.SetFrame(Frame: Integer; Count: Byte);
309 function ClampInt(X, A, B: Integer): Integer;
310 begin
311 Result := X;
312 if X < A then Result := A else if X > B then Result := B;
313 end;
315 begin
316 if Enabled and (FCurTexture >= 0) and
317 (FTextureIDs[FCurTexture].Anim) and
318 (FTextureIDs[FCurTexture].AnTex <> nil) and
319 (Width > 0) and (Height > 0) and (FAlpha < 255) then
320 begin
321 FCurFrame := ClampInt(Frame, 0, FTextureIDs[FCurTexture].AnTex.TotalFrames);
322 FCurFrameCount := Count;
323 FTextureIDs[FCurTexture].AnTex.CurrentFrame := FCurFrame;
324 FTextureIDs[FCurTexture].AnTex.CurrentCounter := FCurFrameCount;
325 end;
326 end;
328 procedure TPanel.NextTexture(AnimLoop: Byte = 0);
329 begin
330 Assert(FCurTexture >= -1, 'FCurTexture < -1');
332 // Íåò òåêñòóð:
333 if Length(FTextureIDs) = 0 then
334 FCurTexture := -1
335 else
336 // Òîëüêî îäíà òåêñòóðà:
337 if Length(FTextureIDs) = 1 then
338 begin
339 if FCurTexture = 0 then
340 FCurTexture := -1
341 else
342 FCurTexture := 0;
343 end
344 else
345 // Áîëüøå îäíîé òåêñòóðû:
346 begin
347 // Ñëåäóþùàÿ:
348 Inc(FCurTexture);
349 // Ñëåäóþùåé íåò - âîçâðàò ê íà÷àëó:
350 if FCurTexture >= Length(FTextureIDs) then
351 FCurTexture := 0;
352 end;
354 // Ïåðåêëþ÷èëèñü íà âèäèìóþ àíèì. òåêñòóðó:
355 if (FCurTexture >= 0) and FTextureIDs[FCurTexture].Anim then
356 begin
357 if (FTextureIDs[FCurTexture].AnTex = nil) then
358 begin
359 g_FatalError(_lc[I_GAME_ERROR_SWITCH_TEXTURE]);
360 Exit;
361 end;
363 if AnimLoop = 1 then
364 FTextureIDs[FCurTexture].AnTex.Loop := True
365 else
366 if AnimLoop = 2 then
367 FTextureIDs[FCurTexture].AnTex.Loop := False;
369 FTextureIDs[FCurTexture].AnTex.Reset();
370 end;
372 LastAnimLoop := AnimLoop;
373 end;
375 procedure TPanel.SetTexture(ID: Integer; AnimLoop: Byte = 0);
376 begin
377 // Íåò òåêñòóð:
378 if Length(FTextureIDs) = 0 then
379 FCurTexture := -1
380 else
381 // Òîëüêî îäíà òåêñòóðà:
382 if Length(FTextureIDs) = 1 then
383 begin
384 if (ID = 0) or (ID = -1) then
385 FCurTexture := ID;
386 end
387 else
388 // Áîëüøå îäíîé òåêñòóðû:
389 begin
390 if (ID >= -1) and (ID <= High(FTextureIDs)) then
391 FCurTexture := ID;
392 end;
394 // Ïåðåêëþ÷èëèñü íà âèäèìóþ àíèì. òåêñòóðó:
395 if (FCurTexture >= 0) and FTextureIDs[FCurTexture].Anim then
396 begin
397 if (FTextureIDs[FCurTexture].AnTex = nil) then
398 begin
399 g_FatalError(_lc[I_GAME_ERROR_SWITCH_TEXTURE]);
400 Exit;
401 end;
403 if AnimLoop = 1 then
404 FTextureIDs[FCurTexture].AnTex.Loop := True
405 else
406 if AnimLoop = 2 then
407 FTextureIDs[FCurTexture].AnTex.Loop := False;
409 FTextureIDs[FCurTexture].AnTex.Reset();
410 end;
412 LastAnimLoop := AnimLoop;
413 end;
415 function TPanel.GetTextureID(): DWORD;
416 begin
417 Result := TEXTURE_NONE;
419 if (FCurTexture >= 0) then
420 begin
421 if FTextureIDs[FCurTexture].Anim then
422 Result := FTextureIDs[FCurTexture].AnTex.FramesID
423 else
424 Result := FTextureIDs[FCurTexture].Tex;
425 end;
426 end;
428 function TPanel.GetTextureCount(): Integer;
429 begin
430 Result := Length(FTextureIDs);
431 if Enabled and (FCurTexture >= 0) then
432 if (FTextureIDs[FCurTexture].Anim) and
433 (FTextureIDs[FCurTexture].AnTex <> nil) and
434 (Width > 0) and (Height > 0) and (FAlpha < 255) then
435 Result := Result + 100;
436 end;
438 procedure TPanel.SaveState(Var Mem: TBinMemoryWriter);
439 var
440 sig: DWORD;
441 anim: Boolean;
442 begin
443 if (not SaveIt) or (Mem = nil) then
444 Exit;
446 // Ñèãíàòóðà ïàíåëè:
447 sig := PANEL_SIGNATURE; // 'PANL'
448 Mem.WriteDWORD(sig);
449 // Îòêðûòà/çàêðûòà, åñëè äâåðü:
450 Mem.WriteBoolean(Enabled);
451 // Íàïðàâëåíèå ëèôòà, åñëè ëèôò:
452 Mem.WriteByte(LiftType);
453 // Íîìåð òåêóùåé òåêñòóðû:
454 Mem.WriteInt(FCurTexture);
455 // Àíèìèðîâàííàÿ ëè òåêóùàÿ òåêñòóðà:
456 if (FCurTexture >= 0) and (FTextureIDs[FCurTexture].Anim) then
457 begin
458 Assert(FTextureIDs[FCurTexture].AnTex <> nil,
459 'TPanel.SaveState: No animation object');
460 anim := True;
461 end
462 else
463 anim := False;
464 Mem.WriteBoolean(anim);
465 // Åñëè äà - ñîõðàíÿåì àíèìàöèþ:
466 if anim then
467 FTextureIDs[FCurTexture].AnTex.SaveState(Mem);
468 end;
470 procedure TPanel.LoadState(var Mem: TBinMemoryReader);
471 var
472 sig: DWORD;
473 anim: Boolean;
474 begin
475 if (not SaveIt) or (Mem = nil) then
476 Exit;
478 // Ñèãíàòóðà ïàíåëè:
479 Mem.ReadDWORD(sig);
480 if sig <> PANEL_SIGNATURE then // 'PANL'
481 begin
482 raise EBinSizeError.Create('TPanel.LoadState: Wrong Panel Signature');
483 end;
484 // Îòêðûòà/çàêðûòà, åñëè äâåðü:
485 Mem.ReadBoolean(Enabled);
486 // Íàïðàâëåíèå ëèôòà, åñëè ëèôò:
487 Mem.ReadByte(LiftType);
488 // Íîìåð òåêóùåé òåêñòóðû:
489 Mem.ReadInt(FCurTexture);
490 // Àíèìèðîâàííàÿ ëè òåêóùàÿ òåêñòóðà:
491 Mem.ReadBoolean(anim);
492 // Åñëè äà - çàãðóæàåì àíèìàöèþ:
493 if anim then
494 begin
495 Assert((FCurTexture >= 0) and
496 (FTextureIDs[FCurTexture].Anim) and
497 (FTextureIDs[FCurTexture].AnTex <> nil),
498 'TPanel.LoadState: No animation object');
499 FTextureIDs[FCurTexture].AnTex.LoadState(Mem);
500 end;
501 end;
503 end.