diff --git a/bin/style.js b/bin/style.js index 691c91351..5a10a57a2 100644 --- a/bin/style.js +++ b/bin/style.js @@ -94,6 +94,9 @@ module.exports = { "min": 0, "max": 1 } + }, + "style.night": { + "fill-color": "blue" } }, { "id": "borders", diff --git a/include/llmr/style/applied_class_properties.hpp b/include/llmr/style/applied_class_properties.hpp index cda3a42a4..0c80b0a17 100644 --- a/include/llmr/style/applied_class_properties.hpp +++ b/include/llmr/style/applied_class_properties.hpp @@ -34,6 +34,10 @@ public: void add(ClassID class_id, timestamp begin, timestamp end, const PropertyValue &value) { properties.emplace_back(class_id, begin, end, value); } + + bool hasTransitions() const { + return properties.size() > 1; + } }; } diff --git a/include/llmr/style/style.hpp b/include/llmr/style/style.hpp index 6b9b4549c..ec1be163f 100644 --- a/include/llmr/style/style.hpp +++ b/include/llmr/style/style.hpp @@ -43,6 +43,8 @@ public: // of applied classes. void updateClasses(); + bool hasTransitions() const; + public: std::shared_ptr sprite; std::shared_ptr layers; diff --git a/include/llmr/style/style_layer.hpp b/include/llmr/style/style_layer.hpp index b04970f7c..e27c5690c 100644 --- a/include/llmr/style/style_layer.hpp +++ b/include/llmr/style/style_layer.hpp @@ -42,6 +42,8 @@ public: void setClasses(const std::vector &class_names, timestamp now, const PropertyTransition &defaultTransition); + bool hasTransitions() const; + private: // Applies all properties from a class, if they haven't been applied already. void applyClassProperties(ClassID class_id, std::set &already_applied, diff --git a/include/llmr/style/style_layer_group.hpp b/include/llmr/style/style_layer_group.hpp index 2122c1628..90c02bc1f 100644 --- a/include/llmr/style/style_layer_group.hpp +++ b/include/llmr/style/style_layer_group.hpp @@ -13,6 +13,7 @@ public: const PropertyTransition &defaultTransition); void updateProperties(float z, timestamp t); + bool hasTransitions() const; public: std::vector> layers; }; diff --git a/src/map/map.cpp b/src/map/map.cpp index 3417f8f6b..ed08d7f0f 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -495,7 +495,7 @@ void Map::render() { #endif // Schedule another rerender when we definitely need a next frame. - if (transform.needsTransition()) { + if (transform.needsTransition() || style->hasTransitions()) { update(); } diff --git a/src/style/style.cpp b/src/style/style.cpp index a08e77ac0..71d37b8dd 100644 --- a/src/style/style.cpp +++ b/src/style/style.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -55,7 +56,7 @@ void Style::updateProperties(float z, timestamp t) { } void Style::setDefaultTransitionDuration(uint16_t duration_milliseconds) { - defaultTransition.duration = duration_milliseconds; + defaultTransition.duration = duration_milliseconds * 1_millisecond; } const std::vector &Style::getAppliedClasses() const { @@ -81,6 +82,16 @@ void Style::updateClasses() { } } +bool Style::hasTransitions() const { + if (layers) { + if (layers->hasTransitions()) { + return true; + } + } + return false; +} + + void Style::loadJSON(const uint8_t *const data) { uv::writelock lock(mtx); diff --git a/src/style/style_layer.cpp b/src/style/style_layer.cpp index 19497aa9e..b41d87d59 100644 --- a/src/style/style_layer.cpp +++ b/src/style/style_layer.cpp @@ -181,6 +181,25 @@ private: const float z; }; +inline float interpolate(const float a, const float b, const float t) { + return (1.0f - t) * a + t * b; +} + +inline Color interpolate(const Color &a, const Color &b, const float t) { + const float rt = 1.0f - t; + return Color {{ + rt * a[0] + t * b[0], + rt * a[1] + t * b[1], + rt * a[2] + t * b[2], + rt * a[3] + t * b[3] + }}; +} + +template +inline T interpolate(const T a, const T b, const float t) { + return t >= 0.5 ? b : a; +} + template void StyleLayer::applyStyleProperty(PropertyKey key, T &target, const float z, const timestamp t) { auto it = appliedStyle.find(key); @@ -189,15 +208,15 @@ void StyleLayer::applyStyleProperty(PropertyKey key, T &target, const float z, c // Iterate through all properties that we need to apply in order. const PropertyEvaluator evaluator(z); for (AppliedClassProperty &property : applied.properties) { - if (property.end >= t) { + if (t >= property.end) { // We overwrite the current property with the new value. target = util::apply_visitor(evaluator, property.value); - } else if (property.begin <= t) { + } else if (t >= property.begin) { // We overwrite the current property partially with the new value. float progress = float(t - property.begin) / float(property.end - property.begin); - target = util::apply_visitor(evaluator, property.value); -// target = (1.0f - progress) * target + (progress) * -// evaluateProperty(property.value, target, z); + target = interpolate(target, util::apply_visitor(evaluator, property.value), progress); + } else { + // Do not apply this property because its transition hasn't begun yet. } } } @@ -268,5 +287,13 @@ void StyleLayer::updateProperties(float z, const timestamp t) { } } +bool StyleLayer::hasTransitions() const { + for (const std::pair &pair : appliedStyle) { + if (pair.second.hasTransitions()) { + return true; + } + } + return false; +} } diff --git a/src/style/style_layer_group.cpp b/src/style/style_layer_group.cpp index bb19df45b..86fe6fa24 100644 --- a/src/style/style_layer_group.cpp +++ b/src/style/style_layer_group.cpp @@ -1,3 +1,4 @@ + #include namespace llmr { @@ -19,4 +20,16 @@ void StyleLayerGroup::updateProperties(float z, timestamp t) { } } +bool StyleLayerGroup::hasTransitions() const { + for (const std::shared_ptr &layer: layers) { + if (layer) { + if (layer->hasTransitions()) { + return true; + } + } + } + return false; +} + + }