1 /*
2 * The ManaPlus Client
3 * Copyright (C) 2004-2009 The Mana World Development Team
4 * Copyright (C) 2009-2010 The Mana Developers
5 * Copyright (C) 2011-2019 The ManaPlus Developers
6 * Copyright (C) 2019-2021 Andrei Karas
7 *
8 * This file is part of The ManaPlus Client.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "resources/map/maplayer.h"
25
26 #include "configuration.h"
27
28 #include "being/localplayer.h"
29
30 #include "enums/resources/map/blockmask.h"
31 #include "enums/resources/map/mapitemtype.h"
32
33 #include "gui/userpalette.h"
34
35 #ifdef USE_OPENGL
36 #include "utils/foreach.h"
37 #endif // USE_OPENGL
38
39 #include "render/graphics.h"
40
41 #include "resources/image/image.h"
42
43 #include "resources/map/mapitem.h"
44 #include "resources/map/maprowvertexes.h"
45 #include "resources/map/metatile.h"
46 #include "resources/map/speciallayer.h"
47
48 #include "debug.h"
49
MapLayer(const std::string & name,const int x,const int y,const int width,const int height,const bool fringeLayer,const int mask,const int tileCondition)50 MapLayer::MapLayer(const std::string &name,
51 const int x,
52 const int y,
53 const int width,
54 const int height,
55 const bool fringeLayer,
56 const int mask,
57 const int tileCondition) :
58 mX(x),
59 mY(y),
60 mPixelX(mX * mapTileSize),
61 mPixelY(mY * mapTileSize + mapTileSize),
62 mWidth(width),
63 mHeight(height),
64 mTiles(new TileInfo[mWidth * mHeight]),
65 mDrawLayerFlags(MapType::NORMAL),
66 mSpecialLayer(nullptr),
67 mTempLayer(nullptr),
68 mName(name),
69 mTempRows(),
70 mMask(mask),
71 mTileCondition(tileCondition),
72 mActorsFix(0),
73 mIsFringeLayer(fringeLayer),
74 mHighlightAttackRange(config.getBoolValue("highlightAttackRange")),
75 mSpecialFlag(true)
76 {
77 // std::fill_n(mTiles, mWidth * mHeight, static_cast<Image*>(nullptr));
78
79 config.addListener("highlightAttackRange", this);
80 }
81
~MapLayer()82 MapLayer::~MapLayer()
83 {
84 config.removeListener("highlightAttackRange", this);
85 CHECKLISTENERS
86 delete []mTiles;
87 delete_all(mTempRows);
88 mTempRows.clear();
89 }
90
optionChanged(const std::string & value)91 void MapLayer::optionChanged(const std::string &value) restrict
92 {
93 if (value == "highlightAttackRange")
94 {
95 mHighlightAttackRange =
96 config.getBoolValue("highlightAttackRange");
97 }
98 }
99
draw(Graphics * const graphics,int startX,int startY,int endX,int endY,const int scrollX,const int scrollY) const100 void MapLayer::draw(Graphics *const graphics,
101 int startX,
102 int startY,
103 int endX,
104 int endY,
105 const int scrollX,
106 const int scrollY) const restrict
107 {
108 BLOCK_START("MapLayer::draw")
109 startX -= mX;
110 startY -= mY;
111 endX -= mX;
112 endY -= mY;
113
114 if (startX < 0)
115 startX = 0;
116 if (startY < 0)
117 startY = 0;
118 if (endX > mWidth)
119 endX = mWidth;
120 if (endY > mHeight)
121 endY = mHeight;
122
123 const int dx = mPixelX - scrollX;
124 const int dy = mPixelY - scrollY;
125 for (int y = startY; y < endY; y++)
126 {
127 const int y32 = y * mapTileSize;
128 const int yWidth = y * mWidth;
129
130 const int py0 = y32 + dy;
131
132 int x0 = startX;
133 TileInfo *tilePtr = &mTiles[CAST_SIZE(x0 + yWidth)];
134 if (tilePtr->isEnabled == false)
135 {
136 if (x0 + tilePtr->nextTile + 1 >= endX)
137 {
138 continue;
139 }
140 x0 += tilePtr->nextTile + 1;
141 tilePtr = &mTiles[CAST_SIZE(x0 + yWidth)];
142 if (mTiles[x0 + yWidth].isEnabled == false)
143 {
144 continue;
145 }
146 }
147 for (int x = x0; x < endX; x++, tilePtr++)
148 {
149 const int x32 = x * mapTileSize;
150
151 const Image *const img = tilePtr->image;
152 const int px = x32 + dx;
153 const int py = py0 - img->mBounds.h;
154 if (mSpecialFlag ||
155 img->mBounds.h <= mapTileSize)
156 {
157 if (tilePtr->count == 0)
158 {
159 graphics->drawImage(img, px, py);
160 }
161 else
162 {
163 graphics->drawPattern(img,
164 px,
165 py,
166 tilePtr->width,
167 img->mBounds.h);
168 }
169 }
170
171 const int nextTile = tilePtr->nextTile;
172 x += nextTile;
173 tilePtr += nextTile;
174 }
175 }
176 BLOCK_END("MapLayer::draw")
177 }
178
drawSDL(Graphics * const graphics) const179 void MapLayer::drawSDL(Graphics *const graphics) const restrict2
180 {
181 BLOCK_START("MapLayer::drawSDL")
182 MapRows::const_iterator rit = mTempRows.begin();
183 const MapRows::const_iterator rit_end = mTempRows.end();
184 while (rit != rit_end)
185 {
186 MapRowImages *const images = &(*rit)->images;
187 MapRowImages::const_iterator iit = images->begin();
188 const MapRowImages::const_iterator iit_end = images->end();
189 while (iit != iit_end)
190 {
191 graphics->drawTileVertexes(*iit);
192 ++ iit;
193 }
194 ++ rit;
195 }
196 BLOCK_END("MapLayer::drawSDL")
197 }
198
199 #ifdef USE_OPENGL
updateSDL(const Graphics * const graphics,int startX,int startY,int endX,int endY,const int scrollX,const int scrollY)200 void MapLayer::updateSDL(const Graphics *const graphics,
201 int startX,
202 int startY,
203 int endX,
204 int endY,
205 const int scrollX,
206 const int scrollY) restrict2
207 {
208 BLOCK_START("MapLayer::updateSDL")
209 delete_all(mTempRows);
210 mTempRows.clear();
211
212 startX -= mX;
213 startY -= mY;
214 endX -= mX;
215 endY -= mY;
216
217 if (startX < 0)
218 startX = 0;
219 if (startY < 0)
220 startY = 0;
221 if (endX > mWidth)
222 endX = mWidth;
223 if (endY > mHeight)
224 endY = mHeight;
225
226 const int dx = mPixelX - scrollX;
227 const int dy = mPixelY - scrollY;
228
229 for (int y = startY; y < endY; y++)
230 {
231 MapRowVertexes *const row = new MapRowVertexes;
232 mTempRows.push_back(row);
233
234 const Image *lastImage = nullptr;
235 ImageVertexes *imgVert = nullptr;
236
237 const int yWidth = y * mWidth;
238 const int py0 = y * mapTileSize + dy;
239 TileInfo *tilePtr = &mTiles[CAST_SIZE(startX + yWidth)];
240
241 for (int x = startX; x < endX; x++, tilePtr++)
242 {
243 if (!tilePtr->isEnabled)
244 continue;
245 Image *const img = (*tilePtr).image;
246 const int px = x * mapTileSize + dx;
247 const int py = py0 - img->mBounds.h;
248 if (mSpecialFlag ||
249 img->mBounds.h <= mapTileSize)
250 {
251 if (lastImage != img)
252 {
253 imgVert = new ImageVertexes;
254 imgVert->image = img;
255 row->images.push_back(imgVert);
256 lastImage = img;
257 }
258 graphics->calcTileSDL(imgVert, px, py);
259 }
260 }
261 }
262 BLOCK_END("MapLayer::updateSDL")
263 }
264
updateOGL(Graphics * const graphics,int startX,int startY,int endX,int endY,const int scrollX,const int scrollY)265 void MapLayer::updateOGL(Graphics *const graphics,
266 int startX,
267 int startY,
268 int endX,
269 int endY,
270 const int scrollX,
271 const int scrollY) restrict2
272 {
273 BLOCK_START("MapLayer::updateOGL")
274 delete_all(mTempRows);
275 mTempRows.clear();
276
277 startX -= mX;
278 startY -= mY;
279 endX -= mX;
280 endY -= mY;
281
282 if (startX < 0)
283 startX = 0;
284 if (startY < 0)
285 startY = 0;
286 if (endX > mWidth)
287 endX = mWidth;
288 if (endY > mHeight)
289 endY = mHeight;
290
291 const int dx = mPixelX - scrollX;
292 const int dy = mPixelY - scrollY;
293
294 MapRowVertexes *const row = new MapRowVertexes;
295 mTempRows.push_back(row);
296 Image *lastImage = nullptr;
297 ImageVertexes *imgVert = nullptr;
298 typedef std::map<int, ImageVertexes*> ImageVertexesMap;
299 ImageVertexesMap imgSet;
300
301 for (int y = startY; y < endY; y++)
302 {
303 const int yWidth = y * mWidth;
304 const int py0 = y * mapTileSize + dy;
305 TileInfo *tilePtr = &mTiles[CAST_SIZE(startX + yWidth)];
306 for (int x = startX; x < endX; x++, tilePtr++)
307 {
308 if (!tilePtr->isEnabled)
309 continue;
310 Image *const img = (*tilePtr).image;
311 const int px = x * mapTileSize + dx;
312 const int py = py0 - img->mBounds.h;
313 const GLuint imgGlImage = img->mGLImage;
314 if (mSpecialFlag ||
315 img->mBounds.h <= mapTileSize)
316 {
317 if ((lastImage == nullptr) ||
318 lastImage->mGLImage != imgGlImage)
319 {
320 if (img->mBounds.w > mapTileSize)
321 imgSet.clear();
322
323 if (imgSet.find(imgGlImage) != imgSet.end())
324 {
325 imgVert = imgSet[imgGlImage];
326 }
327 else
328 {
329 if (lastImage != nullptr)
330 imgSet[lastImage->mGLImage] = imgVert;
331 imgVert = new ImageVertexes;
332 imgVert->ogl.init();
333 imgVert->image = img;
334 row->images.push_back(imgVert);
335 }
336 }
337 lastImage = img;
338 graphics->calcTileVertexes(imgVert, lastImage, px, py);
339 }
340 }
341 }
342 FOR_EACH (MapRowImages::iterator, it, row->images)
343 {
344 graphics->finalize(*it);
345 }
346 BLOCK_END("MapLayer::updateOGL")
347 }
348
drawOGL(Graphics * const graphics) const349 void MapLayer::drawOGL(Graphics *const graphics) const restrict2
350 {
351 BLOCK_START("MapLayer::drawOGL")
352 MapRows::const_iterator rit = mTempRows.begin();
353 const MapRows::const_iterator rit_end = mTempRows.end();
354 while (rit != rit_end)
355 {
356 const MapRowImages *const images = &(*rit)->images;
357 MapRowImages::const_iterator iit = images->begin();
358 const MapRowImages::const_iterator iit_end = images->end();
359 while (iit != iit_end)
360 {
361 graphics->drawTileVertexes(*iit);
362 ++ iit;
363 }
364 ++ rit;
365 }
366 BLOCK_END("MapLayer::drawOGL")
367 }
368 #endif // USE_OPENGL
369
drawSpecialLayer(Graphics * const graphics,const int y,const int startX,const int endX,const int scrollX,const int scrollY) const370 void MapLayer::drawSpecialLayer(Graphics *const graphics,
371 const int y,
372 const int startX,
373 const int endX,
374 const int scrollX,
375 const int scrollY) const restrict
376 {
377 const int y32 = y * mapTileSize;
378 const int py1 = y32 - scrollY;
379 int endX1 = endX;
380 int specialWidth = mSpecialLayer->mWidth;
381 int ptr = y * specialWidth;
382 if (endX1 > specialWidth)
383 endX1 = specialWidth;
384 if (endX1 < 0)
385 endX1 = 0;
386 int x0 = startX;
387 const MapItem *item0 = mSpecialLayer->mTiles[ptr + startX];
388 if ((item0 == nullptr) || item0->mType == MapItemType::EMPTY)
389 {
390 x0 += mSpecialLayer->mCache[ptr + startX] + 1;
391 }
392 for (int x = x0; x < endX1; x++)
393 {
394 const int px1 = x * mapTileSize - scrollX;
395 const MapItem *const item = mSpecialLayer->mTiles[ptr + x];
396 if (item != nullptr)
397 {
398 item->draw(graphics, px1, py1,
399 mapTileSize, mapTileSize);
400 }
401 x += mSpecialLayer->mCache[ptr + x];
402 }
403
404 x0 = startX;
405 specialWidth = mTempLayer->mWidth;
406 ptr = y * specialWidth;
407 endX1 = endX;
408 if (endX1 > specialWidth)
409 endX1 = specialWidth;
410 item0 = mTempLayer->mTiles[ptr + startX];
411 if ((item0 == nullptr) || item0->mType == MapItemType::EMPTY)
412 {
413 x0 += mTempLayer->mCache[ptr + startX] + 1;
414 }
415 for (int x = x0; x < endX1; x++)
416 {
417 const int px1 = x * mapTileSize - scrollX;
418 const MapItem *const item = mTempLayer->mTiles[ptr + x];
419 item->draw(graphics, px1, py1,
420 mapTileSize, mapTileSize);
421 x += mTempLayer->mCache[ptr + x];
422 }
423 }
424
drawFringe(Graphics * const graphics,int startX,int startY,int endX,int endY,const int scrollX,const int scrollY,const Actors & actors) const425 void MapLayer::drawFringe(Graphics *const graphics,
426 int startX,
427 int startY,
428 int endX,
429 int endY,
430 const int scrollX,
431 const int scrollY,
432 const Actors &actors) const restrict
433 {
434 BLOCK_START("MapLayer::drawFringe")
435 if ((localPlayer == nullptr) ||
436 (mSpecialLayer == nullptr) ||
437 (mTempLayer == nullptr))
438 {
439 BLOCK_END("MapLayer::drawFringe")
440 return;
441 }
442
443 startX -= mX;
444 startY -= mY;
445 endX -= mX;
446 endY -= mY;
447
448 if (startX < 0)
449 startX = 0;
450 if (startY < 0)
451 startY = 0;
452 if (endX > mWidth)
453 endX = mWidth;
454 if (endY > mHeight)
455 endY = mHeight;
456
457 ActorsCIter ai = actors.begin();
458 const ActorsCIter ai_end = actors.end();
459
460 const int dx = mPixelX - scrollX;
461 const int dy = mPixelY - scrollY;
462
463 const int specialHeight = mSpecialLayer->mHeight;
464
465 const bool flag = mDrawLayerFlags == MapType::SPECIAL3 ||
466 mDrawLayerFlags == MapType::SPECIAL4 ||
467 mDrawLayerFlags == MapType::BLACKWHITE;
468
469 const int minEndY = std::min(specialHeight, endY);
470
471 if (flag)
472 { // flag
473 for (int y = startY; y < minEndY; y ++)
474 {
475 const int y32s = (y + mActorsFix) * mapTileSize;
476
477 BLOCK_START("MapLayer::drawFringe drawmobs")
478 // If drawing the fringe layer, make sure all actors above this
479 // row of tiles have been drawn
480 while (ai != ai_end && (*ai)->getSortPixelY() <= y32s)
481 {
482 (*ai)->draw(graphics, -scrollX, -scrollY);
483 ++ ai;
484 }
485 BLOCK_END("MapLayer::drawFringe drawmobs")
486
487 // remove this condition, because it always true
488 if (y < specialHeight)
489 {
490 drawSpecialLayer(graphics,
491 y,
492 startX,
493 endX,
494 scrollX,
495 scrollY);
496 }
497 }
498
499 for (int y = minEndY; y < endY; y++)
500 {
501 const int y32s = (y + mActorsFix) * mapTileSize;
502
503 BLOCK_START("MapLayer::drawFringe drawmobs")
504 // If drawing the fringe layer, make sure all actors above this
505 // row of tiles have been drawn
506 while (ai != ai_end && (*ai)->getSortPixelY() <= y32s)
507 {
508 (*ai)->draw(graphics, -scrollX, -scrollY);
509 ++ ai;
510 }
511 BLOCK_END("MapLayer::drawFringe drawmobs")
512 }
513 }
514 else
515 { // !flag
516 for (int y = startY; y < minEndY; y ++)
517 {
518 const int y32 = y * mapTileSize;
519 const int y32s = (y + mActorsFix) * mapTileSize;
520 const int yWidth = y * mWidth;
521
522 BLOCK_START("MapLayer::drawFringe drawmobs")
523 // If drawing the fringe layer, make sure all actors above this
524 // row of tiles have been drawn
525 while (ai != ai_end &&
526 (*ai)->getSortPixelY() <= y32s)
527 {
528 (*ai)->draw(graphics, -scrollX, -scrollY);
529 ++ ai;
530 }
531 BLOCK_END("MapLayer::drawFringe drawmobs")
532
533 const int py0 = y32 + dy;
534
535 int x0 = startX;
536 TileInfo *tilePtr = &mTiles[CAST_SIZE(x0 + yWidth)];
537 if (tilePtr->isEnabled == false)
538 {
539 drawSpecialLayer(graphics,
540 y,
541 0,
542 std::min(x0 + tilePtr->nextTile + 1, endX),
543 scrollX,
544 scrollY);
545 if (x0 + tilePtr->nextTile + 1 >= endX)
546 {
547 continue;
548 }
549 x0 += tilePtr->nextTile + 1;
550 tilePtr = &mTiles[CAST_SIZE(x0 + yWidth)];
551 if (mTiles[x0 + yWidth].isEnabled == false)
552 continue;
553 }
554 for (int x = x0; x < endX; x++, tilePtr++)
555 {
556 const int x32 = x * mapTileSize;
557 const Image *const img = tilePtr->image;
558 if (mSpecialFlag ||
559 img->mBounds.h <= mapTileSize)
560 {
561 const int px = x32 + dx;
562 const int py = py0 - img->mBounds.h;
563
564 if (tilePtr->count == 0)
565 {
566 graphics->drawImage(img, px, py);
567 }
568 else
569 {
570 graphics->drawPattern(img,
571 px,
572 py,
573 tilePtr->width,
574 img->mBounds.h);
575 }
576 }
577
578 const int nextTile = tilePtr->nextTile;
579 // remove this condition, because it always true
580 if (y < specialHeight)
581 {
582 drawSpecialLayer(graphics,
583 y,
584 x,
585 std::min(x + nextTile + 1, endX),
586 scrollX,
587 scrollY);
588 }
589 x += nextTile;
590 tilePtr += nextTile;
591 }
592 }
593
594 for (int y = minEndY; y < endY; y++)
595 {
596 const int y32 = y * mapTileSize;
597 const int y32s = (y + mActorsFix) * mapTileSize;
598 const int yWidth = y * mWidth;
599
600 BLOCK_START("MapLayer::drawFringe drawmobs")
601 // If drawing the fringe layer, make sure all actors above this
602 // row of tiles have been drawn
603 while (ai != ai_end && (*ai)->getSortPixelY() <= y32s)
604 {
605 (*ai)->draw(graphics, -scrollX, -scrollY);
606 ++ ai;
607 }
608 BLOCK_END("MapLayer::drawFringe drawmobs")
609
610 const int py0 = y32 + dy;
611
612 int x0 = startX;
613 TileInfo *tilePtr = &mTiles[CAST_SIZE(x0 + yWidth)];
614 if (tilePtr->isEnabled == false)
615 {
616 if (x0 + tilePtr->nextTile + 1 >= endX)
617 continue;
618 x0 += tilePtr->nextTile + 1;
619 tilePtr = &mTiles[CAST_SIZE(x0 + yWidth)];
620 if (mTiles[x0 + yWidth].isEnabled == false)
621 continue;
622 }
623 for (int x = x0; x < endX; x++, tilePtr++)
624 {
625 const int x32 = x * mapTileSize;
626 const Image *const img = tilePtr->image;
627 const int px = x32 + dx;
628 const int py = py0 - img->mBounds.h;
629 if (mSpecialFlag ||
630 img->mBounds.h <= mapTileSize)
631 {
632 const int c = tilePtr->count;
633
634 if (c == 0)
635 {
636 graphics->drawImage(img, px, py);
637 }
638 else
639 {
640 graphics->drawPattern(img,
641 px,
642 py,
643 tilePtr->width,
644 img->mBounds.h);
645 }
646 }
647 const int nextTile = tilePtr->nextTile;
648 x += nextTile;
649 tilePtr += nextTile;
650 }
651 }
652 } // !flag
653
654 // Draw any remaining actors
655 if (mDrawLayerFlags != MapType::SPECIAL3 &&
656 mDrawLayerFlags != MapType::SPECIAL4)
657 {
658 BLOCK_START("MapLayer::drawFringe drawmobs")
659 while (ai != ai_end)
660 {
661 (*ai)->draw(graphics, -scrollX, -scrollY);
662 ++ai;
663 }
664 BLOCK_END("MapLayer::drawFringe drawmobs")
665 if (mHighlightAttackRange)
666 {
667 const int px = localPlayer->getPixelX()
668 - scrollX - mapTileSize / 2;
669 const int py = localPlayer->getPixelY() - scrollY - mapTileSize;
670 const int attackRange = localPlayer->getAttackRange()
671 * mapTileSize;
672
673 int x = px - attackRange;
674 int y = py - attackRange;
675 int w = 2 * attackRange + mapTileSize;
676 int h = w;
677 if (attackRange <= mapTileSize)
678 {
679 x -= mapTileSize / 2;
680 y -= mapTileSize / 2;
681 w += mapTileSize;
682 h += mapTileSize;
683 }
684
685 if (userPalette != nullptr)
686 {
687 graphics->setColor(userPalette->getColorWithAlpha(
688 UserColorId::ATTACK_RANGE));
689 graphics->fillRectangle(Rect(x, y, w, h));
690 graphics->setColor(userPalette->getColorWithAlpha(
691 UserColorId::ATTACK_RANGE_BORDER));
692 graphics->drawRectangle(Rect(x, y, w, h));
693 }
694 }
695 }
696 BLOCK_END("MapLayer::drawFringe")
697 }
698
getTileDrawWidth(const TileInfo * restrict tilePtr,const int endX,int & restrict width,int & restrict nextTile)699 int MapLayer::getTileDrawWidth(const TileInfo *restrict tilePtr,
700 const int endX,
701 int &restrict width,
702 int &restrict nextTile)
703 {
704 BLOCK_START("MapLayer::getTileDrawWidth")
705 const Image *const img1 = tilePtr->image;
706 int c = 0;
707 width = img1->mBounds.w;
708 for (int x = 1; x < endX; x++)
709 {
710 tilePtr ++;
711 const Image *const img = tilePtr->image;
712 if (img == nullptr ||
713 tilePtr->isEnabled == false)
714 {
715 break;
716 }
717 if (img != img1)
718 {
719 nextTile = c;
720 BLOCK_END("MapLayer::getTileDrawWidth")
721 return c;
722 }
723 c ++;
724 width += img->mBounds.w;
725 }
726 int c2 = c;
727 for (int x2 = c2 + 1; x2 < endX; x2++)
728 {
729 if (tilePtr->image != nullptr &&
730 tilePtr->isEnabled == true)
731 {
732 break;
733 }
734 c2 ++;
735 tilePtr ++;
736 }
737 nextTile = c2;
738 BLOCK_END("MapLayer::getTileDrawWidth")
739 return c;
740 }
741
getEmptyTileDrawWidth(const TileInfo * restrict tilePtr,const int endX,int & restrict nextTile)742 int MapLayer::getEmptyTileDrawWidth(const TileInfo *restrict tilePtr,
743 const int endX,
744 int &restrict nextTile)
745 {
746 BLOCK_START("MapLayer::getEmptyTileDrawWidth")
747 int c = 0;
748 for (int x = 1; x < endX; x++)
749 {
750 tilePtr ++;
751 const Image *const img = tilePtr->image;
752 if (img != nullptr && tilePtr->isEnabled == true)
753 break;
754 c ++;
755 }
756 BLOCK_END("MapLayer::getEmptyTileDrawWidth")
757
758 nextTile = c;
759 return c;
760 }
761
updateConditionTiles(const MetaTile * const metaTiles,const int width,const int height)762 void MapLayer::updateConditionTiles(const MetaTile *const metaTiles,
763 const int width,
764 const int height) restrict
765 {
766 const int width1 = width < mWidth ? width : mWidth;
767 const int height1 = height < mHeight ? height : mHeight;
768
769 for (int y = mY; y < height1; y ++)
770 {
771 const MetaTile *metaPtr = metaTiles + (y - mY) * width;
772 TileInfo *tilePtr = mTiles + y * mWidth;
773 for (int x = mX; x < width1; x ++, metaPtr ++, tilePtr ++)
774 {
775 if (tilePtr->image != nullptr &&
776 (((metaPtr->blockmask & mTileCondition) != 0) ||
777 (metaPtr->blockmask == 0 &&
778 mTileCondition == BlockMask::GROUND)))
779 {
780 tilePtr->isEnabled = true;
781 }
782 else
783 {
784 tilePtr->isEnabled = false;
785 }
786 }
787 }
788 }
789
updateCache(const int width,const int height)790 void MapLayer::updateCache(const int width,
791 const int height) restrict
792 {
793 const int width1 = width < mWidth ? width : mWidth;
794 const int height1 = height < mHeight ? height : mHeight;
795
796 for (int y = mY; y < height1; y ++)
797 {
798 for (int x = mX; x < width1; x ++)
799 {
800 TileInfo *tilePtr = mTiles + y * mWidth + x;
801 int nextTile = 0;
802 if (tilePtr->image == nullptr || tilePtr->isEnabled == false)
803 {
804 tilePtr->isEnabled = false;
805 tilePtr->count = getEmptyTileDrawWidth(tilePtr,
806 width1 - x,
807 nextTile);
808 tilePtr->width = 0;
809 }
810 else
811 {
812 int tileWidth = 0;
813 tilePtr->count = getTileDrawWidth(tilePtr,
814 width1 - x,
815 tileWidth,
816 nextTile);
817 tilePtr->width = tileWidth;
818 }
819 tilePtr->nextTile = nextTile;
820 }
821 }
822 }
823
calcMemoryLocal() const824 int MapLayer::calcMemoryLocal() const
825 {
826 return static_cast<int>(sizeof(MapLayer) +
827 sizeof(TileInfo) * mWidth * mHeight +
828 sizeof(MapRowVertexes) * mTempRows.capacity());
829 }
830
calcMemoryChilds(const int level) const831 int MapLayer::calcMemoryChilds(const int level) const
832 {
833 int sz = 0;
834 if (mSpecialLayer != nullptr)
835 sz += mSpecialLayer->calcMemory(level + 1);
836 if (mTempLayer != nullptr)
837 sz += mTempLayer->calcMemory(level + 1);
838 return sz;
839 }
840