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);
2324const Extent MediumWndSize (300 , 250 );
2425const 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
5357void 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-
228155bool 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+ }
0 commit comments