diff --git a/src/api/include/projectM-4/user_sprites.h b/src/api/include/projectM-4/user_sprites.h index 1f76646f65..87bba1c11d 100644 --- a/src/api/include/projectM-4/user_sprites.h +++ b/src/api/include/projectM-4/user_sprites.h @@ -123,6 +123,28 @@ PROJECTM_EXPORT void projectm_sprite_set_max_sprites(projectm_handle instance, */ PROJECTM_EXPORT uint32_t projectm_sprite_get_max_sprites(projectm_handle instance); +/** + * @brief Retrieves the current value of an expression variable of a given sprite. + * + * @param instance The projectM instance handle. + * @param sprite_id The sprite ID returned by projectm_sprite_create() to retrieve the value for. + * @param var_name The variable name to retrieve the value for. + * @return The current value of the requested variable. Returns 0.0 if the variable is not defined. + * @since 4.2.0 + */ +PROJECTM_EXPORT double projectm_sprite_get_var(projectm_handle instance, uint32_t sprite_id, const char* var_name); + +/** + * @brief Sets the value of the given variable for a single sprite instance. + * + * @param instance The projectM instance handle. + * @param sprite_id The sprite ID returned by projectm_sprite_create() to set the value for. + * @param var_name The variable to set a new value for. + * @param value The new value. + * @since 4.2.0 + */ +PROJECTM_EXPORT void projectm_sprite_set_var(projectm_handle instance, uint32_t sprite_id, const char* var_name, double value); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/libprojectM/ProjectM.cpp b/src/libprojectM/ProjectM.cpp index a042f244c6..5693bf2487 100644 --- a/src/libprojectM/ProjectM.cpp +++ b/src/libprojectM/ProjectM.cpp @@ -366,6 +366,16 @@ auto ProjectM::UserSpriteIdentifiers() const -> std::vector return m_spriteManager->ActiveSpriteIdentifiers(); } +auto ProjectM::UserSpriteGetVariableValue(uint32_t spriteId, const std::string& variableName) const -> double +{ + return m_spriteManager->GetSpriteVariableValue(spriteId, variableName); +} + +void ProjectM::UserSpriteSetVariableValue(uint32_t spriteId, const std::string& variableName, double value) +{ + m_spriteManager->SetSpriteVariableValue(spriteId, variableName, value); +} + void ProjectM::BurnInTexture(uint32_t openGlTextureId, int left, int top, int width, int height) { if (m_activePreset) diff --git a/src/libprojectM/ProjectM.hpp b/src/libprojectM/ProjectM.hpp index 9879e77f0c..eb7e1adbc4 100644 --- a/src/libprojectM/ProjectM.hpp +++ b/src/libprojectM/ProjectM.hpp @@ -271,6 +271,22 @@ class PROJECTM_CXX_EXPORT ProjectM */ auto UserSpriteIdentifiers() const -> std::vector; + /** + * @brief Returns the current value of a variable in a user sprite's expression code. + * @param spriteId The sprite ID to retrieve the value for. + * @param variableName The variable to retrieve the value for. + * @return The value of the requested variable and sprite. + */ + auto UserSpriteGetVariableValue(uint32_t spriteId, const std::string& variableName) const -> double; + + /** + * @brief Set the value of a variable in a user sprite's expression code. + * @param spriteId The sprite ID to set the value for. + * @param variableName The variable to set the value for. + * @param value The new value. + */ + void UserSpriteSetVariableValue(uint32_t spriteId, const std::string& variableName, double value); + /** * @brief Draws the given texture on the active preset's main texture to get a "burn-in" effect. * @param openGlTextureId The OpenGL texture to draw onto the active preset(s). diff --git a/src/libprojectM/ProjectMCWrapper.cpp b/src/libprojectM/ProjectMCWrapper.cpp index cd2bca2f2e..3c4c30839b 100644 --- a/src/libprojectM/ProjectMCWrapper.cpp +++ b/src/libprojectM/ProjectMCWrapper.cpp @@ -538,6 +538,19 @@ uint32_t projectm_sprite_get_max_sprites(projectm_handle instance) return projectMInstance->UserSpriteLimit(); } +double projectm_sprite_get_var(projectm_handle instance, uint32_t sprite_id, const char* var_name) +{ + auto* projectMInstance = handle_to_instance(instance); + + return projectMInstance->UserSpriteGetVariableValue(sprite_id, var_name); +} + +void projectm_sprite_set_var(projectm_handle instance, uint32_t sprite_id, const char* var_name, double value) +{ + auto* projectMInstance = handle_to_instance(instance); + + projectMInstance->UserSpriteSetVariableValue(sprite_id, var_name, value); +} void projectm_set_log_callback(projectm_log_callback callback, bool current_thread_only, void* user_data) { if (current_thread_only) diff --git a/src/libprojectM/UserSprites/MilkdropSprite.cpp b/src/libprojectM/UserSprites/MilkdropSprite.cpp index 7a8af5cb9e..2350ad2179 100644 --- a/src/libprojectM/UserSprites/MilkdropSprite.cpp +++ b/src/libprojectM/UserSprites/MilkdropSprite.cpp @@ -290,6 +290,26 @@ auto MilkdropSprite::Done() const -> bool return m_spriteDone; } +auto MilkdropSprite::GetVariableValue(const std::string& variableName) const -> double +{ + PRJM_EVAL_F const* var = projectm_eval_context_register_variable(m_codeContext.spriteCodeContext, variableName.c_str()); + if (var != nullptr) + { + return *var; + } + + return 0.0; +} + +void MilkdropSprite::SetVariableValue(const std::string& variableName, double value) +{ + PRJM_EVAL_F * var = projectm_eval_context_register_variable(m_codeContext.spriteCodeContext, variableName.c_str()); + if (var != nullptr) + { + *var = value; + } +} + MilkdropSprite::CodeContext::CodeContext() : spriteCodeContext(projectm_eval_context_create(nullptr, nullptr)) { diff --git a/src/libprojectM/UserSprites/MilkdropSprite.hpp b/src/libprojectM/UserSprites/MilkdropSprite.hpp index d19139012b..806b0cbae5 100644 --- a/src/libprojectM/UserSprites/MilkdropSprite.hpp +++ b/src/libprojectM/UserSprites/MilkdropSprite.hpp @@ -27,6 +27,10 @@ class MilkdropSprite : public Sprite auto Done() const -> bool override; + auto GetVariableValue(const std::string& variableName) const -> double override; + + void SetVariableValue(const std::string& variableName, double value) override; + private: /** * @brief Context for the init and per-frame code. @@ -43,7 +47,7 @@ class MilkdropSprite : public Sprite /** * @brief Compiles and runs the init code of the sprite once, if any. - * Also sets up a the default values of the output variables. + * Also sets up the default values of the output variables. * @param initCode The initialization code. */ void RunInitCode(const std::string& initCode, const Renderer::RenderContext& renderContext); @@ -74,15 +78,15 @@ class MilkdropSprite : public Sprite // Output variables PRJM_EVAL_F* done{}; //!< If this becomes non-zero, the sprite is deleted. Default: 0.0 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 - PRJM_EVAL_F* x{}; //!< Sprite x position (position of the image center). Range from -1000 to 1000. Default: 0.5 - PRJM_EVAL_F* y{}; //!< Sprite y position (position of the image center). Range from -1000 to 1000. Default: 0.5 - PRJM_EVAL_F* sx{}; //!< Sprite x scaling factor. Range from -1000 to 1000. Default: 1.0 - PRJM_EVAL_F* sy{}; //!< Sprite y scaling factor. Range from -1000 to 1000. Default: 1.0 + PRJM_EVAL_F* x{}; //!< Sprite X position (position of the image center). Range from -1000 to 1000. Default: 0.5 + PRJM_EVAL_F* y{}; //!< Sprite Y position (position of the image center). Range from -1000 to 1000. Default: 0.5 + PRJM_EVAL_F* sx{}; //!< Sprite X scaling factor. Range from -1000 to 1000. Default: 1.0 + PRJM_EVAL_F* sy{}; //!< Sprite Y scaling factor. Range from -1000 to 1000. Default: 1.0 PRJM_EVAL_F* rot{}; //!< Sprite rotation in radians (2*PI equals one full rotation). Default: 0.0 - PRJM_EVAL_F* flipx{}; //!< If flag is non-zero, the sprite is flipped on the x axis. Default: 0.0 - PRJM_EVAL_F* flipy{}; //!< If flag is non-zero, the sprite is flipped on the y axis. Default: 0.0 - 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 - 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 + PRJM_EVAL_F* flipx{}; //!< If flag is non-zero, the sprite is flipped on the X axis. Default: 0.0 + PRJM_EVAL_F* flipy{}; //!< If flag is non-zero, the sprite is flipped on the Y axis. Default: 0.0 + 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 + 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 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 PRJM_EVAL_F* r{}; //!< Modulation color used in some blending modes. Default: 1.0 PRJM_EVAL_F* g{}; //!< Modulation color used in some blending modes. Default: 1.0 diff --git a/src/libprojectM/UserSprites/Sprite.hpp b/src/libprojectM/UserSprites/Sprite.hpp index 629426af52..bd6524489f 100644 --- a/src/libprojectM/UserSprites/Sprite.hpp +++ b/src/libprojectM/UserSprites/Sprite.hpp @@ -47,6 +47,20 @@ class Sprite * @return true if the sprite should be deleted, false if not. */ virtual auto Done() const -> bool = 0; + + /** + * @brief Returns the current value of a variable in the sprite's expression code. + * @param variableName The variable to retrieve the value for. + * @return The value of the requested variable and sprite. + */ + virtual auto GetVariableValue(const std::string& variableName) const -> double = 0; + + /** + * @brief Set the value of a variable in the sprite's expression code. + * @param variableName The variable to set the value for. + * @param value The new value. + */ + virtual void SetVariableValue(const std::string& variableName, double value) = 0; }; } // namespace UserSprites diff --git a/src/libprojectM/UserSprites/SpriteManager.cpp b/src/libprojectM/UserSprites/SpriteManager.cpp index 7be05f814d..9891ad8792 100644 --- a/src/libprojectM/UserSprites/SpriteManager.cpp +++ b/src/libprojectM/UserSprites/SpriteManager.cpp @@ -65,7 +65,8 @@ void SpriteManager::Draw(const Audio::FrameAudioData& audioData, { std::vector toDestroy; - for (auto& idAndSprite : m_sprites) { + for (auto& idAndSprite : m_sprites) + { idAndSprite.second->Draw(audioData, renderContext, outputFramebufferObject, presets); if (idAndSprite.second->Done()) @@ -132,6 +133,40 @@ auto SpriteManager::SpriteSlots() const -> uint32_t return m_spriteSlots; } +auto SpriteManager::GetSpriteVariableValue(SpriteIdentifier spriteIdentifier, const std::string& variableName) const -> double +{ + if (m_spriteIdentifiers.find(spriteIdentifier) == m_spriteIdentifiers.end()) + { + return 0.0; + } + + for (const auto& idAndSprite : m_sprites) + { + if (idAndSprite.first == spriteIdentifier) + { + return idAndSprite.second->GetVariableValue(variableName); + } + } + + return 0.0; +} + +void SpriteManager::SetSpriteVariableValue(SpriteIdentifier spriteIdentifier, const std::string& variableName, double value) +{ + if (m_spriteIdentifiers.find(spriteIdentifier) == m_spriteIdentifiers.end()) + { + return; + } + + for (const auto& idAndSprite : m_sprites) + { + if (idAndSprite.first == spriteIdentifier) + { + idAndSprite.second->SetVariableValue(variableName, value); + } + } +} + auto SpriteManager::GetLowestFreeIdentifier() -> SpriteIdentifier { SpriteIdentifier lowestId = 0; diff --git a/src/libprojectM/UserSprites/SpriteManager.hpp b/src/libprojectM/UserSprites/SpriteManager.hpp index 6ad391cd4c..050243dc90 100644 --- a/src/libprojectM/UserSprites/SpriteManager.hpp +++ b/src/libprojectM/UserSprites/SpriteManager.hpp @@ -82,6 +82,22 @@ class SpriteManager */ auto SpriteSlots() const -> uint32_t; + /** + * @brief Returns the current value of a variable in a user sprite's expression code. + * @param spriteIdentifier The sprite ID to retrieve the value for. + * @param variableName The variable to retrieve the value for. + * @return The value of the requested variable and sprite. + */ + auto GetSpriteVariableValue(SpriteIdentifier spriteIdentifier, const std::string& variableName) const -> double; + + /** + * @brief Set the value of a variable in a user sprite's expression code. + * @param spriteIdentifier The sprite ID to set the value for. + * @param variableName The variable to set the value for. + * @param value The new value. + */ + void SetSpriteVariableValue(SpriteIdentifier spriteIdentifier, const std::string& variableName, double value); + private: using SpriteIdPair = std::pair;