GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/resources/map/maplayer.cpp Lines: 203 395 51.4 %
Date: 2018-11-12 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-2018  The ManaPlus Developers
6
 *
7
 *  This file is part of The ManaPlus Client.
8
 *
9
 *  This program is free software; you can redistribute it and/or modify
10
 *  it under the terms of the GNU General Public License as published by
11
 *  the Free Software Foundation; either version 2 of the License, or
12
 *  any later version.
13
 *
14
 *  This program is distributed in the hope that it will be useful,
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 *  GNU General Public License for more details.
18
 *
19
 *  You should have received a copy of the GNU General Public License
20
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
#include "resources/map/maplayer.h"
24
25
#include "configuration.h"
26
27
#include "being/localplayer.h"
28
29
#include "enums/resources/map/blockmask.h"
30
#include "enums/resources/map/mapitemtype.h"
31
32
#include "gui/userpalette.h"
33
34
#ifdef USE_OPENGL
35
#include "utils/foreach.h"
36
#endif  // USE_OPENGL
37
38
#include "render/graphics.h"
39
40
#include "resources/image/image.h"
41
42
#include "resources/map/mapitem.h"
43
#include "resources/map/maprowvertexes.h"
44
#include "resources/map/metatile.h"
45
#include "resources/map/speciallayer.h"
46
47
#include "debug.h"
48
49
69
MapLayer::MapLayer(const std::string &name,
50
                   const int x,
51
                   const int y,
52
                   const int width,
53
                   const int height,
54
                   const bool fringeLayer,
55
                   const int mask,
56
69
                   const int tileCondition) :
57
    mX(x),
58
    mY(y),
59
69
    mPixelX(mX * mapTileSize),
60
69
    mPixelY(mY * mapTileSize + mapTileSize),
61
    mWidth(width),
62
    mHeight(height),
63

190191
    mTiles(new TileInfo[mWidth * mHeight]),
64
    mDrawLayerFlags(MapType::NORMAL),
65
    mSpecialLayer(nullptr),
66
    mTempLayer(nullptr),
67
    mName(name),
68
    mTempRows(),
69
    mMask(mask),
70
    mTileCondition(tileCondition),
71
    mActorsFix(0),
72
    mIsFringeLayer(fringeLayer),
73

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

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

40
            if (mSpecialFlag ||
154
                img->mBounds.h <= mapTileSize)
155
            {
156
40
                if (tilePtr->count == 0)
157
                {
158
28
                    graphics->drawImage(img, px, py);
159
                }
160
                else
161
                {
162
12
                    graphics->drawPattern(img,
163
                        px,
164
                        py,
165
                        tilePtr->width,
166
24
                        img->mBounds.h);
167
                }
168
            }
169
170
40
            const int nextTile = tilePtr->nextTile;
171
40
            x += nextTile;
172
40
            tilePtr += nextTile;
173
        }
174
    }
175
    BLOCK_END("MapLayer::draw")
176
22
}
177
178
void MapLayer::drawSDL(Graphics *const graphics) const restrict2
179
{
180
    BLOCK_START("MapLayer::drawSDL")
181
    MapRows::const_iterator rit = mTempRows.begin();
182
    const MapRows::const_iterator rit_end = mTempRows.end();
183
    while (rit != rit_end)
184
    {
185
        MapRowImages *const images = &(*rit)->images;
186
        MapRowImages::const_iterator iit = images->begin();
187
        const MapRowImages::const_iterator iit_end = images->end();
188
        while (iit != iit_end)
189
        {
190
            graphics->drawTileVertexes(*iit);
191
            ++ iit;
192
        }
193
        ++ rit;
194
    }
195
    BLOCK_END("MapLayer::drawSDL")
196
}
197
198
#ifdef USE_OPENGL
199
void MapLayer::updateSDL(const Graphics *const graphics,
200
                         int startX,
201
                         int startY,
202
                         int endX,
203
                         int endY,
204
                         const int scrollX,
205
                         const int scrollY) restrict2
