GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/resources/map/maplayer.cpp Lines: 205 407 50.4 %
Date: 2017-11-29 Branches: 112 286 39.2 %

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-2017  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
138
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
138
                   const int tileCondition) :
57
    mX(x),
58
    mY(y),
59
138
    mPixelX(mX * mapTileSize),
60
138
    mPixelY(mY * mapTileSize + mapTileSize),
61
    mWidth(width),
62
    mHeight(height),
63

380382
    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

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

552
    config.addListener("highlightAttackRange", this);
79
138
}
80
81
690
MapLayer::~MapLayer()
82
{
83
552
    config.removeListener("highlightAttackRange", this);
84
    CHECKLISTENERS
85
138
    delete []mTiles;
86
276
    delete_all(mTempRows);
87
276
    mTempRows.clear();
88
276
}
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
100400
void MapLayer::setTile(const int x,
100
                       const int y,
101
                       Image *const img) restrict
102
{
103
100400
    mTiles[x + y * mWidth].image = img;
104
100400
}
105
106
44
void MapLayer::draw(Graphics *const graphics,
107
                    int startX,
108
                    int startY,
109
                    int endX,
110
                    int endY,
111
                    const int scrollX,
112
                    const int scrollY) const restrict
113
{
114
    BLOCK_START("MapLayer::draw")
115
44
    startX -= mX;
116
44
    startY -= mY;
117
44
    endX -= mX;
118
44
    endY -= mY;
119
120
44
    if (startX < 0)
121
        startX = 0;
122
44
    if (startY < 0)
123
        startY = 0;
124
44
    if (endX > mWidth)
125
        endX = mWidth;
126
44
    if (endY > mHeight)
127
        endY = mHeight;
128
129
44
    const int dx = mPixelX - scrollX;
130
44
    const int dy = mPixelY - scrollY;
131
880
    for (int y = startY; y < endY; y++)
132
    {
133
836
        const int y32 = y * mapTileSize;
134
836
        const int yWidth = y * mWidth;
135
136
836
        const int py0 = y32 + dy;
137
138
836
        int x0 = startX;
139
836
        TileInfo *tilePtr = &mTiles[CAST_SIZE(x0 + yWidth)];
140
836
        if (tilePtr->isEnabled == false)
141
        {
142
804
            if (x0 + tilePtr->nextTile + 1 >= endX)
143
            {
144
792
                continue;
145
            }
146
12
            x0 += tilePtr->nextTile + 1;
147
12
            tilePtr = &mTiles[CAST_SIZE(x0 + yWidth)];
148
12
            if (mTiles[x0 + yWidth].isEnabled == false)
149
            {
150
                continue;
151
            }
152
        }
153
204
        for (int x = x0; x < endX; x++, tilePtr++)
154
        {
155
80
            const int x32 = x * mapTileSize;
156
157
80
            const Image *const img = tilePtr->image;
158
80
            const int px = x32 + dx;
159
80
            const int py = py0 - img->mBounds.h;
160

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

1784
    if ((item0 == nullptr) || item0->mType == MapItemType::EMPTY)
395
    {
396
1762
        x0 += mSpecialLayer->mCache[ptr + startX] + 1;
397
    }
398
1888
    for (int x = x0; x < endX1; x++)
399
    {
400
52
        const int px1 = x * mapTileSize - scrollX;
401
52
        const MapItem *const item = mSpecialLayer->mTiles[ptr + x];
402
52
        if (item != nullptr)
403
        {
404
52
            item->draw(graphics, px1, py1,
405
                mapTileSize, mapTileSize);
406
        }
407
52
        x += mSpecialLayer->mCache[ptr + x];
408
    }
409
410
1784
    x0 = startX;
411
1784
    specialWidth = mTempLayer->mWidth;
412
1784
    ptr = y * specialWidth;
413
1784
    endX1 = endX;
414
1784
    if (endX1 > specialWidth)
415
        endX1 = specialWidth;
416
1784
    item0 = mTempLayer->mTiles[ptr + startX];
417

1784
    if ((item0 == nullptr) || item0->mType == MapItemType::EMPTY)
418
    {
419
1770
        x0 += mTempLayer->mCache[ptr + startX] + 1;
420
    }
421
1856
    for (int x = x0; x < endX1; x++)
422
    {
423
36
        const int px1 = x * mapTileSize - scrollX;
424
36
        const MapItem *const item = mTempLayer->mTiles[ptr + x];
425
36
        item->draw(graphics, px1, py1,
426
            mapTileSize, mapTileSize);
427
36
        x += mTempLayer->mCache[ptr + x];
428
    }
429
1784
}
430
431
52
void MapLayer::drawFringe(Graphics *const graphics,
432
                          int startX,
433
                          int startY,
434
                          int endX,
435
                          int endY,
436
                          const int scrollX,
437
                          const int scrollY,
438
                          const Actors &actors) const restrict
439
{
440
    BLOCK_START("MapLayer::drawFringe")
441

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

1636
            while (ai != ai_end &&
532
                   (*ai)->getSortPixelY() <= y32s)
533
            {
534
                (*ai)->draw(graphics, -scrollX, -scrollY);
535
                ++ ai;
536
            }
537
            BLOCK_END("MapLayer::drawFringe drawmobs")
538
539
1636
            const int py0 = y32 + dy;
540
541
1636
            int x0 = startX;
542
1636
            TileInfo *tilePtr = &mTiles[CAST_SIZE(x0 + yWidth)];
543
1636
            if (tilePtr->isEnabled == false)
544
            {
545
1604
                drawSpecialLayer(graphics,
546
                    y,
547
                    0,
548
4812
                    std::min(x0 + tilePtr->nextTile + 1, endX),
549
                    scrollX,
550
                    scrollY);
551
1604
                if (x0 + tilePtr->nextTile + 1 >= endX)
552
                {
553
1584
                    continue;
554
                }
555
20
                x0 += tilePtr->nextTile + 1;
556
20
                tilePtr = &mTiles[CAST_SIZE(x0 + yWidth)];
557
20
                if (mTiles[x0 + yWidth].isEnabled == false)
558
                    continue;
559
            }
560
308
            for (int x = x0; x < endX; x++, tilePtr++)
561
            {
562
128
                const int x32 = x * mapTileSize;
563
128
                const Image *const img = tilePtr->image;
564

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

516
        if (img == nullptr ||
719
206
            tilePtr->isEnabled == false)
720
        {
721
            break;
722
        }
723
198
        if (img != img1)
724
        {
725
90
            nextTile = c;
726
            BLOCK_END("MapLayer::getTileDrawWidth")
727
90
            return c;
728
        }
729
108
        c ++;
730
108
        width += img->mBounds.w;
731
    }
732
172
    int c2 = c;
733
3578
    for (int x2 = c2 + 1; x2 < endX; x2++)
734
    {
735

3848
        if (tilePtr->image != nullptr &&
736
396
            tilePtr->isEnabled == true)
737
        {
738
            break;
739
        }
740
3406
        c2 ++;
741
3406
        tilePtr ++;
742
    }
743
172
    nextTile = c2;
744
    BLOCK_END("MapLayer::getTileDrawWidth")
745
172
    return c;
746
}
747
748
20
int MapLayer::getEmptyTileDrawWidth(const TileInfo *restrict tilePtr,
749
                                    const int endX,
750
                                    int &restrict nextTile)
751
{
752
    BLOCK_START("MapLayer::getEmptyTileDrawWidth")
753
159928
    int c = 0;
754

8048824
    for (int x = 1; x < endX; x++)
755
    {
756
7889240
        tilePtr ++;
757
7889240
        const Image *const img = tilePtr->image;
758


7889240
        if (img != nullptr && tilePtr->isEnabled == true)
759
            break;
760
7888896
        c ++;
761
    }
762
    BLOCK_END("MapLayer::getEmptyTileDrawWidth")
763
764
159928
    nextTile = c;
765
20
    return c;
766
}
767
768
void MapLayer::setDrawLayerFlags(const MapTypeT &n) restrict
769
{
770
    mDrawLayerFlags = n;
771
    mSpecialFlag = (mDrawLayerFlags != MapType::SPECIAL &&
772
        mDrawLayerFlags != MapType::SPECIAL2 &&
773
        mDrawLayerFlags != MapType::SPECIAL4);
774
}
775
776
12
void MapLayer::updateConditionTiles(const MetaTile *const metaTiles,
777
                                    const int width,
778
                                    const int height) restrict
779
{
780
12
    const int width1 = width < mWidth ? width : mWidth;
781
12
    const int height1 = height < mHeight ? height : mHeight;
782
783
1616
    for (int y = mY; y < height1; y ++)
784
    {
785
1604
        const MetaTile *metaPtr = metaTiles + (y - mY) * width;
786
1604
        TileInfo *tilePtr = mTiles + y * mWidth;
787
161608
        for (int x = mX; x < width1; x ++, metaPtr ++, tilePtr ++)
788
        {
789

200024
            if (tilePtr->image != nullptr &&
790
80026
                (((metaPtr->blockmask & mTileCondition) != 0) ||
791
40006
                (metaPtr->blockmask == 0 &&
792
                mTileCondition == BlockMask::GROUND)))
793
            {
794
14
                tilePtr->isEnabled = true;
795
            }
796
            else
797
            {
798
159990
                tilePtr->isEnabled = false;
799
            }
800
        }
801
    }
802
12
}
803
804
64
void MapLayer::updateCache(const int width,
805
                           const int height) restrict
806
{
807
64
    const int width1 = width < mWidth ? width : mWidth;
808
64
    const int height1 = height < mHeight ? height : mHeight;
809
810
1712
    for (int y = mY; y < height1; y ++)
811
    {
812
161762
        for (int x = mX; x < width1; x ++)
813
        {
814
160114
            TileInfo *tilePtr = mTiles + y * mWidth + x;
815
160114
            int nextTile = 0;
816

160114
            if (tilePtr->image == nullptr || tilePtr->isEnabled == false)
817
            {
818
159908
                tilePtr->isEnabled = false;
819
319816
                tilePtr->count = getEmptyTileDrawWidth(tilePtr,
820
                    width1 - x,
821
                    nextTile);
822
159908
                tilePtr->width = 0;
823
            }
824
            else
825
            {
826
206
                int tileWidth = 0;
827
206
                tilePtr->count = getTileDrawWidth(tilePtr,
828
                    width1 - x,
829
                    tileWidth,
830
                    nextTile);
831
206
                tilePtr->width = tileWidth;
832
            }
833
160114
            tilePtr->nextTile = nextTile;
834
        }
835
    }
836
64
}
837
838
int MapLayer::calcMemoryLocal() const
839
{
840
    return static_cast<int>(sizeof(MapLayer) +
841
        sizeof(TileInfo) * mWidth * mHeight +
842
        sizeof(MapRowVertexes) * mTempRows.capacity());
843
}
844
845
int MapLayer::calcMemoryChilds(const int level) const
846
{
847
    int sz = 0;
848
    if (mSpecialLayer != nullptr)
849
        sz += mSpecialLayer->calcMemory(level + 1);
850
    if (mTempLayer != nullptr)
851
        sz += mTempLayer->calcMemory(level + 1);
852
    return sz;
853
4
}