Skip to content

Commit 021c270

Browse files
Add class for picking and tracking objects
PickedMovableObject represents a node object figure that has been picked to be followed in the observation window.
1 parent b3a7e6a commit 021c270

2 files changed

Lines changed: 190 additions & 0 deletions

File tree

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
// Copyright (C) 2005 - 2023 Settlers Freaks (sf-team at siedler25.org)
2+
//
3+
// SPDX-License-Identifier: GPL-2.0-or-later
4+
5+
#include "PickedMovableObject.h"
6+
#include "desktops/dskGameInterface.h"
7+
#include "drivers/VideoDriverWrapper.h"
8+
#include "world/GameWorldBase.h"
9+
#include "world/GameWorldView.h"
10+
#include "nodeObjs/noMovable.h"
11+
#include <cmath>
12+
13+
using namespace std::chrono_literals;
14+
15+
namespace {
16+
constexpr unsigned PickRadius = 2;
17+
constexpr unsigned TrackRadius = 5;
18+
constexpr auto PickedObjectExpiration = 5s;
19+
20+
// Make (ab-)use of CheckPointsInRadius() easier
21+
constexpr bool CheckPointsBreak = true;
22+
constexpr bool CheckPointsContinue = false;
23+
} // namespace
24+
25+
PickedMovableObject PickedMovableObject::pick(const GameWorldView& gwv, MapPoint mapPt, DrawPoint drawPt, bool expire)
26+
{
27+
// DEBUG REMOVE BEFORE MERGE
28+
unsigned i = 1;
29+
30+
const auto offset = gwv.GetOffset();
31+
const auto center = gwv.GetSize() / 2.f;
32+
const auto zoomFactor = gwv.GetZoomFactor();
33+
const auto& world = gwv.GetWorld();
34+
const auto worldSize = world.GetSize() * DrawPoint(TR_W, TR_H);
35+
auto minDistance = std::numeric_limits<float>::max();
36+
37+
PickedMovableObject pmo;
38+
39+
world.CheckPointsInRadius(
40+
mapPt, PickRadius,
41+
[&](MapPoint curPt, unsigned) {
42+
if(gwv.GetViewer().GetVisibility(curPt) != Visibility::Visible)
43+
return CheckPointsContinue;
44+
45+
DrawPoint curDrawPt = world.GetNodePos(curPt);
46+
if(curDrawPt.x < offset.x)
47+
curDrawPt.x += worldSize.x;
48+
if(curDrawPt.y < offset.y)
49+
curDrawPt.y += worldSize.y;
50+
curDrawPt -= offset;
51+
for(const noBase& obj : world.GetFigures(curPt))
52+
{
53+
const auto* movable = dynamic_cast<const noMovable*>(&obj);
54+
if(!movable)
55+
continue;
56+
57+
DrawPoint objDrawPt = curDrawPt;
58+
if(movable->IsMoving())
59+
objDrawPt += movable->CalcWalkingRelative();
60+
objDrawPt = DrawPoint((objDrawPt - center) * zoomFactor + center);
61+
62+
// DEBUG REMOVE BEFORE MERGE
63+
dskGameInterface::SetDebugPoint(i++, objDrawPt, 8, 4, MakeColor(255, 255, 0, 255));
64+
65+
auto diff = Point<float>(objDrawPt - drawPt);
66+
float distance = std::sqrt(diff.x * diff.x + diff.y * diff.y);
67+
if(distance < minDistance)
68+
{
69+
pmo.id_ = movable->GetObjId();
70+
pmo.mapPt_ = curPt;
71+
pmo.drawPt_ = objDrawPt; // TODO Do we need the unwrapped point here or was this always wrong?
72+
minDistance = distance;
73+
}
74+
}
75+
76+
return CheckPointsContinue;
77+
},
78+
true);
79+
80+
if(pmo.isValid() && expire)
81+
pmo.expiration_.start();
82+
83+
return pmo;
84+
}
85+
86+
PickedMovableObject PickedMovableObject::pickAtCursor(const GameWorldView& gwv, bool expire)
87+
{
88+
return pick(gwv, gwv.GetSelectedPt(), DrawPoint(VIDEODRIVER.GetMousePos()), expire);
89+
}
90+
91+
PickedMovableObject PickedMovableObject::pickAtViewCenter(const GameWorldView& gwv, bool expire)
92+
{
93+
const auto centerMapPt = gwv.GetWorld().MakeMapPoint((gwv.GetFirstPt() + gwv.GetLastPt()) / 2);
94+
const auto centerDrawPt = DrawPoint(gwv.GetSize() / 2u);
95+
return pick(gwv, centerMapPt, centerDrawPt, expire);
96+
}
97+
98+
bool PickedMovableObject::isValid() const
99+
{
100+
return id_ != 0 && (!expiration_.isRunning() || expiration_.getElapsed() < PickedObjectExpiration);
101+
}
102+
103+
void PickedMovableObject::cancelExpiration()
104+
{
105+
expiration_.stop();
106+
}
107+
108+
void PickedMovableObject::invalidate()
109+
{
110+
id_ = 0;
111+
}
112+
113+
bool PickedMovableObject::track(const GameWorldView& gwv)
114+
{
115+
if(!isValid())
116+
return false;
117+
118+
const auto& world = gwv.GetWorld();
119+
const auto success = world.CheckPointsInRadius(
120+
mapPt_, TrackRadius,
121+
[&](MapPoint curPt, unsigned) {
122+
if(gwv.GetViewer().GetVisibility(curPt) != Visibility::Visible)
123+
return CheckPointsContinue;
124+
125+
for(const noBase& obj : world.GetFigures(curPt))
126+
{
127+
if(obj.GetObjId() != id_)
128+
continue;
129+
130+
const auto& movable = dynamic_cast<const noMovable&>(obj);
131+
mapPt_ = curPt;
132+
drawPt_ = world.GetNodePos(curPt);
133+
if(movable.IsMoving())
134+
drawPt_ += movable.CalcWalkingRelative();
135+
136+
return CheckPointsBreak;
137+
}
138+
return CheckPointsContinue;
139+
},
140+
true);
141+
142+
if(!success)
143+
invalidate();
144+
145+
return success;
146+
}
147+
148+
bool PickedMovableObject::track(GameWorldView& gwv, bool moveTo)
149+
{
150+
const auto success = track(gwv);
151+
if(success && moveTo)
152+
gwv.MoveTo(drawPt_ - gwv.GetSize() / 2u);
153+
return success;
154+
}

