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

Return-To-The-Roots / s25client / 20618416952

31 Dec 2025 11:51AM UTC coverage: 50.569% (+0.06%) from 50.506%
20618416952

Pull #1850

github

web-flow
Merge c015ce8be into 109e7720c
Pull Request #1850: Refactor handling of mouse messages

57 of 103 new or added lines in 4 files covered. (55.34%)

14 existing lines in 4 files now uncovered.

22569 of 44630 relevant lines covered (50.57%)

35759.33 hits per line

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

0.0
/libs/s25main/ingameWindows/iwObservate.cpp
1
// Copyright (C) 2005 - 2021 Settlers Freaks (sf-team at siedler25.org)
2
//
3
// SPDX-License-Identifier: GPL-2.0-or-later
4

5
#include "iwObservate.h"
6
#include "CollisionDetection.h"
7
#include "Loader.h"
8
#include "Settings.h"
9
#include "WindowManager.h"
10
#include "controls/ctrlImageButton.h"
11
#include "controls/ctrlTimer.h"
12
#include "driver/MouseCoords.h"
13
#include "drivers/VideoDriverWrapper.h"
14
#include "ogl/glArchivItem_Bitmap.h"
15
#include "world/GameWorldBase.h"
16
#include "world/GameWorldView.h"
17
#include "world/GameWorldViewer.h"
18
#include "nodeObjs/noMovable.h"
19
#include "gameTypes/RoadBuildState.h"
20
#include "gameData/const_gui_ids.h"
21
#include <cmath>
22

23
const Extent SmallWndSize(260, 190);
24
const Extent MediumWndSize(300, 250);
25
const Extent BigWndSize(340, 310);
26

27
enum
28
{
29
    ID_tmrUpdateFollow = 5
30
};
31

32
iwObservate::iwObservate(GameWorldView& gwv, const MapPoint selectedPt)
×
33
    : IngameWindow(CGI_OBSERVATION, IngameWindow::posAtMouse, SmallWndSize, _("Observation window"), nullptr, false,
34
                   CloseBehavior::NoRightClick),
35
      parentView(gwv),
36
      view(new GameWorldView(gwv.GetViewer(), Position(GetDrawPos() * DrawPoint(10, 15)), GetSize() - Extent::all(20))),
×
37
      selectedPt(selectedPt), lastWindowPos(Point<unsigned short>::Invalid()), isScrolling(false), zoomLvl(0),
×
38
      followMovableId(0)
×
39
{
40
    view->MoveToMapPt(selectedPt);
×
41
    view->SetZoomFactor(1.9f, false);
×
42

43
    const Extent btSize(36, 36);
×
44
    DrawPoint btPos(GetSize().x / 2, GetSize().y);
×
45
    btPos -= DrawPoint(btSize.x * 2, 50);
×
46
    // Lupe: 36
47
    AddImageButton(1, btPos, btSize, TextureColor::Grey, LOADER.GetImageN("io", 36), _("Zoom"));
×
48
    // Kamera (Folgen): 43
49
    btPos.x += btSize.x;
×
50
    AddImageButton(2, btPos, btSize, TextureColor::Grey, LOADER.GetImageN("io", 43), _("Follow object"));
×
51
    // Zum Ort
52
    btPos.x += btSize.x;
×
53
    AddImageButton(3, btPos, btSize, TextureColor::Grey, LOADER.GetImageN("io", 107), _("Go to place"));
×
54
    // Fenster vergroessern/verkleinern
55
    btPos.x += btSize.x;
×
56
    AddImageButton(4, btPos, btSize, TextureColor::Grey, LOADER.GetImageN("io", 109), _("Resize window"));
×
57

58
    // Synchronize visibility of HUD elements with parentView
59
    parentView.CopyHudSettingsTo(*view, false);
×
60
    gwvSettingsConnection =
61
      parentView.onHudSettingsChanged.connect([this]() { parentView.CopyHudSettingsTo(*view, false); });
×
62

63
    // Check the followed object periodically
64
    using namespace std::chrono_literals;
65
    AddTimer(ID_tmrUpdateFollow, 1s)->Stop();
×
66
}
×
67

