Skip to content

Commit b6277e8

Browse files
committed
Add API to set or retrieve values from user sprite expression variables
This enables developers to externally control user sprites from the application code, e.g. allowing for interactive effects like rotation or movement to display logos, watermarks and other stuff.
1 parent 4d28493 commit b6277e8

9 files changed

Lines changed: 160 additions & 10 deletions

File tree

src/api/include/projectM-4/user_sprites.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,28 @@ PROJECTM_EXPORT void projectm_sprite_set_max_sprites(projectm_handle instance,
123123
*/
124124
PROJECTM_EXPORT uint32_t projectm_sprite_get_max_sprites(projectm_handle instance);
125125

126+
/**
127+
* @brief Retrieves the current value of an expression variable of a given sprite.
128+
*
129+
* @param instance The projectM instance handle.
130+
* @param sprite_id The sprite ID returned by projectm_sprite_create() to retrieve the value for.
131+
* @param var_name The variable name to retrieve the value for.
132+
* @return The current value of the requested variable. Returns 0.0 if the variable is not defined.
133+
* @since 4.2.0
134+
*/
135+
PROJECTM_EXPORT double projectm_sprite_get_var(projectm_handle instance, uint32_t sprite_id, const char* var_name);
136+
137+
/**
138+
* @brief Sets the value of the given variable for a single sprite instance.
139+
*
140+
* @param instance The projectM instance handle.
141+
* @param sprite_id The sprite ID returned by projectm_sprite_create() to set the value for.
142+
* @param var_name The variable to set a new value for.
143+
* @param value The new value.
144+
* @since 4.2.0
145+
*/
146+
PROJECTM_EXPORT void projectm_sprite_set_var(projectm_handle instance, uint32_t sprite_id, const char* var_name, double value);
147+
126148
#ifdef __cplusplus
127149
} // extern "C"
128150
#endif

src/libprojectM/ProjectM.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,16 @@ auto ProjectM::UserSpriteIdentifiers() const -> std::vector<uint32_t>
366366
return m_spriteManager->ActiveSpriteIdentifiers();
367367
}
368368

