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

Return-To-The-Roots / s25client / 11773270424

11 Nov 2024 06:21AM UTC coverage: 50.051% (+0.04%) from 50.015%
11773270424

push

github

web-flow
Merge pull request #1710 from Flamefire/fix-campaign-load-dsk

Load campaign data only once

24 of 174 new or added lines in 5 files covered. (13.79%)

60 existing lines in 5 files now uncovered.

22197 of 44349 relevant lines covered (50.05%)

32988.9 hits per line

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

80.19
/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 getImage = [](const ImageResource& res) {
15✔
24
        auto* img = LOADER.GetImageN(ResourceId::make(res.filePath), res.index);
15✔
25
        if(!img)
15✔
NEW
26
            throw std::runtime_error(
×
NEW
27
              helpers::format(_("Loading of images %s for map selection failed."), res.filePath));
×
28
        return img;
15✔
29
    };
30

31
    {
32
        std::vector<std::string> pathsToLoad;
6✔
33
        for(const auto& res : {data.background, data.map, data.missionMapMask, data.marker, data.conquered})
33✔
34
            pathsToLoad.push_back(res.filePath.string());
15✔
35
        LOADER.LoadFiles(pathsToLoad);
3✔
36
    }
37

38
    background = getImage(data.background);
3✔
39
    map = getImage(data.map);
3✔
40
    missionMapMask = getImage(data.missionMapMask);
3✔
41
    marker = getImage(data.marker);
3✔
42
    conquered = getImage(data.conquered);
3✔
43
    if(map->GetSize() != missionMapMask->GetSize())
3✔
44
        throw std::runtime_error(_("Map and mission mask have different sizes."));
×
45

46
    enabledMaskMemory =
47
      libsiedler2::getAllocator().create<libsiedler2::baseArchivItem_Bitmap>(libsiedler2::BobType::Bitmap);
3✔
48
    enabledMask = dynamic_cast<glArchivItem_Bitmap*>(enabledMaskMemory.get());
3✔
49
    RTTR_Assert(enabledMask);
3✔
50
    enabledMask->init(missionMapMask->getWidth(), missionMapMask->getHeight(), libsiedler2::TextureFormat::BGRA);
3✔
51
}
3✔
52

53
ctrlMapSelection::ctrlMapSelection(Window* parent, unsigned id, const DrawPoint& pos, const Extent& size,
3✔
54
                                   const SelectionMapInputData& inputData)
3✔
55
    : Window(parent, id, pos, size), mapImages(inputData), inputData(inputData),
56
      missionStatus(inputData.missionSelectionInfos.size()), preview(false)
3✔
57
{
58
    updateEnabledMask();
3✔
59
}
3✔
60

61
ctrlMapSelection::~ctrlMapSelection() = default;
3✔
62

63
void ctrlMapSelection::updateEnabledMask()
15✔
64
{
65
    RTTR_Assert(mapImages.enabledMask->GetSize() == mapImages.missionMapMask->GetSize());
15✔
66
    const libsiedler2::ColorBGRA disabledColor(inputData.disabledColor);
15✔
67

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

74
        libsiedler2::ColorBGRA newColor;
250,000✔
75
        if(matchingMissionIdx >= 0 && !missionStatus[matchingMissionIdx].playable)
250,000✔
76
            newColor = disabledColor;
87,500✔
77
        mapImages.enabledMask->setPixel(pt.x, pt.y, newColor);
250,000✔
78
    }
79
}
15✔
80

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

89
    missionStatus = status;
12✔
90
    updateEnabledMask();
12✔
91
}
12✔
92

93
void ctrlMapSelection::setSelection(size_t select)
198✔
94
{
95
    if(select < inputData.missionSelectionInfos.size())
198✔
96
    {
97
        if(missionStatus[select].playable)
195✔
98
            currentSelectionPos = inputData.missionSelectionInfos[select].ankerPos;
180✔
99
    } else
100
        currentSelectionPos = Position::Invalid();
3✔
101
}
198✔
102

