Skip to content

Commit bef6906

Browse files
Pick object to follow early
Pick the object to follow when the activity window is shown.
1 parent 0cb008a commit bef6906

File tree

4 files changed

+64
-108
lines changed

4 files changed

+64
-108
lines changed

libs/s25main/ingameWindows/iwAction.cpp

Lines changed: 12 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,7 @@ 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(std::make_unique<iwObservate>(gwv, selectedPt, std::move(pickedObject_)));
711713
DisableMousePosResetOnClose();
712714
Close();
713715
break;
@@ -731,3 +733,11 @@ void iwAction::DisableMousePosResetOnClose()
731733
{
732734
mousePosAtOpen_ = DrawPoint::Invalid();
733735
}
736+
737+
void iwAction::Draw_()
738+
{
739+
IngameWindow::Draw_();
740+
741+
// track picked object (if valid)
742+
pickedObject_.Track(gwv);
743+
}

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: 40 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,13 +42,16 @@ 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"));
4849
// Fenster vergroessern/verkleinern
4950
btPos.x += btSize.x;
5051
AddImageButton(4, btPos, btSize, TextureColor::Grey, LOADER.GetImageN("io", 109), _("Resize window"));
52+
53+
// Set follow button tooltip
54+
UpdateFollowButton();
5155
}
5256

5357
void iwObservate::Msg_ButtonClick(const unsigned ctrl_id)
@@ -69,53 +73,19 @@ void iwObservate::Msg_ButtonClick(const unsigned ctrl_id)
6973
view->SetZoomFactor(2.3f);
7074
break;
7175
case 2:
72-
{
73-
if(followMovableId)
74-
followMovableId = 0;
75-
else
76-
{
77-
const DrawPoint centerDrawPt = DrawPoint(view->GetSize() / 2u);
78-
79-
double minDistance = std::numeric_limits<double>::max();
80-
81-
for(int y = view->GetFirstPt().y; y <= view->GetLastPt().y; ++y)
82-
{
83-
for(int x = view->GetFirstPt().x; x <= view->GetLastPt().x; ++x)
84-
{
85-
Position curOffset;
86-
const MapPoint curPt =
87-
view->GetViewer().GetTerrainRenderer().ConvertCoords(Position(x, y), &curOffset);
88-
DrawPoint curDrawPt = view->GetWorld().GetNodePos(curPt) - view->GetOffset() + curOffset;
89-
90-
if(view->GetViewer().GetVisibility(curPt) != Visibility::Visible)
91-
continue;
92-
93-
for(const noBase& obj : view->GetWorld().GetFigures(curPt))
94-
{
95-
const auto* movable = dynamic_cast<const noMovable*>(&obj);
96-
if(!movable)
97-
continue;
98-
99-
DrawPoint objDrawPt = curDrawPt;
100-
101-
if(movable->IsMoving())
102-
objDrawPt += movable->CalcWalkingRelative();
103-
104-
DrawPoint diffToCenter = objDrawPt - centerDrawPt;
105-
double distance = sqrt(pow(diffToCenter.x, 2) + pow(diffToCenter.y, 2));
106-
107-
if(distance < minDistance)
108-
{
109-
followMovableId = movable->GetObjId();
110-
minDistance = distance;
111-
}
112-
}
113-
}
114-
}
115-
}
116-
76+
if(following)
77+
// Stop following
78+
pickedObject.Invalidate();
79+
else if(!pickedObject.IsValid())
80+
// If object is invalid, pick new object at center of view
81+
pickedObject = PickedMovableObject::PickAtViewCenter(*view, false);
82+
83+
// Follow picked object, if valid
84+
following = lastValid = pickedObject.IsValid();
85+
// Cancel expiration; only has an effect if we started following the initially picked object
86+
pickedObject.CancelExpiration();
87+
UpdateFollowButton();
11788
break;
118-
}
11989
case 3:
12090
parentView.MoveToMapPt(MapPoint(view->GetLastPt() - (view->GetLastPt() - view->GetFirstPt()) / 2));
12191
break;
@@ -159,11 +129,14 @@ void iwObservate::Draw_()
159129
lastWindowPos = GetPos();
160130
}
161131

162-
if(followMovableId)
132+
// If the object was valid previously, track it (checks IsValid() for us)
133+
// If it returns false, it either expired or we lost it
134+
if(lastValid && !pickedObject.Track(*view, following))
163135
{
164-
if(!MoveToFollowedObj())
165-
followMovableId = 0;
136+
following = false;
137+
UpdateFollowButton();
166138
}
139+
lastValid = pickedObject.IsValid();
167140

168141
if(!IsMinimized())
169142
{
@@ -172,59 +145,13 @@ void iwObservate::Draw_()
172145

173146
view->Draw(road, parentView.GetSelectedPt(), false);
174147
// Draw indicator for center point
175-
if(!followMovableId)
148+
if(!following && !lastValid)
176149
LOADER.GetMapTexture(23)->DrawFull(view->GetPos() + view->GetSize() / 2u);
177150
}
178151

179152
return IngameWindow::Draw_();
180153
}
181154

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-
228155
bool iwObservate::Msg_MouseMove(const MouseCoords& mc)
229156
{
230157
if(isScrolling)
@@ -252,7 +179,9 @@ bool iwObservate::Msg_RightDown(const MouseCoords& mc)
252179
scrollOrigin = mc.GetPos();
253180

254181
isScrolling = true;
255-
followMovableId = 0;
182+
following = lastValid = false;
183+
pickedObject.Invalidate();
184+
UpdateFollowButton();
256185
WINDOWMANAGER.SetCursor(Cursor::Scroll);
257186
} else
258187
{
@@ -270,3 +199,14 @@ bool iwObservate::Msg_RightUp(const MouseCoords& /*mc*/)
270199

271200
return true;
272201
}
202+
203+
void iwObservate::UpdateFollowButton()
204+
{
205+
auto* button = GetCtrl<ctrlImageButton>(2);
206+
if(following)
207+
button->SetTooltip(_("Stop following object"));
208+
else if(pickedObject.IsValid())
209+
button->SetTooltip(_("Follow picked object"));
210+
else
211+
button->SetTooltip(_("Follow object near the center"));
212+
}

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

1011
class GameWorldView;
@@ -27,19 +28,19 @@ class iwObservate : public IngameWindow
2728

2829
unsigned zoomLvl;
2930

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

3336
public:
34-
iwObservate(GameWorldView& gwv, MapPoint selectedPt);
37+
iwObservate(GameWorldView& gwv, MapPoint selectedPt, PickedMovableObject&& pmo);
3538

3639
private:
3740
void Draw_() override;
3841
void Msg_ButtonClick(unsigned ctrl_id) override;
3942
bool Msg_MouseMove(const MouseCoords& mc) override;
4043
bool Msg_RightDown(const MouseCoords& mc) override;
4144
bool Msg_RightUp(const MouseCoords& mc) override;
42-
/// Move view to the object we currently follow, return true if it can still be found
43-
bool MoveToFollowedObj();
44-
inline bool MoveToFollowedObj(MapPoint ptToCheck);
45+
void UpdateFollowButton();
4546
};

0 commit comments

Comments
 (0)