DEADSOFTWARE

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