77#include " Loader.h"
88#include " Settings.h"
99#include " WindowManager.h"
10+ #include " controls/ctrlButton.h"
1011#include " controls/ctrlImageButton.h"
12+ #include " desktops/dskGameInterface.h"
1113#include " driver/MouseCoords.h"
1214#include " drivers/VideoDriverWrapper.h"
1315#include " ogl/glArchivItem_Bitmap.h"
@@ -42,13 +44,13 @@ void PickedMovableObject::ExpireIn(unsigned long ticks)
4244 expiration = VIDEODRIVER .GetTickCount () + ticks;
4345}
4446
45- iwObservate::iwObservate (GameWorldView& gwv, const MapPoint selectedPt)
47+ iwObservate::iwObservate (GameWorldView& gwv, const MapPoint selectedPt, const PickedMovableObject& pmo )
4648 : IngameWindow(CGI_OBSERVATION , IngameWindow::posAtMouse, SmallWndSize, _(" Observation window" ), nullptr, false,
4749 CloseBehavior::NoRightClick),
4850 parentView(gwv),
4951 view(new GameWorldView(gwv.GetViewer(), Position(GetDrawPos() * DrawPoint(10 , 15 )), GetSize() - Extent::all(20 ))),
5052 selectedPt(selectedPt), lastWindowPos(Point<unsigned short >::Invalid()), isScrolling(false ), zoomLvl(0 ),
51- followMovableId( 0 )
53+ pickedObject(pmo )
5254{
5355 view->MoveToMapPt (selectedPt);
5456 view->SetZoomFactor (1 .9f , false );
@@ -60,7 +62,9 @@ iwObservate::iwObservate(GameWorldView& gwv, const MapPoint selectedPt)
6062 AddImageButton (1 , btPos, btSize, TextureColor::Grey, LOADER .GetImageN (" io" , 36 ), _ (" Zoom" ));
6163 // Kamera (Folgen): 43
6264 btPos.x += btSize.x ;
63- AddImageButton (2 , btPos, btSize, TextureColor::Grey, LOADER .GetImageN (" io" , 43 ), _ (" Follow object" ));
65+ auto * button = AddImageButton (2 , btPos, btSize, TextureColor::Grey, LOADER .GetImageN (" io" , 43 ), _ (" Follow object" ));
66+ if (pickedObject.IsValid () && !pickedObject.HasExpired ())
67+ button->SetTooltip ((boost::format (_ (" Follow %s" )) % typeid (*pickedObject.movable ).name ()).str ());
6468 // Zum Ort
6569 btPos.x += btSize.x ;
6670 AddImageButton (3 , btPos, btSize, TextureColor::Grey, LOADER .GetImageN (" io" , 107 ), _ (" Go to place" ));
@@ -89,50 +93,29 @@ void iwObservate::Msg_ButtonClick(const unsigned ctrl_id)
8993 break ;
9094 case 2 :
9195 {
92- if (followMovableId )
93- followMovableId = 0 ;
96+ if (followingObject )
97+ followingObject = false ;
9498 else
9599 {
96- const DrawPoint centerDrawPt = DrawPoint (view->GetSize () / 2u );
97-
98- double minDistance = std::numeric_limits<double >::max ();
99-
100- for (int y = view->GetFirstPt ().y ; y <= view->GetLastPt ().y ; ++y)
100+ if (pickedObject.IsValid () && !pickedObject.HasExpired ())
101+ // start following currently picked object
102+ followingObject = true ;
103+ else
101104 {
102- for (int x = view->GetFirstPt ().x ; x <= view->GetLastPt ().x ; ++x)
103- {
104- Position curOffset;
105- const MapPoint curPt =
106- view->GetViewer ().GetTerrainRenderer ().ConvertCoords (Position (x, y), &curOffset);
107- DrawPoint curDrawPt = view->GetWorld ().GetNodePos (curPt) - view->GetOffset () + curOffset;
108-
109- if (view->GetViewer ().GetVisibility (curPt) != Visibility::Visible)
110- continue ;
111-
112- for (const noBase& obj : view->GetWorld ().GetFigures (curPt))
113- {
114- const auto * movable = dynamic_cast <const noMovable*>(&obj);
115- if (!movable)
116- continue ;
117-
118- DrawPoint objDrawPt = curDrawPt;
119-
120- if (movable->IsMoving ())
121- objDrawPt += movable->CalcWalkingRelative ();
122-
123- DrawPoint diffToCenter = objDrawPt - centerDrawPt;
124- double distance = sqrt (pow (diffToCenter.x , 2 ) + pow (diffToCenter.y , 2 ));
125-
126- if (distance < minDistance)
127- {
128- followMovableId = movable->GetObjId ();
129- minDistance = distance;
130- }
131- }
132- }
105+ // pick new object at center of view
106+ const auto & world = view->GetWorld ();
107+ const auto centerMapPt = world.MakeMapPoint ((view->GetFirstPt () + view->GetLastPt ()) / 2 );
108+ const auto centerDrawPt = DrawPoint (view->GetSize () / 2u );
109+ followingObject = PickMovableObject (*view, pickedObject, centerMapPt, centerDrawPt);
133110 }
134111 }
135112
113+ auto * button = GetCtrl<ctrlImageButton>(2 );
114+ if (followingObject)
115+ button->SetTooltip (
116+ (boost::format (_ (" Stop following %s" )) % typeid (*pickedObject.movable ).name ()).str ());
117+ else
118+ button->SetTooltip (_ (" Follow object" ));
136119 break ;
137120 }
138121 case 3 :
@@ -178,10 +161,17 @@ void iwObservate::Draw_()
178161 lastWindowPos = GetPos ();
179162 }
180163
181- if (followMovableId )
164+ if (followingObject )
182165 {
183166 if (!MoveToFollowedObj ())
184- followMovableId = 0 ;
167+ followingObject = false ;
168+ } else if (pickedObject.IsValid ())
169+ {
170+ if (!TrackPickedMovableObject (*view, pickedObject) || pickedObject.HasExpired ())
171+ {
172+ auto * button = GetCtrl<ctrlImageButton>(2 );
173+ button->SetTooltip (_ (" Follow object" ));
174+ }
185175 }
186176
187177 if (!IsMinimized ())
@@ -191,7 +181,7 @@ void iwObservate::Draw_()
191181
192182 view->Draw (road, parentView.GetSelectedPt (), false );
193183 // Draw indicator for center point
194- if (!followMovableId )
184+ if (followingObject )
195185 LOADER .GetMapTexture (23 )->DrawFull (view->GetPos () + view->GetSize () / 2u );
196186 }
197187
@@ -200,36 +190,26 @@ void iwObservate::Draw_()
200190
201191bool iwObservate::MoveToFollowedObj ()
202192{
203- // First look around the center (figure is normally still there)
204- const GameWorldBase& world = view->GetWorld ();
205- const MapPoint centerPt = world.MakeMapPoint ((view->GetFirstPt () + view->GetLastPt ()) / 2 );
206- const std::vector<MapPoint> centerPts = world.GetPointsInRadiusWithCenter (centerPt, 2 );
207- for (const MapPoint& curPt : centerPts)
208- {
209- if (MoveToFollowedObj (curPt))
210- return true ;
211- }
212-
213- // Not at the center (normally due to lags) -> Check full area
214- for (int y = view->GetFirstPt ().y ; y <= view->GetLastPt ().y ; ++y)
215- {
216- for (int x = view->GetFirstPt ().x ; x <= view->GetLastPt ().x ; ++x)
217- {
218- const MapPoint curPt = world.MakeMapPoint (Position (x, y));
219- if (MoveToFollowedObj (curPt))
220- return true ;
221- }
222- }
223- return false ;
193+ const auto & world = view->GetWorld ();
194+ const auto centerPt = world.MakeMapPoint ((view->GetFirstPt () + view->GetLastPt ()) / 2 );
195+ bool result = false ;
196+ world.CheckPointsInRadius (centerPt, 3 , [&, this ](MapPoint curPt, unsigned ) {
197+ result = MoveToFollowedObj (curPt);
198+ if (result)
199+ return CheckPointsBreak;
200+ return CheckPointsContinue;
201+ }, true );
202+ return result;
224203}
225204
226205bool iwObservate::MoveToFollowedObj (const MapPoint ptToCheck)
227206{
207+ const auto id = pickedObject.movable ->GetObjId ();
228208 if (view->GetViewer ().GetVisibility (ptToCheck) != Visibility::Visible)
229209 return false ;
230210 for (const noBase& obj : view->GetWorld ().GetFigures (ptToCheck))
231211 {
232- if (obj.GetObjId () == followMovableId )
212+ if (obj.GetObjId () == id )
233213 {
234214 const auto & followMovable = static_cast <const noMovable&>(obj);
235215 DrawPoint drawPt = view->GetWorld ().GetNodePos (ptToCheck);
@@ -271,7 +251,7 @@ bool iwObservate::Msg_RightDown(const MouseCoords& mc)
271251 scrollOrigin = mc.GetPos ();
272252
273253 isScrolling = true ;
274- followMovableId = 0 ;
254+ followingObject = false ;
275255 WINDOWMANAGER .SetCursor (Cursor::Scroll);
276256 } else
277257 {
0 commit comments