206
{
207
    BLOCK_START("MapLayer::updateSDL")
208
    delete_all(mTempRows);
209
    mTempRows.clear();
210
211
    startX -= mX;
212
    startY -= mY;
213
    endX -= mX;
214
    endY -= mY;
215
216
    if (startX < 0)
217
        startX = 0;
218
    if (startY < 0)
219
        startY = 0;
220
    if (endX > mWidth)
221
        endX = mWidth;
222
    if (endY > mHeight)
223
        endY = mHeight;
224
225
    const int dx = mPixelX - scrollX;
226
    const int dy = mPixelY - scrollY;
227
228
    for (int y = startY; y < endY; y++)
229
    {
230
        MapRowVertexes *const row = new MapRowVertexes;
231
        mTempRows.push_back(row);
232
233
        const Image *lastImage = nullptr;
234
        ImageVertexes *imgVert = nullptr;
235
236
        const int yWidth = y * mWidth;
237
        const int py0 = y * mapTileSize + dy;
238
        TileInfo *tilePtr = &mTiles[CAST_SIZE(startX + yWidth)];
239
240
        for (int x = startX; x < endX; x++, tilePtr++)
241
        {
242
            if (!tilePtr->isEnabled)
243
                continue;
244
            Image *const img = (*tilePtr).image;
245
            const int px = x * mapTileSize + dx;
246
            const int py = py0 - img->mBounds.h;
247
            if (mSpecialFlag ||
248
                img->mBounds.h <= mapTileSize)
249
            {
250
                if (lastImage != img)
251
                {
252
                    imgVert = new ImageVertexes;
253
                    imgVert->image = img;
254
                    row->images.push_back(imgVert);
255
                    lastImage = img;
256
                }
257
                graphics->calcTileSDL(imgVert, px, py);
258
            }
259
        }
260
    }
261
    BLOCK_END("MapLayer::updateSDL")
262
}
263
264
void MapLayer::updateOGL(Graphics *const graphics,
265
                         int startX,
266
                         int startY,
267
                         int endX,
268
                         int endY,
269
                         const int scrollX,
270
                         const int scrollY) restrict2
271
{
272
    BLOCK_START("MapLayer::updateOGL")
273
    delete_all(mTempRows);
274
    mTempRows.clear();
275
276
    startX -= mX;
277
    startY -= mY;
278
    endX -= mX;
279
    endY -= mY;
280
281
    if (startX < 0)
282
        startX = 0;
283
    if (startY < 0)
284
        startY = 0;
285
    if (endX > mWidth)
286
        endX = mWidth;
287
    if (endY > mHeight)
288
        endY = mHeight;
289
290
    const int dx = mPixelX - scrollX;
291
    const int dy = mPixelY - scrollY;
292
293
    MapRowVertexes *const row = new MapRowVertexes;
294
    mTempRows.push_back(row);
295
    Image *lastImage = nullptr;
296
    ImageVertexes *imgVert = nullptr;
297
    typedef std::map<int, ImageVertexes*> ImageVertexesMap;
298
    ImageVertexesMap imgSet;
299
300
    for (int y = startY; y < endY; y++)
301
    {
302
        const int yWidth = y * mWidth;
303
        const int py0 = y * mapTileSize + dy;
304
        TileInfo *tilePtr = &mTiles[CAST_SIZE(startX + yWidth)];
305
        for (int x = startX; x < endX; x++, tilePtr++)
306
        {
307
            if (!tilePtr->isEnabled)
308
                continue;
309
            Image *const img = (*tilePtr).image;
310
            const int px = x * mapTileSize + dx;
311
            const int py = py0 - img->mBounds.h;
312
            const GLuint imgGlImage = img->mGLImage;
313
            if (mSpecialFlag ||
314
                img->mBounds.h <= mapTileSize)
315
            {
316
                if ((lastImage == nullptr) ||
317
                    lastImage->mGLImage != imgGlImage)
318
                {
319
                    if (img->mBounds.w > mapTileSize)
320
                        imgSet.clear();
321
322
                    if (imgSet.find(imgGlImage) != imgSet.end())
323
                    {
324
                        imgVert = imgSet[imgGlImage];
325
                    }
326
                    else
327
                    {
328
                        if (lastImage != nullptr)
329
                            imgSet[lastImage->mGLImage] = imgVert;
330
                        imgVert = new ImageVertexes;
331
                        imgVert->ogl.init();
332
                        imgVert->image = img;
333
                        row->images.push_back(imgVert);
334
                    }
335
                }
336
                lastImage = img;
337
                graphics->calcTileVertexes(imgVert, lastImage, px, py);
338
            }
339
        }
340
    }
341
    FOR_EACH (MapRowImages::iterator, it, row->images)
342
    {
343
        graphics->finalize(*it);
344
    }
345
    BLOCK_END("MapLayer::updateOGL")
346
}
347
348
void MapLayer::drawOGL(Graphics *const graphics) const restrict2
349
{
350
    BLOCK_START("MapLayer::drawOGL")
351
    MapRows::const_iterator rit = mTempRows.begin();
352
    const MapRows::const_iterator rit_end = mTempRows.end();
353
    while (rit != rit_end)
354
    {
355
        const MapRowImages *const images = &(*rit)->images;
356
        MapRowImages::const_iterator iit = images->begin();
357
        const MapRowImages::const_iterator iit_end = images->end();
358
        while (iit != iit_end)
359
        {
360
            graphics->drawTileVertexes(*iit);
361
            ++ iit;
362
        }
363
        ++ rit;
364
    }
365
    BLOCK_END("MapLayer::drawOGL")
366
}
367
#endif  // USE_OPENGL
368
369
892
void MapLayer::drawSpecialLayer(Graphics *const graphics,
370
                                const int y,
371
                                const int startX,
372
                                const int endX,
373
                                const int scrollX,
374
                                const int scrollY) const restrict
