Add API flag to start presets with clean canvas

Adds projectm_set_preset_start_clean() and projectm_get_preset_start_clean()
functions to control whether new presets start with a black canvas or inherit
the previous preset's last frame.

Default behavior remains unchanged (copy previous frame), but applications
can now opt-in to clean starts by setting this flag to true.

Fixes #298
This commit is contained in:
Mischa
2026-01-21 21:34:30 -08:00
committed by Mischa Spiegelmock
parent 5acd8bf9ee
commit ceb86ebca7
4 changed files with 60 additions and 1 deletions

View File

@ -370,6 +370,30 @@ PROJECTM_EXPORT void projectm_set_window_size(projectm_handle instance, size_t w
*/
PROJECTM_EXPORT void projectm_get_window_size(projectm_handle instance, size_t* width, size_t* height);
/**
* @brief Sets whether newly loaded presets should start with a clean (black) canvas.
*
* By default, when switching presets, the last frame of the previous preset is copied into
* the new preset's main texture, creating a visual continuity. Setting this flag to true
* will cause each new preset to start with a black canvas instead.
*
* This is useful for applications that want a clean start for each preset, avoiding the
* "ghosting" effect from the previous preset.
*
* @param instance The projectM instance handle.
* @param enabled True to start new presets with a clean canvas, false to copy the previous frame. Default: false
* @since 4.2.0
*/
PROJECTM_EXPORT void projectm_set_preset_start_clean(projectm_handle instance, bool enabled);
/**
* @brief Returns whether newly loaded presets start with a clean canvas.
* @param instance The projectM instance handle.
* @return True if presets start with a clean canvas, false if the previous frame is copied.
* @since 4.2.0
*/
PROJECTM_EXPORT bool projectm_get_preset_start_clean(projectm_handle instance);
#ifdef __cplusplus
} // extern "C"
#endif

View File

@ -291,7 +291,7 @@ void ProjectM::StartPresetTransition(std::unique_ptr<Preset>&& preset, bool hard
m_transition.reset();
}
if (m_activePreset)
if (m_activePreset && !m_presetStartClean)
{
preset->DrawInitialImage(m_activePreset->OutputTexture(), GetRenderContext());
}
@ -384,6 +384,16 @@ auto ProjectM::PresetLocked() const -> bool
return m_presetLocked;
}
void ProjectM::SetPresetStartClean(bool enabled)
{
m_presetStartClean = enabled;
}
auto ProjectM::PresetStartClean() const -> bool
{
return m_presetStartClean;
}
void ProjectM::SetFrameTime(double secondsSinceStart)
{
m_timeKeeper->SetFrameTime(secondsSinceStart);

View File

@ -208,6 +208,18 @@ public:
/// Returns true if the active preset is locked
auto PresetLocked() const -> bool;
/**
* @brief Sets whether newly loaded presets should start with a clean (black) canvas.
* @param enabled True to start with a clean canvas, false to copy the previous frame.
*/
void SetPresetStartClean(bool enabled);
/**
* @brief Returns whether newly loaded presets start with a clean canvas.
* @return True if presets start with a clean canvas.
*/
auto PresetStartClean() const -> bool;
auto PCM() -> Audio::PCM&;
auto WindowWidth() -> int;
@ -305,6 +317,7 @@ private:
bool m_presetLocked{false}; //!< If true, the preset change event will not be sent.
bool m_presetChangeNotified{false}; //!< Stores whether the user has been notified that projectM wants to switch the preset.
bool m_presetStartClean{false}; //!< If true, new presets start with a black canvas instead of the previous frame.
std::unique_ptr<PresetFactoryManager> m_presetFactoryManager; //!< Provides access to all available preset factories.

View File

@ -417,6 +417,18 @@ void projectm_set_window_size(projectm_handle instance, size_t width, size_t hei
projectMInstance->SetWindowSize(static_cast<uint32_t>(width), static_cast<uint32_t>(height));
}
void projectm_set_preset_start_clean(projectm_handle instance, bool enabled)
{
auto projectMInstance = handle_to_instance(instance);
projectMInstance->SetPresetStartClean(enabled);
}
bool projectm_get_preset_start_clean(projectm_handle instance)
{
auto projectMInstance = handle_to_instance(instance);
return projectMInstance->PresetStartClean();
}
unsigned int projectm_pcm_get_max_samples()
{
return libprojectM::Audio::WaveformSamples;