diff --git a/src/supertux/game_object.cpp b/src/supertux/game_object.cpp index 9d82d28a475..73438d3df8d 100644 --- a/src/supertux/game_object.cpp +++ b/src/supertux/game_object.cpp @@ -207,6 +207,13 @@ GameObject::after_editor_set() m_previous_type = -1; } +void +GameObject::remove_me() +{ + m_scheduled_for_removal = true; + GameObjectManager::s_needs_flushing_gameobjects_removed = true; +} + int GameObject::type_id_to_value(const std::string& id) const { diff --git a/src/supertux/game_object.hpp b/src/supertux/game_object.hpp index 843e6202d53..60f1658e279 100644 --- a/src/supertux/game_object.hpp +++ b/src/supertux/game_object.hpp @@ -119,7 +119,7 @@ class GameObject virtual void on_flip(float height) {} /** schedules this object to be removed at the end of the frame */ - virtual void remove_me() { m_scheduled_for_removal = true; } + virtual void remove_me(); /** returns true if the object is not scheduled to be removed yet */ bool is_valid() const { return !m_scheduled_for_removal; } diff --git a/src/supertux/game_object_manager.cpp b/src/supertux/game_object_manager.cpp index 17b0490b35c..41c2027b6b6 100644 --- a/src/supertux/game_object_manager.cpp +++ b/src/supertux/game_object_manager.cpp @@ -25,6 +25,9 @@ #include "supertux/game_object_factory.hpp" bool GameObjectManager::s_draw_solids_only = false; +bool GameObjectManager::s_needs_flushing_gameobjects_added = false; +bool GameObjectManager::s_needs_flushing_gameobjects_removed = false; +bool GameObjectManager::s_needs_flushing_tilemaps = false; GameObjectManager::GameObjectManager(bool undo_tracking) : m_initialized(false), @@ -134,6 +137,7 @@ GameObjectManager::add_object(std::unique_ptr object) GameObject& tmp = *object; m_gameobjects_new.push_back(std::move(object)); + s_needs_flushing_gameobjects_added = true; return tmp; } @@ -182,6 +186,12 @@ GameObjectManager::draw(DrawingContext& context) void GameObjectManager::flush_game_objects() { + if(!s_needs_flushing_gameobjects_added && + !s_needs_flushing_gameobjects_removed && + !s_needs_flushing_tilemaps) + return; + + if(s_needs_flushing_gameobjects_removed) { // cleanup marked objects m_gameobjects.erase( std::remove_if(m_gameobjects.begin(), m_gameobjects.end(), @@ -196,8 +206,10 @@ GameObjectManager::flush_game_objects() } }), m_gameobjects.end()); + s_needs_flushing_gameobjects_removed = false; } + if(s_needs_flushing_gameobjects_added) { // add newly created objects // Objects might add new objects in finish_construction(), so we // loop until no new objects show up. @@ -213,8 +225,14 @@ GameObjectManager::flush_game_objects() } } } + s_needs_flushing_gameobjects_added = false; + } + + if(s_needs_flushing_tilemaps) + { + update_tilemaps(); + s_needs_flushing_tilemaps = false; } - update_tilemaps(); m_initialized = true; } @@ -381,7 +399,12 @@ GameObjectManager::this_before_object_add(GameObject& object) } { // by_type_index - m_objects_by_type_index[std::type_index(typeid(object))].push_back(&object); + auto typeIdx = std::type_index(typeid(object)); + m_objects_by_type_index[typeIdx].push_back(&object); + if(typeIdx == typeid(TileMap)) + { + s_needs_flushing_tilemaps = true; + } } save_object_change(object, true); @@ -409,6 +432,7 @@ GameObjectManager::this_before_object_remove(GameObject& object) auto it = std::find(vec.begin(), vec.end(), &object); assert(it != vec.end()); vec.erase(it); + s_needs_flushing_gameobjects_removed = true; } } diff --git a/src/supertux/game_object_manager.hpp b/src/supertux/game_object_manager.hpp index 857c2546e6f..c3e3c872fb9 100644 --- a/src/supertux/game_object_manager.hpp +++ b/src/supertux/game_object_manager.hpp @@ -37,6 +37,9 @@ class GameObjectManager { public: static bool s_draw_solids_only; + static bool s_needs_flushing_gameobjects_added; + static bool s_needs_flushing_gameobjects_removed; + static bool s_needs_flushing_tilemaps; private: struct NameResolveRequest