Guest User

Untitled

a guest
May 21st, 2018
62
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.34 KB | None | 0 0
  1. diff -r cf8abedaa878 hedgewars/uLandObjects.pas
  2. --- a/hedgewars/uLandObjects.pas Mon May 07 23:43:01 2018 +0300
  3. +++ b/hedgewars/uLandObjects.pas Thu May 17 00:03:21 2018 +0300
  4. @@ -28,6 +28,7 @@
  5. procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface); inline;
  6. procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word); inline;
  7. procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word; Flip: boolean);
  8. +procedure BlitOverlayAndGenerateCollisionInfo(cpX, cpY: Longword; Image: PSDL_Surface);
  9. procedure BlitImageUsingMask(cpX, cpY: Longword; Image, Mask: PSDL_Surface);
  10. procedure AddOnLandObjects(Surface: PSDL_Surface);
  11. procedure SetLand(var LandWord: Word; Pixel: LongWord); inline;
  12. @@ -42,14 +43,25 @@
  13. MAXTHEMEOBJECTS = 32;
  14. cThemeCFGFilename = 'theme.cfg';
  15.  
  16. -type TRectsArray = array[0..MaxRects] of TSDL_Rect;
  17. +type PLongWord = ^LongWord;
  18. + TRectsArray = array[0..MaxRects] of TSDL_Rect;
  19. PRectArray = ^TRectsArray;
  20. + TThemeObjectOverlay = record
  21. + Position: TPoint;
  22. + Surf: PSDL_Surface;
  23. + Width, Height: LongWord;
  24. + end;
  25. TThemeObject = record
  26. + Name: ShortString;
  27. Surf, Mask: PSDL_Surface;
  28. inland: array[0..Pred(MAXOBJECTRECTS)] of TSDL_Rect;
  29. outland: array[0..Pred(MAXOBJECTRECTS)] of TSDL_Rect;
  30. - inrectcnt: Longword;
  31. - outrectcnt: Longword;
  32. + anchors: array[0..Pred(MAXOBJECTRECTS)] of TSDL_Rect;
  33. + overlays: array[0..Pred(MAXOBJECTRECTS)] of TThemeObjectOverlay;
  34. + inrectcnt: LongInt;
  35. + outrectcnt: LongInt;
  36. + anchorcnt: LongInt;
  37. + overlaycnt: LongInt;
  38. Width, Height: Longword;
  39. Maxcnt: Longword;
  40. end;
  41. @@ -123,6 +135,7 @@
  42. Width:= Image^.w;
  43.  
  44. p:= Image^.pixels;
  45. +
  46. for y:= 0 to Pred(Image^.h) do
  47. begin
  48. for x:= 0 to Pred(Width) do
  49. @@ -138,14 +151,14 @@
  50. if (cReducedQuality and rqBlurryLand) = 0 then
  51. begin
  52. if (LandPixels[cpY + y, cpX + x] = 0)
  53. - or (((p^[px] and AMask) <> 0) and (((LandPixels[cpY + y, cpX + x] and AMask) shr AShift) < 255)) then
  54. + or (((LandPixels[cpY + y, cpX + x] and AMask) shr AShift) < 255) then
  55. LandPixels[cpY + y, cpX + x]:= p^[px];
  56. end
  57. else
  58. if LandPixels[(cpY + y) div 2, (cpX + x) div 2] = 0 then
  59. LandPixels[(cpY + y) div 2, (cpX + x) div 2]:= p^[px];
  60.  
  61. - if (Land[cpY + y, cpX + x] <= lfAllObjMask) and ((p^[px] and AMask) <> 0) then
  62. + if Land[cpY + y, cpX + x] <= lfAllObjMask then
  63. Land[cpY + y, cpX + x]:= lfObject or LandFlags
  64. end;
  65. end;
  66. @@ -157,6 +170,63 @@
  67. WriteLnToConsole(msgOK)
  68. end;
  69.  
  70. +function LerpByte(src, dst: Byte; l: LongWord): LongWord; inline;
  71. +begin
  72. + LerpByte:= ((255 - l) * src + l * dst) div 255;
  73. +end;
  74. +
  75. +procedure BlitOverlayAndGenerateCollisionInfo(cpX, cpY: Longword; Image: PSDL_Surface);
  76. +var p: PLongwordArray;
  77. + pLandColor: PLongWord;
  78. + x, y, alpha, color, landColor: LongWord;
  79. +begin
  80. +WriteToConsole('Generating overlay collision info... ');
  81. +
  82. +if SDL_MustLock(Image) then
  83. + if SDLCheck(SDL_LockSurface(Image) >= 0, 'SDL_LockSurface', true) then exit;
  84. +
  85. +if checkFails(Image^.format^.BytesPerPixel = 4, 'Land object overlay should be 32bit', true)
  86. + and SDL_MustLock(Image) then
  87. + SDL_UnlockSurface(Image);
  88. +
  89. +p:= Image^.pixels;
  90. +
  91. +for y:= 0 to Pred(Image^.h) do
  92. + begin
  93. + for x:= 0 to Pred(Image^.w) do
  94. + begin
  95. + color:= p^[x];
  96. + if (color and AMask) <> 0 then
  97. + begin
  98. + if (cReducedQuality and rqBlurryLand) = 0 then
  99. + pLandColor:= @LandPixels[cpY + y, cpX + x]
  100. + else
  101. + pLandColor:= @LandPixels[(cpY + y) div 2, (cpX + x) div 2];
  102. +
  103. + alpha:= (color and AMask) shr AShift;
  104. + if (alpha <> $FF) and (pLandColor^ <> 0) then
  105. + begin
  106. + landColor:= pLandColor^;
  107. + color:=
  108. + (LerpByte((landColor and RMask) shr RShift, (color and RMask) shr RShift, alpha) shl RShift)
  109. + or (LerpByte((landColor and GMask) shr GShift, (color and GMask) shr GShift, alpha) shl GShift)
  110. + or (LerpByte((landColor and BMask) shr BShift, (color and BMask) shr BShift, alpha) shl BShift)
  111. + or (LerpByte(alpha, 255, (landColor and AMask) shr AShift) shl AShift)
  112. + end;
  113. + pLandColor^:= color;
  114. +
  115. + if Land[cpY + y, cpX + x] <= lfAllObjMask then
  116. + Land[cpY + y, cpX + x]:= lfObject
  117. + end;
  118. + end;
  119. + p:= PLongwordArray(@(p^[Image^.pitch shr 2]))
  120. + end;
  121. +
  122. +if SDL_MustLock(Image) then
  123. + SDL_UnlockSurface(Image);
  124. +WriteLnToConsole(msgOK)
  125. +end;
  126. +
  127. procedure BlitImageUsingMask(cpX, cpY: Longword; Image, Mask: PSDL_Surface);
  128. var p, mp: PLongwordArray;
  129. x, y: Longword;
  130. @@ -355,27 +425,83 @@
  131. CheckLand:= bRes;
  132. end;
  133.  
  134. +function CheckLandAny(rect: TSDL_Rect; dX, dY, LandType: Longword): boolean;
  135. +var tmpx, tmpy, bx, by: LongInt;
  136. +begin
  137. + inc(rect.x, dX);
  138. + inc(rect.y, dY);
  139. + bx:= rect.x + rect.w - 1;
  140. + by:= rect.y + rect.h - 1;
  141. + CheckLandAny:= false;
  142. +
  143. + if (((rect.x and LAND_WIDTH_MASK) or (bx and LAND_WIDTH_MASK) or
  144. + (rect.y and LAND_HEIGHT_MASK) or (by and LAND_HEIGHT_MASK)) = 0) then
  145. + begin
  146. + for tmpx := rect.x to bx do
  147. + begin
  148. + if (((Land[rect.y, tmpx] and LandType) or (Land[by, tmpx] and LandType)) <> 0) then
  149. + begin
  150. + CheckLandAny := true;
  151. + exit;
  152. + end
  153. + end;
  154. + for tmpy := rect.y to by do
  155. + begin
  156. + if (((Land[tmpy, rect.x] and LandType) or (Land[tmpy, bx] and LandType)) <> 0) then
  157. + begin
  158. + CheckLandAny := true;
  159. + exit;
  160. + end
  161. + end;
  162. + end;
  163. +end;
  164. +
  165. function CheckCanPlace(x, y: Longword; var Obj: TThemeObject): boolean;
  166. var i: Longword;
  167. - bRes: boolean;
  168. + bRes, anchored: boolean;
  169. + overlayP1, overlayP2: TPoint;
  170. begin
  171. with Obj do begin
  172. bRes:= true;
  173. - i:= 1;
  174. - while bRes and (i <= inrectcnt) do
  175. + i:= 0;
  176. + while bRes and (i < overlaycnt) do
  177. + begin
  178. + overlayP1.x:= overlays[i].Position.x + x;
  179. + overlayP1.y:= overlays[i].Position.y + y;
  180. + overlayP2.x:= overlayP1.x + overlays[i].Width - 1;
  181. + overlayP2.y:= overlayP1.y + overlays[i].Height - 1;
  182. + bRes:= (((LAND_WIDTH_MASK and overlayP1.x) or (LAND_HEIGHT_MASK and overlayP1.y) or
  183. + (LAND_WIDTH_MASK and overlayP2.x) or (LAND_HEIGHT_MASK and overlayP2.y)) = 0)
  184. + and (not CheckIntersect(overlayP1.x, overlayP1.y, overlays[i].Width, overlays[i].Height));
  185. + inc(i)
  186. + end;
  187. +
  188. + i:= 0;
  189. + while bRes and (i < inrectcnt) do
  190. begin
  191. bRes:= CheckLand(inland[i], x, y, lfBasic);
  192. inc(i)
  193. end;
  194.  
  195. - i:= 1;
  196. - while bRes and (i <= outrectcnt) do
  197. + i:= 0;
  198. + while bRes and (i < outrectcnt) do
  199. begin
  200. bRes:= CheckLand(outland[i], x, y, 0);
  201. inc(i)
  202. end;
  203.  
  204. if bRes then
  205. + begin
  206. + anchored:= anchorcnt = 0;
  207. + for i:= 1 to anchorcnt do
  208. + begin
  209. + anchored := CheckLandAny(anchors[i], x, y, lfLandMask);
  210. + if anchored then break;
  211. + end;
  212. + bRes:= anchored;
  213. + end;
  214. +
  215. + if bRes then
  216. bRes:= not CheckIntersect(x, y, Width, Height);
  217.  
  218. CheckCanPlace:= bRes;
  219. @@ -386,7 +512,7 @@
  220. const MaxPointsIndex = 2047;
  221. var x, y: Longword;
  222. ar: array[0..MaxPointsIndex] of TPoint;
  223. - cnt, i: Longword;
  224. + cnt, i, ii: Longword;
  225. bRes: boolean;
  226. begin
  227. TryPut:= false;
  228. @@ -400,7 +526,7 @@
  229. y:= topY+32; // leave room for a hedgie to teleport in
  230. repeat
  231.  
  232. - if (inland[1].x = 0) and (inland[1].y = 0) and (inland[1].w = 0) and (inland[1].h = 0) then
  233. + if (inrectcnt > 0) and (inland[0].x = 0) and (inland[0].y = 0) and (inland[0].w = 0) and (inland[0].h = 0) then
  234. y := LAND_HEIGHT - Height;
  235.  
  236. if CheckCanPlace(x, y, Obj) then
  237. @@ -426,6 +552,18 @@
  238. BlitImageUsingMask(ar[i].x, ar[i].y, Obj.Surf, Obj.Mask)
  239. else BlitImageAndGenerateCollisionInfo(ar[i].x, ar[i].y, 0, Obj.Surf);
  240. AddRect(ar[i].x, ar[i].y, Width, Height);
  241. +
  242. + ii:= 0;
  243. + while ii < overlaycnt do
  244. + begin
  245. + BlitOverlayAndGenerateCollisionInfo(
  246. + ar[i].x + overlays[ii].Position.X,
  247. + ar[i].y + overlays[ii].Position.Y, overlays[ii].Surf);
  248. + AddRect(ar[i].x + overlays[ii].Position.X,
  249. + ar[i].y + overlays[ii].Position.Y,
  250. + Width, Height);
  251. + inc(ii);
  252. + end;
  253. dec(Maxcnt)
  254. end
  255. else Maxcnt:= 0
  256. @@ -493,8 +631,51 @@
  257. OutError('Object''s rectangle exceeds image: y + h (' + inttostr(y) + ' + ' + inttostr(h) + ') > Height (' + inttostr(Height) + ')', true);
  258. end;
  259.  
  260. +procedure ReadRect(var rect: TSDL_Rect; var s: ShortString);
  261. +var i: LongInt;
  262. +begin
  263. +with rect do
  264. + begin
  265. + i:= Pos(',', s);
  266. + x:= StrToInt(Trim(Copy(s, 1, Pred(i))));
  267. + Delete(s, 1, i);
  268. + i:= Pos(',', s);
  269. + y:= StrToInt(Trim(Copy(s, 1, Pred(i))));
  270. + Delete(s, 1, i);
  271. + i:= Pos(',', s);
  272. + w:= StrToInt(Trim(Copy(s, 1, Pred(i))));
  273. + Delete(s, 1, i);
  274. + i:= Pos(',', s);
  275. + if i = 0 then i:= Succ(Length(S));
  276. + h:= StrToInt(Trim(Copy(s, 1, Pred(i))));
  277. + Delete(s, 1, i);
  278. + end;
  279. +end;
  280. +
  281. +
  282. +
  283. +procedure ReadOverlay(var overlay: TThemeObjectOverlay; var s: ShortString);
  284. +var i: LongInt;
  285. +begin
  286. +with overlay do
  287. + begin
  288. + i:= Pos(',', s);
  289. + Position.X:= StrToInt(Trim(Copy(s, 1, Pred(i))));
  290. + Delete(s, 1, i);
  291. + i:= Pos(',', s);
  292. + Position.Y:= StrToInt(Trim(Copy(s, 1, Pred(i))));
  293. + Delete(s, 1, i);
  294. + i:= Pos(',', s);
  295. + if i = 0 then i:= Succ(Length(S));
  296. + Surf:= LoadDataImage(ptCurrTheme, Trim(Copy(s, 1, Pred(i))), ifColorKey or ifIgnoreCaps or ifCritical);
  297. + Width:= Surf^.w;
  298. + Height:= Surf^.h;
  299. + Delete(s, 1, i);
  300. + end;
  301. +end;
  302. +
  303. procedure ReadThemeInfo(var ThemeObjects: TThemeObjects; var SprayObjects: TSprayObjects);
  304. -var s, key: shortstring;
  305. +var s, key, nameRef: shortstring;
  306. f: PFSFile;
  307. i, y: LongInt;
  308. ii, t: Longword;
  309. @@ -687,7 +868,8 @@
  310. with ThemeObjects.objs[Pred(ThemeObjects.Count)] do
  311. begin
  312. i:= Pos(',', s);
  313. - Surf:= LoadDataImage(ptCurrTheme, Trim(Copy(s, 1, Pred(i))), ifColorKey or ifIgnoreCaps or ifCritical);
  314. + Name:= Trim(Copy(s, 1, Pred(i)));
  315. + Surf:= LoadDataImage(ptCurrTheme, Name, ifColorKey or ifIgnoreCaps or ifCritical);
  316. Width:= Surf^.w;
  317. Height:= Surf^.h;
  318. Mask:= LoadDataImage(ptCurrTheme, Trim(Copy(s, 1, Pred(i)))+'_mask', ifColorKey or ifIgnoreCaps);
  319. @@ -714,50 +896,61 @@
  320. Delete(s, 1, i);
  321. end;
  322.  
  323. - for ii:= 1 to inrectcnt do
  324. - with inland[ii] do
  325. - begin
  326. - i:= Pos(',', s);
  327. - x:= StrToInt(Trim(Copy(s, 1, Pred(i))));
  328. - Delete(s, 1, i);
  329. - i:= Pos(',', s);
  330. - y:= StrToInt(Trim(Copy(s, 1, Pred(i))));
  331. - Delete(s, 1, i);
  332. - i:= Pos(',', s);
  333. - w:= StrToInt(Trim(Copy(s, 1, Pred(i))));
  334. - Delete(s, 1, i);
  335. - i:= Pos(',', s);
  336. - h:= StrToInt(Trim(Copy(s, 1, Pred(i))));
  337. - Delete(s, 1, i);
  338. - CheckRect(Width, Height, x, y, w, h)
  339. - end;
  340. + if inrectcnt > MAXOBJECTRECTS then
  341. + OutError('Object''s inland rectangle count should be no more than '+ inttostr(MAXOBJECTRECTS) +' (it was '+ inttostr(inrectcnt) +').', true);
  342. +
  343. + for ii:= 0 to Pred(inrectcnt) do
  344. + ReadRect(inland[ii], s);
  345.  
  346. i:= Pos(',', s);
  347. outrectcnt:= StrToInt(Trim(Copy(s, 1, Pred(i))));
  348. Delete(s, 1, i);
  349. - for ii:= 1 to outrectcnt do
  350. - with outland[ii] do
  351. - begin
  352. - i:= Pos(',', s);
  353. - x:= StrToInt(Trim(Copy(s, 1, Pred(i))));
  354. - Delete(s, 1, i);
  355. - i:= Pos(',', s);
  356. - y:= StrToInt(Trim(Copy(s, 1, Pred(i))));
  357. - Delete(s, 1, i);
  358. - i:= Pos(',', s);
  359. - w:= StrToInt(Trim(Copy(s, 1, Pred(i))));
  360. - Delete(s, 1, i);
  361. - if ii = outrectcnt then
  362. - h:= StrToInt(Trim(s))
  363. - else
  364. - begin
  365. - i:= Pos(',', s);
  366. - h:= StrToInt(Trim(Copy(s, 1, Pred(i))));
  367. - Delete(s, 1, i)
  368. - end;
  369. - CheckRect(Width, Height, x, y, w, h)
  370. - end;
  371.  
  372. + if outrectcnt > MAXOBJECTRECTS then
  373. + OutError('Object''s outland rectangle count should be no more than '+ inttostr(MAXOBJECTRECTS) +' (it was '+ inttostr(outrectcnt) +').', true);
  374. +
  375. + for ii:= 0 to Pred(outrectcnt) do
  376. + ReadRect(outland[ii], s);
  377. + end;
  378. + end
  379. + else if key = 'anchors' then
  380. + begin
  381. + i:= Pos(',', s);
  382. + nameRef:= Trim(Copy(s, 1, Pred(i)));
  383. + for ii:= 0 to Pred(ThemeObjects.Count) do
  384. + if ThemeObjects.objs[ii].Name = nameRef then with ThemeObjects.objs[ii] do
  385. + begin
  386. + if anchorcnt <> 0 then
  387. + OutError('Duplicate anchors declaration for ' + nameRef, true);
  388. + Delete(s, 1, i);
  389. + i:= Pos(',', s);
  390. + anchorcnt:= StrToInt(Trim(Copy(s, 1, Pred(i))));
  391. + Delete(s, 1, i);
  392. + if anchorcnt > MAXOBJECTRECTS then
  393. + OutError('Object''s anchor rectangle count should be no more than '+ inttostr(MAXOBJECTRECTS) +' (it was '+ inttostr(anchorcnt) +').', true);
  394. + for t:= 0 to Pred(anchorcnt) do
  395. + ReadRect(anchors[t], s);
  396. + break
  397. + end;
  398. + end
  399. + else if key = 'overlays' then
  400. + begin
  401. + i:= Pos(',', s);
  402. + nameRef:= Trim(Copy(s, 1, Pred(i)));
  403. + for ii:= 0 to Pred(ThemeObjects.Count) do
  404. + if ThemeObjects.objs[ii].Name = nameRef then with ThemeObjects.objs[ii] do
  405. + begin
  406. + if overlaycnt <> 0 then
  407. + OutError('Duplicate overlays declaration for ' + nameRef, true);
  408. + Delete(s, 1, i);
  409. + i:= Pos(',', s);
  410. + overlaycnt:= StrToInt(Trim(Copy(s, 1, Pred(i))));
  411. + Delete(s, 1, i);
  412. + if overlaycnt > MAXOBJECTRECTS then
  413. + OutError('Object''s overlay count should be no more than '+ inttostr(MAXOBJECTRECTS) +' (it was '+ inttostr(overlaycnt) +').', true);
  414. + for t:= 0 to Pred(overlaycnt) do
  415. + ReadOverlay(overlays[t], s);
  416. + break
  417. end;
  418. end
  419. else if key = 'spray' then
  420. @@ -1009,7 +1202,7 @@
  421. end;
  422.  
  423. procedure FreeLandObjects();
  424. -var i: Longword;
  425. +var i, ii: Longword;
  426. begin
  427. for i:= 0 to Pred(MAXTHEMEOBJECTS) do
  428. begin
  429. @@ -1019,6 +1212,17 @@
  430. SDL_FreeSurface(SprayObjects.objs[i].Surf);
  431. ThemeObjects.objs[i].Surf:= nil;
  432. SprayObjects.objs[i].Surf:= nil;
  433. +
  434. + ii:= 0;
  435. + while ii < ThemeObjects.objs[i].overlaycnt do
  436. + begin
  437. + if ThemeObjects.objs[i].overlays[ii].Surf <> nil then
  438. + begin
  439. + SDL_FreeSurface(ThemeObjects.objs[i].overlays[ii].Surf);
  440. + ThemeObjects.objs[i].overlays[ii].Surf:= nil;
  441. + end;
  442. + inc(ii);
  443. + end;
  444. end;
  445. end;
Add Comment
Please, Sign In to add comment