From cc1a1a4269c2932e190f8f266b8e0b46aa84dd1d Mon Sep 17 00:00:00 2001 From: Florian Albrechtskirchinger Date: Sat, 15 Jul 2023 14:21:12 +0200 Subject: [PATCH] Pick object to follow early Pick the object to follow when the activity window is shown. --- libs/s25main/ingameWindows/iwAction.cpp | 16 ++- libs/s25main/ingameWindows/iwAction.h | 5 + libs/s25main/ingameWindows/iwObservate.cpp | 114 +++++++++------------ libs/s25main/ingameWindows/iwObservate.h | 8 +- 4 files changed, 70 insertions(+), 73 deletions(-) diff --git a/libs/s25main/ingameWindows/iwAction.cpp b/libs/s25main/ingameWindows/iwAction.cpp index a7c96ae37..b2a612dd5 100644 --- a/libs/s25main/ingameWindows/iwAction.cpp +++ b/libs/s25main/ingameWindows/iwAction.cpp @@ -297,6 +297,10 @@ iwAction::iwAction(GameInterface& gi, GameWorldView& gwv, const Tabs& tabs, MapP curPos.x += btSize.x; group->AddImageButton(4, curPos, btSize, TextureColor::Grey, LOADER.GetImageN("io", 107), _("Notify allies of this location")); + + // try to pick a movable object at the cursor now, in case the user activates the observation window later + if(iwObservate::PickMovableObjectAtCursor(gwv, pickedObject_)) + pickedObject_.ExpireIn(PickedMovableObject::EXPIRATION); } main_tab->SetSelection(0, true); @@ -706,8 +710,7 @@ void iwAction::Msg_ButtonClick_TabWatch(const unsigned ctrl_id) switch(ctrl_id) { case 1: - // TODO: bestimen, was an der position selected ist - WINDOWMANAGER.Show(std::make_unique(gwv, selectedPt)); + WINDOWMANAGER.Show(std::make_unique(gwv, selectedPt, pickedObject_)); DisableMousePosResetOnClose(); Close(); break; @@ -731,3 +734,12 @@ void iwAction::DisableMousePosResetOnClose() { mousePosAtOpen_ = DrawPoint::Invalid(); } + +void iwAction::Draw_() +{ + IngameWindow::Draw_(); + + // track picked object for a while + if(pickedObject_.IsValid() && !pickedObject_.HasExpired()) + iwObservate::TrackPickedMovableObject(gwv, pickedObject_); +} diff --git a/libs/s25main/ingameWindows/iwAction.h b/libs/s25main/ingameWindows/iwAction.h index 52bd6a731..a0d5b1a64 100644 --- a/libs/s25main/ingameWindows/iwAction.h +++ b/libs/s25main/ingameWindows/iwAction.h @@ -5,6 +5,7 @@ #pragma once #include "IngameWindow.h" +#include "ingameWindows/iwObservate.h" #include "gameTypes/MapCoordinates.h" #include #include @@ -69,6 +70,8 @@ class iwAction : public IngameWindow /// Die einzelnen Höhen für die einzelnen Tabs im Bautab std::array building_tab_heights; + PickedMovableObject pickedObject_; + public: iwAction(GameInterface& gi, GameWorldView& gwv, const Tabs& tabs, MapPoint selectedPt, const DrawPoint& mousePos, Params params, bool military_buildings); @@ -98,4 +101,6 @@ class iwAction : public IngameWindow void AddAttackControls(ctrlGroup* group, unsigned attackers_count); void AddUpgradeRoad(ctrlGroup* group, unsigned& x, unsigned& width); bool DoUpgradeRoad(); + + void Draw_() override; }; diff --git a/libs/s25main/ingameWindows/iwObservate.cpp b/libs/s25main/ingameWindows/iwObservate.cpp index 219ec9631..4d05cc104 100644 --- a/libs/s25main/ingameWindows/iwObservate.cpp +++ b/libs/s25main/ingameWindows/iwObservate.cpp @@ -7,7 +7,9 @@ #include "Loader.h" #include "Settings.h" #include "WindowManager.h" +#include "controls/ctrlButton.h" #include "controls/ctrlImageButton.h" +#include "desktops/dskGameInterface.h" #include "driver/MouseCoords.h" #include "drivers/VideoDriverWrapper.h" #include "ogl/glArchivItem_Bitmap.h" @@ -43,13 +45,13 @@ void PickedMovableObject::ExpireIn(unsigned long ticks) expiration = VIDEODRIVER.GetTickCount() + ticks; } -iwObservate::iwObservate(GameWorldView& gwv, const MapPoint selectedPt) +iwObservate::iwObservate(GameWorldView& gwv, const MapPoint selectedPt, const PickedMovableObject& pmo) : IngameWindow(CGI_OBSERVATION, IngameWindow::posAtMouse, SmallWndSize, _("Observation window"), nullptr, false, CloseBehavior::NoRightClick), parentView(gwv), view(new GameWorldView(gwv.GetViewer(), Position(GetDrawPos() * DrawPoint(10, 15)), GetSize() - Extent::all(20))), selectedPt(selectedPt), lastWindowPos(Point::Invalid()), isScrolling(false), zoomLvl(0), - followMovableId(0) + pickedObject(pmo) { view->MoveToMapPt(selectedPt); view->SetZoomFactor(1.9f, false); @@ -61,7 +63,9 @@ iwObservate::iwObservate(GameWorldView& gwv, const MapPoint selectedPt) AddImageButton(1, btPos, btSize, TextureColor::Grey, LOADER.GetImageN("io", 36), _("Zoom")); // Kamera (Folgen): 43 btPos.x += btSize.x; - AddImageButton(2, btPos, btSize, TextureColor::Grey, LOADER.GetImageN("io", 43), _("Follow object")); + auto* button = AddImageButton(2, btPos, btSize, TextureColor::Grey, LOADER.GetImageN("io", 43), _("Follow object")); + if(pickedObject.IsValid() && !pickedObject.HasExpired()) + button->SetTooltip((boost::format(_("Follow %s")) % typeid(*pickedObject.movable).name()).str()); // Zum Ort btPos.x += btSize.x; AddImageButton(3, btPos, btSize, TextureColor::Grey, LOADER.GetImageN("io", 107), _("Go to place")); @@ -90,50 +94,29 @@ void iwObservate::Msg_ButtonClick(const unsigned ctrl_id) break; case 2: { - if(followMovableId) - followMovableId = 0; + if(followingObject) + followingObject = false; else { - const DrawPoint centerDrawPt = DrawPoint(view->GetSize() / 2u); - - double minDistance = std::numeric_limits::max(); - - for(int y = view->GetFirstPt().y; y <= view->GetLastPt().y; ++y) + if(pickedObject.IsValid() && !pickedObject.HasExpired()) + // start following currently picked object + followingObject = true; + else { - for(int x = view->GetFirstPt().x; x <= view->GetLastPt().x; ++x) - { - Position curOffset; - const MapPoint curPt = - view->GetViewer().GetTerrainRenderer().ConvertCoords(Position(x, y), &curOffset); - DrawPoint curDrawPt = view->GetWorld().GetNodePos(curPt) - view->GetOffset() + curOffset; - - if(view->GetViewer().GetVisibility(curPt) != Visibility::Visible) - continue; - - for(const noBase& obj : view->GetWorld().GetFigures(curPt)) - { - const auto* movable = dynamic_cast(&obj); - if(!movable) - continue; - - DrawPoint objDrawPt = curDrawPt; - - if(movable->IsMoving()) - objDrawPt += movable->CalcWalkingRelative(); - - DrawPoint diffToCenter = objDrawPt - centerDrawPt; - double distance = sqrt(pow(diffToCenter.x, 2) + pow(diffToCenter.y, 2)); - - if(distance < minDistance) - { - followMovableId = movable->GetObjId(); - minDistance = distance; - } - } - } + // pick new object at center of view + const auto& world = view->GetWorld(); + const auto centerMapPt = world.MakeMapPoint((view->GetFirstPt() + view->GetLastPt()) / 2); + const auto centerDrawPt = DrawPoint(view->GetSize() / 2u); + followingObject = PickMovableObject(*view, pickedObject, centerMapPt, centerDrawPt); } } + auto* button = GetCtrl(2); + if(followingObject) + button->SetTooltip( + (boost::format(_("Stop following %s")) % typeid(*pickedObject.movable).name()).str()); + else + button->SetTooltip(_("Follow object")); break; } case 3: @@ -179,10 +162,17 @@ void iwObservate::Draw_() lastWindowPos = GetPos(); } - if(followMovableId) + if(followingObject) { if(!MoveToFollowedObj()) - followMovableId = 0; + followingObject = false; + } else if(pickedObject.IsValid()) + { + if(!TrackPickedMovableObject(*view, pickedObject) || pickedObject.HasExpired()) + { + auto* button = GetCtrl(2); + button->SetTooltip(_("Follow object")); + } } if(!IsMinimized()) @@ -192,7 +182,7 @@ void iwObservate::Draw_() view->Draw(road, parentView.GetSelectedPt(), false); // Draw indicator for center point - if(!followMovableId) + if(followingObject) LOADER.GetMapTexture(23)->DrawFull(view->GetPos() + view->GetSize() / 2u); } @@ -201,36 +191,26 @@ void iwObservate::Draw_() bool iwObservate::MoveToFollowedObj() { - // First look around the center (figure is normally still there) - const GameWorldBase& world = view->GetWorld(); - const MapPoint centerPt = world.MakeMapPoint((view->GetFirstPt() + view->GetLastPt()) / 2); - const std::vector centerPts = world.GetPointsInRadiusWithCenter(centerPt, 2); - for(const MapPoint& curPt : centerPts) - { - if(MoveToFollowedObj(curPt)) - return true; - } - - // Not at the center (normally due to lags) -> Check full area - for(int y = view->GetFirstPt().y; y <= view->GetLastPt().y; ++y) - { - for(int x = view->GetFirstPt().x; x <= view->GetLastPt().x; ++x) - { - const MapPoint curPt = world.MakeMapPoint(Position(x, y)); - if(MoveToFollowedObj(curPt)) - return true; - } - } - return false; + const auto& world = view->GetWorld(); + const auto centerPt = world.MakeMapPoint((view->GetFirstPt() + view->GetLastPt()) / 2); + bool result = false; + world.CheckPointsInRadius(centerPt, 3, [&, this](MapPoint curPt, unsigned) { + result = MoveToFollowedObj(curPt); + if(result) + return CheckPointsBreak; + return CheckPointsContinue; + }, true); + return result; } bool iwObservate::MoveToFollowedObj(const MapPoint ptToCheck) { + const auto id = pickedObject.movable->GetObjId(); if(view->GetViewer().GetVisibility(ptToCheck) != Visibility::Visible) return false; for(const noBase& obj : view->GetWorld().GetFigures(ptToCheck)) { - if(obj.GetObjId() == followMovableId) + if(obj.GetObjId() == id) { const auto& followMovable = static_cast(obj); DrawPoint drawPt = view->GetWorld().GetNodePos(ptToCheck); @@ -272,7 +252,7 @@ bool iwObservate::Msg_RightDown(const MouseCoords& mc) scrollOrigin = mc.GetPos(); isScrolling = true; - followMovableId = 0; + followingObject = false; WINDOWMANAGER.SetCursor(Cursor::Scroll); } else { diff --git a/libs/s25main/ingameWindows/iwObservate.h b/libs/s25main/ingameWindows/iwObservate.h index 3746bb209..28f8aea7b 100644 --- a/libs/s25main/ingameWindows/iwObservate.h +++ b/libs/s25main/ingameWindows/iwObservate.h @@ -13,7 +13,7 @@ class noMovable; struct PickedMovableObject { - static constexpr unsigned long EXPIRATION = 5000; + static constexpr unsigned long EXPIRATION = 6000; PickedMovableObject() = default; @@ -44,15 +44,15 @@ class iwObservate : public IngameWindow unsigned zoomLvl; - /// id of object currently followed or INVALID_ID - unsigned followMovableId; + PickedMovableObject pickedObject; + bool followingObject = false; public: static bool PickMovableObject(const GameWorldView& gwv, PickedMovableObject& pmo, MapPoint mapPt, DrawPoint drawPt); static bool PickMovableObjectAtCursor(const GameWorldView& gwv, PickedMovableObject& pmo); static bool TrackPickedMovableObject(const GameWorldView& gwv, PickedMovableObject& pmo); - iwObservate(GameWorldView& gwv, MapPoint selectedPt); + iwObservate(GameWorldView& gwv, MapPoint selectedPt, const PickedMovableObject& pmo); private: void Draw_() override;