Skip to content

Commit 4d318e4

Browse files
Pick object to follow early
Pick the object to follow when the activity window is shown.
1 parent 021c270 commit 4d318e4

File tree

4 files changed

+62
-108
lines changed

4 files changed

+62
-108
lines changed

libs/s25main/ingameWindows/iwAction.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,9 @@ iwAction::iwAction(GameInterface& gi, GameWorldView& gwv, const Tabs& tabs, MapP
297297
curPos.x += btSize.x;
298298
group->AddImageButton(4, curPos, btSize, TextureColor::Grey, LOADER.GetImageN("io", 107),
299299
_("Notify allies of this location"));
300+
301+
// Try to pick a movable object at the cursor now, in case the user activates the observation window later
302+
pickedObject_ = PickedMovableObject::pickAtCursor(gwv, true);
300303
}
301304

302305
main_tab->SetSelection(0, true);
@@ -706,8 +709,8 @@ void iwAction::Msg_ButtonClick_TabWatch(const unsigned ctrl_id)
706709
switch(ctrl_id)
707710
{
708711
case 1:
709-
// TODO: bestimen, was an der position selected ist
710-
WINDOWMANAGER.Show(std::make_unique<iwObservate>(gwv, selectedPt));
712+
WINDOWMANAGER.Show(
713+
std::make_unique<iwObservate>(gwv, selectedPt, std::exchange(pickedObject_, PickedMovableObject{})));
711714
DisableMousePosResetOnClose();
712715
Close();
713716
break;
@@ -731,3 +734,11 @@ void iwAction::DisableMousePosResetOnClose()
731734
{
732735
mousePosAtOpen_ = DrawPoint::Invalid();
733736
}
737+
738+
void iwAction::Draw_()
739+
{
740+
IngameWindow::Draw_();
741+
742+
// Track picked object (if valid)
743+
pickedObject_.track(gwv);
744+
}

libs/s25main/ingameWindows/iwAction.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#pragma once
66

77
#include "IngameWindow.h"
8+
#include "PickedMovableObject.h"
89
#include "gameTypes/MapCoordinates.h"
910
#include <boost/variant.hpp>
1011
#include <array>
@@ -69,6 +70,8 @@ class iwAction : public IngameWindow
6970
/// Die einzelnen Höhen für die einzelnen Tabs im Bautab
7071
std::array<unsigned short, 4> building_tab_heights;
7172

73+
PickedMovableObject pickedObject_;
74+
7275
public:
7376
iwAction(GameInterface& gi, GameWorldView& gwv, const Tabs& tabs, MapPoint selectedPt, const DrawPoint& mousePos,
7477
Params params, bool military_buildings);
@@ -98,4 +101,6 @@ class iwAction : public IngameWindow
98101
void AddAttackControls(ctrlGroup* group, unsigned attackers_count);
99102
void AddUpgradeRoad(ctrlGroup* group, unsigned& x, unsigned& width);
100103
bool DoUpgradeRoad();
104+
105+
void Draw_() override;
101106
};

libs/s25main/ingameWindows/iwObservate.cpp

Lines changed: 37 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "iwObservate.h"
66
#include "CollisionDetection.h"
77
#include "Loader.h"
8+
#include "PickedMovableObject.h"
89
#include "Settings.h"
910
#include "WindowManager.h"
1011
#include "controls/ctrlImageButton.h"
@@ -23,13 +24,13 @@ const Extent SmallWndSize(260, 190);
2324
const Extent MediumWndSize(300, 250);
2425
const Extent BigWndSize(340, 310);
2526

26-
iwObservate::iwObservate(GameWorldView& gwv, const MapPoint selectedPt)
27+
iwObservate::iwObservate(GameWorldView& gwv, const MapPoint selectedPt, PickedMovableObject&& pmo)
2728
: IngameWindow(CGI_OBSERVATION, IngameWindow::posAtMouse, SmallWndSize, _("Observation window"), nullptr, false,
2829
CloseBehavior::NoRightClick),
2930
parentView(gwv),
3031
view(new GameWorldView(gwv.GetViewer(), Position(GetDrawPos() * DrawPoint(10, 15)), GetSize() - Extent::all(20))),
3132
selectedPt(selectedPt), lastWindowPos(Point<unsigned short>::Invalid()), isScrolling(false), zoomLvl(0),
32-
followMovableId(0)
33+
pickedObject(std::move(pmo)), following(false), lastValid(pickedObject.isValid())
3334
{
3435
view->MoveToMapPt(selectedPt);
3536
view->SetZoomFactor(1.9f, false);
@@ -41,7 +42,7 @@ iwObservate::iwObservate(GameWorldView& gwv, const MapPoint selectedPt)
4142
AddImageButton(1, btPos, btSize, TextureColor::Grey, LOADER.GetImageN("io", 36), _("Zoom"));
4243
// Kamera (Folgen): 43
4344
btPos.x += btSize.x;
44-
AddImageButton(2, btPos, btSize, TextureColor::Grey, LOADER.GetImageN("io", 43), _("Follow object"));
45+
AddImageButton(2, btPos, btSize, TextureColor::Grey, LOADER.GetImageN("io", 43));
4546
// Zum Ort
4647
btPos.x += btSize.x;
4748
AddImageButton(3, btPos, btSize, TextureColor::Grey, LOADER.GetImageN("io", 107), _("Go to place"));
@@ -53,6 +54,9 @@ iwObservate::iwObservate(GameWorldView& gwv, const MapPoint selectedPt)
5354
parentView.CopyHudSettingsTo(*view, false);
5455
gwvSettingsConnection =
5556
parentView.onHudSettingsChanged.connect([this]() { parentView.CopyHudSettingsTo(*view, false); });
57+
58+
// Set follow button tooltip
59+
UpdateFollowButton();
5660
}
5761

