DEADSOFTWARE

9672be8f5834b37e169c9410123a4cf9bb6ac510
[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 end
204 else if not g_Map_IsSpecialTexture(Textures[PanelRec.TextureNum].TextureName) then
205 begin
206 FTextureWidth := Textures[PanelRec.TextureNum].Width;
207 FTextureHeight := Textures[PanelRec.TextureNum].Height;
208 FAlpha := PanelRec.Alpha;
209 FBlending := ByteBool(PanelRec.Flags and PANEL_FLAG_BLENDING);
210 end;
211 end;
213 destructor TPanel.Destroy();
214 var
215 i: Integer;
216 begin
217 for i := 0 to High(FTextureIDs) do
218 if FTextureIDs[i].Anim then
219 FTextureIDs[i].AnTex.Free();
220 SetLength(FTextureIDs, 0);
222 Inherited;
223 end;
225 procedure TPanel.Draw();
226 var
227 xx, yy: Integer;
228 NoTextureID: DWORD;
229 NW, NH: Word;
230 begin
231 if Enabled and (FCurTexture >= 0) and
232 (Width > 0) and (Height > 0) and (FAlpha < 255) and
233 g_Collide(X, Y, Width, Height,
234 sX, sY, sWidth, sHeight) then
235 begin
236 if FTextureIDs[FCurTexture].Anim then
237 begin // Àíèìèðîâàííàÿ òåêñòóðà
238 if FTextureIDs[FCurTexture].AnTex = nil then
239 Exit;
241 for xx := 0 to (Width div FTextureWidth)-1 do
242 for yy := 0 to (Height div FTextureHeight)-1 do
243 FTextureIDs[FCurTexture].AnTex.Draw(
244 X + xx*FTextureWidth,
245 Y + yy*FTextureHeight, M_NONE);
246 end
247 else
248 begin // Îáû÷íàÿ òåêñòóðà
249 case FTextureIDs[FCurTexture].Tex of
250 TEXTURE_SPECIAL_WATER:
251 e_DrawFillQuad(X, Y, X+Width-1, Y+Height-1,
252 0, 0, 255, 0, B_FILTER);
253 TEXTURE_SPECIAL_ACID1:
254 e_DrawFillQuad(X, Y, X+Width-1, Y+Height-1,
255 0, 128, 0, 0, B_FILTER);
256 TEXTURE_SPECIAL_ACID2:
257 e_DrawFillQuad(X, Y, X+Width-1, Y+Height-1,
258 128, 0, 0, 0, B_FILTER);
259 TEXTURE_NONE:
260 if g_Texture_Get('NOTEXTURE', NoTextureID) then
261 begin
262 e_GetTextureSize(NoTextureID, @NW, @NH);
263 e_DrawFill(NoTextureID, X, Y, Width div NW, Height div NH,
264 0, False, False);
265 end else
266 begin
267 xx := X + (Width div 2);
268 yy := Y + (Height div 2);
269 e_DrawFillQuad(X, Y, xx, yy,
270 255, 0, 255, 0);
271 e_DrawFillQuad(xx, Y, X+Width-1, yy,
272 255, 255, 0, 0);
273 e_DrawFillQuad(X, yy, xx, Y+Height-1,
274 255, 255, 0, 0);
275 e_DrawFillQuad(xx, yy, X+Width-1, Y+Height-1,
276 255, 0, 255, 0);
277 end;
279 else
280 e_DrawFill(FTextureIDs[FCurTexture].Tex, X, Y,
281 Width div FTextureWidth,
282 Height div FTextureHeight,
283 FAlpha, True, FBlending);
284 end;
285 end;
286 end;
287 end;
289 procedure TPanel.Update();
290 begin
291 if Enabled and (FCurTexture >= 0) and
292 (FTextureIDs[FCurTexture].Anim) and
293 (FTextureIDs[FCurTexture].AnTex <> nil) and
294 (Width > 0) and (Height > 0) and (FAlpha < 255) then
295 begin
296 FTextureIDs[FCurTexture].AnTex.Update();
297 FCurFrame := FTextureIDs[FCurTexture].AnTex.CurrentFrame;
298 FCurFrameCount := FTextureIDs[FCurTexture].AnTex.CurrentCounter;
299 end;
300 end;
302 procedure TPanel.SetFrame(Frame: Integer; Count: Byte);
304 function ClampInt(X, A, B: Integer): Integer;
305 begin
306 Result := X;
307 if X < A then Result := A else if X > B then Result := B;
308 end;
310 begin
311 if Enabled and (FCurTexture >= 0) and
312 (FTextureIDs[FCurTexture].Anim) and
313 (FTextureIDs[FCurTexture].AnTex <> nil) and
314 (Width > 0) and (Height > 0) and (FAlpha < 255) then
315 begin
316 FCurFrame := ClampInt(Frame, 0, FTextureIDs[FCurTexture].AnTex.TotalFrames);
317 FCurFrameCount := Count;
318 FTextureIDs[FCurTexture].AnTex.CurrentFrame := FCurFrame;
319 FTextureIDs[FCurTexture].AnTex.CurrentCounter := FCurFrameCount;
320 end;
321 end;
323 procedure TPanel.NextTexture(AnimLoop: Byte = 0);
324 begin
325 Assert(FCurTexture >= -1, 'FCurTexture < -1');
327 // Íåò òåêñòóð:
328 if Length(FTextureIDs) = 0 then
329 FCurTexture := -1
330 else
331 // Òîëüêî îäíà òåêñòóðà:
332 if Length(FTextureIDs) = 1 then
333 begin
334 if FCurTexture = 0 then
335 FCurTexture := -1
336 else
337 FCurTexture := 0;
338 end
339 else
340 // Áîëüøå îäíîé òåêñòóðû:
341 begin
342 // Ñëåäóþùàÿ:
343 Inc(FCurTexture);
344 // Ñëåäóþùåé íåò - âîçâðàò ê íà÷àëó:
345 if FCurTexture >= Length(FTextureIDs) then
346 FCurTexture := 0;
347 end;
349 // Ïåðåêëþ÷èëèñü íà âèäèìóþ àíèì. òåêñòóðó:
350 if (FCurTexture >= 0) and FTextureIDs[FCurTexture].Anim then
351 begin
352 if (FTextureIDs[FCurTexture].AnTex = nil) then
353 begin
354 g_FatalError(_lc[I_GAME_ERROR_SWITCH_TEXTURE]);
355 Exit;
356 end;
358 if AnimLoop = 1 then
359 FTextureIDs[FCurTexture].AnTex.Loop := True
360 else
361 if AnimLoop = 2 then
362 FTextureIDs[FCurTexture].AnTex.Loop := False;
364 FTextureIDs[FCurTexture].AnTex.Reset();
365 end;
367 LastAnimLoop := AnimLoop;
368 end;
370 procedure TPanel.SetTexture(ID: Integer; AnimLoop: Byte = 0);
371 begin
372 // Íåò òåêñòóð:
373 if Length(FTextureIDs) = 0 then
374 FCurTexture := -1
375 else
376 // Òîëüêî îäíà òåêñòóðà:
377 if Length(FTextureIDs) = 1 then
378 begin
379 if (ID = 0) or (ID = -1) then
380 FCurTexture := ID;
381 end
382 else
383 // Áîëüøå îäíîé òåêñòóðû:
384 begin
385 if (ID >= -1) and (ID <= High(FTextureIDs)) then
386 FCurTexture := ID;
387 end;
389 // Ïåðåêëþ÷èëèñü íà âèäèìóþ àíèì. òåêñòóðó:
390 if (FCurTexture >= 0) and FTextureIDs[FCurTexture].Anim then
391 begin
392 if (FTextureIDs[FCurTexture].AnTex = nil) then
393 begin
394 g_FatalError(_lc[I_GAME_ERROR_SWITCH_TEXTURE]);
395 Exit;
396 end;
398 if AnimLoop = 1 then
399 FTextureIDs[FCurTexture].AnTex.Loop := True
400 else
401 if AnimLoop = 2 then
402 FTextureIDs[FCurTexture].AnTex.Loop := False;
404 FTextureIDs[FCurTexture].AnTex.Reset();
405 end;
407 LastAnimLoop := AnimLoop;
408 end;
410 function TPanel.GetTextureID(): DWORD;
411 begin
412 Result := TEXTURE_NONE;
414 if (FCurTexture >= 0) then
415 begin
416 if FTextureIDs[FCurTexture].Anim then
417 Result := FTextureIDs[FCurTexture].AnTex.FramesID
418 else
419 Result := FTextureIDs[FCurTexture].Tex;
420 end;
421 end;
423 function TPanel.GetTextureCount(): Integer;
424 begin
425 Result := Length(FTextureIDs);
426 if Enabled and (FCurTexture >= 0) then
427 if (FTextureIDs[FCurTexture].Anim) and
428 (FTextureIDs[FCurTexture].AnTex <> nil) and
429 (Width > 0) and (Height > 0) and (FAlpha < 255) then
430 Result := Result + 100;
431 end;
433 procedure TPanel.SaveState(Var Mem: TBinMemoryWriter);
434 var
435 sig: DWORD;
436 anim: Boolean;
437 begin
438 if (not SaveIt) or (Mem = nil) then
439 Exit;
441 // Ñèãíàòóðà ïàíåëè:
442 sig := PANEL_SIGNATURE; // 'PANL'
443 Mem.WriteDWORD(sig);
444 // Îòêðûòà/çàêðûòà, åñëè äâåðü:
445 Mem.WriteBoolean(Enabled);
446 // Íàïðàâëåíèå ëèôòà, åñëè ëèôò:
447 Mem.WriteByte(LiftType);
448 // Íîìåð òåêóùåé òåêñòóðû:
449 Mem.WriteInt(FCurTexture);
450 // Àíèìèðîâàííàÿ ëè òåêóùàÿ òåêñòóðà:
451 if (FCurTexture >= 0) and (FTextureIDs[FCurTexture].Anim) then
452 begin
453 Assert(FTextureIDs[FCurTexture].AnTex <> nil,
454 'TPanel.SaveState: No animation object');
455 anim := True;
456 end
457 else
458 anim := False;
459 Mem.WriteBoolean(anim);
460 // Åñëè äà - ñîõðàíÿåì àíèìàöèþ:
461 if anim then
462 FTextureIDs[FCurTexture].AnTex.SaveState(Mem);
463 end;
465 procedure TPanel.LoadState(var Mem: TBinMemoryReader);
466 var
467 sig: DWORD;
468 anim: Boolean;
469 begin
470 if (not SaveIt) or (Mem = nil) then
471 Exit;
473 // Ñèãíàòóðà ïàíåëè:
474 Mem.ReadDWORD(sig);
475 if sig <> PANEL_SIGNATURE then // 'PANL'
476 begin
477 raise EBinSizeError.Create('TPanel.LoadState: Wrong Panel Signature');
478 end;
479 // Îòêðûòà/çàêðûòà, åñëè äâåðü:
480 Mem.ReadBoolean(Enabled);
481 // Íàïðàâëåíèå ëèôòà, åñëè ëèôò:
482 Mem.ReadByte(LiftType);
483 // Íîìåð òåêóùåé òåêñòóðû:
484 Mem.ReadInt(FCurTexture);
485 // Àíèìèðîâàííàÿ ëè òåêóùàÿ òåêñòóðà:
486 Mem.ReadBoolean(anim);
487 // Åñëè äà - çàãðóæàåì àíèìàöèþ:
488 if anim then
489 begin
490 Assert((FCurTexture >= 0) and
491 (FTextureIDs[FCurTexture].Anim) and
492 (FTextureIDs[FCurTexture].AnTex <> nil),
493 'TPanel.LoadState: No animation object');
494 FTextureIDs[FCurTexture].AnTex.LoadState(Mem);
495 end;
496 end;
498 end.