Skip to content

Commit 9266716

Browse files
committed
Implement user sprite manager and factory
1 parent 760a4c9 commit 9266716

File tree

4 files changed

+199
-31
lines changed

4 files changed

+199
-31
lines changed

Diff for: src/libprojectM/UserSprites/Factory.cpp

+14-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
1-
#include "Factory.hpp"
1+
#include "UserSprites/Factory.hpp"
2+
3+
#include "UserSprites/MilkdropSprite.hpp"
4+
5+
#include <Utils.hpp>
26

37
namespace libprojectM {
48
namespace UserSprites {
59

6-
Factory::Factory()
10+
auto Factory::CreateSprite(const std::string& type) -> Sprite::Ptr
711
{
8-
}
12+
const auto lowerCaseType = Utils::ToLower(type);
913

10-
Factory::~Factory()
11-
{
14+
if (lowerCaseType == "milkdrop")
15+
{
16+
return std::make_unique<MilkdropSprite>();
17+
}
18+
19+
return {};
1220
}
1321

22+
1423
} // namespace UserSprites
1524
} // namespace libprojectM

Diff for: src/libprojectM/UserSprites/Factory.hpp

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
#pragma once
22

3+
#include "UserSprites/Sprite.hpp"
4+
5+
#include <memory>
6+
#include <string>
7+
38
namespace libprojectM {
49
namespace UserSprites {
510

611
class Factory
712
{
813
public:
9-
Factory();
10-
11-
virtual ~Factory();
14+
Factory() = delete;
1215

13-
private:
16+
static auto CreateSprite(const std::string& type) -> Sprite::Ptr;
1417
};
1518

1619
} // namespace UserSprites

Diff for: src/libprojectM/UserSprites/SpriteManager.cpp

+132-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,143 @@
1-
#include "SpriteManager.hpp"
1+
#include "UserSprites/SpriteManager.hpp"
2+
3+
#include "UserSprites/Factory.hpp"
4+
5+
#include <Renderer/Shader.hpp>
6+
7+
#include <algorithm>
28

39
namespace libprojectM {
410
namespace UserSprites {
511

6-
SpriteManager::SpriteManager()
12+
auto SpriteManager::Spawn(const std::string& type,
13+
const std::string& spriteData,
14+
const Renderer::RenderContext& renderContext) -> uint32_t
15+
{
16+
// If user set the limit to zero, don't bother.
17+
if (m_spriteSlots == 0)
18+
{
19+
return 0;
20+
}
21+
22+
auto sprite = Factory::CreateSprite(type);
23+
24+
if (!sprite)
25+
{
26+
return 0;
27+
}
28+
29+
try
30+
{
31+
sprite->Init(spriteData, renderContext);
32+
}
33+
catch (SpriteException& ex)
34+
{
35+
return 0;
36+
}
37+
catch (Renderer::ShaderException& ex)
38+
{
39+
return 0;
40+
}
41+
catch (...)
42+
{
43+
return 0;
44+
}
45+
46+
auto spriteIdentifier = GetLowestFreeIdentifier();
47+
48+
// Already at max sprites, destroy the oldest sprite to make room.
49+
if (m_sprites.size() == m_spriteSlots)
50+
{
51+
Destroy(m_sprites.front().first);
52+
}
53+
54+
m_sprites.emplace_back(spriteIdentifier, std::move(sprite));
55+
m_spriteIdentifiers.insert(spriteIdentifier);
56+
57+
return spriteIdentifier;
58+
}
59+
60+
void SpriteManager::Draw(const Audio::FrameAudioData& audioData,
61+
const Renderer::RenderContext& renderContext,
62+
uint32_t outputFramebufferObject,
63+
Sprite::PresetList presets)
64+
{
65+
for (auto& idAndSprite : m_sprites) {
66+
idAndSprite.second->Draw(audioData, renderContext, outputFramebufferObject, presets);
67+
68+
if (idAndSprite.second->Done())
69+
{
70+
Destroy(idAndSprite.first);
71+
}
72+
}
73+
}
74+
75+
void SpriteManager::Destroy(SpriteIdentifier spriteIdentifier)
76+
{
77+
if (m_spriteIdentifiers.find(spriteIdentifier) == m_spriteIdentifiers.end())
78+
{
79+
return;
80+
}
81+
82+
m_spriteIdentifiers.erase(spriteIdentifier);
83+
m_sprites.remove_if([spriteIdentifier](const auto& idAndSprite) {
84+
return idAndSprite.first == spriteIdentifier;
85+
});
86+
}
87+
88+
void SpriteManager::DestroyAll()
89+
{
90+
m_spriteIdentifiers.clear();
91+
m_sprites.clear();
92+
}
93+
94+
auto SpriteManager::ActiveSpriteCount() const -> uint32_t
795
{
96+
return m_sprites.size();
897
}
998

10-
SpriteManager::~SpriteManager()
99+
auto SpriteManager::ActiveSpriteIdentifiers() const -> std::vector<SpriteIdentifier>
11100
{
101+
std::vector<SpriteIdentifier> identifierList;
102+
for (auto& idAndSprite : m_sprites) {
103+
identifierList.emplace_back(idAndSprite.first);
104+
}
105+
106+
return identifierList;
107+
}
108+
109+
void SpriteManager::SpriteSlots(uint32_t slots)
110+
{
111+
m_spriteSlots = slots;
112+
113+
// Remove excess sprites if limit was lowered
114+
while (m_sprites.size() > slots)
115+
{
116+
m_spriteIdentifiers.erase(m_sprites.front().first);
117+
m_sprites.pop_front();
118+
}
119+
}
120+
121+
auto SpriteManager::SpriteSlots() const -> uint32_t
122+
{
123+
return m_spriteSlots;
124+
}
125+
126+
auto SpriteManager::GetLowestFreeIdentifier() -> SpriteIdentifier
127+
{
128+
SpriteIdentifier lowestId = 0;
129+
130+
for (const auto& spriteId : m_spriteIdentifiers)
131+
{
132+
if (spriteId > lowestId + 1)
133+
{
134+
return lowestId + 1;
135+
}
136+
137+
lowestId = spriteId;
138+
}
139+
140+
return lowestId + 1;
12141
}
13142

14143
} // namespace UserSprites

Diff for: src/libprojectM/UserSprites/SpriteManager.hpp

+46-19
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,56 @@
11
#pragma once
22

3-
#include "Sprite.hpp"
3+
#include "UserSprites/Sprite.hpp"
4+
5+
#include <Renderer/RenderContext.hpp>
46

57
#include <cstdint>
68
#include <list>
9+
#include <set>
10+
#include <utility>
11+
#include <vector>
712

813
namespace libprojectM {
914
namespace UserSprites {
1015

1116
class SpriteManager
1217
{
1318
public:
14-
SpriteManager();
15-
16-
virtual ~SpriteManager();
19+
using SpriteIdentifier = uint32_t;
1720

1821
/**
1922
* @brief Spawns a new sprite.
23+
* @param type The type name of the sprite.
24+
* @param spriteData The sprite code/data, depending on the type.
25+
* @return A unique, non-zero identifier if the sprite was successfully spawned, or zero if an error occurred.
2026
*/
21-
void Spawn();
27+
auto Spawn(const std::string& type,
28+
const std::string& spriteData,
29+
const Renderer::RenderContext& renderContext) -> SpriteIdentifier;
2230

2331
/**
2432
* @brief Draws all active sprites.
33+
* @param audioData The frame audio data structure.
34+
* @param renderContext The current frame's rendering context.
35+
* @param outputFramebufferObject Framebuffer object the sprite will be rendered to.
36+
* @param presets The active preset, plus eventually the transitioning one. Used for the burn-in effect.
2537
*/
26-
void Draw();
38+
void Draw(const Audio::FrameAudioData& audioData,
39+
const Renderer::RenderContext& renderContext,
40+
uint32_t outputFramebufferObject,
41+
Sprite::PresetList presets);
2742

2843
/**
29-
* @brief Queues a single active sprite for destruction.
30-
*
31-
* The index is the 0-based index of the sprite in the list of currently active sprites, with 0 being the
32-
* oldest sprite being displayed. Sprites marked for destruction will be removed when drawing the next frame.
44+
* @brief Destroys a single active sprite.
3345
*
34-
* If spriteIndex is larger than the maximum index available, no action is taken.
46+
* If spriteIdentifier is invalid, no action will be taken.
3547
*
36-
* @param spriteIndex The slot index of the sprite to destroy.
48+
* @param spriteIdentifier The identifier of the sprite to destroy.
3749
*/
38-
void Destroy(uint32_t spriteIndex);
50+
void Destroy(SpriteIdentifier spriteIdentifier);
3951

4052
/**
41-
* @brief Marks all active sprites for destruction.
53+
* @brief Destroys all active sprites.
4254
*
4355
* Sprites will be removed when drawing the next frame.
4456
*/
@@ -48,12 +60,18 @@ class SpriteManager
4860
* @brief Returns the current number of active sprites.
4961
* @return The current number of active sprites.
5062
*/
51-
auto ActiveSprites() const -> uint32_t;
63+
auto ActiveSpriteCount() const -> uint32_t;
64+
65+
/**
66+
* @brief Returns a set of identifiers for all active sprites.
67+
* @return A vector with the identifiers of all active sprites.
68+
*/
69+
auto ActiveSpriteIdentifiers() const -> std::vector<SpriteIdentifier>;
5270

5371
/**
54-
* @brief Sets the numer of available sprite slots, e.g. the number of concurrently active sprites.
72+
* @brief Sets the number of available sprite slots, e.g. the number of concurrently active sprites.
5573
* If there are more active sprites than the newly set limit, the oldest sprites will be destroyed
56-
* when drawing the next frame until the new limit it met.
74+
* in order until the new limit is matched.
5775
* @param slots The maximum number of active sprites. 0 disables user sprites. Default is 16.
5876
*/
5977
void SpriteSlots(uint32_t slots);
@@ -65,8 +83,17 @@ class SpriteManager
6583
auto SpriteSlots() const -> uint32_t;
6684

6785
private:
68-
uint32_t m_spriteSlots{16}; //!< Max number of active sprites.
69-
std::list<Sprite::Ptr> m_sprites; //!< Active sprites.
86+
using SpriteIdPair = std::pair<SpriteIdentifier, Sprite::Ptr>;
87+
88+
/**
89+
* Returns the lowest free ID, starting at 1.
90+
* @return The lowest available/unused sprite ID.
91+
*/
92+
SpriteIdentifier GetLowestFreeIdentifier();
93+
94+
uint32_t m_spriteSlots{16}; //!< Max number of active sprites.
95+
std::set<SpriteIdentifier> m_spriteIdentifiers; //!< Set to keep track of ordered sprite IDs.
96+
std::list<SpriteIdPair> m_sprites; //!< Active sprites with their identifier.
7097
};
7198

7299
} // namespace UserSprites

0 commit comments

Comments
 (0)