GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/resources/map/maplayer.cpp Lines: 203 395 51.4 %
Date: 2021-03-17 Branches: 113 292 38.7 %

Line Branch Exec Source
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
50
69
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
69
                   const int tileCondition) :
58
    mX(x),
59
    mY(y),
60
69
    mPixelX(mX * mapTileSize),
61
69
    mPixelY(mY * mapTileSize + mapTileSize),
62
    mWidth(width),
63
    mHeight(height),
64

190191
    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

276
    mHighlightAttackRange(config.getBoolValue("highlightAttackRange")),
75
621
    mSpecialFlag(true)
76
{
77
//    std::fill_n(mTiles, mWidth * mHeight, static_cast<Image*>(nullptr));
78
79

276
    config.addListener("highlightAttackRange", this);
80
69
}
81
82
345
MapLayer::~MapLayer()
83
{
84
276
    config.removeListener("highlightAttackRange", this);
85
    CHECKLISTENERS
86
69
    delete []mTiles;
87
138
    delete_all(mTempRows);
88
138
    mTempRows.clear();
89
138
}
90
91
void MapLayer::optionChanged(const std::string &value) restrict
92
{
93
    if (value == "highlightAttackRange")
94
    {
95
        mHighlightAttackRange =
96
            config.getBoolValue("highlightAttackRange");
97
    }
98
}
99
100
22
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
22
    startX -= mX;
110
22
    startY -= mY;
111
22
    endX -= mX;
112
22
    endY -= mY;
113
114
22
    if (startX < 0)
115
        startX = 0;
116
22
    if (startY < 0)
117
        startY = 0;
118
22
    if (endX > mWidth)
119
        endX = mWidth;
120
22
    if (endY > mHeight)
121
        endY = mHeight;
122
123
22
    const int dx = mPixelX - scrollX;
124
22
    const int dy = mPixelY - scrollY;
125
440
    for (int y = startY; y < endY; y++)
126
    {
127
418
        const int y32 = y * mapTileSize;
128
418
        const int yWidth = y * mWidth;
129
130
418
        const int py0 = y32 + dy;
131
132
418
        int x0 = startX;
133
418
        TileInfo *tilePtr = &mTiles[CAST_SIZE(x0 + yWidth)];
134
418
        if (tilePtr->isEnabled == false)
135
        {
136
402
            if (x0 + tilePtr->nextTile + 1 >= endX)
137
            {
138
                continue;
139
            }
140
6
            x0 += tilePtr->nextTile + 1;
141
6
            tilePtr = &mTiles[CAST_SIZE(x0 + yWidth)];
142
6
            if (mTiles[x0 + yWidth].isEnabled == false)
143
            {
144
                continue;
145
            }
146
        }
147
102
        for (int x = x0; x < endX; x++, tilePtr++)
148
        {
149
40
            const int x32 = x * mapTileSize;
150
151
40
            const Image *const img = tilePtr->image;
152
40
            const int px = x32 + dx;
153
40
            const int py = py0 - img->mBounds.h;
154

40
            if (mSpecialFlag ||
155
                img->mBounds.h <= mapTileSize)
156
            {
157
40
                if (tilePtr->count == 0)
158
                {
159
28
                    graphics->drawImage(img, px, py);
160
                }
161
                else
162
                {
163
12
                    graphics->drawPattern(img,
164
                        px,
165
                        py,
166
                        tilePtr->width,
167
24
                        img->mBounds.h);
168
                }
169
            }
170
171
40
            const int nextTile = tilePtr->nextTile;
172
40
            x += nextTile;
173
40
            tilePtr += nextTile;
174
        }
175
    }
176
    BLOCK_END("MapLayer::draw")
177
22
}
178
179
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
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
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
349
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
370
892
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
892
    const int y32 = y * mapTileSize;
378
892
    const int py1 = y32 - scrollY;
379
892
    int endX1 = endX;
380
892
    int specialWidth = mSpecialLayer->mWidth;
381
892
    int ptr = y * specialWidth;
382
892
    if (endX1 > specialWidth)
383
        endX1 = specialWidth;
384
892
    if (endX1 < 0)
385
        endX1 = 0;
386
892
    int x0 = startX;
387
892
    const MapItem *item0 = mSpecialLayer->mTiles[ptr + startX];
388

892
    if ((item0 == nullptr) || item0->mType == MapItemType::EMPTY)
389
    {
390
881
        x0 += mSpecialLayer->mCache[ptr + startX] + 1;
391
    }
392
944
    for (int x = x0; x < endX1; x++)
393
    {
394
26
        const int px1 = x * mapTileSize - scrollX;
395
26
        const MapItem *const item = mSpecialLayer->mTiles[ptr + x];
396
26
        if (item != nullptr)
397
        {
398
            item->draw(graphics, px1, py1,
399
26
                mapTileSize, mapTileSize);
400
        }
401
26
        x += mSpecialLayer->mCache[ptr + x];
402
    }