5862
void iwObservate::Msg_ButtonClick(const unsigned ctrl_id)
@@ -74,53 +78,17 @@ void iwObservate::Msg_ButtonClick(const unsigned ctrl_id)
7478
view->SetZoomFactor(2.3f);
7579
break;
7680
case 2:
77-
{
78-
if(followMovableId)
79-
followMovableId = 0;
80-
else
81-
{
82-
const DrawPoint centerDrawPt = DrawPoint(view->GetSize() / 2u);
83-
84-
double minDistance = std::numeric_limits<double>::max();
85-
86-
for(int y = view->GetFirstPt().y; y <= view->GetLastPt().y; ++y)
87-
{
88-
for(int x = view->GetFirstPt().x; x <= view->GetLastPt().x; ++x)
89-
{
90-
Position curOffset;
91-
const MapPoint curPt =
92-
view->GetViewer().GetTerrainRenderer().ConvertCoords(Position(x, y), &curOffset);
93-
DrawPoint curDrawPt = view->GetWorld().GetNodePos(curPt) - view->GetOffset() + curOffset;
94-
95-
if(view->GetViewer().GetVisibility(curPt) != Visibility::Visible)
96-
continue;
97-
98-
for(const noBase& obj : view->GetWorld().GetFigures(curPt))
99-
{
100-
const auto* movable = dynamic_cast<const noMovable*>(&obj);
101-
if(!movable)
102-
continue;
103-
104-
DrawPoint objDrawPt = curDrawPt;
105-
106-
if(movable->IsMoving())
107-
objDrawPt += movable->CalcWalkingRelative();
108-
109-
DrawPoint diffToCenter = objDrawPt - centerDrawPt;
110-
double distance = sqrt(pow(diffToCenter.x, 2) + pow(diffToCenter.y, 2));
111-
112-
if(distance < minDistance)
113-
{
114-
followMovableId = movable->GetObjId();
115-
minDistance = distance;
116-
}
117-
}
118-
}
119-
}
120-
}
121-
81+
if(following)
82+
pickedObject.invalidate(); // Stop following
83+
else if(!pickedObject.isValid()) // If object is invalid, pick new object at center of view
84+
pickedObject = PickedMovableObject::pickAtViewCenter(*view, false);
85+
86+
// Follow picked object, if valid
87+
following = lastValid = pickedObject.isValid();
88+
// Ensure the object doesn't expire if we started following the initially picked object
89+
pickedObject.cancelExpiration();
90+
UpdateFollowButton();
12291
break;
123-
}
12492
case 3:
12593
parentView.MoveToMapPt(MapPoint(view->GetLastPt() - (view->GetLastPt() - view->GetFirstPt()) / 2));
12694
break;
@@ -159,10 +127,12 @@ void iwObservate::Draw_()
159127
lastWindowPos = GetPos();
160128
}
161129

162-
if(followMovableId)
130+
// If the object was valid previously, track it (checks isValid() for us)
131+
// If it returns false, it either expired or we lost it
132+
if(lastValid && !pickedObject.track(*view, following))
163133
{
164-
if(!MoveToFollowedObj())
165-
followMovableId = 0;
134+
following = lastValid = false;
135+
UpdateFollowButton();
166136
}
167137

168138
if(!IsMinimized())
@@ -172,59 +142,13 @@ void iwObservate::Draw_()
172142

173143
view->Draw(road, parentView.GetSelectedPt(), false);
174144
// Draw indicator for center point
175-
if(!followMovableId)
145+
if(!following && !lastValid)
176146
LOADER.GetMapTexture(23)->DrawFull(view->GetPos() + view->GetSize() / 2u);
177147
}
178148