375
{
376
892
    const int y32 = y * mapTileSize;
377
892
    const int py1 = y32 - scrollY;
378
892
    int endX1 = endX;
379
892
    int specialWidth = mSpecialLayer->mWidth;
380
892
    int ptr = y * specialWidth;
381
892
    if (endX1 > specialWidth)
382
        endX1 = specialWidth;
383
892
    if (endX1 < 0)
384
        endX1 = 0;
385
892
    int x0 = startX;
386
892
    const MapItem *item0 = mSpecialLayer->mTiles[ptr + startX];
387

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

892
    if ((item0 == nullptr) || item0->mType == MapItemType::EMPTY)
411
    {
412
885
        x0 += mTempLayer->mCache[ptr + startX] + 1;
413
    }
414
928
    for (int x = x0; x < endX1; x++)
415
    {
416
18
        const int px1 = x * mapTileSize - scrollX;
417
18
        const MapItem *const item = mTempLayer->mTiles[ptr + x];
418
        item->draw(graphics, px1, py1,
419
18
            mapTileSize, mapTileSize);
420
18
        x += mTempLayer->mCache[ptr + x];
421
    }
422
892
}
423
424
26
void MapLayer::drawFringe(Graphics *const graphics,
425
                          int startX,
426
                          int startY,
427
                          int endX,
428
                          int endY,
429
                          const int scrollX,
430
                          const int scrollY,
431
                          const Actors &actors) const restrict