403
404
892
    x0 = startX;
405
892
    specialWidth = mTempLayer->mWidth;
406
892
    ptr = y * specialWidth;
407
892
    endX1 = endX;
408
892
    if (endX1 > specialWidth)
409
        endX1 = specialWidth;
410
892
    item0 = mTempLayer->mTiles[ptr + startX];
411

892
    if ((item0 == nullptr) || item0->mType == MapItemType::EMPTY)
412
    {
413
885
        x0 += mTempLayer->mCache[ptr + startX] + 1;
414
    }
415
928
    for (int x = x0; x < endX1; x++)
416
    {
417
18
        const int px1 = x * mapTileSize - scrollX;
418
18
        const MapItem *const item = mTempLayer->mTiles[ptr + x];
419
        item->draw(graphics, px1, py1,
420
18
            mapTileSize, mapTileSize);
421
18
        x += mTempLayer->mCache[ptr + x];
422
    }
423
892
}
424
425
26
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

52
    if ((localPlayer == nullptr) ||
436
52
        (mSpecialLayer == nullptr) ||
437
26
        (mTempLayer == nullptr))
438
    {
439
        BLOCK_END("MapLayer::drawFringe")
440
        return;
441
    }
442
443
26
    startX -= mX;
444
26
    startY -= mY;
445
26
    endX -= mX;
446
26
    endY -= mY;
447
448
26
    if (startX < 0)
449
        startX = 0;
450
26
    if (startY < 0)
451
        startY = 0;
452
26
    if (endX > mWidth)
453
        endX = mWidth;
454
26
    if (endY > mHeight)
455
        endY = mHeight;
456
457
52
    ActorsCIter ai = actors.begin();
458
26
    const ActorsCIter ai_end = actors.end();
459
460
26
    const int dx = mPixelX - scrollX;
461
26
    const int dy = mPixelY - scrollY;
462
463
26
    const int specialHeight = mSpecialLayer->mHeight;
464
465
26
    const bool flag = mDrawLayerFlags == MapType::SPECIAL3 ||
466
26
        mDrawLayerFlags == MapType::SPECIAL4 ||
467
26
        mDrawLayerFlags == MapType::BLACKWHITE;
468
469
26
    const int minEndY = std::min(specialHeight, endY);
470
471
26
    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
1662
        for (int y = startY; y < minEndY; y ++)
517
        {
518
818
            const int y32 = y * mapTileSize;
519
818
            const int y32s = (y + mActorsFix) * mapTileSize;
520
818
            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

818
            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
818
            const int py0 = y32 + dy;
534
535
818
            int x0 = startX;
536
818
            TileInfo *tilePtr = &mTiles[CAST_SIZE(x0 + yWidth)];
537
818
            if (tilePtr->isEnabled == false)
538
            {
539
802
                drawSpecialLayer(graphics,
540
                    y,
541
                    0,
542
2406
                    std::min(x0 + tilePtr->nextTile + 1, endX),
543
                    scrollX,
544
802
                    scrollY);
545
802
                if (x0 + tilePtr->nextTile + 1 >= endX)
546
                {
547
                    continue;
548
                }
549
10
                x0 += tilePtr->nextTile + 1;
550
10
                tilePtr = &mTiles[CAST_SIZE(x0 + yWidth)];
551
10
                if (mTiles[x0 + yWidth].isEnabled == false)
552
                    continue;
553
            }
554
154
            for (int x = x0; x < endX; x++, tilePtr++)
555
            {
556
64
                const int x32 = x * mapTileSize;
557
64
                const Image *const img = tilePtr->image;
558

64
                if (mSpecialFlag ||
559
                    img->mBounds.h <= mapTileSize)
560
                {
561
64
                    const int px = x32 + dx;
562
64
                    const int py = py0 - img->mBounds.h;
563
564
64
                    if (tilePtr->count == 0)
565
                    {
566
40
                        graphics->drawImage(img, px, py);
567
                    }
568
                    else
569
                    {
570
24
                        graphics->drawPattern(img,
571
                            px,
572
                            py,
573
                            tilePtr->width,
574
48
                            img->mBounds.h);
575
                    }
576
                }
577
578
64
                const int nextTile = tilePtr->nextTile;
579
                // remove this condition, because it always true
580
64
                if (y < specialHeight)
581
                {
582
64
                    drawSpecialLayer(graphics,
583
                        y,
584
                        x,
585
192
                        std::min(x + nextTile + 1, endX),
586
                        scrollX,
587
64
                        scrollY);
588
                }
589
64
                x += nextTile;
590
64
                tilePtr += nextTile;
591
            }
592
        }
593
594
26
        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
26
    if (mDrawLayerFlags != MapType::SPECIAL3 &&
656
        mDrawLayerFlags != MapType::SPECIAL4)
