GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/resources/map/maplayer.cpp Lines: 206 402 51.2 %
Date: 2018-09-20 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
50200
void MapLayer::setTile(const int x,
100
                       const int y,
101
                       Image *const img) restrict
102
{
103
50200
    mTiles[x + y * mWidth].image = img;
104
50200
}
105
106
22
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
22
    startX -= mX;
116
22
    startY -= mY;
117
22
    endX -= mX;
118
22
    endY -= mY;
119
120
22
    if (startX < 0)
121
        startX = 0;
122
22
    if (startY < 0)
123
        startY = 0;
124
22
    if (endX > mWidth)
125
        endX = mWidth;
126
22
    if (endY > mHeight)
127
        endY = mHeight;
128
129
22
    const int dx = mPixelX - scrollX;
130
22
    const int dy = mPixelY - scrollY;
131
440
    for (int y = startY; y < endY; y++)
132
    {
133
418
        const int y32 = y * mapTileSize;
134
418
        const int yWidth = y * mWidth;
135
136
418
        const int py0 = y32 + dy;
137
138
418
        int x0 = startX;
139
418
        TileInfo *tilePtr = &mTiles[CAST_SIZE(x0 + yWidth)];
140
418
        if (tilePtr->isEnabled == false)
141
        {
142
402
            if (x0 + tilePtr->nextTile + 1 >= endX)
143
            {
144
                continue;
145
            }
146
6
            x0 += tilePtr->nextTile + 1;
147
6
            tilePtr = &mTiles[CAST_SIZE(x0 + yWidth)];
148
6
            if (mTiles[x0 + yWidth].isEnabled == false)
149
            {
150
                continue;
151
            }
152
        }
153
102
        for (int x = x0; x < endX; x++, tilePtr++)
154
        {
155
40
            const int x32 = x * mapTileSize;
156
157
40
            const Image *const img = tilePtr->image;
158
40
            const int px = x32 + dx;
159
40
            const int py = py0 - img->mBounds.h;
160

40
            if (mSpecialFlag ||
161
                img->mBounds.h <= mapTileSize)
162
            {
163
40
                if (tilePtr->count == 0)
164
                {
165
28
                    graphics->drawImage(img, px, py);
166
                }
167
                else
168
                {
169
12
                    graphics->drawPattern(img,
170
                        px,
171
                        py,
172
                        tilePtr->width,
173
24
                        img->mBounds.h);
174
                }
175
            }
176
177
40
            const int nextTile = tilePtr->nextTile;
178
40
            x += nextTile;
179
40
            tilePtr += nextTile;
180
        }
181
    }
182
    BLOCK_END("MapLayer::draw")
183
22
}
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
892
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
892
    const int y32 = y * mapTileSize;
384
892
    const int py1 = y32 - scrollY;
385
892
    int endX1 = endX;
386
892
    int specialWidth = mSpecialLayer->mWidth;
387
892
    int ptr = y * specialWidth;
388
892
    if (endX1 > specialWidth)
389
        endX1 = specialWidth;
390
892
    if (endX1 < 0)
391
        endX1 = 0;
392
892
    int x0 = startX;
393
892
    const MapItem *item0 = mSpecialLayer->mTiles[ptr + startX];
394

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

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

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

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

64
                if (mSpecialFlag ||
565
                    img->mBounds.h <= mapTileSize)
566
                {
567
64
                    const int px = x32 + dx;
568
64
                    const int py = py0 - img->mBounds.h;
569
570
64
                    if (tilePtr->count == 0)
571
                    {
572
40
                        graphics->drawImage(img, px, py);
573
                    }
574
                    else
575
                    {
576
24
                        graphics->drawPattern(img,
577
                            px,
578
                            py,
579
                            tilePtr->width,
580
48
                            img->mBounds.h);
581
                    }
582
                }
583
584
64
                const int nextTile = tilePtr->nextTile;
585
                // remove this condition, because it always true
586
64
                if (y < specialHeight)
587
                {
588
64
                    drawSpecialLayer(graphics,
589
                        y,
590
                        x,
591
192
                        std::min(x + nextTile + 1, endX),
592
                        scrollX,
593
64
                        scrollY);
594
                }
595
64
                x += nextTile;
596
64
                tilePtr += nextTile;
597
            }
598
        }
599
600
26
        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
26
    if (mDrawLayerFlags != MapType::SPECIAL3 &&
662
        mDrawLayerFlags != MapType::SPECIAL4)
663
    {
664
        BLOCK_START("MapLayer::drawFringe drawmobs")
665
26
        while (ai != ai_end)
666
        {
667
            (*ai)->draw(graphics, -scrollX, -scrollY);
668
            ++ai;
669
        }
670
        BLOCK_END("MapLayer::drawFringe drawmobs")
671
26
        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
131
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
131
    const Image *const img1 = tilePtr->image;
712
131
    int c = 0;
713
131
    width = img1->mBounds.w;
714
185
    for (int x = 1; x < endX; x++)
715
    {
716
155
        tilePtr ++;
717
155
        const Image *const img = tilePtr->image;
718

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

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

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


3944620
        if (img != nullptr && tilePtr->isEnabled == true)
759
            break;
760
3944448
        c ++;
761
    }
762
    BLOCK_END("MapLayer::getEmptyTileDrawWidth")
763
764
79964
    nextTile = c;
765
10
    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
6
void MapLayer::updateConditionTiles(const MetaTile *const metaTiles,
777
                                    const int width,
778
                                    const int height) restrict
779
{
780
6
    const int width1 = width < mWidth ? width : mWidth;
781
6
    const int height1 = height < mHeight ? height : mHeight;
782
783
808
    for (int y = mY; y < height1; y ++)
784
    {
785
802
        const MetaTile *metaPtr = metaTiles + (y - mY) * width;
786
802
        TileInfo *tilePtr = mTiles + y * mWidth;
787
80804
        for (int x = mX; x < width1; x ++, metaPtr ++, tilePtr ++)
788
        {
789

100012
            if (tilePtr->image != nullptr &&
790
40013
                (((metaPtr->blockmask & mTileCondition) != 0) ||
791
20003
                (metaPtr->blockmask == 0 &&
792
                mTileCondition == BlockMask::GROUND)))
793
            {
794
7
                tilePtr->isEnabled = true;
795
            }
796
            else
797
            {
798
79995
                tilePtr->isEnabled = false;
799
            }
800
        }
801
    }
802
6
}
803
804
32
void MapLayer::updateCache(const int width,
805
                           const int height) restrict
806
{
807
32
    const int width1 = width < mWidth ? width : mWidth;
808
32
    const int height1 = height < mHeight ? height : mHeight;
809
810
856
    for (int y = mY; y < height1; y ++)
811
    {
812
80881
        for (int x = mX; x < width1; x ++)
813
        {
814
80057
            TileInfo *tilePtr = mTiles + y * mWidth + x;
815
80057
            int nextTile = 0;
816

80057
            if (tilePtr->image == nullptr || tilePtr->isEnabled == false)
817
            {
818
79954
                tilePtr->isEnabled = false;
819
159908
                tilePtr->count = getEmptyTileDrawWidth(tilePtr,
820
                    width1 - x,
821
                    nextTile);
822
79954
                tilePtr->width = 0;
823
            }
824
            else
825
            {
826
103
                int tileWidth = 0;
827
103
                tilePtr->count = getTileDrawWidth(tilePtr,
828
                    width1 - x,
829
                    tileWidth,
830
                    nextTile);
831
103
                tilePtr->width = tileWidth;
832
            }
833
80057
            tilePtr->nextTile = nextTile;
834
        }
835
    }
836
32
}
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
2
}