432
{
433
    BLOCK_START("MapLayer::drawFringe")
434

52
    if ((localPlayer == nullptr) ||
435
52
        (mSpecialLayer == nullptr) ||
436
26
        (mTempLayer == nullptr))
437
    {
438
        BLOCK_END("MapLayer::drawFringe")
439
        return;
440
    }
441
442
26
    startX -= mX;
443
26
    startY -= mY;
444
26
    endX -= mX;
445
26
    endY -= mY;
446
447
26
    if (startX < 0)
448
        startX = 0;
449
26
    if (startY < 0)
450
        startY = 0;
451
26
    if (endX > mWidth)
452
        endX = mWidth;
453
26
    if (endY > mHeight)
454
        endY = mHeight;
455
456
52
    ActorsCIter ai = actors.begin();
457
26
    const ActorsCIter ai_end = actors.end();
458
459
26
    const int dx = mPixelX - scrollX;
460
26
    const int dy = mPixelY - scrollY;
461
462
26
    const int specialHeight = mSpecialLayer->mHeight;
463
464
26
    const bool flag = mDrawLayerFlags == MapType::SPECIAL3 ||
465
26
        mDrawLayerFlags == MapType::SPECIAL4 ||
466
26
        mDrawLayerFlags == MapType::BLACKWHITE;
467
468
26
    const int minEndY = std::min(specialHeight, endY);
469
470
26
    if (flag)
471
    {   // flag
472
        for (int y = startY; y < minEndY; y ++)
473
        {
474
            const int y32s = (y + mActorsFix) * mapTileSize;
475
476
            BLOCK_START("MapLayer::drawFringe drawmobs")
477
            // If drawing the fringe layer, make sure all actors above this
478
            // row of tiles have been drawn
479
            while (ai != ai_end && (*ai)->getSortPixelY() <= y32s)
480
            {
481
                (*ai)->draw(graphics, -scrollX, -scrollY);
482
                ++ ai;
483
            }
484
            BLOCK_END("MapLayer::drawFringe drawmobs")
485
486
            // remove this condition, because it always true
487
            if (y < specialHeight)
488
            {
489
                drawSpecialLayer(graphics,
490
                    y,
491
                    startX,
492
                    endX,
493
                    scrollX,
494
                    scrollY);
495
            }
496
        }
497
498
        for (int y = minEndY; y < endY; y++)
499
        {
500
            const int y32s = (y + mActorsFix) * mapTileSize;
501
502
            BLOCK_START("MapLayer::drawFringe drawmobs")
503
            // If drawing the fringe layer, make sure all actors above this
504
            // row of tiles have been drawn
505
            while (ai != ai_end && (*ai)->getSortPixelY() <= y32s)
506
            {
507
                (*ai)->draw(graphics, -scrollX, -scrollY);
508
                ++ ai;
509
            }
510
            BLOCK_END("MapLayer::drawFringe drawmobs")
511
        }
512
    }
513
    else
514
    {   // !flag
515
1662
        for (int y = startY; y < minEndY; y ++)
516
        {
517
818
            const int y32 = y * mapTileSize;
518
818
            const int y32s = (y + mActorsFix) * mapTileSize;
519
818
            const int yWidth = y * mWidth;
520
521
            BLOCK_START("MapLayer::drawFringe drawmobs")
522
            // If drawing the fringe layer, make sure all actors above this
523
            // row of tiles have been drawn
524

818
            while (ai != ai_end &&
525
                   (*ai)->getSortPixelY() <= y32s)
526
            {
527
                (*ai)->draw(graphics, -scrollX, -scrollY);
528
                ++ ai;
529
            }
530
            BLOCK_END("MapLayer::drawFringe drawmobs")
531
532
818
            const int py0 = y32 + dy;
533
534
818
            int x0 = startX;
535
818
            TileInfo *tilePtr = &mTiles[CAST_SIZE(x0 + yWidth)];
536
818
            if (tilePtr->isEnabled == false)
537
            {
538
802
                drawSpecialLayer(graphics,
539
                    y,
540
                    0,
541
2406
                    std::min(x0 + tilePtr->nextTile + 1, endX),
542
                    scrollX,
543
802
                    scrollY);
544
802
                if (x0 + tilePtr->nextTile + 1 >= endX)
545
                {
546
                    continue;
547
                }
548
10
                x0 += tilePtr->nextTile + 1;
549
10
                tilePtr = &mTiles[CAST_SIZE(x0 + yWidth)];
550
10
                if (mTiles[x0 + yWidth].isEnabled == false)
551
                    continue;
552
            }
553
154
            for (int x = x0; x < endX; x++, tilePtr++)
554
            {
555
64
                const int x32 = x * mapTileSize;
556
64
                const Image *const img = tilePtr->image;
557

64
                if (mSpecialFlag ||
558
                    img->mBounds.h <= mapTileSize)
559
                {
560
64
                    const int px = x32 + dx;
561
64
                    const int py = py0 - img->mBounds.h;
562
563
64
                    if (tilePtr->count == 0)
564
                    {
565
40
                        graphics->drawImage(img, px, py);
566
                    }
567
                    else
568
                    {
569
24
                        graphics->drawPattern(img,
570
                            px,
571
                            py,
572
                            tilePtr->width,
573
48
                            img->mBounds.h);
574
                    }
575
                }
576
577
64
                const int nextTile = tilePtr->nextTile;
578
                // remove this condition, because it always true
579
64
                if (y < specialHeight)
580
                {
581
64
                    drawSpecialLayer(graphics,
582
                        y,
583
                        x,
584
192
                        std::min(x + nextTile + 1, endX),
585
                        scrollX,
586
64
                        scrollY);
587
                }
588
64
                x += nextTile;
589
64
                tilePtr += nextTile;
590
            }
591
        }
592
593
26
        for (int y = minEndY; y < endY; y++)
594
        {
595
            const int y32 = y * mapTileSize;
596
            const int y32s = (y + mActorsFix) * mapTileSize;
597
            const int yWidth = y * mWidth;
598
599
            BLOCK_START("MapLayer::drawFringe drawmobs")
600
            // If drawing the fringe layer, make sure all actors above this
601
            // row of tiles have been drawn
602
            while (ai != ai_end && (*ai)->getSortPixelY() <= y32s)
603
            {
604
                (*ai)->draw(graphics, -scrollX, -scrollY);
605
                ++ ai;
606
            }
607
            BLOCK_END("MapLayer::drawFringe drawmobs")
608
609
            const int py0 = y32 + dy;
610
611
            int x0 = startX;
612
            TileInfo *tilePtr = &mTiles[CAST_SIZE(x0 + yWidth)];
613
            if (tilePtr->isEnabled == false)
614
            {
615
                if (x0 + tilePtr->nextTile + 1 >= endX)
616
                    continue;
617
                x0 += tilePtr->nextTile + 1;
618
                tilePtr = &mTiles[CAST_SIZE(x0 + yWidth)];
619
                if (mTiles[x0 + yWidth].isEnabled == false)
620
                    continue;
621
            }
622
            for (int x = x0; x < endX; x++, tilePtr++)
623
            {
624
                const int x32 = x * mapTileSize;
625
                const Image *const img = tilePtr->image;
626
                const int px = x32 + dx;
627
                const int py = py0 - img->mBounds.h;
628
                if (mSpecialFlag ||
629
                    img->mBounds.h <= mapTileSize)
630
                {
631
                    const int c = tilePtr->count;
632
633
                    if (c == 0)
634
                    {
635
                        graphics->drawImage(img, px, py);
636
                    }
637
                    else
638
                    {
639
                        graphics->drawPattern(img,
640
                            px,
641
                            py,
642
                            tilePtr->width,
643
                            img->mBounds.h);
644
                    }
645
                }
646
                const int nextTile = tilePtr->nextTile;
647
                x += nextTile;
648
                tilePtr += nextTile;
649
            }
650
        }
651
    }  // !flag
652
653
    // Draw any remaining actors
654
26
    if (mDrawLayerFlags != MapType::SPECIAL3 &&
655
        mDrawLayerFlags != MapType::SPECIAL4)
656
    {
657
        BLOCK_START("MapLayer::drawFringe drawmobs")
658
26
        while (ai != ai_end)
659
        {
660
            (*ai)->draw(graphics, -scrollX, -scrollY);
661
            ++ai;
662
        }
663
        BLOCK_END("MapLayer::drawFringe drawmobs")
664
26
        if (mHighlightAttackRange)
665
        {
666
            const int px = localPlayer->getPixelX()
667
                - scrollX - mapTileSize / 2;
668
            const int py = localPlayer->getPixelY() - scrollY - mapTileSize;
669
            const int attackRange = localPlayer->getAttackRange()
670
                * mapTileSize;
671
672
            int x = px - attackRange;
673
            int y = py - attackRange;
674
            int w = 2 * attackRange + mapTileSize;
675
            int h = w;
676
            if (attackRange <= mapTileSize)
677
            {
678
                x -= mapTileSize / 2;
679
                y -= mapTileSize / 2;
680
                w += mapTileSize;
681
                h += mapTileSize;
682
            }
683
684
            if (userPalette != nullptr)
685
            {
686
                graphics->setColor(userPalette->getColorWithAlpha(
687
                    UserColorId::ATTACK_RANGE));
688
                graphics->fillRectangle(Rect(x, y, w, h));
689
                graphics->setColor(userPalette->getColorWithAlpha(
690
                    UserColorId::ATTACK_RANGE_BORDER));
691
                graphics->drawRectangle(Rect(x, y, w, h));
692
            }
693
        }
694
    }
695
    BLOCK_END("MapLayer::drawFringe")
696
}
697
698
131
int MapLayer::getTileDrawWidth(const TileInfo *restrict tilePtr,
699
                               const int endX,
700
                               int &restrict width,
701
                               int &restrict nextTile)
