#pragma once #include <memory> #include <stack> #include <map> template<typename Type, class SpriteFactory, class Sprite, typename = std::enable_if_t<std::is_enum<Type>::value>> class SpriteContainer { public: explicit SpriteContainer(std::initializer_list<Type>&& types, std::unique_ptr<SpriteFactory>&& factory, std::size_t reserve_size = 20) : _sprite_factory(std::move(factory)), _poll_reserve_size(reserve_size) { for (const Type& type : types) reallocatePoll(type); } inline std::shared_ptr<Sprite> getSprite(Type type) { SpritePoll& poll = _sprite_dispatcher.at(type); if (poll.empty()) reallocatePoll(type); std::shared_ptr<Sprite> sprite = poll.top(); poll.pop(); return sprite; } inline void resetSprite(const std::shared_ptr<Sprite> &sprite, Type action) noexcept { _sprite_dispatcher[action].push(sprite); } ~SpriteContainer(){} private: inline void reallocatePoll(Type sprite_type) { SpritePoll &poll = _sprite_dispatcher[sprite_type]; for (std::size_t i = 0; i < _poll_reserve_size; ++i) { poll.push(_sprite_factory->create(sprite_type)); } } using SpritePoll = std::stack<std::shared_ptr<Sprite>>; std::map<Type, SpritePoll> _sprite_dispatcher; std::unique_ptr<SpriteFactory> _sprite_factory; std::size_t _poll_reserve_size; };