• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Return-To-The-Roots / s25client / 9374022113

04 Jun 2024 08:49PM UTC coverage: 50.392% (-0.008%) from 50.4%
9374022113

Pull #1671

github

web-flow
Merge e7217890a into fad2022f6
Pull Request #1671: Add `indexOf_if` and refactor `helpers::` related functions

70 of 86 new or added lines in 15 files covered. (81.4%)

12 existing lines in 4 files now uncovered.

22007 of 43672 relevant lines covered (50.39%)

32612.07 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

79.38
/libs/s25main/controls/ctrlMapSelection.cpp
1
// Copyright (C) 2024 Settlers Freaks (sf-team at siedler25.org)
2
//
3
// SPDX-License-Identifier: GPL-2.0-or-later
4

5
#include "ctrlMapSelection.h"
6
#include "CollisionDetection.h"
7
#include "Loader.h"
8
#include "RttrForeachPt.h"
9
#include "driver/MouseCoords.h"
10
#include "helpers/Range.h"
11
#include "helpers/containerUtils.h"
12
#include "helpers/format.hpp"
13
#include "mygettext/mygettext.h"
14
#include "ogl/glArchivItem_Bitmap.h"
15
#include <libsiedler2/ArchivItem_Bitmap.h>
16
#include <libsiedler2/ColorBGRA.h>
17
#include <libsiedler2/IAllocator.h>
18
#include <libsiedler2/libsiedler2.h>
19
#include <algorithm>
20

21
ctrlMapSelection::MapImages::MapImages(const SelectionMapInputData& data)
3✔
22
{
23
    auto loadImage = [](const ImageResource& res) {
15✔
24
        if(LOADER.LoadFiles({res.filePath.string()}))
30✔
25
        {
26
            auto* img = LOADER.GetImageN(ResourceId::make(res.filePath), res.index);
15✔
27
            if(img)
15✔
28
                return img;
15✔
29
        }
NEW
30
        throw std::runtime_error(helpers::format(_("Loading of images %s for map selection failed."), res.filePath));
×
31
    };
32

33
    background = loadImage(data.background);
3✔
34
    map = loadImage(data.map);
3✔
35
    missionMapMask = loadImage(data.missionMapMask);
3✔
36
    marker = loadImage(data.marker);
3✔
37
    conquered = loadImage(data.conquered);
3✔
38
    if(map->GetSize() != missionMapMask->GetSize())
3✔
NEW
39
        throw std::runtime_error(_("Map and mission mask have different sizes."));
×
40

41
    enabledMaskMemory =
42
      libsiedler2::getAllocator().create<libsiedler2::baseArchivItem_Bitmap>(libsiedler2::BobType::Bitmap);
3✔
43
    enabledMask = dynamic_cast<glArchivItem_Bitmap*>(enabledMaskMemory.get());
3✔
44
    RTTR_Assert(enabledMask);
3✔
45
    enabledMask->init(missionMapMask->getWidth(), missionMapMask->getHeight(), libsiedler2::TextureFormat::BGRA);
3✔
46
}
3✔
47

48
ctrlMapSelection::ctrlMapSelection(Window* parent, unsigned id, const DrawPoint& pos, const Extent& size,
3✔
49
                                   const SelectionMapInputData& inputData)
3✔
50
    : Window(parent, id, pos, size), mapImages(inputData), inputData(inputData),
51
      missionStatus(inputData.missionSelectionInfos.size()), preview(false)
3✔
52
{
53
    updateEnabledMask();
3✔
54
}
3✔
55

56
ctrlMapSelection::~ctrlMapSelection() = default;
3✔
57

58
void ctrlMapSelection::updateEnabledMask()
15✔
59
{
60
    RTTR_Assert(mapImages.enabledMask->GetSize() == mapImages.missionMapMask->GetSize());
15✔
61
    const libsiedler2::ColorBGRA disabledColor(inputData.disabledColor);
15✔
62

63
    RTTR_FOREACH_PT(Point<uint16_t>, mapImages.enabledMask->GetSize())
251,515✔
64
    {
65
        const auto pixelColor = mapImages.missionMapMask->getPixel(pt.x, pt.y).asValue();
250,000✔
66
        const auto matchingMissionIdx = helpers::indexOf_if(
250,000✔
67
          inputData.missionSelectionInfos, [pixelColor](const auto& val) { return val.maskAreaColor == pixelColor; });
812,500✔
68

69
        libsiedler2::ColorBGRA newColor;
250,000✔
70
        if(matchingMissionIdx >= 0 && !missionStatus[matchingMissionIdx].playable)
250,000✔
71
            newColor = disabledColor;
87,500✔
72
        mapImages.enabledMask->setPixel(pt.x, pt.y, newColor);
250,000✔
73
    }
74
}
15✔
75

