367 lines
15 KiB
Plaintext
367 lines
15 KiB
Plaintext
<%
|
|
const type = locals.type;
|
|
const layoutProperties = locals.layoutProperties;
|
|
const paintProperties = locals.paintProperties;
|
|
const allProperties = paintProperties.concat(layoutProperties);
|
|
|
|
// Define the mapping from capability keys to struct member names
|
|
const memberMap = {
|
|
'Source': 'source',
|
|
'Pass3D': 'pass3d',
|
|
'Layout': 'layout',
|
|
'FadingTiles': 'fadingTiles',
|
|
'CrossTileIndex': 'crossTileIndex',
|
|
'TileKind': 'tileKind'
|
|
};
|
|
-%>
|
|
// clang-format off
|
|
|
|
// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
|
|
|
|
#include <mbgl/style/layers/<%- type.replace(/-/g, '_') %>_layer.hpp>
|
|
#include <mbgl/style/layers/<%- type.replace(/-/g, '_') %>_layer_impl.hpp>
|
|
#include <mbgl/style/layer_observer.hpp>
|
|
#include <mbgl/style/conversion/color_ramp_property_value.hpp>
|
|
#include <mbgl/style/conversion/constant.hpp>
|
|
#include <mbgl/style/conversion/property_value.hpp>
|
|
#include <mbgl/style/conversion/transition_options.hpp>
|
|
#include <mbgl/style/conversion/json.hpp>
|
|
#include <mbgl/style/conversion_impl.hpp>
|
|
#include <mbgl/util/traits.hpp>
|
|
|
|
#include <mapbox/eternal.hpp>
|
|
|
|
namespace mbgl {
|
|
namespace style {
|
|
|
|
<%
|
|
let layerCapabilities = {};
|
|
let defaults = { caps: { 'Source': 'NotRequired',
|
|
'Pass3D': 'NotRequired',
|
|
'Layout': 'NotRequired',
|
|
'FadingTiles': 'NotRequired',
|
|
'CrossTileIndex': 'NotRequired',
|
|
'TileKind' : 'NotRequired'
|
|
},
|
|
require: function(cap) {
|
|
let copy = Object.assign({}, this);
|
|
copy.caps = Object.assign({}, this.caps);
|
|
copy.caps[cap] = 'Required';
|
|
return copy;
|
|
},
|
|
set: function(cap, value) {
|
|
let copy = Object.assign({}, this);
|
|
copy.caps = Object.assign({}, this.caps);
|
|
copy.caps[cap] = value;
|
|
return copy;
|
|
},
|
|
finalize: function() {
|
|
return Object.keys(this.caps).reduce((acc, key) => {
|
|
acc.push(`${key}::${this.caps[key]}`);
|
|
return acc;
|
|
}, []);
|
|
}
|
|
};
|
|
|
|
layerCapabilities['background'] = defaults.finalize();
|
|
layerCapabilities['fill'] = defaults.require('Source')
|
|
.require('Layout')
|
|
.set('TileKind', 'Geometry')
|
|
.finalize();
|
|
layerCapabilities['fill-extrusion'] = defaults.require('Source')
|
|
.require('Pass3D')
|
|
.require('Layout')
|
|
.set('TileKind', 'Geometry')
|
|
.finalize();
|
|
layerCapabilities['hillshade'] = defaults.require('Source')
|
|
.require('Pass3D')
|
|
.set('TileKind', 'RasterDEM')
|
|
.finalize();
|
|
layerCapabilities['color-relief'] = defaults.require('Source')
|
|
.set('TileKind', 'RasterDEM')
|
|
.finalize();
|
|
layerCapabilities['symbol'] = defaults.require('Source')
|
|
.require('Layout')
|
|
.require('FadingTiles')
|
|
.require('CrossTileIndex')
|
|
.set('TileKind', 'Geometry')
|
|
.finalize();
|
|
layerCapabilities['circle'] = defaults.require('Source')
|
|
.require('Layout')
|
|
.set('TileKind', 'Geometry')
|
|
.finalize();
|
|
layerCapabilities['line'] = layerCapabilities['fill'];
|
|
layerCapabilities['heatmap'] = defaults.require('Source')
|
|
.require('Pass3D')
|
|
.set('TileKind', 'Geometry')
|
|
.finalize();
|
|
layerCapabilities['raster'] = defaults.require('Source').set('TileKind', 'Raster').finalize();
|
|
layerCapabilities['location-indicator'] = defaults.finalize();
|
|
|
|
// Splits lines that are over 120 characters at the firts occurance of '='.
|
|
const split120Line = line => {
|
|
const ident = ' ';
|
|
if (line.length + ident.length > 120) {
|
|
return line.replace('=', `=\n${ident}`);
|
|
}
|
|
return line;
|
|
};
|
|
|
|
%>
|
|
// static
|
|
const LayerTypeInfo* <%- camelize(type) %>Layer::Impl::staticTypeInfo() noexcept {
|
|
const static LayerTypeInfo typeInfo{.type="<%- type %>",
|
|
<%- layerCapabilities[type].map(cap => {
|
|
const key = cap.split('::')[0];
|
|
return `.${memberMap[key]}=LayerTypeInfo::${cap}`;
|
|
}).join(',\n ') %>};
|
|
return &typeInfo;
|
|
}
|
|
|
|
<% if ((type === 'background') || (type === 'location-indicator')) { -%>
|
|
<%- camelize(type) %>Layer::<%- camelize(type) %>Layer(const std::string& layerID)
|
|
: Layer(makeMutable<Impl>(layerID, std::string())) {
|
|
}
|
|
<% } else { -%>
|
|
<%- camelize(type) %>Layer::<%- camelize(type) %>Layer(const std::string& layerID, const std::string& sourceID)
|
|
: Layer(makeMutable<Impl>(layerID, sourceID)) {
|
|
}
|
|
<% } -%>
|
|
|
|
<%- camelize(type) %>Layer::<%- camelize(type) %>Layer(Immutable<Impl> impl_)
|
|
: Layer(std::move(impl_)) {
|
|
}
|
|
|
|
<%- camelize(type) %>Layer::~<%- camelize(type) %>Layer() {
|
|
weakFactory.invalidateWeakPtrs();
|
|
}
|
|
|
|
const <%- camelize(type) %>Layer::Impl& <%- camelize(type) %>Layer::impl() const {
|
|
return static_cast<const Impl&>(*baseImpl);
|
|
}
|
|
|
|
Mutable<<%- camelize(type) %>Layer::Impl> <%- camelize(type) %>Layer::mutableImpl() const {
|
|
return makeMutable<Impl>(impl());
|
|
}
|
|
|
|
std::unique_ptr<Layer> <%- camelize(type) %>Layer::cloneRef(const std::string& id_) const {
|
|
auto impl_ = mutableImpl();
|
|
impl_->id = id_;
|
|
impl_->paint = <%- camelize(type) %>PaintProperties::Transitionable();
|
|
return std::make_unique<<%- camelize(type) %>Layer>(std::move(impl_));
|
|
}
|
|
|
|
<% if (layoutProperties.length) { -%>
|
|
void <%- camelize(type) %>Layer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>& writer) const {
|
|
layout.stringify(writer);
|
|
}
|
|
<% } else { -%>
|
|
void <%- camelize(type) %>Layer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const {
|
|
}
|
|
<% } -%>
|
|
|
|
// Layout properties
|
|
|
|
<% for (const property of layoutProperties) { -%>
|
|
<%- propertyValueType(property) %> <%- camelize(type) %>Layer::getDefault<%- camelize(property.name) %>() {
|
|
return <%- camelize(property.name) %>::defaultValue();
|
|
}
|
|
|
|
const <%- propertyValueType(property) %>& <%- camelize(type) %>Layer::get<%- camelize(property.name) %>() const {
|
|
return impl().layout.get<<%- camelize(property.name) %>>();
|
|
}
|
|
|
|
void <%- camelize(type) %>Layer::set<%- camelize(property.name) %>(const <%- propertyValueType(property) %>& value) {
|
|
if (value == get<%- camelize(property.name) %>()) return;
|
|
auto impl_ = mutableImpl();
|
|
impl_->layout.get<<%- camelize(property.name) %>>() = value;
|
|
baseImpl = std::move(impl_);
|
|
observer->onLayerChanged(*this);
|
|
}
|
|
<% } -%>
|
|
|
|
// Paint properties
|
|
<% for (const property of paintProperties) { %>
|
|
<%- propertyValueType(property) %> <%- camelize(type) %>Layer::getDefault<%- camelize(property.name) %>() {
|
|
<% if (property.name === 'heatmap-color') { -%>
|
|
conversion::Error error;
|
|
std::string rawValue = R"JSON(<%- JSON.stringify(property.default) %>)JSON";
|
|
return *conversion::convertJSON<<%- propertyValueType(property)%>>(rawValue, error);
|
|
<% } else { -%>
|
|
return {<%- defaultValue(property) %>};
|
|
<% } -%>
|
|
}
|
|
|
|
const <%- propertyValueType(property) %>& <%- camelize(type) %>Layer::get<%- camelize(property.name) %>() const {
|
|
return impl().paint.template get<<%- camelize(property.name) %>>().value;
|
|
}
|
|
|
|
void <%- camelize(type) %>Layer::set<%- camelize(property.name) %>(const <%- propertyValueType(property) %>& value) {
|
|
if (value == get<%- camelize(property.name) %>())
|
|
return;
|
|
auto impl_ = mutableImpl();
|
|
impl_->paint.template get<<%- camelize(property.name) %>>().value = value;
|
|
<% if (property.name === 'line-width') { -%>
|
|
impl_->paint.template get<LineFloorWidth>().value = value;
|
|
<% } -%>
|
|
baseImpl = std::move(impl_);
|
|
observer->onLayerChanged(*this);
|
|
}
|
|
|
|
void <%- camelize(type) %>Layer::set<%- camelize(property.name) %>Transition(const TransitionOptions& options) {
|
|
auto impl_ = mutableImpl();
|
|
impl_->paint.template get<<%- camelize(property.name) %>>().options = options;
|
|
baseImpl = std::move(impl_);
|
|
}
|
|
|
|
TransitionOptions <%- camelize(type) %>Layer::get<%- camelize(property.name) %>Transition() const {
|
|
return impl().paint.template get<<%- camelize(property.name) %>>().options;
|
|
}
|
|
<% } -%>
|
|
|
|
using namespace conversion;
|
|
|
|
namespace {
|
|
|
|
constexpr uint8_t kPaintPropertyCount = <%- paintProperties.length * 2 -%>u;
|
|
|
|
enum class Property : uint8_t {
|
|
<% for (const property of paintProperties) { -%>
|
|
<%- camelize(property.name) %>,
|
|
<% } -%>
|
|
<% for (const property of paintProperties) { -%>
|
|
<%- camelize(property.name) %>Transition,
|
|
<% } -%>
|
|
<% for (let i = 0; i < layoutProperties.length; ++i) { -%>
|
|
<% if (i===0) { -%>
|
|
<%- camelize(layoutProperties[i].name) %> = kPaintPropertyCount,
|
|
<% } else { -%>
|
|
<%- camelize(layoutProperties[i].name) %>,
|
|
<% } -%>
|
|
<% } -%>
|
|
};
|
|
|
|
template <typename T>
|
|
constexpr uint8_t toUint8(T t) noexcept {
|
|
return uint8_t(mbgl::underlying_type(t));
|
|
}
|
|
|
|
constexpr const auto layerProperties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>(
|
|
{<%- paintProperties.map(p => `{"${p.name}", toUint8(Property::${camelize(p.name)})}`).join(',\n ') %>,
|
|
<% if (!layoutProperties.length) { -%>
|
|
<%- paintProperties.map(p => `{"${p.name}-transition", toUint8(Property::${camelize(p.name)}Transition)}`).join(',\n ') %>});
|
|
<% } else { -%>
|
|
<%- paintProperties.map(p => `{"${p.name}-transition", toUint8(Property::${camelize(p.name)}Transition)}`).join(',\n ') %>,
|
|
<%- layoutProperties.map(p => `{"${p.name}", toUint8(Property::${camelize(p.name)})}`).join(',\n ') %>});
|
|
<% } -%>
|
|
|
|
StyleProperty getLayerProperty(const <%- camelize(type) %>Layer& layer, Property property) {
|
|
switch (property) {
|
|
<% for (const property of paintProperties) { -%>
|
|
case Property::<%- camelize(property.name) %>:
|
|
return makeStyleProperty(layer.get<%- camelize(property.name) %>());
|
|
<% } -%>
|
|
<% for (const property of paintProperties) { -%>
|
|
case Property::<%- camelize(property.name) %>Transition:
|
|
return makeStyleProperty(layer.get<%- camelize(property.name) %>Transition());
|
|
<% } -%>
|
|
<% for (const property of layoutProperties) { -%>
|
|
case Property::<%- camelize(property.name) %>:
|
|
return makeStyleProperty(layer.get<%- camelize(property.name) %>());
|
|
<% } -%>
|
|
}
|
|
return {};
|
|
}
|
|
|
|
StyleProperty getLayerProperty(const <%- camelize(type) -%>Layer& layer, const std::string& name) {
|
|
const auto it = layerProperties.find(name.c_str());
|
|
if (it == layerProperties.end()) {
|
|
return {};
|
|
}
|
|
return getLayerProperty(layer, static_cast<Property>(it->second));
|
|
}
|
|
|
|
} // namespace
|
|
|
|
Value <%- camelize(type) %>Layer::serialize() const {
|
|
auto result = Layer::serialize();
|
|
assert(result.getObject());
|
|
for (const auto& property : layerProperties) {
|
|
auto styleProperty = getLayerProperty(*this, static_cast<Property>(property.second));
|
|
if (styleProperty.getKind() == StyleProperty::Kind::Undefined) continue;
|
|
serializeProperty(result, styleProperty, property.first.c_str(), property.second < kPaintPropertyCount);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
std::optional<Error> <%- camelize(type) %>Layer::setPropertyInternal(const std::string& name, const Convertible& value) {
|
|
const auto it = layerProperties.find(name.c_str());
|
|
if (it == layerProperties.end()) return Error{"layer doesn't support this property"};
|
|
|
|
auto property = static_cast<Property>(it->second);
|
|
|
|
<%
|
|
const conversions = {};
|
|
for (const property of allProperties) {
|
|
const dataDriven = property['property-type'] === 'data-driven' || property['property-type'] === 'cross-faded-data-driven';
|
|
const convertTokens = property.name === 'icon-image' || property.name === 'text-field';
|
|
const conversion = `const auto& typedValue = convert<${propertyValueType(property)}>(value, error, ${dataDriven}, ${convertTokens})`;
|
|
conversions[conversion] = conversions[conversion] || [];
|
|
conversions[conversion].push(property);
|
|
}
|
|
const reduceConditions = (total, e) => {
|
|
const splitter = ' || ';
|
|
const ident = ' ';
|
|
let totalLength = total.length + e.length + ident.length + splitter.length + 3 /* ||*/;
|
|
const lastCR = total.lastIndexOf('\n');
|
|
const length = (lastCR == -1) ? totalLength : (totalLength - (ident.length + lastCR));
|
|
return total + (length <= 120 ? splitter : ` ||\n${ident}`) + e;
|
|
}
|
|
-%>
|
|
<% for (const key in conversions) {
|
|
const properties = conversions[key];
|
|
-%>
|
|
if (<%- properties.map(p => `property == Property::${camelize(p.name)}`).reduce(reduceConditions) %>) {
|
|
Error error;
|
|
<%- split120Line(key) %>;
|
|
if (!typedValue) {
|
|
return error;
|
|
}
|
|
<% if (properties.length == 1) { %>
|
|
set<%- camelize(properties[0].name) %>(*typedValue);
|
|
return std::nullopt;
|
|
<% } else for (const property of properties) { %>
|
|
if (property == Property::<%- camelize(property.name) %>) {
|
|
set<%- camelize(property.name) %>(*typedValue);
|
|
return std::nullopt;
|
|
}
|
|
<% } -%>
|
|
}
|
|
<% } %>
|
|
Error error;
|
|
std::optional<TransitionOptions> transition = convert<TransitionOptions>(value, error);
|
|
if (!transition) {
|
|
return error;
|
|
}
|
|
<% for (const property of paintProperties) { %>
|
|
if (property == Property::<%- camelize(property.name) %>Transition) {
|
|
set<%- camelize(property.name) %>Transition(*transition);
|
|
return std::nullopt;
|
|
}
|
|
<% } %>
|
|
return Error{"layer doesn't support this property"};
|
|
}
|
|
|
|
StyleProperty <%- camelize(type) %>Layer::getProperty(const std::string& name) const {
|
|
return getLayerProperty(*this, name);
|
|
}
|
|
|
|
Mutable<Layer::Impl> <%- camelize(type) %>Layer::mutableBaseImpl() const {
|
|
return staticMutableCast<Layer::Impl>(mutableImpl());
|
|
}
|
|
|
|
} // namespace style
|
|
} // namespace mbgl
|
|
|
|
// clang-format on
|