103
std::optional<unsigned> ctrlMapSelection::getSelection() const
222✔
104
{
105
    if(!currentSelectionPos.isValid())
222✔
106
        return std::nullopt;
12✔
107
    const auto result = helpers::indexOf_if(inputData.missionSelectionInfos,
210✔
108
                                            [currentSelectionPos = this->currentSelectionPos](const auto& val) {
384✔
109
                                                return val.ankerPos == currentSelectionPos;
384✔
110
                                            });
111
    RTTR_Assert(result >= 0);
210✔
112
    return static_cast<unsigned>(result);
210✔
113
}
114

115
void ctrlMapSelection::setPreview(bool previewOnly)
6✔
116
{
117
    preview = previewOnly;
6✔
118
}
6✔
119

120
bool ctrlMapSelection::Msg_LeftUp(const MouseCoords& mc)
198✔
121
{
122
    if(!preview && IsMouseOver(mc.GetPos()))
198✔
123
    {
124
        const auto pickPos = invertScale(mc.GetPos() - getMapPosition());
186✔
125

126
        const auto pixelColor = mapImages.missionMapMask
186✔
127
                                  ->getPixel(helpers::clamp(pickPos.x, 0u, mapImages.map->GetSize().x - 1),
186✔
128
                                             helpers::clamp(pickPos.y, 0u, mapImages.map->GetSize().y - 1))
372✔
129
                                  .asValue();
186✔
130

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

134
        if(matchingMissionIdx >= 0)
186✔
135
        {
136
            setSelection(matchingMissionIdx);
180✔
137
            GetParent()->Msg_ButtonClick(GetID());
180✔
138
        }
139
        return true;
186✔
140
    }
141
    return false;
12✔
142
}
143

144
bool ctrlMapSelection::IsMouseOver(const Position& mousePos) const
186✔
145
{
146
    return IsPointInRect(mousePos, GetDrawRect());
186✔
147
}
148

149
float ctrlMapSelection::getScaleFactor()
558✔
150
{
151
    const auto ratio = PointF(GetSize()) / mapImages.background->GetSize();
558✔
152
    return std::min(ratio.x, ratio.y);
558✔
153
}
154

155
DrawPoint ctrlMapSelection::invertScale(const DrawPoint& scaleIt)
186✔
156
{
157
    return DrawPoint(scaleIt / getScaleFactor());
186✔
158
}
159

160
DrawPoint ctrlMapSelection::getBackgroundPosition()
186✔
161
{
162
    return GetDrawPos() + (GetSize() - scale(mapImages.background->GetSize())) / 2;
186✔
163
}
164

165
DrawPoint ctrlMapSelection::getMapPosition()
186✔
166
{
167
    return getBackgroundPosition() + scale(inputData.mapOffsetInBackground);
186✔
168
}
169

170
void ctrlMapSelection::drawImageOnMap(glArchivItem_Bitmap* image, const Position& drawPos)
×
171
{
172
    const auto originCorrection = image->GetOrigin() - scale(image->GetOrigin());
×
173
    image->DrawFull(Rect(getMapPosition() + scale(drawPos) + originCorrection, scale(image->GetSize())));
×
174
}
×
175

176
void ctrlMapSelection::Draw_()
×
177
{
178
    Window::Draw_();
×
179

180
    mapImages.background->DrawFull(Rect(getBackgroundPosition(), scale(mapImages.background->GetSize())));
×
181

182
    const Rect mapRect = Rect(getMapPosition(), scale(mapImages.map->GetSize()));
×
183
    mapImages.map->DrawFull(mapRect);
×
184
    mapImages.enabledMask->DrawFull(mapRect);
×
185

186
    for(const auto idx : helpers::range(missionStatus.size()))
×
187
    {
188
        if(missionStatus[idx].conquered)
×
189
            drawImageOnMap(mapImages.conquered, inputData.missionSelectionInfos[idx].ankerPos);
×
190
    }
191

192
    if(!preview && currentSelectionPos.isValid())
×
193
        drawImageOnMap(mapImages.marker, currentSelectionPos);
×
194
}
×
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