Skip to content

Commit

Permalink
Pick object to follow early
Browse files Browse the repository at this point in the history
Pick the object to follow when the activity window is shown.
  • Loading branch information
falbrechtskirchinger committed Jul 20, 2023
1 parent b19225a commit 1b0811a
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 108 deletions.
14 changes: 12 additions & 2 deletions libs/s25main/ingameWindows/iwAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,9 @@ 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
pickedObject_ = PickedMovableObject::PickAtCursor(gwv, true);
}

main_tab->SetSelection(0, true);
Expand Down Expand Up @@ -706,8 +709,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<iwObservate>(gwv, selectedPt));
WINDOWMANAGER.Show(std::make_unique<iwObservate>(gwv, selectedPt, std::move(pickedObject_)));
DisableMousePosResetOnClose();
Close();
break;
Expand All @@ -731,3 +733,11 @@ void iwAction::DisableMousePosResetOnClose()
{
mousePosAtOpen_ = DrawPoint::Invalid();
}

void iwAction::Draw_()
{
IngameWindow::Draw_();

// track picked object (if valid)
pickedObject_.Track(gwv);
}
5 changes: 5 additions & 0 deletions libs/s25main/ingameWindows/iwAction.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#pragma once

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

PickedMovableObject pickedObject_;

public:
iwAction(GameInterface& gi, GameWorldView& gwv, const Tabs& tabs, MapPoint selectedPt, const DrawPoint& mousePos,
Params params, bool military_buildings);
Expand Down Expand Up @@ -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;
};
140 changes: 40 additions & 100 deletions libs/s25main/ingameWindows/iwObservate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "iwObservate.h"
#include "CollisionDetection.h"
#include "Loader.h"
#include "PickedMovableObject.h"
#include "Settings.h"
#include "WindowManager.h"
#include "controls/ctrlImageButton.h"
Expand All @@ -23,13 +24,13 @@ const Extent SmallWndSize(260, 190);
const Extent MediumWndSize(300, 250);
const Extent BigWndSize(340, 310);

iwObservate::iwObservate(GameWorldView& gwv, const MapPoint selectedPt)
iwObservate::iwObservate(GameWorldView& gwv, const MapPoint selectedPt, 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<unsigned short>::Invalid()), isScrolling(false), zoomLvl(0),
followMovableId(0)
pickedObject(std::move(pmo)), following(false), lastValid(pickedObject.IsValid())
{
view->MoveToMapPt(selectedPt);
view->SetZoomFactor(1.9f, false);
Expand All @@ -41,13 +42,16 @@ 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"));
AddImageButton(2, btPos, btSize, TextureColor::Grey, LOADER.GetImageN("io", 43));
// Zum Ort
btPos.x += btSize.x;
AddImageButton(3, btPos, btSize, TextureColor::Grey, LOADER.GetImageN("io", 107), _("Go to place"));
// Fenster vergroessern/verkleinern
btPos.x += btSize.x;
AddImageButton(4, btPos, btSize, TextureColor::Grey, LOADER.GetImageN("io", 109), _("Resize window"));

// Set follow button tooltip
UpdateFollowButton();
}

void iwObservate::Msg_ButtonClick(const unsigned ctrl_id)
Expand All @@ -69,53 +73,19 @@ void iwObservate::Msg_ButtonClick(const unsigned ctrl_id)
view->SetZoomFactor(2.3f);
break;
case 2:
{
if(followMovableId)
followMovableId = 0;
else
{
const DrawPoint centerDrawPt = DrawPoint(view->GetSize() / 2u);

double minDistance = std::numeric_limits<double>::max();

for(int y = view->GetFirstPt().y; y <= view->GetLastPt().y; ++y)
{
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<const noMovable*>(&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;
}
}
}
}
}

if(following)
// Stop following
pickedObject.Invalidate();
else if(!pickedObject.IsValid())
// If object is invalid, pick new object at center of view
pickedObject = PickedMovableObject::PickAtViewCenter(*view, false);

