summaryrefslogtreecommitdiff
path: root/src/mbgl/style
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/style')
-rw-r--r--src/mbgl/style/layers/fill_extrusion_layer_impl.hpp2
-rw-r--r--src/mbgl/style/light_impl.hpp74
-rw-r--r--src/mbgl/style/paint_property.hpp75
-rw-r--r--src/mbgl/style/parser.cpp16
-rw-r--r--src/mbgl/style/parser.hpp4
-rw-r--r--src/mbgl/style/source_impl.cpp8
-rw-r--r--src/mbgl/style/source_impl.hpp1
-rw-r--r--src/mbgl/style/style.cpp22
-rw-r--r--src/mbgl/style/style.hpp5
-rw-r--r--src/mbgl/style/transitioning_property.hpp77
-rw-r--r--src/mbgl/style/types.cpp5
11 files changed, 209 insertions, 80 deletions
diff --git a/src/mbgl/style/layers/fill_extrusion_layer_impl.hpp b/src/mbgl/style/layers/fill_extrusion_layer_impl.hpp
index f6f9753460..2353bd99fe 100644
--- a/src/mbgl/style/layers/fill_extrusion_layer_impl.hpp
+++ b/src/mbgl/style/layers/fill_extrusion_layer_impl.hpp
@@ -16,8 +16,6 @@ public:
std::unique_ptr<RenderLayer> createRenderLayer() const override;
FillExtrusionPaintProperties::Cascading cascading;
-
- //style::FillExtrusionLayer::Impl* const impl;
};
} // namespace style
diff --git a/src/mbgl/style/light_impl.hpp b/src/mbgl/style/light_impl.hpp
new file mode 100644
index 0000000000..d1825090fc
--- /dev/null
+++ b/src/mbgl/style/light_impl.hpp
@@ -0,0 +1,74 @@
+#pragma once
+
+#include <mbgl/style/light.hpp>
+#include <mbgl/style/transitioning_property.hpp>
+#include <mbgl/style/cascade_parameters.hpp>
+#include <mbgl/style/property_evaluator.hpp>
+#include <mbgl/style/property_evaluation_parameters.hpp>
+#include <mbgl/util/ignore.hpp>
+
+namespace mbgl {
+namespace style {
+
+template <class TypeList>
+class Transitioning;
+
+template <class... Ps>
+class Transitioning<TypeList<Ps...>> : public IndexedTuple<
+ TypeList<Ps...>,
+ TypeList<TransitioningProperty<typename Ps::ValueType>...>>
+{
+private:
+ using Properties = TypeList<Ps...>;
+ using Raw = IndexedTuple<Properties, Properties>;
+ using Super = IndexedTuple<
+ TypeList<Ps...>,
+ TypeList<TransitioningProperty<typename Ps::ValueType>...>>;
+
+public:
+ Transitioning() = default;
+ Transitioning(const Raw& raw, Transitioning&& prior, const CascadeParameters& params)
+ : Super {
+ TransitioningProperty<typename Ps::ValueType>(
+ raw.template get<Ps>().value,
+ std::move(prior.template get<Ps>()),
+ raw.template get<Ps>().transition.reverseMerge(params.transition),
+ params.now)...
+ } {}
+
+ bool hasTransition() const {
+ bool result = false;
+ util::ignore({ result |= this->template get<Ps>().hasTransition()... });
+ return result;
+ }
+};
+
+template <class TypeList>
+class Evaluated;
+
+template <class... Ps>
+class Evaluated<TypeList<Ps...>> : public IndexedTuple<
+ TypeList<Ps...>,
+ TypeList<typename Ps::Type...>>
+{
+private:
+ using Properties = TypeList<Ps...>;
+ using TransitioningPs = Transitioning<Properties>;
+ using Super = IndexedTuple<
+ TypeList<Ps...>,
+ TypeList<typename Ps::Type...>>;
+
+public:
+ Evaluated() = default;
+ Evaluated(TransitioningPs& transitioning, const PropertyEvaluationParameters& params)
+ : Super {
+ transitioning.template get<Ps>()
+ .evaluate(PropertyEvaluator<typename Ps::Type>(params, Ps::defaultValue()), params.now)...
+ } {}
+};
+
+using TransitioningLight = Transitioning<LightProperties>;
+using EvaluatedLight = Evaluated<LightProperties>;
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/paint_property.hpp b/src/mbgl/style/paint_property.hpp
index 7f7018748c..dd8d6c0b50 100644
--- a/src/mbgl/style/paint_property.hpp
+++ b/src/mbgl/style/paint_property.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include <mbgl/style/transitioning_property.hpp>
#include <mbgl/style/class_dictionary.hpp>
#include <mbgl/style/property_value.hpp>
#include <mbgl/style/data_driven_property_value.hpp>
@@ -24,68 +25,6 @@ class GeometryTileFeature;
namespace style {
template <class Value>
-class UnevaluatedPaintProperty {
-public:
- UnevaluatedPaintProperty() = default;
-
- UnevaluatedPaintProperty(Value value_,
- UnevaluatedPaintProperty<Value> prior_,
- TransitionOptions transition,
- TimePoint now)
- : begin(now + transition.delay.value_or(Duration::zero())),
- end(begin + transition.duration.value_or(Duration::zero())),
- value(std::move(value_)) {
- if (transition.isDefined()) {
- prior = { std::move(prior_) };
- }
- }
-
- template <class Evaluator>
- auto evaluate(const Evaluator& evaluator, TimePoint now) {
- auto finalValue = value.evaluate(evaluator);
- if (!prior) {
- // No prior value.
- return finalValue;
- } else if (now >= end) {
- // Transition from prior value is now complete.
- prior = {};
- return finalValue;
- } else if (value.isDataDriven()) {
- // Transitions to data-driven properties are not supported.
- // We snap immediately to the data-driven value so that, when we perform layout,
- // we see the data-driven function and can use it to populate vertex buffers.
- prior = {};
- return finalValue;
- } else if (now < begin) {
- // Transition hasn't started yet.
- return prior->get().evaluate(evaluator, now);
- } else {
- // Interpolate between recursively-calculated prior value and final.
- float t = std::chrono::duration<float>(now - begin) / (end - begin);
- return util::interpolate(prior->get().evaluate(evaluator, now), finalValue, util::DEFAULT_TRANSITION_EASE.solve(t, 0.001));
- }
- }
-
- bool hasTransition() const {
- return bool(prior);
- }
-
- bool isUndefined() const {
- return value.isUndefined();
- }
-
- const Value& getValue() const {
- return value;
- }
-
-private:
- optional<mapbox::util::recursive_wrapper<UnevaluatedPaintProperty<Value>>> prior;
- TimePoint begin;
- TimePoint end;
- Value value;
-};
-
-template <class Value>
class CascadingPaintProperty {
public:
bool isUndefined() const {
@@ -112,8 +51,8 @@ public:
transitions[klass ? ClassDictionary::Get().lookup(*klass) : ClassID::Default] = transition;
}
- template <class UnevaluatedPaintProperty>
- UnevaluatedPaintProperty cascade(const CascadeParameters& params, UnevaluatedPaintProperty prior) const {
+ template <class TransitioningProperty>
+ TransitioningProperty cascade(const CascadeParameters& params, TransitioningProperty prior) const {
TransitionOptions transition;
Value value;
@@ -131,7 +70,7 @@ public:
}
}
- return UnevaluatedPaintProperty(std::move(value),
+ return TransitioningProperty(std::move(value),
std::move(prior),
transition.reverseMerge(params.transition),
params.now);
@@ -147,7 +86,7 @@ class PaintProperty {
public:
using ValueType = PropertyValue<T>;
using CascadingType = CascadingPaintProperty<ValueType>;
- using UnevaluatedType = UnevaluatedPaintProperty<ValueType>;
+ using UnevaluatedType = TransitioningProperty<ValueType>;
using EvaluatorType = PropertyEvaluator<T>;
using EvaluatedType = T;
static constexpr bool IsDataDriven = false;
@@ -158,7 +97,7 @@ class DataDrivenPaintProperty {
public:
using ValueType = DataDrivenPropertyValue<T>;
using CascadingType = CascadingPaintProperty<ValueType>;
- using UnevaluatedType = UnevaluatedPaintProperty<ValueType>;
+ using UnevaluatedType = TransitioningProperty<ValueType>;
using EvaluatorType = DataDrivenPropertyEvaluator<T>;
using EvaluatedType = PossiblyEvaluatedPropertyValue<T>;
static constexpr bool IsDataDriven = true;
@@ -172,7 +111,7 @@ class CrossFadedPaintProperty {
public:
using ValueType = PropertyValue<T>;
using CascadingType = CascadingPaintProperty<ValueType>;
- using UnevaluatedType = UnevaluatedPaintProperty<ValueType>;
+ using UnevaluatedType = TransitioningProperty<ValueType>;
using EvaluatorType = CrossFadedPropertyEvaluator<T>;
using EvaluatedType = Faded<T>;
static constexpr bool IsDataDriven = false;
diff --git a/src/mbgl/style/parser.cpp b/src/mbgl/style/parser.cpp
index 19ea8cefee..c407e438fb 100644
--- a/src/mbgl/style/parser.cpp
+++ b/src/mbgl/style/parser.cpp
@@ -4,6 +4,7 @@
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/source.hpp>
#include <mbgl/style/conversion/layer.hpp>
+#include <mbgl/style/conversion/light.hpp>
#include <mbgl/util/logging.hpp>
@@ -82,6 +83,10 @@ StyleParseResult Parser::parse(const std::string& json) {
}
}
+ if (document.HasMember("light")) {
+ parseLight(document["light"]);
+ }
+
if (document.HasMember("sources")) {
parseSources(document["sources"]);
}
@@ -107,6 +112,17 @@ StyleParseResult Parser::parse(const std::string& json) {
return nullptr;
}
+void Parser::parseLight(const JSValue& value) {
+ conversion::Error error;
+ optional<Light> converted = conversion::convert<Light>(value, error);
+ if (!converted) {
+ Log::Warning(Event::ParseStyle, error.message);
+ return;
+ }
+
+ light = *converted;
+}
+
void Parser::parseSources(const JSValue& value) {
if (!value.IsObject()) {
Log::Warning(Event::ParseStyle, "sources must be an object");
diff --git a/src/mbgl/style/parser.hpp b/src/mbgl/style/parser.hpp
index a05a0b316a..32b8a7a8bc 100644
--- a/src/mbgl/style/parser.hpp
+++ b/src/mbgl/style/parser.hpp
@@ -2,6 +2,7 @@
#include <mbgl/style/layer.hpp>
#include <mbgl/style/source.hpp>
+#include <mbgl/style/light.hpp>
#include <mbgl/util/rapidjson.hpp>
#include <mbgl/util/font_stack.hpp>
@@ -31,6 +32,8 @@ public:
std::vector<std::unique_ptr<Source>> sources;
std::vector<std::unique_ptr<Layer>> layers;
+ Light light;
+
std::string name;
LatLng latLng;
double zoom = 0;
@@ -41,6 +44,7 @@ public:
std::vector<FontStack> fontStacks() const;
private:
+ void parseLight(const JSValue&);
void parseSources(const JSValue&);
void parseLayers(const JSValue&);
void parseLayer(const std::string& id, const JSValue&, std::unique_ptr<Layer>&);
diff --git a/src/mbgl/style/source_impl.cpp b/src/mbgl/style/source_impl.cpp
index 9fabc54f7d..7a65dd1ded 100644
--- a/src/mbgl/style/source_impl.cpp
+++ b/src/mbgl/style/source_impl.cpp
@@ -57,8 +57,9 @@ void Source::Impl::invalidateTiles() {
}
void Source::Impl::startRender(algorithm::ClipIDGenerator& generator,
- const mat4& projMatrix,
- const TransformState& transform) {
+ const mat4& projMatrix,
+ const mat4& clipMatrix,
+ const TransformState& transform) {
if (type == SourceType::Vector ||
type == SourceType::GeoJSON ||
type == SourceType::Annotations) {
@@ -67,8 +68,7 @@ void Source::Impl::startRender(algorithm::ClipIDGenerator& generator,
for (auto& pair : renderTiles) {
auto& tile = pair.second;
- transform.matrixFor(tile.matrix, tile.id);
- matrix::multiply(tile.matrix, projMatrix, tile.matrix);
+ tile.calculateMatrices(projMatrix, clipMatrix, transform);
}
}
diff --git a/src/mbgl/style/source_impl.hpp b/src/mbgl/style/source_impl.hpp
index b4473cbc84..387428ec59 100644
--- a/src/mbgl/style/source_impl.hpp
+++ b/src/mbgl/style/source_impl.hpp
@@ -60,6 +60,7 @@ public:
void startRender(algorithm::ClipIDGenerator&,
const mat4& projMatrix,
+ const mat4& clipMatrix,
const TransformState&);
void finishRender(Painter&);
diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp
index e8141c3c6b..8dfe7eac06 100644
--- a/src/mbgl/style/style.cpp
+++ b/src/mbgl/style/style.cpp
@@ -54,6 +54,7 @@ Style::Style(Scheduler& scheduler_, FileSource& fileSource_, float pixelRatio)
glyphAtlas(std::make_unique<GlyphAtlas>(Size{ 2048, 2048 }, fileSource)),
spriteAtlas(std::make_unique<SpriteAtlas>(Size{ 1024, 1024 }, pixelRatio)),
lineAtlas(std::make_unique<LineAtlas>(Size{ 256, 512 })),
+ light(std::make_unique<Light>()),
observer(&nullObserver) {
glyphAtlas->setObserver(this);
spriteAtlas->setObserver(this);
@@ -141,6 +142,7 @@ void Style::setJSON(const std::string& json) {
defaultZoom = parser.zoom;
defaultBearing = parser.bearing;
defaultPitch = parser.pitch;
+ light = std::make_unique<Light>(parser.light);
glyphAtlas->setURL(parser.glyphURL);
spriteAtlas->load(parser.spriteURL, scheduler, fileSource);
@@ -352,6 +354,8 @@ void Style::cascade(const TimePoint& timePoint, MapMode mode) {
for (const auto& layer : renderLayers) {
layer->cascade(parameters);
}
+
+ transitioningLight = TransitioningLight(*light, std::move(transitioningLight), parameters);
}
void Style::recalculate(float z, const TimePoint& timePoint, MapMode mode) {
@@ -370,7 +374,7 @@ void Style::recalculate(float z, const TimePoint& timePoint, MapMode mode) {
mode == MapMode::Continuous ? util::DEFAULT_FADE_DURATION : Duration::zero()
};
- hasPendingTransitions = false;
+ hasPendingTransitions = transitioningLight.hasTransition();
for (const auto& layer : renderLayers) {
hasPendingTransitions |= layer->evaluate(parameters);
@@ -389,6 +393,8 @@ void Style::recalculate(float z, const TimePoint& timePoint, MapMode mode) {
}
}
+ evaluatedLight = EvaluatedLight(transitioningLight, parameters);
+
// Remove the existing tiles if we didn't end up re-enabling the source.
for (const auto& source : sources) {
if (!source->baseImpl->enabled) {
@@ -509,8 +515,9 @@ RenderData Style::getRenderData(MapDebugOptions debugOptions, float angle) const
});
}
- for (auto& tileRef : sortedTiles) {
- auto& tile = tileRef.get();
+ std::vector<std::reference_wrapper<RenderTile>> sortedTilesForInsertion;
+ for (auto tileIt = sortedTiles.begin(); tileIt != sortedTiles.end(); ++tileIt) {
+ auto& tile = tileIt->get();
if (!tile.tile.isRenderable()) {
continue;
}
@@ -523,8 +530,9 @@ RenderData Style::getRenderData(MapDebugOptions debugOptions, float angle) const
// Look back through the buckets we decided to render to find out whether there is
// already a bucket from this layer that is a parent of this tile. Tiles are ordered
// by zoom level when we obtain them from getTiles().
- for (auto it = result.order.rbegin(); it != result.order.rend() && (&it->layer == layer.get()); ++it) {
- if (tile.tile.id.isChildOf(it->tile->tile.id)) {
+ for (auto it = sortedTilesForInsertion.rbegin();
+ it != sortedTilesForInsertion.rend(); ++it) {
+ if (tile.tile.id.isChildOf(it->get().tile.id)) {
skip = true;
break;
}
@@ -536,10 +544,12 @@ RenderData Style::getRenderData(MapDebugOptions debugOptions, float angle) const
auto bucket = tile.tile.getBucket(*layer);
if (bucket) {
- result.order.emplace_back(*layer, &tile, bucket);
+ sortedTilesForInsertion.emplace_back(tile);
tile.used = true;
}
}
+
+ result.order.emplace_back(*layer, std::move(sortedTilesForInsertion));
}
return result;
diff --git a/src/mbgl/style/style.hpp b/src/mbgl/style/style.hpp
index 127430a89f..26959c9fbf 100644
--- a/src/mbgl/style/style.hpp
+++ b/src/mbgl/style/style.hpp
@@ -6,6 +6,7 @@
#include <mbgl/style/layer_observer.hpp>
#include <mbgl/style/update_batch.hpp>
#include <mbgl/renderer/render_layer.hpp>
+#include <mbgl/style/light_impl.hpp>
#include <mbgl/text/glyph_atlas_observer.hpp>
#include <mbgl/sprite/sprite_atlas_observer.hpp>
#include <mbgl/map/mode.hpp>
@@ -120,6 +121,10 @@ public:
std::unique_ptr<SpriteAtlas> spriteAtlas;
std::unique_ptr<LineAtlas> lineAtlas;
+ std::unique_ptr<Light> light;
+ TransitioningLight transitioningLight;
+ EvaluatedLight evaluatedLight;
+
private:
std::vector<std::unique_ptr<Source>> sources;
std::vector<std::unique_ptr<Layer>> layers;
diff --git a/src/mbgl/style/transitioning_property.hpp b/src/mbgl/style/transitioning_property.hpp
new file mode 100644
index 0000000000..5456322b33
--- /dev/null
+++ b/src/mbgl/style/transitioning_property.hpp
@@ -0,0 +1,77 @@
+#pragma once
+
+#include <mbgl/style/property_value.hpp>
+#include <mbgl/style/data_driven_property_value.hpp>
+#include <mbgl/style/transition_options.hpp>
+#include <mbgl/util/interpolate.hpp>
+
+#include <utility>
+
+namespace mbgl {
+namespace style {
+
+template <class Value>
+class TransitioningProperty {
+public:
+ TransitioningProperty() = default;
+
+ TransitioningProperty(Value value_,
+ TransitioningProperty<Value> prior_,
+ TransitionOptions transition,
+ TimePoint now)
+ : begin(now + transition.delay.value_or(Duration::zero())),
+ end(begin + transition.duration.value_or(Duration::zero())),
+ value(std::move(value_)) {
+ if (transition.isDefined()) {
+ prior = { std::move(prior_) };
+ }
+ }
+
+ template <class Evaluator>
+ auto evaluate(const Evaluator& evaluator, TimePoint now) {
+ auto finalValue = value.evaluate(evaluator);
+ if (!prior) {
+ // No prior value.
+ return finalValue;
+ } else if (now >= end) {
+ // Transition from prior value is now complete.
+ prior = {};
+ return finalValue;
+ } else if (value.isDataDriven()) {
+ // Transitions to data-driven properties are not supported.
+ // We snap immediately to the data-driven value so that, when we perform layout,
+ // we see the data-driven function and can use it to populate vertex buffers.
+ prior = {};
+ return finalValue;
+ } else if (now < begin) {
+ // Transition hasn't started yet.
+ return prior->get().evaluate(evaluator, now);
+ } else {
+ // Interpolate between recursively-calculated prior value and final.
+ float t = std::chrono::duration<float>(now - begin) / (end - begin);
+ return util::interpolate(prior->get().evaluate(evaluator, now), finalValue,
+ util::DEFAULT_TRANSITION_EASE.solve(t, 0.001));
+ }
+ }
+
+ bool hasTransition() const {
+ return bool(prior);
+ }
+
+ bool isUndefined() const {
+ return value.isUndefined();
+ }
+
+ const Value& getValue() const {
+ return value;
+ }
+
+private:
+ optional<mapbox::util::recursive_wrapper<TransitioningProperty<Value>>> prior;
+ TimePoint begin;
+ TimePoint end;
+ Value value;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/types.cpp b/src/mbgl/style/types.cpp
index bf2ba8a793..b37e73ffb1 100644
--- a/src/mbgl/style/types.cpp
+++ b/src/mbgl/style/types.cpp
@@ -89,4 +89,9 @@ MBGL_DEFINE_ENUM(IconTextFitType, {
{ IconTextFitType::Height, "height" },
});
+MBGL_DEFINE_ENUM(LightAnchorType, {
+ { LightAnchorType::Map, "map" },
+ { LightAnchorType::Viewport, "viewport" }
+});
+
} // namespace mbgl