diff --git a/ext/ghoul b/ext/ghoul index bb643bb1d5..3bd220b9fc 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit bb643bb1d578a8cf471476d7a555d5170cb105c9 +Subproject commit 3bd220b9fc3d8f05af79c1c5c7594755499b77be diff --git a/modules/base/rendering/renderablemodel.cpp b/modules/base/rendering/renderablemodel.cpp index 56aefb946a..5c0bc62f3f 100644 --- a/modules/base/rendering/renderablemodel.cpp +++ b/modules/base/rendering/renderablemodel.cpp @@ -150,9 +150,25 @@ namespace { // In format 'YYYY MM DD hh:mm:ss'. std::optional animationStartTime [[codegen::dateTime()]]; + enum class TimeUnit { + Millisecond, + Second + }; + // The time scale for the animation relative to seconds. - // Ex if animation is in milli seconds then AnimationTimeScale = 1000 - std::optional animationTimeScale; + // Ex, if animation is in milliseconds then AnimationTimeScale = 0.001 or + // AnimationTimeScale = "Millisecond", default is "Second" + std::optional> animationTimeScale; + + enum class AnimationMode { + Once, + LoopFromStart, + Bounce + }; + + // The mode of how the animation should be played back. + // Default is animation is played back once at the start time + std::optional animationMode; // [[codegen::verbatim(AmbientIntensityInfo.description)]] std::optional ambientIntensity; @@ -176,7 +192,7 @@ namespace { std::optional rotationVector; // [[codegen::verbatim(LightSourcesInfo.description)]] - std::optional> lightSources [[codegen::reference("core_light_source")]]; + std::optional> lightSources [[codegen::reference("core_light_source")]]; // [[codegen::verbatim(DisableDepthTestInfo.description)]] std::optional disableDepthTest; @@ -297,7 +313,37 @@ RenderableModel::RenderableModel(const ghoul::Dictionary& dictionary) } if (p.animationTimeScale.has_value()) { - _geometry->setTimeScale(*p.animationTimeScale); + if (std::holds_alternative(*p.animationTimeScale)) { + _geometry->setTimeScale(std::get(*p.animationTimeScale)); + } + else if (std::holds_alternative(*p.animationTimeScale)) { + Parameters::TimeUnit timeUnit = + std::get(*p.animationTimeScale); + + switch (timeUnit) { + case Parameters::TimeUnit::Millisecond: + _geometry->setTimeScale(0.001); + break; + case Parameters::TimeUnit::Second: + _geometry->setTimeScale(1.0); + break; + } + } + } + + if (p.animationMode.has_value()) { + switch (*p.animationMode) { + case Parameters::AnimationMode::LoopFromStart: + _animationMode = AnimationMode::LoopFromStart; + break; + case Parameters::AnimationMode::Bounce: + _animationMode = AnimationMode::Bounce; + break; + case Parameters::AnimationMode::Once: + default: + _animationMode = AnimationMode::Once; + break; + } } if (p.modelTransform.has_value()) { @@ -534,8 +580,22 @@ void RenderableModel::update(const UpdateData& data) { ghoul::opengl::updateUniformLocations(*_program, _uniformCache, UniformNames); } - double realtiveTime = data.time.j2000Seconds() - data.time.convertTime(_animationStart); if (_geometry->hasAnimation()) { + double realtiveTime; + switch (_animationMode) { + case AnimationMode::LoopFromStart: + realtiveTime = std::fmod( + data.time.j2000Seconds() - data.time.convertTime(_animationStart), + _geometry->animationDuration() + ); + break; + case AnimationMode::Once: + default: + realtiveTime = + data.time.j2000Seconds() - data.time.convertTime(_animationStart); + break; + } + _geometry->update(realtiveTime); } } diff --git a/modules/base/rendering/renderablemodel.h b/modules/base/rendering/renderablemodel.h index da96c8a1da..7ef6d4a977 100644 --- a/modules/base/rendering/renderablemodel.h +++ b/modules/base/rendering/renderablemodel.h @@ -70,10 +70,17 @@ public: static documentation::Documentation Documentation(); private: + enum class AnimationMode { + Once = 0, + LoopFromStart, + Bounce + }; + std::unique_ptr _geometry; bool _forceRenderInvisible = false; bool _notifyInvisibleDropped = true; std::string _animationStart; + AnimationMode _animationMode; properties::FloatProperty _ambientIntensity;