// Follow picked object, if valid
following = lastValid = pickedObject.IsValid();
// Cancel expiration; only has an effect if we started following the initially picked object
pickedObject.CancelExpiration();
UpdateFollowButton();
break;
}
case 3:
parentView.MoveToMapPt(MapPoint(view->GetLastPt() - (view->GetLastPt() - view->GetFirstPt()) / 2));
break;
Expand Down Expand Up @@ -159,11 +129,14 @@ void iwObservate::Draw_()
lastWindowPos = GetPos();
}

if(followMovableId)
// If the object was valid previously, track it (checks IsValid() for us)
// If it returns false, it either expired or we lost it
if(lastValid && !pickedObject.Track(*view, following))
{
if(!MoveToFollowedObj())
followMovableId = 0;
following = false;
UpdateFollowButton();
}
lastValid = pickedObject.IsValid();

if(!IsMinimized())
{
Expand All @@ -172,59 +145,13 @@ void iwObservate::Draw_()

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

return IngameWindow::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<MapPoint> 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;
}

bool iwObservate::MoveToFollowedObj(const MapPoint ptToCheck)
{
if(view->GetViewer().GetVisibility(ptToCheck) != Visibility::Visible)
return false;
for(const noBase& obj : view->GetWorld().GetFigures(ptToCheck))
{
if(obj.GetObjId() == followMovableId)
{
const auto& followMovable = static_cast<const noMovable&>(obj);
DrawPoint drawPt = view->GetWorld().GetNodePos(ptToCheck);

if(followMovable.IsMoving())
drawPt += followMovable.CalcWalkingRelative();

view->MoveTo(drawPt - view->GetSize() / 2u);
return true;
}
}
return false;
}

bool iwObservate::Msg_MouseMove(const MouseCoords& mc)
{
if(isScrolling)
Expand Down Expand Up @@ -252,7 +179,9 @@ bool iwObservate::Msg_RightDown(const MouseCoords& mc)
scrollOrigin = mc.GetPos();

isScrolling = true;
followMovableId = 0;
following = lastValid = false;
pickedObject.Invalidate();
UpdateFollowButton();
WINDOWMANAGER.SetCursor(Cursor::Scroll);
} else
{
Expand All @@ -270,3 +199,14 @@ bool iwObservate::Msg_RightUp(const MouseCoords& /*mc*/)

return true;
}

void iwObservate::UpdateFollowButton()
{
auto* button = GetCtrl<ctrlImageButton>(2);
if(following)
button->SetTooltip(_("Stop following object"));
else if(pickedObject.IsValid())
button->SetTooltip(_("Follow picked object"));
else
button->SetTooltip(_("Follow object near the center"));
}
13 changes: 7 additions & 6 deletions libs/s25main/ingameWindows/iwObservate.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#pragma once

#include "IngameWindow.h"
#include "PickedMovableObject.h"
#include "gameTypes/MapCoordinates.h"

class GameWorldView;
Expand All @@ -27,19 +28,19 @@ class iwObservate : public IngameWindow

unsigned zoomLvl;

/// id of object currently followed or INVALID_ID
unsigned followMovableId;
// Follow object
PickedMovableObject pickedObject;
bool following;
bool lastValid; // keep previous IsValid() result to detect transitions

public:
iwObservate(GameWorldView& gwv, MapPoint selectedPt);
iwObservate(GameWorldView& gwv, MapPoint selectedPt, PickedMovableObject&& pmo);

private:
void Draw_() override;
void Msg_ButtonClick(unsigned ctrl_id) override;
bool Msg_MouseMove(const MouseCoords& mc) override;
bool Msg_RightDown(const MouseCoords& mc) override;
bool Msg_RightUp(const MouseCoords& mc) override;
/// Move view to the object we currently follow, return true if it can still be found
bool MoveToFollowedObj();
inline bool MoveToFollowedObj(MapPoint ptToCheck);
void UpdateFollowButton();
};

0 comments on commit 1b0811a

Please sign in to comment.