76
void ctrlMapSelection::setMissionsStatus(const std::vector<MissionStatus>& status)
12✔
77
{
78
    if(inputData.missionSelectionInfos.size() != status.size())
12✔
79
    {
80
        throw std::runtime_error(
×
81
          helpers::format("List has wrong size. %1% != %2%", inputData.missionSelectionInfos.size(), status.size()));
×
82
    }
83

84
    missionStatus = status;
12✔
85
    updateEnabledMask();
12✔
86
}
12✔
87

88
void ctrlMapSelection::setSelection(size_t select)
198✔
89
{
90
    if(select < inputData.missionSelectionInfos.size())
198✔
91
    {
92
        if(missionStatus[select].playable)
195✔
93
            currentSelectionPos = inputData.missionSelectionInfos[select].ankerPos;
180✔
94
    } else
95
        currentSelectionPos = Position::Invalid();
3✔
96
}
198✔
97

98
int ctrlMapSelection::getCurrentSelection() const
222✔
99
{
100
    return static_cast<int>(helpers::indexOf_if(inputData.missionSelectionInfos,
222✔
101
                                                [&](const auto& val) { return val.ankerPos == currentSelectionPos; }));
642✔
102
}
103

104
void ctrlMapSelection::setPreview(bool previewOnly)
6✔
105
{
106
    preview = previewOnly;
6✔
107
}
6✔
108

109
bool ctrlMapSelection::Msg_LeftUp(const MouseCoords& mc)
198✔
110
{
111
    if(!preview && IsMouseOver(mc.GetPos()))
198✔
112
    {
113
        const auto pickPos = invertScale(mc.GetPos() - getMapPosition());
186✔
114

115
        const auto pixelColor = mapImages.missionMapMask
186✔
116
                                  ->getPixel(helpers::clamp(pickPos.x, 0u, mapImages.map->GetSize().x - 1),
186✔
117
                                             helpers::clamp(pickPos.y, 0u, mapImages.map->GetSize().y - 1))
372✔
118
                                  .asValue();
186✔
119

120
        const auto matchingMissionIdx = helpers::indexOf_if(
186✔
121
          inputData.missionSelectionInfos, [pixelColor](const auto& val) { return val.maskAreaColor == pixelColor; });
564✔
122

123
        if(matchingMissionIdx >= 0)
186✔
124
        {
125
            setSelection(matchingMissionIdx);
180✔
126
            GetParent()->Msg_ButtonClick(GetID());
180✔
127
        }
128
        return true;
186✔
129
    }
130
    return false;
12✔
131
}
132

133
bool ctrlMapSelection::IsMouseOver(const Position& mousePos) const
186✔
134
{
135
    return IsPointInRect(mousePos, GetDrawRect());
186✔
136
}
137

138
float ctrlMapSelection::getScaleFactor()
558✔
139
{
140
    const auto ratio = PointF(GetSize()) / mapImages.background->GetSize();
558✔
141
    return std::min(ratio.x, ratio.y);
558✔
142
}
143

144
DrawPoint ctrlMapSelection::invertScale(const DrawPoint& scaleIt)
186✔
145
{
146
    return DrawPoint(scaleIt / getScaleFactor());
186✔
147
}
148

149
DrawPoint ctrlMapSelection::getBackgroundPosition()
186✔
150
{
151
    return GetDrawPos() + (GetSize() - scale(mapImages.background->GetSize())) / 2;
186✔
152
}
153

154
DrawPoint ctrlMapSelection::getMapPosition()
186✔
155
{
156
    return getBackgroundPosition() + scale(inputData.mapOffsetInBackground);
186✔
157
}
158

159
void ctrlMapSelection::drawImageOnMap(glArchivItem_Bitmap* image, const Position& drawPos)
×
160
{
NEW
161
    const auto originCorrection = image->GetOrigin() - scale(image->GetOrigin());
×
NEW
162
    image->DrawFull(Rect(getMapPosition() + scale(drawPos) + originCorrection, scale(image->GetSize())));
×
UNCOV
163
}
×
164

165
void ctrlMapSelection::Draw_()
×
166
{
167
    Window::Draw_();
×
168

169
    mapImages.background->DrawFull(Rect(getBackgroundPosition(), scale(mapImages.background->GetSize())));
×
170

171
    const Rect mapRect = Rect(getMapPosition(), scale(mapImages.map->GetSize()));
×
172
    mapImages.map->DrawFull(mapRect);
×
173
    mapImages.enabledMask->DrawFull(mapRect);
×
174

175
    for(const auto idx : helpers::range(missionStatus.size()))
×
176
    {
NEW
177
        if(missionStatus[idx].conquered)
×
NEW
178
            drawImageOnMap(mapImages.conquered, inputData.missionSelectionInfos[idx].ankerPos);
×
179
    }
180

181
    if(!preview && currentSelectionPos.isValid())
×
UNCOV
182
        drawImageOnMap(mapImages.marker, currentSelectionPos);
×
183
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc