summaryrefslogtreecommitdiff
path: root/src/mbgl/style/paint_properties_map.hpp
blob: e32f723d8d4d97052a17e00038a836a6cd2c0f5e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#ifndef MBGL_PAINT_PROPERTIES_MAP
#define MBGL_PAINT_PROPERTIES_MAP

#include <mbgl/style/applied_class_properties.hpp>
#include <mbgl/style/property_evaluator.hpp>
#include <mbgl/style/class_dictionary.hpp>
#include <mbgl/style/property_key.hpp>

#include <mbgl/util/interpolate.hpp>

#include <rapidjson/document.h>

#include <map>
#include <set>
#include <functional>

namespace mbgl {

class ClassProperties;
class PropertyTransition;
class StyleCascadeParameters;

using JSVal = rapidjson::Value;

class PaintPropertiesMap {
public:
    void cascade(const StyleCascadeParameters&);

    bool hasTransitions() const;
    void removeExpiredTransitions(const TimePoint& now);

    // Call the function for each "paint" or "paint.*" object in the layer.
    void parseEach(const JSVal& layer, std::function<void (ClassProperties&, const JSVal&)>);

    template <typename T>
    void calculate(PropertyKey key, T& target, const StyleCalculationParameters& parameters) {
        auto it = appliedStyle.find(key);
        if (it != appliedStyle.end()) {
            AppliedClassPropertyValues &applied = it->second;
            // Iterate through all properties that we need to apply in order.
            const PropertyEvaluator<T> evaluator(parameters);
            for (auto& property : applied.propertyValues) {
                if (parameters.now >= property.begin) {
                    // We overwrite the current property with the new value.
                    target = mapbox::util::apply_visitor(evaluator, property.value);
                } else {
                    // Do not apply this property because its transition hasn't begun yet.
                }
            }
        }
    }

    template <typename T>
    void calculateTransitioned(PropertyKey key, T& target, const StyleCalculationParameters& parameters) {
        auto it = appliedStyle.find(key);
        if (it != appliedStyle.end()) {
            AppliedClassPropertyValues &applied = it->second;
            // Iterate through all properties that we need to apply in order.
            const PropertyEvaluator<T> evaluator(parameters);
            for (auto& property : applied.propertyValues) {
                if (parameters.now >= property.end) {
                    // We overwrite the current property with the new value.
                    target = mapbox::util::apply_visitor(evaluator, property.value);
                } else if (parameters.now >= property.begin) {
                    // We overwrite the current property partially with the new value.
                    float progress = std::chrono::duration<float>(parameters.now - property.begin) / (property.end - property.begin);
                    target = util::interpolate(target, mapbox::util::apply_visitor(evaluator, property.value), progress);
                    hasPendingTransitions = true;
                } else {
                    // Do not apply this property because its transition hasn't begun yet.
                }
            }
        }
    }

    // Raw parsed paint class to property value map.
    std::map<ClassID, ClassProperties> paints;

private:
    // Applies all properties from a class, if they haven't been applied already.
    void cascadeClass(const ClassID,
                      std::set<PropertyKey>&,
                      const StyleCascadeParameters&);

    // For every property, stores a list of applied property values, with
    // optional transition times.
    std::map<PropertyKey, AppliedClassPropertyValues> appliedStyle;

    // Stores whether there are pending transitions to be done on each update.
    bool hasPendingTransitions = false;
};

};

#endif