657
    {
658
        BLOCK_START("MapLayer::drawFringe drawmobs")
659
26
        while (ai != ai_end)
660
        {
661
            (*ai)->draw(graphics, -scrollX, -scrollY);
662
            ++ai;
663
        }
664
        BLOCK_END("MapLayer::drawFringe drawmobs")
665
26
        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
699
131
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
131
    const Image *const img1 = tilePtr->image;
706
131
    int c = 0;
707
131
    width = img1->mBounds.w;
708
185
    for (int x = 1; x < endX; x++)
709
    {
710
155
        tilePtr ++;
711
155
        const Image *const img = tilePtr->image;
712

258
        if (img == nullptr ||
713
103
            tilePtr->isEnabled == false)
714
        {
715
            break;
716
        }
717
99
        if (img != img1)
718
        {
719
45
            nextTile = c;
720
            BLOCK_END("MapLayer::getTileDrawWidth")
721
45
            return c;
722
        }
723
54
        c ++;
724
54
        width += img->mBounds.w;
725
    }
726
86
    int c2 = c;
727
1789
    for (int x2 = c2 + 1; x2 < endX; x2++)
728
    {
729

1924
        if (tilePtr->image != nullptr &&
730
198
            tilePtr->isEnabled == true)
731
        {
732
            break;
733
        }
734
1703
        c2 ++;
735
1703
        tilePtr ++;
736
    }
737
86
    nextTile = c2;
738
    BLOCK_END("MapLayer::getTileDrawWidth")
739
86
    return c;
740
}
741
742
10
int MapLayer::getEmptyTileDrawWidth(const TileInfo *restrict tilePtr,
743
                                    const int endX,
744
                                    int &restrict nextTile)
745
{
746
    BLOCK_START("MapLayer::getEmptyTileDrawWidth")
747
79964
    int c = 0;
748

4024412
    for (int x = 1; x < endX; x++)
749
    {
750
3944620
        tilePtr ++;
751
3944620
        const Image *const img = tilePtr->image;
752


3944620
        if (img != nullptr && tilePtr->isEnabled == true)
753
            break;
754
3944448
        c ++;
755
    }
756
    BLOCK_END("MapLayer::getEmptyTileDrawWidth")
757
758
79964
    nextTile = c;
759
10
    return c;
760
}
761
762
6
void MapLayer::updateConditionTiles(const MetaTile *const metaTiles,
763
                                    const int width,
764
                                    const int height) restrict
765
{
766
6
    const int width1 = width < mWidth ? width : mWidth;
767
6
    const int height1 = height < mHeight ? height : mHeight;
768
769
808
    for (int y = mY; y < height1; y ++)
770
    {
771
802
        const MetaTile *metaPtr = metaTiles + (y - mY) * width;
772
802
        TileInfo *tilePtr = mTiles + y * mWidth;
773
80804
        for (int x = mX; x < width1; x ++, metaPtr ++, tilePtr ++)
774
        {
775

100012
            if (tilePtr->image != nullptr &&
776
40013
                (((metaPtr->blockmask & mTileCondition) != 0) ||
777
20003
                (metaPtr->blockmask == 0 &&
778
                mTileCondition == BlockMask::GROUND)))
779
            {
780
7
                tilePtr->isEnabled = true;
781
            }
782
            else
783
            {
784
79995
                tilePtr->isEnabled = false;
785
            }
786
        }
787
    }
788
6
}
789
790
32
void MapLayer::updateCache(const int width,
791
                           const int height) restrict
792
{
793
32
    const int width1 = width < mWidth ? width : mWidth;
794
32
    const int height1 = height < mHeight ? height : mHeight;
795
796
856
    for (int y = mY; y < height1; y ++)
797
    {
798
80881
        for (int x = mX; x < width1; x ++)
799
        {
800
80057
            TileInfo *tilePtr = mTiles + y * mWidth + x;
801
80057
            int nextTile = 0;
802

80057
            if (tilePtr->image == nullptr || tilePtr->isEnabled == false)
803
            {
804
79954
                tilePtr->isEnabled = false;
805
159908
                tilePtr->count = getEmptyTileDrawWidth(tilePtr,
806
                    width1 - x,
807
                    nextTile);
808
79954
                tilePtr->width = 0;
809
            }
810
            else
811
            {
812
103
                int tileWidth = 0;
813
103
                tilePtr->count = getTileDrawWidth(tilePtr,
814
                    width1 - x,
815
                    tileWidth,
816
                    nextTile);
817
103
                tilePtr->width = tileWidth;
818
            }
819
80057
            tilePtr->nextTile = nextTile;
820
        }
821
    }
822
32
}
823
824
int MapLayer::calcMemoryLocal() const
825
{
826
    return static_cast<int>(sizeof(MapLayer) +
827
        sizeof(TileInfo) * mWidth * mHeight +
828
        sizeof(MapRowVertexes) * mTempRows.capacity());
829
}
830
831
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
2
}