DEADSOFTWARE

more particles code; still somewhat buggy with mplats, tho, but i'll take care of...
[d2df-sdl.git] / src / game / g_panel.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, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *)
16 {$INCLUDE ../shared/a_modes.inc}
17 {$M+}
18 unit g_panel;
20 interface
22 uses
23 MAPDEF, BinEditor, g_textures, xdynrec;
25 type
26 TAddTextureArray = Array of
27 record
28 Texture: Cardinal;
29 Anim: Boolean;
30 end;
32 TPanel = Class (TObject)
33 private
34 const
35 private
36 mGUID: Integer; // will be assigned in "g_map.pas"
37 FTextureWidth: Word;
38 FTextureHeight: Word;
39 FAlpha: Byte;
40 FBlending: Boolean;
41 FTextureIDs: Array of
42 record
43 case Anim: Boolean of
44 False: (Tex: Cardinal);
45 True: (AnTex: TAnimation);
46 end;
48 mMovingSpeed: TDFPoint;
49 mMovingStart: TDFPoint;
50 mMovingEnd: TDFPoint;
51 mMovingActive: Boolean;
53 private
54 function getx1 (): Integer; inline;
55 function gety1 (): Integer; inline;
56 function getvisvalid (): Boolean; inline;
58 public
59 FCurTexture: Integer; // Íîìåð òåêóùåé òåêñòóðû
60 FCurFrame: Integer;
61 FCurFrameCount: Byte;
62 FX, FY: Integer;
63 FWidth, FHeight: Word;
64 FPanelType: Word;
65 FSaveIt: Boolean; // Ñîõðàíÿòü ïðè SaveState?
66 FEnabled: Boolean;
67 FDoor: Boolean;
68 FMoved: Boolean;
69 FLiftType: Byte;
70 FLastAnimLoop: Byte;
71 // sorry, there fields are public to allow setting 'em in g_map; this should be fixed later
72 // for now, PLEASE, don't modify 'em, or all hell will break loose
73 arrIdx: Integer; // index in one of internal arrays; sorry
74 tag: Integer; // used in coldets and such; sorry; see g_map.GridTagXXX
75 proxyId: Integer; // proxy id in map grid (DO NOT USE!)
76 mapId: AnsiString; // taken directly from map file; dunno why it is here
78 constructor Create(PanelRec: TDynRecord;
79 AddTextures: TAddTextureArray;
80 CurTex: Integer;
81 var Textures: TLevelTextureArray; aguid: Integer);
82 destructor Destroy(); override;
84 procedure Draw();
85 procedure DrawShadowVolume(lightX: Integer; lightY: Integer; radius: Integer);
86 procedure Update();
87 procedure SetFrame(Frame: Integer; Count: Byte);
88 procedure NextTexture(AnimLoop: Byte = 0);
89 procedure SetTexture(ID: Integer; AnimLoop: Byte = 0);
90 function GetTextureID(): Cardinal;
91 function GetTextureCount(): Integer;
93 procedure SaveState(var Mem: TBinMemoryWriter);
94 procedure LoadState(var Mem: TBinMemoryReader);
96 procedure positionChanged (); inline;
98 function isGBack (): Boolean; inline; // gRenderBackgrounds
99 function isGStep (): Boolean; inline; // gSteps
100 function isGWall (): Boolean; inline; // gWalls
101 function isGAcid1 (): Boolean; inline; // gAcid1
102 function isGAcid2 (): Boolean; inline; // gAcid2
103 function isGWater (): Boolean; inline; // gWater
104 function isGFore (): Boolean; inline; // gRenderForegrounds
105 function isGLift (): Boolean; inline; // gLifts
106 function isGBlockMon (): Boolean; inline; // gBlockMon
109 public
110 property visvalid: Boolean read getvisvalid; // panel is "visvalid" when it's width and height are positive
112 published
113 property guid: Integer read mGUID; // will be assigned in "g_map.pas"
114 property x0: Integer read FX;
115 property y0: Integer read FY;
116 property x1: Integer read getx1; // inclusive!
117 property y1: Integer read gety1; // inclusive!
118 property x: Integer read FX write FX;
119 property y: Integer read FY write FY;
120 property width: Word read FWidth write FWidth;
121 property height: Word read FHeight write FHeight;
122 property panelType: Word read FPanelType write FPanelType;
123 property saveIt: Boolean read FSaveIt write FSaveIt; // Ñîõðàíÿòü ïðè SaveState?
124 property enabled: Boolean read FEnabled write FEnabled; // Ñîõðàíÿòü ïðè SaveState?
125 property door: Boolean read FDoor write FDoor; // Ñîõðàíÿòü ïðè SaveState?
126 property moved: Boolean read FMoved write FMoved; // Ñîõðàíÿòü ïðè SaveState?
127 property liftType: Byte read FLiftType write FLiftType; // Ñîõðàíÿòü ïðè SaveState?
128 property lastAnimLoop: Byte read FLastAnimLoop write FLastAnimLoop; // Ñîõðàíÿòü ïðè SaveState?
130 property movingActive: Boolean read mMovingActive write mMovingActive;
132 public
133 property movingSpeed: TDFPoint read mMovingSpeed write mMovingSpeed;
134 property movingStart: TDFPoint read mMovingStart write mMovingStart;
135 property movingEnd: TDFPoint read mMovingEnd write mMovingEnd;
136 end;
138 TPanelArray = Array of TPanel;
140 implementation
142 uses
143 SysUtils, g_basic, g_map, g_game, g_gfx, e_graphics,
144 g_console, g_language, g_monsters, g_player, e_log, GL;
146 const
147 PANEL_SIGNATURE = $4C4E4150; // 'PANL'
149 { T P a n e l : }
151 constructor TPanel.Create(PanelRec: TDynRecord;
152 AddTextures: TAddTextureArray;
153 CurTex: Integer;
154 var Textures: TLevelTextureArray; aguid: Integer);
155 var
156 i: Integer;
157 begin
158 X := PanelRec.X;
159 Y := PanelRec.Y;
160 Width := PanelRec.Width;
161 Height := PanelRec.Height;
162 FAlpha := 0;
163 FBlending := False;
164 FCurFrame := 0;
165 FCurFrameCount := 0;
166 LastAnimLoop := 0;
167 Moved := False;
169 mapId := PanelRec.id;
170 mGUID := aguid;
172 mMovingSpeed := PanelRec.moveSpeed;
173 mMovingStart := PanelRec.moveStart;
174 mMovingEnd := PanelRec.moveEnd;
175 mMovingActive := PanelRec['move_active'].varvalue;
177 // Òèï ïàíåëè:
178 PanelType := PanelRec.PanelType;
179 Enabled := True;
180 Door := False;
181 LiftType := 0;
182 SaveIt := False;
184 case PanelType of
185 PANEL_OPENDOOR:
186 begin
187 Enabled := False;
188 Door := True;
189 SaveIt := True;
190 end;
191 PANEL_CLOSEDOOR:
192 begin
193 Door := True;
194 SaveIt := True;
195 end;
196 PANEL_LIFTUP:
197 SaveIt := True;
198 PANEL_LIFTDOWN:
199 begin
200 LiftType := 1;
201 SaveIt := True;
202 end;
203 PANEL_LIFTLEFT:
204 begin
205 LiftType := 2;
206 SaveIt := True;
207 end;
208 PANEL_LIFTRIGHT:
209 begin
210 LiftType := 3;
211 SaveIt := True;
212 end;
213 end;
215 // Íåâèäèìàÿ:
216 if ByteBool(PanelRec.Flags and PANEL_FLAG_HIDE) then
217 begin
218 SetLength(FTextureIDs, 0);
219 FCurTexture := -1;
220 Exit;
221 end;
222 // Ïàíåëè, íå èñïîëüçóþùèå òåêñòóðû:
223 if ByteBool(PanelType and
224 (PANEL_LIFTUP or
225 PANEL_LIFTDOWN or
226 PANEL_LIFTLEFT or
227 PANEL_LIFTRIGHT or
228 PANEL_BLOCKMON)) then
229 begin
230 SetLength(FTextureIDs, 0);
231 FCurTexture := -1;
232 Exit;
233 end;
235 // Åñëè ýòî æèäêîñòü áåç òåêñòóðû - ñïåöòåêñòóðó:
236 if WordBool(PanelType and (PANEL_WATER or PANEL_ACID1 or PANEL_ACID2)) and
237 (not ByteBool(PanelRec.Flags and PANEL_FLAG_WATERTEXTURES)) then
238 begin
239 SetLength(FTextureIDs, 1);
240 FTextureIDs[0].Anim := False;
242 case PanelRec.PanelType of
243 PANEL_WATER:
244 FTextureIDs[0].Tex := LongWord(TEXTURE_SPECIAL_WATER);
245 PANEL_ACID1:
246 FTextureIDs[0].Tex := LongWord(TEXTURE_SPECIAL_ACID1);
247 PANEL_ACID2:
248 FTextureIDs[0].Tex := LongWord(TEXTURE_SPECIAL_ACID2);
249 end;
251 FCurTexture := 0;
252 Exit;
253 end;
255 SetLength(FTextureIDs, Length(AddTextures));
257 if CurTex < 0 then
258 FCurTexture := -1
259 else
260 if CurTex >= Length(FTextureIDs) then
261 FCurTexture := Length(FTextureIDs) - 1
262 else
263 FCurTexture := CurTex;
265 for i := 0 to Length(FTextureIDs)-1 do
266 begin
267 FTextureIDs[i].Anim := AddTextures[i].Anim;
268 if FTextureIDs[i].Anim then
269 begin // Àíèìèðîâàííàÿ òåêñòóðà
270 FTextureIDs[i].AnTex :=
271 TAnimation.Create(Textures[AddTextures[i].Texture].FramesID,
272 True, Textures[AddTextures[i].Texture].Speed);
273 FTextureIDs[i].AnTex.Blending := ByteBool(PanelRec.Flags and PANEL_FLAG_BLENDING);
274 FTextureIDs[i].AnTex.Alpha := PanelRec.Alpha;
275 SaveIt := True;
276 end
277 else
278 begin // Îáû÷íàÿ òåêñòóðà
279 FTextureIDs[i].Tex := Textures[AddTextures[i].Texture].TextureID;
280 end;
281 end;
283 // Òåêñòóð íåñêîëüêî - íóæíî ñîõðàíÿòü òåêóùóþ:
284 if Length(FTextureIDs) > 1 then
285 SaveIt := True;
287 // Åñëè íå ñïåöòåêñòóðà, òî çàäàåì ðàçìåðû:
288 if PanelRec.TextureNum > High(Textures) then
289 begin
290 e_WriteLog(Format('WTF?! PanelRec.TextureNum is out of limits! (%d : %d)', [PanelRec.TextureNum, High(Textures)]), MSG_FATALERROR);
291 FTextureWidth := 2;
292 FTextureHeight := 2;
293 FAlpha := 0;
294 FBlending := ByteBool(0);
295 end
296 else if not g_Map_IsSpecialTexture(Textures[PanelRec.TextureNum].TextureName) then
297 begin
298 FTextureWidth := Textures[PanelRec.TextureNum].Width;
299 FTextureHeight := Textures[PanelRec.TextureNum].Height;
300 FAlpha := PanelRec.Alpha;
301 FBlending := ByteBool(PanelRec.Flags and PANEL_FLAG_BLENDING);
302 end;
303 end;
305 destructor TPanel.Destroy();
306 var
307 i: Integer;
308 begin
309 for i := 0 to High(FTextureIDs) do
310 if FTextureIDs[i].Anim then
311 FTextureIDs[i].AnTex.Free();
312 SetLength(FTextureIDs, 0);
314 Inherited;
315 end;
317 function TPanel.getx1 (): Integer; inline; begin result := X+Width-1; end;
318 function TPanel.gety1 (): Integer; inline; begin result := Y+Height-1; end;
319 function TPanel.getvisvalid (): Boolean; inline; begin result := (Width > 0) and (Height > 0); end;
321 function TPanel.isGBack (): Boolean; inline; begin result := ((tag and GridTagBack) <> 0); end;
322 function TPanel.isGStep (): Boolean; inline; begin result := ((tag and GridTagStep) <> 0); end;
323 function TPanel.isGWall (): Boolean; inline; begin result := ((tag and (GridTagWall or GridTagDoor)) <> 0); end;
324 function TPanel.isGAcid1 (): Boolean; inline; begin result := ((tag and GridTagAcid1) <> 0); end;
325 function TPanel.isGAcid2 (): Boolean; inline; begin result := ((tag and GridTagAcid2) <> 0); end;
326 function TPanel.isGWater (): Boolean; inline; begin result := ((tag and GridTagWater) <> 0); end;
327 function TPanel.isGFore (): Boolean; inline; begin result := ((tag and GridTagFore) <> 0); end;
328 function TPanel.isGLift (): Boolean; inline; begin result := ((tag and GridTagLift) <> 0); end;
329 function TPanel.isGBlockMon (): Boolean; inline; begin result := ((tag and GridTagBlockMon) <> 0); end;
331 procedure TPanel.Draw();
332 var
333 xx, yy: Integer;
334 NoTextureID: DWORD;
335 NW, NH: Word;
336 begin
337 if {Enabled and} (FCurTexture >= 0) and
338 (Width > 0) and (Height > 0) and (FAlpha < 255) and
339 ((g_dbg_scale <> 1.0) or g_Collide(X, Y, Width, Height, sX, sY, sWidth, sHeight)) then
340 begin
341 if FTextureIDs[FCurTexture].Anim then
342 begin // Àíèìèðîâàííàÿ òåêñòóðà
343 if FTextureIDs[FCurTexture].AnTex = nil then
344 Exit;
346 for xx := 0 to (Width div FTextureWidth)-1 do
347 for yy := 0 to (Height div FTextureHeight)-1 do
348 FTextureIDs[FCurTexture].AnTex.Draw(
349 X + xx*FTextureWidth,
350 Y + yy*FTextureHeight, M_NONE);
351 end
352 else
353 begin // Îáû÷íàÿ òåêñòóðà
354 case FTextureIDs[FCurTexture].Tex of
355 LongWord(TEXTURE_SPECIAL_WATER):
356 e_DrawFillQuad(X, Y, X+Width-1, Y+Height-1,
357 0, 0, 255, 0, B_FILTER);
358 LongWord(TEXTURE_SPECIAL_ACID1):
359 e_DrawFillQuad(X, Y, X+Width-1, Y+Height-1,
360 0, 128, 0, 0, B_FILTER);
361 LongWord(TEXTURE_SPECIAL_ACID2):
362 e_DrawFillQuad(X, Y, X+Width-1, Y+Height-1,
363 128, 0, 0, 0, B_FILTER);
364 LongWord(TEXTURE_NONE):
365 if g_Texture_Get('NOTEXTURE', NoTextureID) then
366 begin
367 e_GetTextureSize(NoTextureID, @NW, @NH);
368 e_DrawFill(NoTextureID, X, Y, Width div NW, Height div NH,
369 0, False, False);
370 end else
371 begin
372 xx := X + (Width div 2);
373 yy := Y + (Height div 2);
374 e_DrawFillQuad(X, Y, xx, yy,
375 255, 0, 255, 0);
376 e_DrawFillQuad(xx, Y, X+Width-1, yy,
377 255, 255, 0, 0);
378 e_DrawFillQuad(X, yy, xx, Y+Height-1,
379 255, 255, 0, 0);
380 e_DrawFillQuad(xx, yy, X+Width-1, Y+Height-1,
381 255, 0, 255, 0);
382 end;
384 else
385 e_DrawFill(FTextureIDs[FCurTexture].Tex, X, Y,
386 Width div FTextureWidth,
387 Height div FTextureHeight,
388 FAlpha, True, FBlending);
389 end;
390 end;
391 end;
392 end;
394 procedure TPanel.DrawShadowVolume(lightX: Integer; lightY: Integer; radius: Integer);
395 procedure extrude (x: Integer; y: Integer);
396 begin
397 glVertex2i(x+(x-lightX)*500, y+(y-lightY)*500);
398 //e_WriteLog(Format(' : (%d,%d)', [x+(x-lightX)*300, y+(y-lightY)*300]), MSG_WARNING);
399 end;
401 procedure drawLine (x0: Integer; y0: Integer; x1: Integer; y1: Integer);
402 begin
403 // does this side facing the light?
404 if ((x1-x0)*(lightY-y0)-(lightX-x0)*(y1-y0) >= 0) then exit;
405 //e_WriteLog(Format('lightpan: (%d,%d)-(%d,%d)', [x0, y0, x1, y1]), MSG_WARNING);
406 // this edge is facing the light, extrude and draw it
407 glVertex2i(x0, y0);
408 glVertex2i(x1, y1);
409 extrude(x1, y1);
410 extrude(x0, y0);
411 end;
413 begin
414 if radius < 4 then exit;
415 if Enabled and (FCurTexture >= 0) and (Width > 0) and (Height > 0) and (FAlpha < 255) and g_Collide(X, Y, Width, Height, sX, sY, sWidth, sHeight) then
416 begin
417 if not FTextureIDs[FCurTexture].Anim then
418 begin
419 case FTextureIDs[FCurTexture].Tex of
420 LongWord(TEXTURE_SPECIAL_WATER): exit;
421 LongWord(TEXTURE_SPECIAL_ACID1): exit;
422 LongWord(TEXTURE_SPECIAL_ACID2): exit;
423 LongWord(TEXTURE_NONE): exit;
424 end;
425 end;
426 if (X+Width < lightX-radius) then exit;
427 if (Y+Height < lightY-radius) then exit;
428 if (X > lightX+radius) then exit;
429 if (Y > lightY+radius) then exit;
430 //e_DrawFill(FTextureIDs[FCurTexture].Tex, X, Y, Width div FTextureWidth, Height div FTextureHeight, FAlpha, True, FBlending);
432 glBegin(GL_QUADS);
433 drawLine(x, y, x+width, y); // top
434 drawLine(x+width, y, x+width, y+height); // right
435 drawLine(x+width, y+height, x, y+height); // bottom
436 drawLine(x, y+height, x, y); // left
437 glEnd();
438 end;
439 end;
442 procedure TPanel.positionChanged (); inline;
443 var
444 px, py, pw, ph: Integer;
445 begin
446 if (proxyId >= 0) then
447 begin
448 monsGrid.getBodyDims(proxyId, px, py, pw, ph);
449 if (px <> x) or (py <> y) or (pw <> Width) or (ph <> Height) then
450 begin
451 g_Mark(px, py, pw, ph, MARK_WALL, false);
452 if (pw <> Width) or (ph <> Height) then mapGrid.moveResizeBody(proxyId, X, Y, Width, Height)
453 else mapGrid.moveBody(proxyId, X, Y);
454 g_Mark(X, Y, Width, Height, MARK_WALL);
455 end;
456 end;
457 end;
460 var
461 monMoveList: array of TMonster = nil;
462 monMoveListUsed: Integer = 0;
464 procedure TPanel.Update();
465 var
466 nx, ny: Integer;
467 f: Integer;
469 function doPush (px, py, pw, ph: Integer; out dx, dy: Integer): Boolean;
470 begin
471 result := g_Collide(px, py, pw, ph, nx, ny, Width, Height);
472 if result then
473 begin
474 // need to push
475 if (mMovingSpeed.X < 0) then dx := nx-(px+pw)
476 else if (mMovingSpeed.X > 0) then dx := (nx+Width)-px
477 else dx := 0;
478 if (mMovingSpeed.Y < 0) then dy := ny-(py+ph)
479 else if (mMovingSpeed.Y > 0) then dy := (ny+Height)-py
480 else dy := 0;
481 end
482 else
483 begin
484 dx := 0;
485 dy := 0;
486 end;
487 end;
489 function monMove (mon: TMonster): Boolean;
490 begin
491 result := false; // don't stop
492 mon.GameX := mon.GameX+mMovingSpeed.X;
493 mon.GameY := mon.GameY+mMovingSpeed.Y;
494 if (monMoveListUsed >= Length(monMoveList)) then SetLength(monMoveList, monMoveListUsed+64);
495 monMoveList[monMoveListUsed] := mon;
496 Inc(monMoveListUsed);
497 end;
499 function monPush (mon: TMonster): Boolean;
500 var
501 px, py, pw, ph, dx, dy: Integer;
502 begin
503 result := false; // don't stop
504 mon.getMapBox(px, py, pw, ph);
505 if doPush(px, py, pw, ph, dx, dy) then
506 begin
507 mon.GameX := mon.GameX+dx;
508 mon.GameY := mon.GameY+dy;
509 if (monMoveListUsed >= Length(monMoveList)) then SetLength(monMoveList, monMoveListUsed+64);
510 monMoveList[monMoveListUsed] := mon;
511 Inc(monMoveListUsed);
512 end;
513 end;
515 procedure plrMove (plr: TPlayer);
516 var
517 px, py, pw, ph, dx, dy: Integer;
518 begin
519 if (plr = nil) then exit;
520 plr.getMapBox(px, py, pw, ph);
521 if (py+ph <> Y) then
522 begin
523 // push player
524 if doPush(px, py, pw, ph, dx, dy) then
525 begin
526 plr.GameX := plr.GameX+dx;
527 plr.GameY := plr.GameY+dy;
528 plr.positionChanged();
529 end;
530 exit;
531 end;
532 if (px+pw <= X) then exit;
533 if (px >= X+Width) then exit;
534 plr.GameX := plr.GameX+mMovingSpeed.X;
535 plr.GameY := plr.GameY+mMovingSpeed.Y;
536 plr.positionChanged();
537 end;
539 begin
540 if Enabled and (FCurTexture >= 0) and
541 (FTextureIDs[FCurTexture].Anim) and
542 (FTextureIDs[FCurTexture].AnTex <> nil) and
543 (Width > 0) and (Height > 0) and (FAlpha < 255) then
544 begin
545 FTextureIDs[FCurTexture].AnTex.Update();
546 FCurFrame := FTextureIDs[FCurTexture].AnTex.CurrentFrame;
547 FCurFrameCount := FTextureIDs[FCurTexture].AnTex.CurrentCounter;
548 end;
550 if mMovingActive and (not mMovingSpeed.isZero) then
551 begin
552 monMoveListUsed := 0;
553 nx := X+mMovingSpeed.X;
554 ny := Y+mMovingSpeed.Y;
555 // move monsters on lifts
556 g_Mons_ForEachAt(X, Y-1, Width, 1, monMove);
557 // push monsters
558 g_Mons_ForEachAt(nx, ny, Width, Height, monPush);
559 // move and push players
560 for f := 0 to High(gPlayers) do plrMove(gPlayers[f]);
561 // reverse moving direction, if necessary
562 if (mMovingSpeed.X < 0) and (nx <= mMovingStart.X) then mMovingSpeed.X := -mMovingSpeed.X
563 else if (mMovingSpeed.X > 0) and (nx >= mMovingEnd.X) then mMovingSpeed.X := -mMovingSpeed.X;
564 if (mMovingSpeed.Y < 0) and (ny <= mMovingStart.Y) then mMovingSpeed.Y := -mMovingSpeed.Y
565 else if (mMovingSpeed.Y > 0) and (ny >= mMovingEnd.Y) then mMovingSpeed.Y := -mMovingSpeed.Y;
566 // awake particles
567 //g_Mark(X, Y, Width, Height, MARK_WALL, false);
568 X := nx;
569 Y := ny;
570 //g_Mark(nx, ny, Width, Height, MARK_WALL);
571 // fix grid
572 positionChanged();
573 // notify moved monsters about their movement
574 for f := 0 to monMoveListUsed-1 do monMoveList[f].positionChanged();
575 end;
576 end;
578 procedure TPanel.SetFrame(Frame: Integer; Count: Byte);
580 function ClampInt(X, A, B: Integer): Integer;
581 begin
582 Result := X;
583 if X < A then Result := A else if X > B then Result := B;
584 end;
586 begin
587 if Enabled and (FCurTexture >= 0) and
588 (FTextureIDs[FCurTexture].Anim) and
589 (FTextureIDs[FCurTexture].AnTex <> nil) and
590 (Width > 0) and (Height > 0) and (FAlpha < 255) then
591 begin
592 FCurFrame := ClampInt(Frame, 0, FTextureIDs[FCurTexture].AnTex.TotalFrames);
593 FCurFrameCount := Count;
594 FTextureIDs[FCurTexture].AnTex.CurrentFrame := FCurFrame;
595 FTextureIDs[FCurTexture].AnTex.CurrentCounter := FCurFrameCount;
596 end;
597 end;
599 procedure TPanel.NextTexture(AnimLoop: Byte = 0);
600 begin
601 Assert(FCurTexture >= -1, 'FCurTexture < -1');
603 // Íåò òåêñòóð:
604 if Length(FTextureIDs) = 0 then
605 FCurTexture := -1
606 else
607 // Òîëüêî îäíà òåêñòóðà:
608 if Length(FTextureIDs) = 1 then
609 begin
610 if FCurTexture = 0 then
611 FCurTexture := -1
612 else
613 FCurTexture := 0;
614 end
615 else
616 // Áîëüøå îäíîé òåêñòóðû:
617 begin
618 // Ñëåäóþùàÿ:
619 Inc(FCurTexture);
620 // Ñëåäóþùåé íåò - âîçâðàò ê íà÷àëó:
621 if FCurTexture >= Length(FTextureIDs) then
622 FCurTexture := 0;
623 end;
625 // Ïåðåêëþ÷èëèñü íà âèäèìóþ àíèì. òåêñòóðó:
626 if (FCurTexture >= 0) and FTextureIDs[FCurTexture].Anim then
627 begin
628 if (FTextureIDs[FCurTexture].AnTex = nil) then
629 begin
630 g_FatalError(_lc[I_GAME_ERROR_SWITCH_TEXTURE]);
631 Exit;
632 end;
634 if AnimLoop = 1 then
635 FTextureIDs[FCurTexture].AnTex.Loop := True
636 else
637 if AnimLoop = 2 then
638 FTextureIDs[FCurTexture].AnTex.Loop := False;
640 FTextureIDs[FCurTexture].AnTex.Reset();
641 end;
643 LastAnimLoop := AnimLoop;
644 end;
646 procedure TPanel.SetTexture(ID: Integer; AnimLoop: Byte = 0);
647 begin
648 // Íåò òåêñòóð:
649 if Length(FTextureIDs) = 0 then
650 FCurTexture := -1
651 else
652 // Òîëüêî îäíà òåêñòóðà:
653 if Length(FTextureIDs) = 1 then
654 begin
655 if (ID = 0) or (ID = -1) then
656 FCurTexture := ID;
657 end
658 else
659 // Áîëüøå îäíîé òåêñòóðû:
660 begin
661 if (ID >= -1) and (ID <= High(FTextureIDs)) then
662 FCurTexture := ID;
663 end;
665 // Ïåðåêëþ÷èëèñü íà âèäèìóþ àíèì. òåêñòóðó:
666 if (FCurTexture >= 0) and FTextureIDs[FCurTexture].Anim then
667 begin
668 if (FTextureIDs[FCurTexture].AnTex = nil) then
669 begin
670 g_FatalError(_lc[I_GAME_ERROR_SWITCH_TEXTURE]);
671 Exit;
672 end;
674 if AnimLoop = 1 then
675 FTextureIDs[FCurTexture].AnTex.Loop := True
676 else
677 if AnimLoop = 2 then
678 FTextureIDs[FCurTexture].AnTex.Loop := False;
680 FTextureIDs[FCurTexture].AnTex.Reset();
681 end;
683 LastAnimLoop := AnimLoop;
684 end;
686 function TPanel.GetTextureID(): DWORD;
687 begin
688 Result := LongWord(TEXTURE_NONE);
690 if (FCurTexture >= 0) then
691 begin
692 if FTextureIDs[FCurTexture].Anim then
693 Result := FTextureIDs[FCurTexture].AnTex.FramesID
694 else
695 Result := FTextureIDs[FCurTexture].Tex;
696 end;
697 end;
699 function TPanel.GetTextureCount(): Integer;
700 begin
701 Result := Length(FTextureIDs);
702 if Enabled and (FCurTexture >= 0) then
703 if (FTextureIDs[FCurTexture].Anim) and
704 (FTextureIDs[FCurTexture].AnTex <> nil) and
705 (Width > 0) and (Height > 0) and (FAlpha < 255) then
706 Result := Result + 100;
707 end;
709 procedure TPanel.SaveState(Var Mem: TBinMemoryWriter);
710 var
711 sig: DWORD;
712 anim: Boolean;
713 begin
714 if (Mem = nil) then exit;
715 //if not SaveIt then exit;
717 // Ñèãíàòóðà ïàíåëè:
718 sig := PANEL_SIGNATURE; // 'PANL'
719 Mem.WriteDWORD(sig);
720 // Îòêðûòà/çàêðûòà, åñëè äâåðü:
721 Mem.WriteBoolean(FEnabled);
722 // Íàïðàâëåíèå ëèôòà, åñëè ëèôò:
723 Mem.WriteByte(FLiftType);
724 // Íîìåð òåêóùåé òåêñòóðû:
725 Mem.WriteInt(FCurTexture);
726 // Êîîðäû
727 Mem.WriteInt(FX);
728 Mem.WriteInt(FY);
729 // Àíèìèðîâàííàÿ ëè òåêóùàÿ òåêñòóðà:
730 if (FCurTexture >= 0) and (FTextureIDs[FCurTexture].Anim) then
731 begin
732 Assert(FTextureIDs[FCurTexture].AnTex <> nil,
733 'TPanel.SaveState: No animation object');
734 anim := True;
735 end
736 else
737 anim := False;
738 Mem.WriteBoolean(anim);
739 // Åñëè äà - ñîõðàíÿåì àíèìàöèþ:
740 if anim then
741 FTextureIDs[FCurTexture].AnTex.SaveState(Mem);
742 // moving platform state
743 Mem.WriteInt(mMovingSpeed.X);
744 Mem.WriteInt(mMovingSpeed.Y);
745 Mem.WriteInt(mMovingStart.X);
746 Mem.WriteInt(mMovingStart.Y);
747 Mem.WriteInt(mMovingEnd.X);
748 Mem.WriteInt(mMovingEnd.Y);
749 Mem.WriteBoolean(mMovingActive);
750 end;
752 procedure TPanel.LoadState(var Mem: TBinMemoryReader);
753 var
754 sig: DWORD;
755 anim: Boolean;
756 //ox, oy: Integer;
757 begin
758 if (Mem = nil) then exit;
759 //if not SaveIt then exit;
761 // Ñèãíàòóðà ïàíåëè:
762 Mem.ReadDWORD(sig);
763 if sig <> PANEL_SIGNATURE then // 'PANL'
764 begin
765 raise EBinSizeError.Create('TPanel.LoadState: Wrong Panel Signature');
766 end;
767 // Îòêðûòà/çàêðûòà, åñëè äâåðü:
768 Mem.ReadBoolean(FEnabled);
769 // Íàïðàâëåíèå ëèôòà, åñëè ëèôò:
770 Mem.ReadByte(FLiftType);
771 // Íîìåð òåêóùåé òåêñòóðû:
772 Mem.ReadInt(FCurTexture);
773 // Êîîðäû
774 //ox := FX;
775 //oy := FY;
776 Mem.ReadInt(FX);
777 Mem.ReadInt(FY);
778 //e_LogWritefln('panel %s(%s): old=(%s,%s); new=(%s,%s); delta=(%s,%s)', [arrIdx, proxyId, ox, oy, FX, FY, FX-ox, FY-oy]);
779 // Àíèìèðîâàííàÿ ëè òåêóùàÿ òåêñòóðà:
780 Mem.ReadBoolean(anim);
781 // Åñëè äà - çàãðóæàåì àíèìàöèþ:
782 if anim then
783 begin
784 Assert((FCurTexture >= 0) and
785 (FTextureIDs[FCurTexture].Anim) and
786 (FTextureIDs[FCurTexture].AnTex <> nil),
787 'TPanel.LoadState: No animation object');
788 FTextureIDs[FCurTexture].AnTex.LoadState(Mem);
789 end;
790 // moving platform state
791 Mem.ReadInt(mMovingSpeed.X);
792 Mem.ReadInt(mMovingSpeed.Y);
793 Mem.ReadInt(mMovingStart.X);
794 Mem.ReadInt(mMovingStart.Y);
795 Mem.ReadInt(mMovingEnd.X);
796 Mem.ReadInt(mMovingEnd.Y);
797 Mem.ReadBoolean(mMovingActive);
799 positionChanged();
800 //mapGrid.proxyEnabled[proxyId] := FEnabled; // done in g_map.pas
801 end;
803 end.