68
void iwObservate::Msg_ButtonClick(const unsigned ctrl_id)
×
69
{
70
    switch(ctrl_id)
×
71
    {
72
        case 1:
×
73
            if(++zoomLvl > 4)
×
74
                zoomLvl = 0;
×
75
            if(zoomLvl == 0)
×
76
                view->SetZoomFactor(1.f);
×
77
            else if(zoomLvl == 1)
×
78
                view->SetZoomFactor(1.3f);
×
79
            else if(zoomLvl == 2)
×
80
                view->SetZoomFactor(1.6f);
×
81
            else if(zoomLvl == 3)
×
82
                view->SetZoomFactor(1.9f);
×
83
            else
84
                view->SetZoomFactor(2.3f);
×
85
            break;
×
86
        case 2:
×
87
        {
88
            if(followMovableId)
×
89
            {
90
                followMovableId = 0;
×
91
                GetCtrl<ctrlTimer>(ID_tmrUpdateFollow)->Stop();
×
92
            } else
93
            {
94
                const DrawPoint centerDrawPt = DrawPoint(view->GetSize() / 2u);
×
95

96
                double minDistance = std::numeric_limits<double>::max();
×
97

98
                for(int y = view->GetFirstPt().y; y <= view->GetLastPt().y; ++y)
×
99
                {
100
                    for(int x = view->GetFirstPt().x; x <= view->GetLastPt().x; ++x)
×
101
                    {
102
                        Position curOffset;
×
103
                        const MapPoint curPt =
104
                          view->GetViewer().GetTerrainRenderer().ConvertCoords(Position(x, y), &curOffset);
×
105
                        DrawPoint curDrawPt = view->GetWorld().GetNodePos(curPt) - view->GetOffset() + curOffset;
×
106

107
                        if(view->GetViewer().GetVisibility(curPt) != Visibility::Visible)
×
108
                            continue;
×
109

110
                        for(const noBase& obj : view->GetWorld().GetFigures(curPt))
×
111
                        {
112
                            const auto* movable = dynamic_cast<const noMovable*>(&obj);
×
113
                            if(!movable)
×
114
                                continue;
×
115

116
                            DrawPoint objDrawPt = curDrawPt;
×
117

118
                            if(movable->IsMoving())
×
119
                                objDrawPt += movable->CalcWalkingRelative();
×
120

121
                            DrawPoint diffToCenter = objDrawPt - centerDrawPt;
×
122
                            double distance = sqrt(pow(diffToCenter.x, 2) + pow(diffToCenter.y, 2));
×
123

124
                            if(distance < minDistance)
×
125
                            {
126
                                followMovableId = movable->GetObjId();
×
127
                                minDistance = distance;
×
128
                            }
129
                        }
130
                    }
131
                }
132
                if(followMovableId)
×
133
                    GetCtrl<ctrlTimer>(ID_tmrUpdateFollow)->Start();
×
134
            }
135

136
            break;
×
137
        }
138
        case 3:
×
139
            parentView.MoveToMapPt(MapPoint(view->GetLastPt() - (view->GetLastPt() - view->GetFirstPt()) / 2));
×
140
            break;
×
141
        case 4:
×
142
            int diff = GetSize().x;
×
143

144
            if(GetSize() == SmallWndSize)
×
145
            {
146
                Resize(MediumWndSize);
×
147
            } else if(GetSize() == MediumWndSize)
×
148
            {
149
                Resize(BigWndSize);
×
150
                GetCtrl<ctrlImageButton>(4)->SetImage(LOADER.GetImageN("io", 108));
×
151
            } else
152
            {
153
                Resize(SmallWndSize);
×
154
                GetCtrl<ctrlImageButton>(4)->SetImage(LOADER.GetImageN("io", 109));
×
155
            }
156

157
            diff -= GetSize().x;
×
158
            diff /= 2;
×
159

160
            view->Resize(GetSize() - Extent::all(20));
×
161

162
            for(unsigned i = 1; i <= 4; ++i)
×
163
                GetCtrl<ctrlImageButton>(i)->SetPos(
×
164
                  DrawPoint(GetCtrl<ctrlImageButton>(i)->GetPos().x - diff, GetSize().y - 50));
×
165
    }
166
}
×
167

168
void iwObservate::Msg_Timer(const unsigned ctrl_id)
×
169
{
170
    switch(ctrl_id)
×
171
    {
172
        case ID_tmrUpdateFollow:
×
173
            if(followMovableId && !MoveToFollowedObj())
×
174
            {
175
                followMovableId = 0;
×
176
                GetCtrl<ctrlTimer>(ID_tmrUpdateFollow)->Stop();
×
177
            }
178
            break;
×
179
    }
180
}
×
181