369+
auto ProjectM::UserSpriteGetVariableValue(uint32_t spriteId, const std::string& variableName) const -> double
370+
{
371+
return m_spriteManager->GetSpriteVariableValue(spriteId, variableName);
372+
}
373+
374+
void ProjectM::UserSpriteSetVariableValue(uint32_t spriteId, const std::string& variableName, double value)
375+
{
376+
m_spriteManager->SetSpriteVariableValue(spriteId, variableName, value);
377+
}
378+
369379
void ProjectM::BurnInTexture(uint32_t openGlTextureId, int left, int top, int width, int height)
370380
{
371381
if (m_activePreset)

src/libprojectM/ProjectM.hpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,22 @@ class PROJECTM_CXX_EXPORT ProjectM
271271
*/
272272
auto UserSpriteIdentifiers() const -> std::vector<uint32_t>;
273273

274+
/**
275+
* @brief Returns the current value of a variable in a user sprite's expression code.
276+
* @param spriteId The sprite ID to retrieve the value for.
277+
* @param variableName The variable to retrieve the value for.
278+
* @return The value of the requested variable and sprite.
279+
*/
280+
auto UserSpriteGetVariableValue(uint32_t spriteId, const std::string& variableName) const -> double;
281+
282+
/**
283+
* @brief Set the value of a variable in a user sprite's expression code.
284+
* @param spriteId The sprite ID to set the value for.
285+
* @param variableName The variable to set the value for.
286+
* @param value The new value.
287+
*/
288+
void UserSpriteSetVariableValue(uint32_t spriteId, const std::string& variableName, double value);
289+
274290
/**
275291
* @brief Draws the given texture on the active preset's main texture to get a "burn-in" effect.
276292
* @param openGlTextureId The OpenGL texture to draw onto the active preset(s).

src/libprojectM/ProjectMCWrapper.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,19 @@ uint32_t projectm_sprite_get_max_sprites(projectm_handle instance)
538538
return projectMInstance->UserSpriteLimit();
539539
}
540540

541+
double projectm_sprite_get_var(projectm_handle instance, uint32_t sprite_id, const char* var_name)
542+
{
543+
auto* projectMInstance = handle_to_instance(instance);
544+
545+
return projectMInstance->UserSpriteGetVariableValue(sprite_id, var_name);
546+
}
547+
548+
void projectm_sprite_set_var(projectm_handle instance, uint32_t sprite_id, const char* var_name, double value)
549+
{
550+
auto* projectMInstance = handle_to_instance(instance);
551+
552+
projectMInstance->UserSpriteSetVariableValue(sprite_id, var_name, value);
553+
}
541554
void projectm_set_log_callback(projectm_log_callback callback, bool current_thread_only, void* user_data)
542555
{
543556
if (current_thread_only)

src/libprojectM/UserSprites/MilkdropSprite.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,26 @@ auto MilkdropSprite::Done() const -> bool
290290
return m_spriteDone;
291291
}
292292

293+
auto MilkdropSprite::GetVariableValue(const std::string& variableName) const -> double
294+
{
295+
PRJM_EVAL_F const* var = projectm_eval_context_register_variable(m_codeContext.spriteCodeContext, variableName.c_str());
296+
if (var != nullptr)
297+
{
298+
return *var;
299+
}
300+
301+
return 0.0;
302+
}
303+
304+
void MilkdropSprite::SetVariableValue(const std::string& variableName, double value)
305+
{
306+
PRJM_EVAL_F * var = projectm_eval_context_register_variable(m_codeContext.spriteCodeContext, variableName.c_str());
307+
if (var != nullptr)
308+
{
309+
*var = value;
310+
}
311+
}
312+
293313
MilkdropSprite::CodeContext::CodeContext()
294314
: spriteCodeContext(projectm_eval_context_create(nullptr, nullptr))
295315
{

src/libprojectM/UserSprites/MilkdropSprite.hpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ class MilkdropSprite : public Sprite
2727

2828
auto Done() const -> bool override;
2929

30+
auto GetVariableValue(const std::string& variableName) const -> double override;
31+
32+
void SetVariableValue(const std::string& variableName, double value) override;
33+
3034
private:
3135
/**
3236
* @brief Context for the init and per-frame code.
@@ -43,7 +47,7 @@ class MilkdropSprite : public Sprite
4347

4448
/**
4549
* @brief Compiles and runs the init code of the sprite once, if any.
46-
* Also sets up a the default values of the output variables.
50+
* Also sets up the default values of the output variables.
4751
* @param initCode The initialization code.
4852
*/
4953
void RunInitCode(const std::string& initCode, const Renderer::RenderContext& renderContext);
@@ -74,15 +78,15 @@ class MilkdropSprite : public Sprite
7478
// Output variables
7579
PRJM_EVAL_F* done{}; //!< If this becomes non-zero, the sprite is deleted. Default: 0.0
7680
PRJM_EVAL_F* burn{}; //!< If non-zero, the sprite will be "burned" into currently rendered presets when done is also true, effectively "dissolving" the sprite in the preset. Default: 1.0
77-
PRJM_EVAL_F* x{}; //!< Sprite x position (position of the image center). Range from -1000 to 1000. Default: 0.5
78-
PRJM_EVAL_F* y{}; //!< Sprite y position (position of the image center). Range from -1000 to 1000. Default: 0.5
79-
PRJM_EVAL_F* sx{}; //!< Sprite x scaling factor. Range from -1000 to 1000. Default: 1.0
80-
PRJM_EVAL_F* sy{}; //!< Sprite y scaling factor. Range from -1000 to 1000. Default: 1.0
81+
PRJM_EVAL_F* x{}; //!< Sprite X position (position of the image center). Range from -1000 to 1000. Default: 0.5
82+
PRJM_EVAL_F* y{}; //!< Sprite Y position (position of the image center). Range from -1000 to 1000. Default: 0.5
83+
PRJM_EVAL_F* sx{}; //!< Sprite X scaling factor. Range from -1000 to 1000. Default: 1.0
84+
PRJM_EVAL_F* sy{}; //!< Sprite Y scaling factor. Range from -1000 to 1000. Default: 1.0
8185
PRJM_EVAL_F* rot{}; //!< Sprite rotation in radians (2*PI equals one full rotation). Default: 0.0
82-
PRJM_EVAL_F* flipx{}; //!< If flag is non-zero, the sprite is flipped on the x axis. Default: 0.0
83-
PRJM_EVAL_F* flipy{}; //!< If flag is non-zero, the sprite is flipped on the y axis. Default: 0.0
84-
PRJM_EVAL_F* repeatx{}; //!< Repeat count of the image on the sprite quad on the x axis. Fractional values allowed. Range from 0.01 to 100.0. Default: 1.0
85-
PRJM_EVAL_F* repeaty{}; //!< Repeat count of the image on the sprite quad on the y axis. Fractional values allowed. Range from 0.01 to 100.0. Default: 1.0
86+
PRJM_EVAL_F* flipx{}; //!< If flag is non-zero, the sprite is flipped on the X axis. Default: 0.0
87+
PRJM_EVAL_F* flipy{}; //!< If flag is non-zero, the sprite is flipped on the Y axis. Default: 0.0
88+
PRJM_EVAL_F* repeatx{}; //!< Repeat count of the image on the sprite quad on the X axis. Fractional values allowed. Range from 0.01 to 100.0. Default: 1.0
89+
PRJM_EVAL_F* repeaty{}; //!< Repeat count of the image on the sprite quad on the Y axis. Fractional values allowed. Range from 0.01 to 100.0. Default: 1.0
8690
PRJM_EVAL_F* blendmode{}; //!< Image blending mode. 0 = Alpha blending (default), 1 = Decal mode (no transparency), 2 = Additive blending, 3 = Source color blending, 4 = Color key blending. Default: 0
8791
PRJM_EVAL_F* r{}; //!< Modulation color used in some blending modes. Default: 1.0
8892
PRJM_EVAL_F* g{}; //!< Modulation color used in some blending modes. Default: 1.0

src/libprojectM/UserSprites/Sprite.hpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,20 @@ class Sprite
4747
* @return true if the sprite should be deleted, false if not.
4848
*/
4949
virtual auto Done() const -> bool = 0;
50+
51+
/**
52+
* @brief Returns the current value of a variable in the sprite's expression code.
53+
* @param variableName The variable to retrieve the value for.
54+
* @return The value of the requested variable and sprite.
55+
*/
56+
virtual auto GetVariableValue(const std::string& variableName) const -> double = 0;
57+
58+
/**
59+
* @brief Set the value of a variable in the sprite's expression code.
60+
* @param variableName The variable to set the value for.
61+
* @param value The new value.
62+
*/
63+
virtual void SetVariableValue(const std::string& variableName, double value) = 0;
5064
};
5165