702
{
703
    BLOCK_START("MapLayer::getTileDrawWidth")
704
131
    const Image *const img1 = tilePtr->image;
705
131
    int c = 0;
706
131
    width = img1->mBounds.w;
707
185
    for (int x = 1; x < endX; x++)
708
    {
709
155
        tilePtr ++;
710
155
        const Image *const img = tilePtr->image;
711

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

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

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


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

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

80057
            if (tilePtr->image == nullptr || tilePtr->isEnabled == false)
802
            {
803
79954
                tilePtr->isEnabled = false;
804
159908
                tilePtr->count = getEmptyTileDrawWidth(tilePtr,
805
                    width1 - x,
806
                    nextTile);
807
79954
                tilePtr->width = 0;
808
            }
809
            else
810
            {
811
103
                int tileWidth = 0;
812
103
                tilePtr->count = getTileDrawWidth(tilePtr,
813
                    width1 - x,
814
                    tileWidth,
815
                    nextTile);
816
103
                tilePtr->width = tileWidth;
817
            }
818
80057
            tilePtr->nextTile = nextTile;
819
        }
820
    }
821
32
}
822
823
int MapLayer::calcMemoryLocal() const
824
{
825
    return static_cast<int>(sizeof(MapLayer) +
826
        sizeof(TileInfo) * mWidth * mHeight +
827
        sizeof(MapRowVertexes) * mTempRows.capacity());
828
}
829
830
int MapLayer::calcMemoryChilds(const int level) const
831
{
832
    int sz = 0;
833
    if (mSpecialLayer != nullptr)
834
        sz += mSpecialLayer->calcMemory(level + 1);
835
    if (mTempLayer != nullptr)
836
        sz += mTempLayer->calcMemory(level + 1);
837
    return sz;
838
2
}