182
void iwObservate::DrawBackground()
×
183
{
184
    if(GetPos() != lastWindowPos)
×
185
    {
186
        view->SetPos(GetPos() + DrawPoint(10, 15));
×
187
        lastWindowPos = GetPos();
×
188
    }
189

190
    RoadBuildState road;
×
191
    road.mode = RoadBuildMode::Disabled;
×
192

193
    view->Draw(road, parentView.GetSelectedPt(), false);
×
194
    // Draw indicator for center point
195
    if(!followMovableId)
×
196
        LOADER.GetMapTexture(23)->DrawFull(view->GetPos() + view->GetSize() / 2u);
×
197
}
×
198

199
bool iwObservate::MoveToFollowedObj()
×
200
{
201
    // First look around the center (figure is normally still there)
202
    const GameWorldBase& world = view->GetWorld();
×
203
    const MapPoint centerPt = world.MakeMapPoint((view->GetFirstPt() + view->GetLastPt()) / 2);
×
204
    const std::vector<MapPoint> centerPts = world.GetPointsInRadiusWithCenter(centerPt, 2);
×
205
    for(const MapPoint& curPt : centerPts)
×
206
    {
207
        if(MoveToFollowedObj(curPt))
×
208
            return true;
×
209
    }
210

211
    // Not at the center (normally due to lags) -> Check full area
212
    for(int y = view->GetFirstPt().y; y <= view->GetLastPt().y; ++y)
×
213
    {
214
        for(int x = view->GetFirstPt().x; x <= view->GetLastPt().x; ++x)
×
215
        {
216
            const MapPoint curPt = world.MakeMapPoint(Position(x, y));
×
217
            if(MoveToFollowedObj(curPt))
×
218
                return true;
×
219
        }
220
    }
221
    return false;
×
222
}
223

224
bool iwObservate::MoveToFollowedObj(const MapPoint ptToCheck)
×
225
{
226
    if(view->GetViewer().GetVisibility(ptToCheck) != Visibility::Visible)
×
227
        return false;
×
228
    for(const noBase& obj : view->GetWorld().GetFigures(ptToCheck))
×
229
    {
230
        if(obj.GetObjId() == followMovableId)
×
231
        {
232
            const auto& followMovable = static_cast<const noMovable&>(obj);
×
233
            DrawPoint drawPt = view->GetWorld().GetNodePos(ptToCheck);
×
234

235
            if(followMovable.IsMoving())
×
236
                drawPt += followMovable.CalcWalkingRelative();
×
237

238
            view->MoveTo(drawPt - view->GetSize() / 2u);
×
239
            return true;
×
240
        }
241
    }
242
    return false;
×
243
}
244

245
bool iwObservate::Msg_MouseMove(const MouseCoords& mc)
×
246
{
247
    if(isScrolling)
×
248
    {
249
        int acceleration = SETTINGS.global.smartCursor ? 2 : 3;
×
250

251
        if(SETTINGS.interface.invertMouse)
×
252
            acceleration = -acceleration;
×
253

254
        view->MoveBy((mc.pos - scrollOrigin) * acceleration);
×
255
        VIDEODRIVER.SetMousePos(scrollOrigin);
×
NEW
256
        return true;
×
257
    } else
NEW
258
        return IngameWindow::Msg_MouseMove(mc);
×
259
}
260

261
bool iwObservate::Msg_RightDown(const MouseCoords& mc)
×
262
{
263
    if(IsPointInRect(mc.pos, Rect(view->GetPos(), view->GetSize()))
×
264
       && !IsPointInRect(mc.pos, GetCtrl<ctrlImageButton>(1)->GetDrawRect())
×
265
       && !IsPointInRect(mc.pos, GetCtrl<ctrlImageButton>(2)->GetDrawRect())
×
266
       && !IsPointInRect(mc.pos, GetCtrl<ctrlImageButton>(3)->GetDrawRect())
×
267
       && !IsPointInRect(mc.pos, GetCtrl<ctrlImageButton>(4)->GetDrawRect()))
×
268
    {
269
        scrollOrigin = mc.pos;
×
270

271
        isScrolling = true;
×
272
        followMovableId = 0;
×
273
        WINDOWMANAGER.SetCursor(Cursor::Scroll);
×
274
    } else
275
    {
276
        Close();
×
277
    }
278

279
    return true;
×
280
}
281

282
bool iwObservate::Msg_RightUp(const MouseCoords& /*mc*/)
×
283
{
284
    if(isScrolling)
×
285
        WINDOWMANAGER.SetCursor(Cursor::Hand);
×
286
    isScrolling = false;
×
287

288
    return true;
×
289
}
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