1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-22 07:13:07 +01:00

Don't tween entities that are not visible on screen or when zoomed out

This commit is contained in:
ζeh Matt
2025-05-22 04:13:11 +03:00
parent f71b45b6ef
commit 3770ab0b51
2 changed files with 174 additions and 105 deletions

View File

@@ -10,6 +10,8 @@
#include "../entity/Guest.h" #include "../entity/Guest.h"
#include "../entity/Staff.h" #include "../entity/Staff.h"
#include "../interface/Viewport.h"
#include "../interface/Window.h"
#include "../ride/Vehicle.h" #include "../ride/Vehicle.h"
#include "EntityList.h" #include "EntityList.h"
#include "EntityRegistry.h" #include "EntityRegistry.h"
@@ -17,25 +19,79 @@
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
void EntityTweener::AddEntity(EntityBase* entity) namespace OpenRCT2
{ {
static inline ViewportList GetUnzoomedViewports() noexcept
{
ViewportList viewports;
WindowVisitEach([&](WindowBase* w) {
if (auto* vp = WindowGetViewport(w); vp != nullptr)
{
if (!vp->isVisible)
{
// Ignore viewports that are not visible.
return;
}
if (vp->zoom > ZoomLevel{ 0 })
{
// Ignore viewports that are zoomed out, interpolation wouldn't have much of an effect
// due to the loss of detail.
return;
}
viewports.push_back(vp);
}
});
return viewports;
}
static inline bool IsEntityVisible(const ViewportList& vpList, const EntityBase* entity) noexcept
{
const auto worldLoc = entity->GetLocation();
for (const auto* vp : vpList)
{
const auto screenPos = Translate3DTo2DWithZ(vp->rotation, worldLoc);
if (vp->Contains(screenPos))
{
// Entity is visible in at least one viewport, tween.
return true;
}
}
return false;
}
void EntityTweener::AddEntity(const ViewportList& vpList, EntityBase* entity)
{
if (!IsEntityVisible(vpList, entity))
{
return;
}
Entities.push_back(entity); Entities.push_back(entity);
PrePos.emplace_back(entity->GetLocation()); PrePos.emplace_back(entity->GetLocation());
} }
void EntityTweener::PopulateEntities() void EntityTweener::PopulateEntities()
{ {
const auto vpList = GetUnzoomedViewports();
if (vpList.empty())
{
// No viewports that fit the criteria, bail.
return;
}
for (auto ent : EntityList<Guest>()) for (auto ent : EntityList<Guest>())
{ {
AddEntity(ent); AddEntity(vpList, ent);
} }
for (auto ent : EntityList<Staff>()) for (auto ent : EntityList<Staff>())
{ {
AddEntity(ent); AddEntity(vpList, ent);
} }
for (auto ent : EntityList<Vehicle>()) for (auto ent : EntityList<Vehicle>())
{ {
AddEntity(ent); AddEntity(vpList, ent);
} }
} }
@@ -128,3 +184,5 @@ EntityTweener& EntityTweener::Get()
{ {
return tweener; return tweener;
} }
} // namespace OpenRCT2

View File

@@ -9,10 +9,19 @@
#pragma once #pragma once
#include "../interface/Window.h"
#include "EntityBase.h" #include "EntityBase.h"
#include <sfl/static_vector.hpp>
#include <vector> #include <vector>
namespace OpenRCT2
{
struct Viewport;
// TODO: Move this to somewhere else, currently filters also by zoom.
using ViewportList = sfl::static_vector<Viewport*, kWindowLimitMax>;
class EntityTweener class EntityTweener
{ {
std::vector<EntityBase*> Entities; std::vector<EntityBase*> Entities;
@@ -21,7 +30,7 @@ class EntityTweener
private: private:
void PopulateEntities(); void PopulateEntities();
void AddEntity(EntityBase* entity); void AddEntity(const ViewportList& vp, EntityBase* entity);
public: public:
static EntityTweener& Get(); static EntityTweener& Get();
@@ -33,3 +42,5 @@ public:
void Restore(); void Restore();
void Reset(); void Reset();
}; };
} // namespace OpenRCT2