diff --git a/include/mbgl/style/conversion/light.hpp b/include/mbgl/style/conversion/light.hpp index 30bb90603..ba162516c 100644 --- a/include/mbgl/style/conversion/light.hpp +++ b/include/mbgl/style/conversion/light.hpp @@ -113,7 +113,7 @@ public: return {}; } } - return { light }; + return { std::move(light) }; }; }; diff --git a/include/mbgl/style/light.hpp b/include/mbgl/style/light.hpp index 7942d0d23..8212a58dc 100644 --- a/include/mbgl/style/light.hpp +++ b/include/mbgl/style/light.hpp @@ -5,15 +5,19 @@ #include #include +#include + namespace mbgl { - -class RenderLight; - namespace style { class Light { public: + class Impl; + + Light(); + ~Light(); + static LightAnchorType getDefaultAnchor(); PropertyValue getAnchor() const; void setAnchor(PropertyValue); @@ -38,10 +42,7 @@ public: void setIntensityTransition(const TransitionOptions&); TransitionOptions getIntensityTransition() const; -private: - IndexedTuple properties; - - friend class mbgl::RenderLight; + std::shared_ptr impl; }; } // namespace style diff --git a/include/mbgl/style/light.hpp.ejs b/include/mbgl/style/light.hpp.ejs index 40f85b66b..601e0bd41 100644 --- a/include/mbgl/style/light.hpp.ejs +++ b/include/mbgl/style/light.hpp.ejs @@ -8,15 +8,19 @@ #include #include +#include + namespace mbgl { - -class RenderLight; - namespace style { class Light { public: + class Impl; + + Light(); + ~Light(); + <% for (const property of properties) { -%> static <%- evaluatedType(property) %> getDefault<%- camelize(property.name) %>(); <%- propertyValueType(property) %> get<%- camelize(property.name) %>() const; @@ -25,10 +29,7 @@ public: TransitionOptions get<%- camelize(property.name) %>Transition() const; <% } -%> -private: - IndexedTuple properties; - - friend class mbgl::RenderLight; + std::shared_ptr impl; }; } // namespace style diff --git a/src/mbgl/renderer/render_light.cpp b/src/mbgl/renderer/render_light.cpp index faf89bf9e..134e1829e 100644 --- a/src/mbgl/renderer/render_light.cpp +++ b/src/mbgl/renderer/render_light.cpp @@ -2,12 +2,21 @@ namespace mbgl { -RenderLight::RenderLight(const style::Light light_) - : light(std::move(light_)) { +RenderLight::RenderLight(std::shared_ptr impl_) + : impl(std::move(impl_)) { +} + +RenderLight::RenderLight(std::shared_ptr impl_, const TransitioningLight transitioning_) + : impl(std::move(impl_)) + , transitioning(transitioning_) { +} + +std::unique_ptr RenderLight::copy(std::shared_ptr impl_) const { + return std::make_unique(std::move(impl_), transitioning); } void RenderLight::transition(const CascadeParameters& parameters) { - transitioning = TransitioningLight(light.properties, std::move(transitioning), parameters); + transitioning = TransitioningLight(impl->properties, std::move(transitioning), parameters); } void RenderLight::evaluate(const PropertyEvaluationParameters& parameters) { diff --git a/src/mbgl/renderer/render_light.hpp b/src/mbgl/renderer/render_light.hpp index 1a813ab1f..275f3ae8b 100644 --- a/src/mbgl/renderer/render_light.hpp +++ b/src/mbgl/renderer/render_light.hpp @@ -1,12 +1,15 @@ #pragma once -#include +#include +#include #include #include #include #include #include +#include + namespace mbgl { template @@ -71,7 +74,14 @@ using EvaluatedLight = Evaluated; class RenderLight { public: - RenderLight(const style::Light); + RenderLight(std::shared_ptr); + + // Creates a copy intitalized with previous transitioning light + RenderLight(std::shared_ptr, const TransitioningLight); + + // creates a copy initialized with previous transitioning + // values + std::unique_ptr copy(std::shared_ptr) const; void transition(const CascadeParameters&); void evaluate(const PropertyEvaluationParameters&); @@ -79,10 +89,12 @@ public: const EvaluatedLight& getEvaluated() const; + const std::shared_ptr impl; + private: + TransitioningLight transitioning; EvaluatedLight evaluated; - style::Light light; }; } // namespace mbgl diff --git a/src/mbgl/style/light.cpp b/src/mbgl/style/light.cpp index 0a9cbbee9..b54920713 100644 --- a/src/mbgl/style/light.cpp +++ b/src/mbgl/style/light.cpp @@ -7,30 +7,32 @@ namespace mbgl { namespace style { +Light::Light() + : impl(std::make_unique()) { +} + +Light::~Light() = default; + LightAnchorType Light::getDefaultAnchor() { return LightAnchor::defaultValue(); } PropertyValue Light::getAnchor() const { - return properties.get().value; + return impl->properties.template get().value; } void Light::setAnchor(PropertyValue property) { - properties.get().value = property; - if (observer) { - observer->onLightChanged(*this); - } + impl->properties.template get().value = property; + impl->observer->onLightChanged(*this); } void Light::setAnchorTransition(const TransitionOptions& transition) { - properties.get().transition = transition; - if (observer) { - observer->onLightChanged(*this); - } + impl->properties.template get().transition = transition; + impl->observer->onLightChanged(*this); } TransitionOptions Light::getAnchorTransition() const { - return properties.get().transition; + return impl->properties.template get().transition; } Position Light::getDefaultPosition() { @@ -38,25 +40,21 @@ Position Light::getDefaultPosition() { } PropertyValue Light::getPosition() const { - return properties.get().value; + return impl->properties.template get().value; } void Light::setPosition(PropertyValue property) { - properties.get().value = property; - if (observer) { - observer->onLightChanged(*this); - } + impl->properties.template get().value = property; + impl->observer->onLightChanged(*this); } void Light::setPositionTransition(const TransitionOptions& transition) { - properties.get().transition = transition; - if (observer) { - observer->onLightChanged(*this); - } + impl->properties.template get().transition = transition; + impl->observer->onLightChanged(*this); } TransitionOptions Light::getPositionTransition() const { - return properties.get().transition; + return impl->properties.template get().transition; } Color Light::getDefaultColor() { @@ -64,25 +62,21 @@ Color Light::getDefaultColor() { } PropertyValue Light::getColor() const { - return properties.get().value; + return impl->properties.template get().value; } void Light::setColor(PropertyValue property) { - properties.get().value = property; - if (observer) { - observer->onLightChanged(*this); - } + impl->properties.template get().value = property; + impl->observer->onLightChanged(*this); } void Light::setColorTransition(const TransitionOptions& transition) { - properties.get().transition = transition; - if (observer) { - observer->onLightChanged(*this); - } + impl->properties.template get().transition = transition; + impl->observer->onLightChanged(*this); } TransitionOptions Light::getColorTransition() const { - return properties.get().transition; + return impl->properties.template get().transition; } float Light::getDefaultIntensity() { @@ -90,26 +84,23 @@ float Light::getDefaultIntensity() { } PropertyValue Light::getIntensity() const { - return properties.get().value; + return impl->properties.template get().value; } void Light::setIntensity(PropertyValue property) { - properties.get().value = property; - if (observer) { - observer->onLightChanged(*this); - } + impl->properties.template get().value = property; + impl->observer->onLightChanged(*this); } void Light::setIntensityTransition(const TransitionOptions& transition) { - properties.get().transition = transition; - if (observer) { - observer->onLightChanged(*this); - } + impl->properties.template get().transition = transition; + impl->observer->onLightChanged(*this); } TransitionOptions Light::getIntensityTransition() const { - return properties.get().transition; + return impl->properties.template get().transition; } + } // namespace style } // namespace mbgl diff --git a/src/mbgl/style/light.cpp.ejs b/src/mbgl/style/light.cpp.ejs index 7d2e0ecc1..c82c65c10 100644 --- a/src/mbgl/style/light.cpp.ejs +++ b/src/mbgl/style/light.cpp.ejs @@ -10,33 +10,36 @@ namespace mbgl { namespace style { +Light::Light() + : impl(std::make_unique()) { +} + +Light::~Light() = default; + <% for (const property of properties) { -%> <%- evaluatedType(property) %> Light::getDefault<%- camelize(property.name) %>() { return Light<%- camelize(property.name) %>::defaultValue(); } <%- propertyValueType(property) %> Light::get<%- camelize(property.name) %>() const { - return properties.get>().value; + return impl->properties.template get>().value; } void Light::set<%- camelize(property.name) %>(<%- propertyValueType(property) %> property) { - properties.get>().value = property; - if (observer) { - observer->onLightChanged(*this); - } + impl->properties.template get>().value = property; + impl->observer->onLightChanged(*this); } void Light::set<%- camelize(property.name) %>Transition(const TransitionOptions& transition) { - properties.get>().transition = transition; - if (observer) { - observer->onLightChanged(*this); - } + impl->properties.template get>().transition = transition; + impl->observer->onLightChanged(*this); } TransitionOptions Light::get<%- camelize(property.name) %>Transition() const { - return properties.get>().transition; + return impl->properties.template get>().transition; } <% } -%> + } // namespace style } // namespace mbgl diff --git a/src/mbgl/style/light_impl.cpp b/src/mbgl/style/light_impl.cpp new file mode 100644 index 000000000..e0ab1176e --- /dev/null +++ b/src/mbgl/style/light_impl.cpp @@ -0,0 +1,11 @@ +#include + +namespace mbgl { +namespace style { + +void Light::Impl::setObserver(LightObserver* observer_) { + observer = observer_; +} + +} // namespace style +} // namespace mbgl diff --git a/src/mbgl/style/light_impl.hpp b/src/mbgl/style/light_impl.hpp new file mode 100644 index 000000000..b4fd88674 --- /dev/null +++ b/src/mbgl/style/light_impl.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + +namespace mbgl { +namespace style { + +class Light::Impl { +public: + + LightObserver nullObserver; + LightObserver* observer = &nullObserver; + void setObserver(LightObserver*); + + IndexedTuple properties; +}; + +} // namespace style +} // namespace mbgl diff --git a/src/mbgl/style/light_observer.hpp b/src/mbgl/style/light_observer.hpp new file mode 100644 index 000000000..751a84850 --- /dev/null +++ b/src/mbgl/style/light_observer.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include + +namespace mbgl { +namespace style { + +class LightObserver { +public: + virtual ~LightObserver() = default; + + virtual void onLightChanged(const Light&) {} +}; + +} // namespace style +} // namespace mbgl diff --git a/src/mbgl/style/parser.cpp b/src/mbgl/style/parser.cpp index c407e438f..fc3ccf410 100644 --- a/src/mbgl/style/parser.cpp +++ b/src/mbgl/style/parser.cpp @@ -120,7 +120,7 @@ void Parser::parseLight(const JSValue& value) { return; } - light = *converted; + light = std::move(*converted); } void Parser::parseSources(const JSValue& value) { diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp index 080911b74..4b694917c 100644 --- a/src/mbgl/style/style.cpp +++ b/src/mbgl/style/style.cpp @@ -59,10 +59,11 @@ Style::Style(Scheduler& scheduler_, FileSource& fileSource_, float pixelRatio) spriteAtlas(std::make_unique(Size{ 1024, 1024 }, pixelRatio)), lineAtlas(std::make_unique(Size{ 256, 512 })), light(std::make_unique()), - renderLight(std::make_unique(*light)), + renderLight(std::make_unique(light->impl)), observer(&nullObserver) { glyphAtlas->setObserver(this); spriteAtlas->setObserver(this); + light->impl->setObserver(this); } Style::~Style() { @@ -78,6 +79,7 @@ Style::~Style() { glyphAtlas->setObserver(nullptr); spriteAtlas->setObserver(nullptr); + light->impl->setObserver(nullptr); } bool Style::addClass(const std::string& className) { @@ -313,7 +315,13 @@ void Style::removeRenderLayer(const std::string& id) { void Style::setLight(std::unique_ptr light_) { light = std::move(light_); - renderLight = std::make_unique(*light); + light->impl->setObserver(this); + + // Copy renderlight to preserve the initialised + // transitioning light properties + renderLight = renderLight->copy(light->impl); + + onLightChanged(*light); } Light* Style::getLight() const { @@ -761,6 +769,10 @@ void Style::onLayerLayoutPropertyChanged(Layer& layer, const char * property) { : Update::Repaint); } +void Style::onLightChanged(const Light&) { + observer->onUpdate(Update::Classes | Update::RecalculateStyle); +} + void Style::dumpDebugLogs() const { for (const auto& source : sources) { source->baseImpl->dumpDebugLogs(); diff --git a/src/mbgl/style/style.hpp b/src/mbgl/style/style.hpp index 2756be1ed..7d235dc66 100644 --- a/src/mbgl/style/style.hpp +++ b/src/mbgl/style/style.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,7 @@ class Style : public GlyphAtlasObserver, public SourceObserver, public RenderSourceObserver, public LayerObserver, + public LightObserver, public util::noncopyable { public: Style(Scheduler&, FileSource&, float pixelRatio); @@ -169,6 +171,9 @@ private: void onLayerDataDrivenPaintPropertyChanged(Layer&) override; void onLayerLayoutPropertyChanged(Layer&, const char *) override; + // LightObserver implementation. + void onLightChanged(const Light&) override; + Observer nullObserver; Observer* observer = &nullObserver;