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