5266
} // namespace UserSprites

src/libprojectM/UserSprites/SpriteManager.cpp

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ void SpriteManager::Draw(const Audio::FrameAudioData& audioData,
6565
{
6666
std::vector<SpriteIdentifier> toDestroy;
6767

68-
for (auto& idAndSprite : m_sprites) {
68+
for (auto& idAndSprite : m_sprites)
69+
{
6970
idAndSprite.second->Draw(audioData, renderContext, outputFramebufferObject, presets);
7071

7172
if (idAndSprite.second->Done())
@@ -132,6 +133,40 @@ auto SpriteManager::SpriteSlots() const -> uint32_t
132133
return m_spriteSlots;
133134
}
134135

136+
auto SpriteManager::GetSpriteVariableValue(SpriteIdentifier spriteIdentifier, const std::string& variableName) const -> double
137+
{
138+
if (m_spriteIdentifiers.find(spriteIdentifier) == m_spriteIdentifiers.end())
139+
{
140+
return 0.0;
141+
}
142+
143+
for (const auto& idAndSprite : m_sprites)
144+
{
145+
if (idAndSprite.first == spriteIdentifier)
146+
{
147+
return idAndSprite.second->GetVariableValue(variableName);
148+
}
149+
}
150+
151+
return 0.0;
152+
}
153+
154+
void SpriteManager::SetSpriteVariableValue(SpriteIdentifier spriteIdentifier, const std::string& variableName, double value)
155+
{
156+
if (m_spriteIdentifiers.find(spriteIdentifier) == m_spriteIdentifiers.end())
157+
{
158+
return;
159+
}
160+
161+
for (const auto& idAndSprite : m_sprites)
162+
{
163+
if (idAndSprite.first == spriteIdentifier)
164+
{
165+
idAndSprite.second->SetVariableValue(variableName, value);
166+
}
167+
}
168+
}
169+
135170
auto SpriteManager::GetLowestFreeIdentifier() -> SpriteIdentifier
136171
{
137172
SpriteIdentifier lowestId = 0;

src/libprojectM/UserSprites/SpriteManager.hpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,22 @@ class SpriteManager
8282
*/
8383
auto SpriteSlots() const -> uint32_t;
8484

85+
/**
86+
* @brief Returns the current value of a variable in a user sprite's expression code.
87+
* @param spriteIdentifier The sprite ID to retrieve the value for.
88+
* @param variableName The variable to retrieve the value for.
89+
* @return The value of the requested variable and sprite.
90+
*/
91+
auto GetSpriteVariableValue(SpriteIdentifier spriteIdentifier, const std::string& variableName) const -> double;
92+
93+
/**
94+
* @brief Set the value of a variable in a user sprite's expression code.
95+
* @param spriteIdentifier The sprite ID to set the value for.
96+
* @param variableName The variable to set the value for.
97+
* @param value The new value.
98+
*/
99+
void SetSpriteVariableValue(SpriteIdentifier spriteIdentifier, const std::string& variableName, double value);
100+
85101
private:
86102
using SpriteIdPair = std::pair<SpriteIdentifier, Sprite::Ptr>;
87103

0 commit comments

Comments
 (0)