libs/s25main/PickedMovableObject.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright (C) 2005 - 2023 Settlers Freaks (sf-team at siedler25.org)
2+
//
3+
// SPDX-License-Identifier: GPL-2.0-or-later
4+
5+
#pragma once
6+
7+
#include "DrawPoint.h"
8+
#include "Timer.h"
9+
#include "gameTypes/MapCoordinates.h"
10+
11+
class GameWorldView;
12+
13+
class PickedMovableObject
14+
{
15+
public:
16+
static PickedMovableObject pick(const GameWorldView& gwv, MapPoint mapPt, DrawPoint drawPt, bool expire);
17+
static PickedMovableObject pickAtCursor(const GameWorldView& gwv, bool expire);
18+
static PickedMovableObject pickAtViewCenter(const GameWorldView& gwv, bool expire);
19+
20+
PickedMovableObject() = default;
21+
22+
unsigned id() const { return id_; }
23+
bool isValid() const;
24+
25+
void cancelExpiration();
26+
void invalidate();
27+
28+
bool track(const GameWorldView& gwv);
29+
bool track(GameWorldView& gwv, bool moveTo);
30+
31+
private:
32+
unsigned id_ = 0;
33+
MapPoint mapPt_{};
34+
DrawPoint drawPt_{};
35+
Timer expiration_{};
36+
};

0 commit comments

Comments
 (0)