hedgewars/uLandObjects.pas
changeset 13391 04d1521cb7b8
parent 12915 4d3b52f1ba18
child 13397 166f8f31de3e
equal deleted inserted replaced
13384:cf8abedaa878 13391:04d1521cb7b8
    26 procedure FreeLandObjects();
    26 procedure FreeLandObjects();
    27 procedure LoadThemeConfig;
    27 procedure LoadThemeConfig;
    28 procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface); inline;
    28 procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface); inline;
    29 procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word); inline;
    29 procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word); inline;
    30 procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word; Flip: boolean);
    30 procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word; Flip: boolean);
       
    31 procedure BlitOverlayAndGenerateCollisionInfo(cpX, cpY: Longword; Image: PSDL_Surface);
    31 procedure BlitImageUsingMask(cpX, cpY: Longword;  Image, Mask: PSDL_Surface);
    32 procedure BlitImageUsingMask(cpX, cpY: Longword;  Image, Mask: PSDL_Surface);
    32 procedure AddOnLandObjects(Surface: PSDL_Surface);
    33 procedure AddOnLandObjects(Surface: PSDL_Surface);
    33 procedure SetLand(var LandWord: Word; Pixel: LongWord); inline;
    34 procedure SetLand(var LandWord: Word; Pixel: LongWord); inline;
    34 
    35 
    35 implementation
    36 implementation
    40 const MaxRects = 512;
    41 const MaxRects = 512;
    41       MAXOBJECTRECTS = 16;
    42       MAXOBJECTRECTS = 16;
    42       MAXTHEMEOBJECTS = 32;
    43       MAXTHEMEOBJECTS = 32;
    43       cThemeCFGFilename = 'theme.cfg';
    44       cThemeCFGFilename = 'theme.cfg';
    44 
    45 
    45 type TRectsArray = array[0..MaxRects] of TSDL_Rect;
    46 type PLongWord = ^LongWord;
       
    47      TRectsArray = array[0..MaxRects] of TSDL_Rect;
    46      PRectArray = ^TRectsArray;
    48      PRectArray = ^TRectsArray;
       
    49      TThemeObjectOverlay = record
       
    50                            Position: TPoint;
       
    51                            Surf: PSDL_Surface;
       
    52                            Width, Height: LongWord;
       
    53                            end;
    47      TThemeObject = record
    54      TThemeObject = record
       
    55                      Name: ShortString;
    48                      Surf, Mask: PSDL_Surface;
    56                      Surf, Mask: PSDL_Surface;
    49                      inland: array[0..Pred(MAXOBJECTRECTS)] of TSDL_Rect;
    57                      inland: array[0..Pred(MAXOBJECTRECTS)] of TSDL_Rect;
    50                      outland: array[0..Pred(MAXOBJECTRECTS)] of TSDL_Rect;
    58                      outland: array[0..Pred(MAXOBJECTRECTS)] of TSDL_Rect;
    51                      inrectcnt: Longword;
    59                      anchors: array[0..Pred(MAXOBJECTRECTS)] of TSDL_Rect;
    52                      outrectcnt: Longword;
    60                      overlays: array[0..Pred(MAXOBJECTRECTS)] of TThemeObjectOverlay;
       
    61                      inrectcnt: LongInt;
       
    62                      outrectcnt: LongInt;
       
    63                      anchorcnt: LongInt;
       
    64                      overlaycnt: LongInt;
    53                      Width, Height: Longword;
    65                      Width, Height: Longword;
    54                      Maxcnt: Longword;
    66                      Maxcnt: Longword;
    55                      end;
    67                      end;
    56      TThemeObjects = record
    68      TThemeObjects = record
    57                      Count: LongInt;
    69                      Count: LongInt;
   121 
   133 
   122 if Width = 0 then
   134 if Width = 0 then
   123     Width:= Image^.w;
   135     Width:= Image^.w;
   124 
   136 
   125 p:= Image^.pixels;
   137 p:= Image^.pixels;
       
   138 
   126 for y:= 0 to Pred(Image^.h) do
   139 for y:= 0 to Pred(Image^.h) do
   127     begin
   140     begin
   128     for x:= 0 to Pred(Width) do
   141     for x:= 0 to Pred(Width) do
   129         begin
   142         begin
   130         // map image pixels per line backwards if in flip mode
   143         // map image pixels per line backwards if in flip mode
   136         if (p^[px] and AMask) <> 0 then
   149         if (p^[px] and AMask) <> 0 then
   137             begin
   150             begin
   138             if (cReducedQuality and rqBlurryLand) = 0 then
   151             if (cReducedQuality and rqBlurryLand) = 0 then
   139                 begin
   152                 begin
   140                 if (LandPixels[cpY + y, cpX + x] = 0)
   153                 if (LandPixels[cpY + y, cpX + x] = 0)
   141                 or (((p^[px] and AMask) <> 0) and (((LandPixels[cpY + y, cpX + x] and AMask) shr AShift) < 255)) then
   154                 or (((LandPixels[cpY + y, cpX + x] and AMask) shr AShift) < 255) then
   142                     LandPixels[cpY + y, cpX + x]:= p^[px];
   155                     LandPixels[cpY + y, cpX + x]:= p^[px];
   143                 end
   156                 end
   144             else
   157             else
   145                 if LandPixels[(cpY + y) div 2, (cpX + x) div 2] = 0 then
   158                 if LandPixels[(cpY + y) div 2, (cpX + x) div 2] = 0 then
   146                     LandPixels[(cpY + y) div 2, (cpX + x) div 2]:= p^[px];
   159                     LandPixels[(cpY + y) div 2, (cpX + x) div 2]:= p^[px];
   147 
   160 
   148             if (Land[cpY + y, cpX + x] <= lfAllObjMask) and ((p^[px] and AMask) <> 0) then
   161             if Land[cpY + y, cpX + x] <= lfAllObjMask then
   149                 Land[cpY + y, cpX + x]:= lfObject or LandFlags
   162                 Land[cpY + y, cpX + x]:= lfObject or LandFlags
       
   163             end;
       
   164         end;
       
   165     p:= PLongwordArray(@(p^[Image^.pitch shr 2]))
       
   166     end;
       
   167 
       
   168 if SDL_MustLock(Image) then
       
   169     SDL_UnlockSurface(Image);
       
   170 WriteLnToConsole(msgOK)
       
   171 end;
       
   172 
       
   173 function LerpByte(src, dst: Byte; l: LongWord): LongWord; inline;
       
   174 begin
       
   175     LerpByte:= ((255 - l) * src + l * dst) div 255;
       
   176 end;
       
   177 
       
   178 procedure BlitOverlayAndGenerateCollisionInfo(cpX, cpY: Longword; Image: PSDL_Surface);
       
   179 var p: PLongwordArray;
       
   180     pLandColor: PLongWord;
       
   181     x, y, alpha, color, landColor: LongWord;
       
   182 begin
       
   183 WriteToConsole('Generating overlay collision info... ');
       
   184 
       
   185 if SDL_MustLock(Image) then
       
   186     if SDLCheck(SDL_LockSurface(Image) >= 0, 'SDL_LockSurface', true) then exit;
       
   187 
       
   188 if checkFails(Image^.format^.BytesPerPixel = 4, 'Land object overlay should be 32bit', true)
       
   189    and SDL_MustLock(Image) then
       
   190     SDL_UnlockSurface(Image);
       
   191 
       
   192 p:= Image^.pixels;
       
   193 
       
   194 for y:= 0 to Pred(Image^.h) do
       
   195     begin
       
   196     for x:= 0 to Pred(Image^.w) do
       
   197         begin
       
   198         color:= p^[x];
       
   199         if (color and AMask) <> 0 then
       
   200             begin
       
   201             if (cReducedQuality and rqBlurryLand) = 0 then
       
   202                 pLandColor:= @LandPixels[cpY + y, cpX + x]
       
   203             else
       
   204                 pLandColor:= @LandPixels[(cpY + y) div 2, (cpX + x) div 2];
       
   205 
       
   206             alpha:= (color and AMask) shr AShift;
       
   207             if (alpha <> $FF) and (pLandColor^ <> 0) then
       
   208                 begin
       
   209                 landColor:= pLandColor^;
       
   210                 color:=
       
   211                     (LerpByte((landColor and RMask) shr RShift, (color and RMask) shr RShift, alpha) shl RShift)
       
   212                  or (LerpByte((landColor and GMask) shr GShift, (color and GMask) shr GShift, alpha) shl GShift)
       
   213                  or (LerpByte((landColor and BMask) shr BShift, (color and BMask) shr BShift, alpha) shl BShift)
       
   214                  or (LerpByte(alpha, 255, (landColor and AMask) shr AShift) shl AShift)
       
   215                 end;
       
   216             pLandColor^:= color;
       
   217 
       
   218             if Land[cpY + y, cpX + x] <= lfAllObjMask then
       
   219                 Land[cpY + y, cpX + x]:= lfObject
   150             end;
   220             end;
   151         end;
   221         end;
   152     p:= PLongwordArray(@(p^[Image^.pitch shr 2]))
   222     p:= PLongwordArray(@(p^[Image^.pitch shr 2]))
   153     end;
   223     end;
   154 
   224 
   353     end;
   423     end;
   354 {$WARNINGS ON}
   424 {$WARNINGS ON}
   355 CheckLand:= bRes;
   425 CheckLand:= bRes;
   356 end;
   426 end;
   357 
   427 
       
   428 function CheckLandAny(rect: TSDL_Rect; dX, dY, LandType: Longword): boolean;
       
   429 var tmpx, tmpy, bx, by: LongInt;
       
   430 begin
       
   431     inc(rect.x, dX);
       
   432     inc(rect.y, dY);
       
   433     bx:= rect.x + rect.w - 1;
       
   434     by:= rect.y + rect.h - 1;
       
   435     CheckLandAny:= false;
       
   436 
       
   437     if (((rect.x and LAND_WIDTH_MASK) or (bx and LAND_WIDTH_MASK) or
       
   438          (rect.y and LAND_HEIGHT_MASK) or (by and LAND_HEIGHT_MASK)) = 0) then
       
   439     begin
       
   440         for tmpx := rect.x to bx do
       
   441         begin
       
   442             if (((Land[rect.y, tmpx] and LandType) or (Land[by, tmpx] and LandType)) <> 0) then
       
   443             begin
       
   444                 CheckLandAny := true;
       
   445                 exit;
       
   446             end
       
   447         end;
       
   448         for tmpy := rect.y to by do
       
   449         begin
       
   450             if (((Land[tmpy, rect.x] and LandType) or (Land[tmpy, bx] and LandType)) <> 0) then
       
   451             begin
       
   452                 CheckLandAny := true;
       
   453                 exit;
       
   454             end
       
   455         end;
       
   456     end;
       
   457 end;
       
   458 
   358 function CheckCanPlace(x, y: Longword; var Obj: TThemeObject): boolean;
   459 function CheckCanPlace(x, y: Longword; var Obj: TThemeObject): boolean;
   359 var i: Longword;
   460 var i: Longword;
   360     bRes: boolean;
   461     bRes, anchored: boolean;
       
   462     overlayP1, overlayP2: TPoint;
   361 begin
   463 begin
   362     with Obj do begin
   464     with Obj do begin
   363         bRes:= true;
   465         bRes:= true;
   364         i:= 1;
   466         i:= 0;
   365         while bRes and (i <= inrectcnt) do
   467         while bRes and (i < overlaycnt) do
       
   468             begin
       
   469             overlayP1.x:= overlays[i].Position.x + x;
       
   470             overlayP1.y:= overlays[i].Position.y + y;
       
   471             overlayP2.x:= overlayP1.x + overlays[i].Width - 1;
       
   472             overlayP2.y:= overlayP1.y + overlays[i].Height - 1;
       
   473             bRes:= (((LAND_WIDTH_MASK and overlayP1.x) or (LAND_HEIGHT_MASK and overlayP1.y) or
       
   474                      (LAND_WIDTH_MASK and overlayP2.x) or (LAND_HEIGHT_MASK and overlayP2.y)) = 0)
       
   475                    and (not CheckIntersect(overlayP1.x, overlayP1.y, overlays[i].Width, overlays[i].Height));
       
   476             inc(i)
       
   477             end;
       
   478 
       
   479         i:= 0;
       
   480         while bRes and (i < inrectcnt) do
   366             begin
   481             begin
   367             bRes:= CheckLand(inland[i], x, y, lfBasic);
   482             bRes:= CheckLand(inland[i], x, y, lfBasic);
   368             inc(i)
   483             inc(i)
   369             end;
   484             end;
   370 
   485 
   371         i:= 1;
   486         i:= 0;
   372         while bRes and (i <= outrectcnt) do
   487         while bRes and (i < outrectcnt) do
   373             begin
   488             begin
   374             bRes:= CheckLand(outland[i], x, y, 0);
   489             bRes:= CheckLand(outland[i], x, y, 0);
   375             inc(i)
   490             inc(i)
       
   491             end;
       
   492 
       
   493         if bRes then
       
   494             begin
       
   495             anchored:= anchorcnt = 0;
       
   496             for i:= 1 to anchorcnt do
       
   497                 begin
       
   498                     anchored := CheckLandAny(anchors[i], x, y, lfLandMask);
       
   499                     if anchored then break;
       
   500                 end;
       
   501             bRes:= anchored;
   376             end;
   502             end;
   377 
   503 
   378         if bRes then
   504         if bRes then
   379             bRes:= not CheckIntersect(x, y, Width, Height);
   505             bRes:= not CheckIntersect(x, y, Width, Height);
   380 
   506 
   384 
   510 
   385 function TryPut(var Obj: TThemeObject): boolean;
   511 function TryPut(var Obj: TThemeObject): boolean;
   386 const MaxPointsIndex = 2047;
   512 const MaxPointsIndex = 2047;
   387 var x, y: Longword;
   513 var x, y: Longword;
   388     ar: array[0..MaxPointsIndex] of TPoint;
   514     ar: array[0..MaxPointsIndex] of TPoint;
   389     cnt, i: Longword;
   515     cnt, i, ii: Longword;
   390     bRes: boolean;
   516     bRes: boolean;
   391 begin
   517 begin
   392 TryPut:= false;
   518 TryPut:= false;
   393 cnt:= 0;
   519 cnt:= 0;
   394 with Obj do
   520 with Obj do
   398     x:= 0;
   524     x:= 0;
   399     repeat
   525     repeat
   400         y:= topY+32; // leave room for a hedgie to teleport in
   526         y:= topY+32; // leave room for a hedgie to teleport in
   401         repeat
   527         repeat
   402 
   528 
   403             if (inland[1].x = 0) and (inland[1].y = 0) and (inland[1].w = 0) and (inland[1].h = 0) then
   529             if (inrectcnt > 0) and (inland[0].x = 0) and (inland[0].y = 0) and (inland[0].w = 0) and (inland[0].h = 0) then
   404                 y := LAND_HEIGHT - Height;
   530                 y := LAND_HEIGHT - Height;
   405 
   531 
   406             if CheckCanPlace(x, y, Obj) then
   532             if CheckCanPlace(x, y, Obj) then
   407                 begin
   533                 begin
   408                 ar[cnt].x:= x;
   534                 ar[cnt].x:= x;
   424         i:= getrandom(cnt);
   550         i:= getrandom(cnt);
   425         if Obj.Mask <> nil then
   551         if Obj.Mask <> nil then
   426              BlitImageUsingMask(ar[i].x, ar[i].y, Obj.Surf, Obj.Mask)
   552              BlitImageUsingMask(ar[i].x, ar[i].y, Obj.Surf, Obj.Mask)
   427         else BlitImageAndGenerateCollisionInfo(ar[i].x, ar[i].y, 0, Obj.Surf);
   553         else BlitImageAndGenerateCollisionInfo(ar[i].x, ar[i].y, 0, Obj.Surf);
   428         AddRect(ar[i].x, ar[i].y, Width, Height);
   554         AddRect(ar[i].x, ar[i].y, Width, Height);
       
   555 
       
   556         ii:= 0;
       
   557         while ii < overlaycnt do
       
   558             begin
       
   559             BlitOverlayAndGenerateCollisionInfo(
       
   560                 ar[i].x + overlays[ii].Position.X,
       
   561                 ar[i].y + overlays[ii].Position.Y, overlays[ii].Surf);
       
   562             AddRect(ar[i].x + overlays[ii].Position.X,
       
   563                     ar[i].y + overlays[ii].Position.Y,
       
   564                     Width, Height);
       
   565             inc(ii);
       
   566             end;
   429         dec(Maxcnt)
   567         dec(Maxcnt)
   430         end
   568         end
   431     else Maxcnt:= 0
   569     else Maxcnt:= 0
   432     end;
   570     end;
   433 TryPut:= bRes;
   571 TryPut:= bRes;
   491         OutError('Object''s rectangle exceeds image: x + w (' + inttostr(x) + ' + ' + inttostr(w) + ') > Width (' + inttostr(Width) + ')', true);
   629         OutError('Object''s rectangle exceeds image: x + w (' + inttostr(x) + ' + ' + inttostr(w) + ') > Width (' + inttostr(Width) + ')', true);
   492     if (y + h > Height) then
   630     if (y + h > Height) then
   493         OutError('Object''s rectangle exceeds image: y + h (' + inttostr(y) + ' + ' + inttostr(h) + ') > Height (' + inttostr(Height) + ')', true);
   631         OutError('Object''s rectangle exceeds image: y + h (' + inttostr(y) + ' + ' + inttostr(h) + ') > Height (' + inttostr(Height) + ')', true);
   494 end;
   632 end;
   495 
   633 
       
   634 procedure ReadRect(var rect: TSDL_Rect; var s: ShortString);
       
   635 var i: LongInt;
       
   636 begin
       
   637 with rect do
       
   638     begin
       
   639     i:= Pos(',', s);
       
   640     x:= StrToInt(Trim(Copy(s, 1, Pred(i))));
       
   641     Delete(s, 1, i);
       
   642     i:= Pos(',', s);
       
   643     y:= StrToInt(Trim(Copy(s, 1, Pred(i))));
       
   644     Delete(s, 1, i);
       
   645     i:= Pos(',', s);
       
   646     w:= StrToInt(Trim(Copy(s, 1, Pred(i))));
       
   647     Delete(s, 1, i);
       
   648     i:= Pos(',', s);
       
   649     if i = 0 then i:= Succ(Length(S));
       
   650     h:= StrToInt(Trim(Copy(s, 1, Pred(i))));
       
   651     Delete(s, 1, i);
       
   652     end;
       
   653 end;
       
   654 
       
   655 
       
   656 
       
   657 procedure ReadOverlay(var overlay: TThemeObjectOverlay; var s: ShortString);
       
   658 var i: LongInt;
       
   659 begin
       
   660 with overlay do
       
   661     begin
       
   662     i:= Pos(',', s);
       
   663     Position.X:= StrToInt(Trim(Copy(s, 1, Pred(i))));
       
   664     Delete(s, 1, i);
       
   665     i:= Pos(',', s);
       
   666     Position.Y:= StrToInt(Trim(Copy(s, 1, Pred(i))));
       
   667     Delete(s, 1, i);
       
   668     i:= Pos(',', s);
       
   669     if i = 0 then i:= Succ(Length(S));
       
   670     Surf:= LoadDataImage(ptCurrTheme, Trim(Copy(s, 1, Pred(i))), ifColorKey or ifIgnoreCaps or ifCritical);
       
   671     Width:= Surf^.w;
       
   672     Height:= Surf^.h;
       
   673     Delete(s, 1, i);
       
   674     end;
       
   675 end;
       
   676 
   496 procedure ReadThemeInfo(var ThemeObjects: TThemeObjects; var SprayObjects: TSprayObjects);
   677 procedure ReadThemeInfo(var ThemeObjects: TThemeObjects; var SprayObjects: TSprayObjects);
   497 var s, key: shortstring;
   678 var s, key, nameRef: shortstring;
   498     f: PFSFile;
   679     f: PFSFile;
   499     i, y: LongInt;
   680     i, y: LongInt;
   500     ii, t: Longword;
   681     ii, t: Longword;
   501     c2: TSDL_Color;
   682     c2: TSDL_Color;
   502 begin
   683 begin
   685         begin
   866         begin
   686         inc(ThemeObjects.Count);
   867         inc(ThemeObjects.Count);
   687         with ThemeObjects.objs[Pred(ThemeObjects.Count)] do
   868         with ThemeObjects.objs[Pred(ThemeObjects.Count)] do
   688             begin
   869             begin
   689             i:= Pos(',', s);
   870             i:= Pos(',', s);
   690             Surf:= LoadDataImage(ptCurrTheme, Trim(Copy(s, 1, Pred(i))), ifColorKey or ifIgnoreCaps or ifCritical);
   871             Name:= Trim(Copy(s, 1, Pred(i)));
       
   872             Surf:= LoadDataImage(ptCurrTheme, Name, ifColorKey or ifIgnoreCaps or ifCritical);
   691             Width:= Surf^.w;
   873             Width:= Surf^.w;
   692             Height:= Surf^.h;
   874             Height:= Surf^.h;
   693             Mask:= LoadDataImage(ptCurrTheme, Trim(Copy(s, 1, Pred(i)))+'_mask', ifColorKey or ifIgnoreCaps);
   875             Mask:= LoadDataImage(ptCurrTheme, Trim(Copy(s, 1, Pred(i)))+'_mask', ifColorKey or ifIgnoreCaps);
   694             Delete(s, 1, i);
   876             Delete(s, 1, i);
   695             i:= Pos(',', s);
   877             i:= Pos(',', s);
   712               i:= Pos(',', s);
   894               i:= Pos(',', s);
   713               inrectcnt:= StrToInt(Trim(Copy(s, 1, Pred(i))));
   895               inrectcnt:= StrToInt(Trim(Copy(s, 1, Pred(i))));
   714               Delete(s, 1, i);
   896               Delete(s, 1, i);
   715             end;
   897             end;
   716 
   898 
   717             for ii:= 1 to inrectcnt do
   899             if inrectcnt > MAXOBJECTRECTS then
   718                 with inland[ii] do
   900                 OutError('Object''s inland rectangle count should be no more than '+ inttostr(MAXOBJECTRECTS) +' (it was '+ inttostr(inrectcnt) +').', true);
   719                     begin
   901 
   720                     i:= Pos(',', s);
   902             for ii:= 0 to Pred(inrectcnt) do
   721                     x:= StrToInt(Trim(Copy(s, 1, Pred(i))));
   903                 ReadRect(inland[ii], s);
   722                     Delete(s, 1, i);
       
   723                     i:= Pos(',', s);
       
   724                     y:= StrToInt(Trim(Copy(s, 1, Pred(i))));
       
   725                     Delete(s, 1, i);
       
   726                     i:= Pos(',', s);
       
   727                     w:= StrToInt(Trim(Copy(s, 1, Pred(i))));
       
   728                     Delete(s, 1, i);
       
   729                     i:= Pos(',', s);
       
   730                     h:= StrToInt(Trim(Copy(s, 1, Pred(i))));
       
   731                     Delete(s, 1, i);
       
   732                     CheckRect(Width, Height, x, y, w, h)
       
   733                     end;
       
   734 
   904 
   735             i:= Pos(',', s);
   905             i:= Pos(',', s);
   736             outrectcnt:= StrToInt(Trim(Copy(s, 1, Pred(i))));
   906             outrectcnt:= StrToInt(Trim(Copy(s, 1, Pred(i))));
   737             Delete(s, 1, i);
   907             Delete(s, 1, i);
   738             for ii:= 1 to outrectcnt do
   908 
   739                 with outland[ii] do
   909             if outrectcnt > MAXOBJECTRECTS then
   740                     begin
   910                 OutError('Object''s outland rectangle count should be no more than '+ inttostr(MAXOBJECTRECTS) +' (it was '+ inttostr(outrectcnt) +').', true);
   741                     i:= Pos(',', s);
   911 
   742                     x:= StrToInt(Trim(Copy(s, 1, Pred(i))));
   912             for ii:= 0 to Pred(outrectcnt) do
   743                     Delete(s, 1, i);
   913                 ReadRect(outland[ii], s);
   744                     i:= Pos(',', s);
   914             end;
   745                     y:= StrToInt(Trim(Copy(s, 1, Pred(i))));
   915         end
   746                     Delete(s, 1, i);
   916     else if key = 'anchors' then
   747                     i:= Pos(',', s);
   917         begin
   748                     w:= StrToInt(Trim(Copy(s, 1, Pred(i))));
   918         i:= Pos(',', s);
   749                     Delete(s, 1, i);
   919         nameRef:= Trim(Copy(s, 1, Pred(i)));
   750                     if ii = outrectcnt then
   920         for ii:= 0 to Pred(ThemeObjects.Count) do
   751                         h:= StrToInt(Trim(s))
   921             if ThemeObjects.objs[ii].Name = nameRef then with ThemeObjects.objs[ii] do
   752                     else
   922                 begin
   753                         begin
   923                 if anchorcnt <> 0 then
   754                         i:= Pos(',', s);
   924                     OutError('Duplicate anchors declaration for ' + nameRef, true);
   755                         h:= StrToInt(Trim(Copy(s, 1, Pred(i))));
   925                 Delete(s, 1, i);
   756                         Delete(s, 1, i)
   926                 i:= Pos(',', s);
   757                         end;
   927                 anchorcnt:= StrToInt(Trim(Copy(s, 1, Pred(i))));
   758                     CheckRect(Width, Height, x, y, w, h)
   928                 Delete(s, 1, i);
   759                     end;
   929                 if anchorcnt > MAXOBJECTRECTS then
   760 
   930                     OutError('Object''s anchor rectangle count should be no more than '+ inttostr(MAXOBJECTRECTS) +' (it was '+ inttostr(anchorcnt) +').', true);
       
   931                 for t:= 0 to Pred(anchorcnt) do
       
   932                     ReadRect(anchors[t], s);
       
   933                 break
       
   934                 end;
       
   935         end
       
   936     else if key = 'overlays' then
       
   937         begin
       
   938         i:= Pos(',', s);
       
   939         nameRef:= Trim(Copy(s, 1, Pred(i)));
       
   940         for ii:= 0 to Pred(ThemeObjects.Count) do
       
   941             if ThemeObjects.objs[ii].Name = nameRef then with ThemeObjects.objs[ii] do
       
   942             begin
       
   943                 if overlaycnt <> 0 then
       
   944                     OutError('Duplicate overlays declaration for ' + nameRef, true);
       
   945                 Delete(s, 1, i);
       
   946                 i:= Pos(',', s);
       
   947                 overlaycnt:= StrToInt(Trim(Copy(s, 1, Pred(i))));
       
   948                 Delete(s, 1, i);
       
   949                 if overlaycnt > MAXOBJECTRECTS then
       
   950                     OutError('Object''s overlay count should be no more than '+ inttostr(MAXOBJECTRECTS) +' (it was '+ inttostr(overlaycnt) +').', true);
       
   951                 for t:= 0 to Pred(overlaycnt) do
       
   952                     ReadOverlay(overlays[t], s);
       
   953                 break
   761             end;
   954             end;
   762         end
   955         end
   763     else if key = 'spray' then
   956     else if key = 'spray' then
   764         begin
   957         begin
   765         inc(SprayObjects.Count);
   958         inc(SprayObjects.Count);
  1007 begin
  1200 begin
  1008     ReadThemeInfo(ThemeObjects, SprayObjects)
  1201     ReadThemeInfo(ThemeObjects, SprayObjects)
  1009 end;
  1202 end;
  1010 
  1203 
  1011 procedure FreeLandObjects();
  1204 procedure FreeLandObjects();
  1012 var i: Longword;
  1205 var i, ii: Longword;
  1013 begin
  1206 begin
  1014     for i:= 0 to Pred(MAXTHEMEOBJECTS) do
  1207     for i:= 0 to Pred(MAXTHEMEOBJECTS) do
  1015     begin
  1208     begin
  1016         if ThemeObjects.objs[i].Surf <> nil then
  1209         if ThemeObjects.objs[i].Surf <> nil then
  1017             SDL_FreeSurface(ThemeObjects.objs[i].Surf);
  1210             SDL_FreeSurface(ThemeObjects.objs[i].Surf);
  1018         if SprayObjects.objs[i].Surf <> nil then
  1211         if SprayObjects.objs[i].Surf <> nil then
  1019             SDL_FreeSurface(SprayObjects.objs[i].Surf);
  1212             SDL_FreeSurface(SprayObjects.objs[i].Surf);
  1020         ThemeObjects.objs[i].Surf:= nil;
  1213         ThemeObjects.objs[i].Surf:= nil;
  1021         SprayObjects.objs[i].Surf:= nil;
  1214         SprayObjects.objs[i].Surf:= nil;
       
  1215 
       
  1216         ii:= 0;
       
  1217         while ii < ThemeObjects.objs[i].overlaycnt do
       
  1218             begin
       
  1219             if ThemeObjects.objs[i].overlays[ii].Surf <> nil then
       
  1220                 begin
       
  1221                     SDL_FreeSurface(ThemeObjects.objs[i].overlays[ii].Surf);
       
  1222                     ThemeObjects.objs[i].overlays[ii].Surf:= nil;
       
  1223                 end;
       
  1224             inc(ii);
       
  1225             end;
  1022     end;
  1226     end;
  1023 end;
  1227 end;
  1024 
  1228 
  1025 end.
  1229 end.