179149
return IngameWindow::Draw_();
180150
}
181151

182-
bool iwObservate::MoveToFollowedObj()
183-
{
184-
// First look around the center (figure is normally still there)
185-
const GameWorldBase& world = view->GetWorld();
186-
const MapPoint centerPt = world.MakeMapPoint((view->GetFirstPt() + view->GetLastPt()) / 2);
187-
const std::vector<MapPoint> centerPts = world.GetPointsInRadiusWithCenter(centerPt, 2);
188-
for(const MapPoint& curPt : centerPts)
189-
{
190-
if(MoveToFollowedObj(curPt))
191-
return true;
192-
}
193-
194-
// Not at the center (normally due to lags) -> Check full area
195-
for(int y = view->GetFirstPt().y; y <= view->GetLastPt().y; ++y)
196-
{
197-
for(int x = view->GetFirstPt().x; x <= view->GetLastPt().x; ++x)
198-
{
199-
const MapPoint curPt = world.MakeMapPoint(Position(x, y));
200-
if(MoveToFollowedObj(curPt))
201-
return true;
202-
}
203-
}
204-
return false;
205-
}
206-
207-
bool iwObservate::MoveToFollowedObj(const MapPoint ptToCheck)
208-
{
209-
if(view->GetViewer().GetVisibility(ptToCheck) != Visibility::Visible)
210-
return false;
211-
for(const noBase& obj : view->GetWorld().GetFigures(ptToCheck))
212-
{
213-
if(obj.GetObjId() == followMovableId)
214-
{
215-
const auto& followMovable = static_cast<const noMovable&>(obj);
216-
DrawPoint drawPt = view->GetWorld().GetNodePos(ptToCheck);
217-
218-
if(followMovable.IsMoving())
219-
drawPt += followMovable.CalcWalkingRelative();
220-
221-
view->MoveTo(drawPt - view->GetSize() / 2u);
222-
return true;
223-
}
224-
}
225-
return false;
226-
}
227-
228152
bool iwObservate::Msg_MouseMove(const MouseCoords& mc)
229153
{
230154
if(isScrolling)
@@ -252,7 +176,9 @@ bool iwObservate::Msg_RightDown(const MouseCoords& mc)
252176
scrollOrigin = mc.GetPos();
253177

254178
isScrolling = true;
255-
followMovableId = 0;
179+
following = lastValid = false;
180+
pickedObject.invalidate();
181+
UpdateFollowButton();
256182
WINDOWMANAGER.SetCursor(Cursor::Scroll);
257183
} else
258184
{
@@ -270,3 +196,14 @@ bool iwObservate::Msg_RightUp(const MouseCoords& /*mc*/)
270196

271197
return true;
272198
}
199+
200+
void iwObservate::UpdateFollowButton()
201+
{
202+
auto* button = GetCtrl<ctrlImageButton>(2);
203+
if(following)
204+
button->SetTooltip(_("Stop following object"));
205+
else if(pickedObject.isValid())
206+
button->SetTooltip(_("Follow picked object"));
207+
else
208+
button->SetTooltip(_("Follow object near the center"));
209+
}

libs/s25main/ingameWindows/iwObservate.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#pragma once
66

77
#include "IngameWindow.h"
8+
#include "PickedMovableObject.h"
89
#include "gameTypes/MapCoordinates.h"
910
#include <boost/signals2.hpp>
1011

@@ -28,21 +29,21 @@ class iwObservate : public IngameWindow
2829

2930
unsigned zoomLvl;
3031

31-
/// id of object currently followed or INVALID_ID
32-
unsigned followMovableId;
32+
// Follow object
33+
PickedMovableObject pickedObject;
34+
bool following;
35+
bool lastValid; // keep previous IsValid() result to detect transitions
3336

3437
boost::signals2::scoped_connection gwvSettingsConnection;
3538

3639
public:
37-
iwObservate(GameWorldView& gwv, MapPoint selectedPt);
40+
iwObservate(GameWorldView& gwv, MapPoint selectedPt, PickedMovableObject&& pmo);
3841

3942
private:
4043
void Draw_() override;
4144
void Msg_ButtonClick(unsigned ctrl_id) override;
4245
bool Msg_MouseMove(const MouseCoords& mc) override;
4346
bool Msg_RightDown(const MouseCoords& mc) override;
4447
bool Msg_RightUp(const MouseCoords& mc) override;
45-
/// Move view to the object we currently follow, return true if it can still be found
46-
bool MoveToFollowedObj();
47-
inline bool MoveToFollowedObj(MapPoint ptToCheck);
48+
void UpdateFollowButton();
4849
};

0 commit comments

Comments
 (0)