diff --git a/src/openrct2/Context.cpp b/src/openrct2/Context.cpp
index fe376141b1..6ac59f67a2 100644
--- a/src/openrct2/Context.cpp
+++ b/src/openrct2/Context.cpp
@@ -63,6 +63,7 @@
#include "ui/UiContext.h"
#include "ui/WindowManager.h"
#include "util/Util.h"
+#include "world/EntityTweener.h"
#include "world/Park.h"
#include "world/Sprite.h"
diff --git a/src/openrct2/ReplayManager.cpp b/src/openrct2/ReplayManager.cpp
index 81c6746bd8..e3022c3190 100644
--- a/src/openrct2/ReplayManager.cpp
+++ b/src/openrct2/ReplayManager.cpp
@@ -29,6 +29,7 @@
#include "object/ObjectManager.h"
#include "object/ObjectRepository.h"
#include "rct2/S6Exporter.h"
+#include "world/EntityTweener.h"
#include "world/Park.h"
#include "world/Sprite.h"
#include "zlib.h"
diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj
index c1ec236294..709f91c421 100644
--- a/src/openrct2/libopenrct2.vcxproj
+++ b/src/openrct2/libopenrct2.vcxproj
@@ -443,6 +443,7 @@
+
@@ -865,6 +866,7 @@
+
diff --git a/src/openrct2/network/NetworkBase.cpp b/src/openrct2/network/NetworkBase.cpp
index 67513a98ac..d78195f95f 100644
--- a/src/openrct2/network/NetworkBase.cpp
+++ b/src/openrct2/network/NetworkBase.cpp
@@ -25,6 +25,7 @@
#include "../ui/WindowManager.h"
#include "../util/SawyerCoding.h"
#include "../world/EntityList.h"
+#include "../world/EntityTweener.h"
#include "../world/Location.hpp"
#include "../world/Sprite.h"
#include "network.h"
diff --git a/src/openrct2/peep/Peep.cpp b/src/openrct2/peep/Peep.cpp
index 251ea87d72..8015ae0898 100644
--- a/src/openrct2/peep/Peep.cpp
+++ b/src/openrct2/peep/Peep.cpp
@@ -36,6 +36,7 @@
#include "../windows/Intent.h"
#include "../world/Balloon.h"
#include "../world/Climate.h"
+#include "../world/EntityTweener.h"
#include "../world/Entrance.h"
#include "../world/Footpath.h"
#include "../world/LargeScenery.h"
diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp
index 2cf402ad0a..27fea354e6 100644
--- a/src/openrct2/rct2/S6Importer.cpp
+++ b/src/openrct2/rct2/S6Importer.cpp
@@ -54,6 +54,7 @@
#include "../world/Climate.h"
#include "../world/Duck.h"
#include "../world/EntityList.h"
+#include "../world/EntityTweener.h"
#include "../world/Entrance.h"
#include "../world/Fountain.h"
#include "../world/Litter.h"
diff --git a/src/openrct2/world/EntityTweener.cpp b/src/openrct2/world/EntityTweener.cpp
new file mode 100644
index 0000000000..21de93d9a3
--- /dev/null
+++ b/src/openrct2/world/EntityTweener.cpp
@@ -0,0 +1,120 @@
+/*****************************************************************************
+ * Copyright (c) 2014-2021 OpenRCT2 developers
+ *
+ * For a complete list of all authors, please refer to contributors.md
+ * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
+ *
+ * OpenRCT2 is licensed under the GNU General Public License version 3.
+ *****************************************************************************/
+#include "EntityTweener.h"
+
+#include "../peep/Peep.h"
+#include "../ride/Vehicle.h"
+#include "EntityList.h"
+#include "Sprite.h"
+
+void EntityTweener::PopulateEntities()
+{
+ for (auto ent : EntityList())
+ {
+ Entities.push_back(ent);
+ PrePos.emplace_back(ent->x, ent->y, ent->z);
+ }
+ for (auto ent : EntityList())
+ {
+ Entities.push_back(ent);
+ PrePos.emplace_back(ent->x, ent->y, ent->z);
+ }
+ for (auto ent : EntityList())
+ {
+ Entities.push_back(ent);
+ PrePos.emplace_back(ent->x, ent->y, ent->z);
+ }
+}
+
+void EntityTweener::PreTick()
+{
+ Restore();
+ Reset();
+ PopulateEntities();
+}
+
+void EntityTweener::PostTick()
+{
+ for (auto* ent : Entities)
+ {
+ if (ent == nullptr)
+ {
+ // Sprite was removed, add a dummy position to keep the index aligned.
+ PostPos.emplace_back(0, 0, 0);
+ }
+ else
+ {
+ PostPos.emplace_back(ent->x, ent->y, ent->z);
+ }
+ }
+}
+
+void EntityTweener::RemoveEntity(SpriteBase* entity)
+{
+ if (!entity->Is() && !entity->Is())
+ {
+ // Only peeps and vehicles are tweened, bail if type is incorrect.
+ return;
+ }
+
+ auto it = std::find(Entities.begin(), Entities.end(), entity);
+ if (it != Entities.end())
+ *it = nullptr;
+}
+
+void EntityTweener::Tween(float alpha)
+{
+ const float inv = (1.0f - alpha);
+ for (size_t i = 0; i < Entities.size(); ++i)
+ {
+ auto* ent = Entities[i];
+ if (ent == nullptr)
+ continue;
+
+ auto& posA = PrePos[i];
+ auto& posB = PostPos[i];
+
+ if (posA == posB)
+ continue;
+
+ sprite_set_coordinates(
+ { static_cast(std::round(posB.x * alpha + posA.x * inv)),
+ static_cast(std::round(posB.y * alpha + posA.y * inv)),
+ static_cast(std::round(posB.z * alpha + posA.z * inv)) },
+ ent);
+ ent->Invalidate();
+ }
+}
+
+void EntityTweener::Restore()
+{
+ for (size_t i = 0; i < Entities.size(); ++i)
+ {
+ auto* ent = Entities[i];
+ if (ent == nullptr)
+ continue;
+
+ sprite_set_coordinates(PostPos[i], ent);
+ ent->Invalidate();
+ }
+}
+
+void EntityTweener::Reset()
+{
+ Entities.clear();
+ PrePos.clear();
+ PostPos.clear();
+}
+
+static EntityTweener tweener;
+
+EntityTweener& EntityTweener::Get()
+{
+ return tweener;
+}
diff --git a/src/openrct2/world/EntityTweener.h b/src/openrct2/world/EntityTweener.h
new file mode 100644
index 0000000000..1e3d734185
--- /dev/null
+++ b/src/openrct2/world/EntityTweener.h
@@ -0,0 +1,31 @@
+/*****************************************************************************
+ * Copyright (c) 2014-2021 OpenRCT2 developers
+ *
+ * For a complete list of all authors, please refer to contributors.md
+ * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
+ *
+ * OpenRCT2 is licensed under the GNU General Public License version 3.
+ *****************************************************************************/
+
+#include "SpriteBase.h"
+#include
+
+class EntityTweener
+{
+ std::vector Entities;
+ std::vector PrePos;
+ std::vector PostPos;
+
+private:
+ void PopulateEntities();
+
+public:
+ static EntityTweener& Get();
+
+ void PreTick();
+ void PostTick();
+ void RemoveEntity(SpriteBase* entity);
+ void Tween(float alpha);
+ void Restore();
+ void Reset();
+};
diff --git a/src/openrct2/world/Sprite.cpp b/src/openrct2/world/Sprite.cpp
index a5a7083e14..4aad4b1632 100644
--- a/src/openrct2/world/Sprite.cpp
+++ b/src/openrct2/world/Sprite.cpp
@@ -26,6 +26,7 @@
#include "../scenario/Scenario.h"
#include "Balloon.h"
#include "Duck.h"
+#include "EntityTweener.h"
#include "Fountain.h"
#include "MoneyEffect.h"
#include "Particle.h"
@@ -808,112 +809,6 @@ uint16_t remove_floating_sprites()
return removed;
}
-void EntityTweener::PopulateEntities()
-{
- for (auto ent : EntityList())
- {
- Entities.push_back(ent);
- PrePos.emplace_back(ent->x, ent->y, ent->z);
- }
- for (auto ent : EntityList())
- {
- Entities.push_back(ent);
- PrePos.emplace_back(ent->x, ent->y, ent->z);
- }
- for (auto ent : EntityList())
- {
- Entities.push_back(ent);
- PrePos.emplace_back(ent->x, ent->y, ent->z);
- }
-}
-
-void EntityTweener::PreTick()
-{
- Restore();
- Reset();
- PopulateEntities();
-}
-
-void EntityTweener::PostTick()
-{
- for (auto* ent : Entities)
- {
- if (ent == nullptr)
- {
- // Sprite was removed, add a dummy position to keep the index aligned.
- PostPos.emplace_back(0, 0, 0);
- }
- else
- {
- PostPos.emplace_back(ent->x, ent->y, ent->z);
- }
- }
-}
-
-void EntityTweener::RemoveEntity(SpriteBase* entity)
-{
- if (!entity->Is() && !entity->Is())
- {
- // Only peeps and vehicles are tweened, bail if type is incorrect.
- return;
- }
-
- auto it = std::find(Entities.begin(), Entities.end(), entity);
- if (it != Entities.end())
- *it = nullptr;
-}
-
-void EntityTweener::Tween(float alpha)
-{
- const float inv = (1.0f - alpha);
- for (size_t i = 0; i < Entities.size(); ++i)
- {
- auto* ent = Entities[i];
- if (ent == nullptr)
- continue;
-
- auto& posA = PrePos[i];
- auto& posB = PostPos[i];
-
- if (posA == posB)
- continue;
-
- sprite_set_coordinates(
- { static_cast(std::round(posB.x * alpha + posA.x * inv)),
- static_cast(std::round(posB.y * alpha + posA.y * inv)),
- static_cast(std::round(posB.z * alpha + posA.z * inv)) },
- ent);
- ent->Invalidate();
- }
-}
-
-void EntityTweener::Restore()
-{
- for (size_t i = 0; i < Entities.size(); ++i)
- {
- auto* ent = Entities[i];
- if (ent == nullptr)
- continue;
-
- sprite_set_coordinates(PostPos[i], ent);
- ent->Invalidate();
- }
-}
-
-void EntityTweener::Reset()
-{
- Entities.clear();
- PrePos.clear();
- PostPos.clear();
-}
-
-static EntityTweener tweener;
-
-EntityTweener& EntityTweener::Get()
-{
- return tweener;
-}
-
void sprite_set_flashing(SpriteBase* sprite, bool flashing)
{
assert(sprite->sprite_index < MAX_ENTITIES);
diff --git a/src/openrct2/world/Sprite.h b/src/openrct2/world/Sprite.h
index ccf3d80ead..873bbd6791 100644
--- a/src/openrct2/world/Sprite.h
+++ b/src/openrct2/world/Sprite.h
@@ -14,7 +14,6 @@
#include "SpriteBase.h"
#include
-#include
class DataSerialiser;
@@ -97,24 +96,4 @@ rct_sprite_checksum sprite_checksum();
void sprite_set_flashing(SpriteBase* sprite, bool flashing);
bool sprite_get_flashing(SpriteBase* sprite);
-class EntityTweener
-{
- std::vector Entities;
- std::vector PrePos;
- std::vector PostPos;
-
-private:
- void PopulateEntities();
-
-public:
- static EntityTweener& Get();
-
- void PreTick();
- void PostTick();
- void RemoveEntity(SpriteBase* entity);
- void Tween(float alpha);
- void Restore();
- void Reset();
-};
-
#endif
diff --git a/test/tests/PlayTests.cpp b/test/tests/PlayTests.cpp
index bc203938d5..3b41fb0bfb 100644
--- a/test/tests/PlayTests.cpp
+++ b/test/tests/PlayTests.cpp
@@ -21,6 +21,7 @@
#include
#include
#include
+#include
#include
#include
#include
diff --git a/test/tests/S6ImportExportTests.cpp b/test/tests/S6ImportExportTests.cpp
index 678e4d40e4..7044adfa16 100644
--- a/test/tests/S6ImportExportTests.cpp
+++ b/test/tests/S6ImportExportTests.cpp
@@ -32,6 +32,7 @@
#include
#include
#include
+#include
#include
#include
#include