saving current state
This commit is contained in:
227
src/map/map.cpp
227
src/map/map.cpp
@@ -36,6 +36,10 @@ Map::Map(View& view)
|
||||
}
|
||||
|
||||
Map::~Map() {
|
||||
// Clear the style first before the rest of the constructor deletes members of this object.
|
||||
// This is required because members of the style reference the Map object in their destructors.
|
||||
style.reset();
|
||||
|
||||
if (async) {
|
||||
stop();
|
||||
}
|
||||
@@ -167,17 +171,6 @@ void Map::setup() {
|
||||
|
||||
painter.setup();
|
||||
|
||||
sources.emplace("outdoors",
|
||||
std::unique_ptr<Source>(new Source(*this,
|
||||
painter,
|
||||
kVectorTileURL,
|
||||
Source::Type::vector,
|
||||
{{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }},
|
||||
512,
|
||||
0,
|
||||
14,
|
||||
true)));
|
||||
|
||||
setStyleJSON(styleJSON);
|
||||
}
|
||||
|
||||
@@ -387,49 +380,44 @@ bool Map::getDebug() const {
|
||||
return debug;
|
||||
}
|
||||
|
||||
void Map::setAppliedClasses(std::set<std::string> appliedClasses) {
|
||||
style->cancelTransitions();
|
||||
|
||||
style->appliedClasses.swap(appliedClasses);
|
||||
|
||||
update();
|
||||
void Map::toggleClass(const std::string &name) {
|
||||
style->toggleClass(name);
|
||||
}
|
||||
|
||||
std::set<std::string> Map::getAppliedClasses() const {
|
||||
return style->appliedClasses;
|
||||
}
|
||||
//void Map::setAppliedClasses(const std::vector<std::string> &appliedClasses) {
|
||||
// style->cancelTransitions();
|
||||
//
|
||||
// style->appliedClasses = appliedClasses;
|
||||
//
|
||||
// update();
|
||||
//}
|
||||
//
|
||||
//const std::vector<std::string> &Map::getAppliedClasses() const {
|
||||
// return style->appliedClasses;
|
||||
//}
|
||||
|
||||
void Map::setDefaultTransitionDuration(uint64_t duration_milliseconds) {
|
||||
style->setDefaultTransitionDuration(duration_milliseconds);
|
||||
}
|
||||
|
||||
void Map::updateTiles() {
|
||||
for (auto &pair : sources) {
|
||||
const std::unique_ptr<Source> &source = pair.second;
|
||||
if (source->enabled) {
|
||||
source->update();
|
||||
}
|
||||
for (const std::shared_ptr<Source> &source : style->getActiveSources()) {
|
||||
source->update(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void Map::updateRenderState() {
|
||||
std::forward_list<Tile::ID> ids;
|
||||
|
||||
for (const auto &pair : sources) {
|
||||
Source &source = *pair.second;
|
||||
if (source.enabled) {
|
||||
ids.splice_after(ids.before_begin(), source.getIDs());
|
||||
source.updateMatrices(state);
|
||||
}
|
||||
for (const std::shared_ptr<Source> &source : style->getActiveSources()) {
|
||||
ids.splice_after(ids.before_begin(), source->getIDs());
|
||||
source->updateMatrices(painter.projMatrix, state);
|
||||
}
|
||||
|
||||
const std::map<Tile::ID, ClipID> clipIDs = computeClipIDs(ids);
|
||||
|
||||
for (const auto &pair : sources) {
|
||||
Source &source = *pair.second;
|
||||
if (source.enabled) {
|
||||
source.updateClipIDs(clipIDs);
|
||||
}
|
||||
for (const std::shared_ptr<Source> &source : style->getActiveSources()) {
|
||||
source->updateClipIDs(clipIDs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -491,14 +479,13 @@ void Map::render() {
|
||||
|
||||
updateRenderState();
|
||||
|
||||
painter.drawClippingMasks(sources);
|
||||
painter.drawClippingMasks(style->getActiveSources());
|
||||
|
||||
#if defined(DEBUG)
|
||||
// Generate debug information
|
||||
size_t source_id = 0;
|
||||
for (const auto &pair : sources) {
|
||||
const Source &source = *pair.second;
|
||||
size_t count = source.getTileCount();
|
||||
for (const std::shared_ptr<Source> &source : style->getActiveSources()) {
|
||||
size_t count = source->getTileCount();
|
||||
debug.emplace_back(util::sprintf<100>("source %d: %d\n", source_id, count));
|
||||
source_id++;
|
||||
}
|
||||
@@ -512,11 +499,8 @@ void Map::render() {
|
||||
// This guarantees that we have at least one function per tile called.
|
||||
// When only rendering layers via the stylesheet, it's possible that we don't
|
||||
// ever visit a tile during rendering.
|
||||
for (const auto &pair : sources) {
|
||||
Source &source = *pair.second;
|
||||
const std::string &name = pair.first;
|
||||
gl::group group(std::string("debug ") + name);
|
||||
source.finishRender();
|
||||
for (const std::shared_ptr<Source> &source : style->getActiveSources()) {
|
||||
source->finishRender(painter);
|
||||
}
|
||||
|
||||
painter.renderMatte();
|
||||
@@ -533,9 +517,14 @@ void Map::render() {
|
||||
glFlush();
|
||||
}
|
||||
|
||||
void Map::renderLayers(const std::vector<LayerDescription>& layers) {
|
||||
void Map::renderLayers(std::shared_ptr<StyleLayerGroup> layers) {
|
||||
if (!layers) {
|
||||
// Make sure that we actually do have a layer group.
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Correctly compute the number of layers recursively beforehand.
|
||||
float strata_thickness = 1.0f / (layers.size() + 1);
|
||||
float strata_thickness = 1.0f / (layers->size() + 1);
|
||||
|
||||
// - FIRST PASS ------------------------------------------------------------
|
||||
// Render everything top-to-bottom by using reverse iterators. Render opaque
|
||||
@@ -544,9 +533,9 @@ void Map::renderLayers(const std::vector<LayerDescription>& layers) {
|
||||
if (debug::renderTree) {
|
||||
std::cout << std::string(indent++ * 4, ' ') << "OPAQUE {" << std::endl;
|
||||
}
|
||||
typedef std::vector<LayerDescription>::const_reverse_iterator riterator;
|
||||
typedef std::vector<StyleLayer::Ptr>::reverse_iterator riterator;
|
||||
int i = 0;
|
||||
for (riterator it = layers.rbegin(), end = layers.rend(); it != end; ++it, ++i) {
|
||||
for (riterator it = layers->rbegin(), end = layers->rend(); it != end; ++it, ++i) {
|
||||
painter.setOpaque();
|
||||
painter.setStrata(i * strata_thickness);
|
||||
renderLayer(*it, Opaque);
|
||||
@@ -561,9 +550,9 @@ void Map::renderLayers(const std::vector<LayerDescription>& layers) {
|
||||
if (debug::renderTree) {
|
||||
std::cout << std::string(indent++ * 4, ' ') << "TRANSLUCENT {" << std::endl;
|
||||
}
|
||||
typedef std::vector<LayerDescription>::const_iterator iterator;
|
||||
typedef std::vector<StyleLayer::Ptr>::iterator iterator;
|
||||
--i;
|
||||
for (iterator it = layers.begin(), end = layers.end(); it != end; ++it, --i) {
|
||||
for (iterator it = layers->begin(), end = layers->end(); it != end; ++it, --i) {
|
||||
painter.setTranslucent();
|
||||
painter.setStrata(i * strata_thickness);
|
||||
renderLayer(*it, Translucent);
|
||||
@@ -573,48 +562,22 @@ void Map::renderLayers(const std::vector<LayerDescription>& layers) {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Styles>
|
||||
typename Styles::const_iterator find_style(const Styles &styles, const LayerDescription &layer_desc) {
|
||||
auto it = styles.find(layer_desc.name);
|
||||
#if defined(DEBUG)
|
||||
if (it == styles.end()) {
|
||||
if (debug::renderWarnings) {
|
||||
fprintf(stderr, "[WARNING] can't find class named '%s' in style\n",
|
||||
layer_desc.name.c_str());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return it;
|
||||
}
|
||||
|
||||
template <typename Styles>
|
||||
bool is_invisible(const Styles &styles, const LayerDescription &layer_desc) {
|
||||
auto it = find_style(styles, layer_desc);
|
||||
if (it == styles.end()) {
|
||||
// We don't have a style, so we fall back to the default style which is
|
||||
// always visible.
|
||||
return false;
|
||||
}
|
||||
return !it->second.isVisible();
|
||||
}
|
||||
|
||||
void Map::renderLayer(const LayerDescription& layer_desc, RenderPass pass) {
|
||||
if (layer_desc.child_layer.size()) {
|
||||
void Map::renderLayer(std::shared_ptr<StyleLayer> layer_desc, RenderPass pass) {
|
||||
if (layer_desc->layers) {
|
||||
// This is a layer group. We render them during our translucent render pass.
|
||||
if (pass == Translucent) {
|
||||
auto it = find_style(style->computed.composites, layer_desc);
|
||||
const CompositeProperties &properties = (it != style->computed.composites.end()) ? it->second : defaultCompositeProperties;
|
||||
const CompositeProperties &properties = layer_desc->getProperties<CompositeProperties>();
|
||||
if (properties.isVisible()) {
|
||||
gl::group group(std::string("group: ") + layer_desc.name);
|
||||
gl::group group(std::string("group: ") + layer_desc->id);
|
||||
|
||||
if (debug::renderTree) {
|
||||
std::cout << std::string(indent++ * 4, ' ') << "+ " << layer_desc.name
|
||||
std::cout << std::string(indent++ * 4, ' ') << "+ " << layer_desc->id
|
||||
<< " (Composite) {" << std::endl;
|
||||
}
|
||||
|
||||
painter.pushFramebuffer();
|
||||
|
||||
renderLayers(layer_desc.child_layer);
|
||||
renderLayers(layer_desc->layers);
|
||||
|
||||
GLuint texture = painter.popFramebuffer();
|
||||
|
||||
@@ -626,63 +589,51 @@ void Map::renderLayer(const LayerDescription& layer_desc, RenderPass pass) {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (layer_desc.bucket_name == "background") {
|
||||
} else if (layer_desc->id == "background") {
|
||||
// This layer defines the background color.
|
||||
} else {
|
||||
// This is a singular layer. Try to find the bucket associated with
|
||||
// this layer and render it.
|
||||
|
||||
auto bucket_it = style->buckets.find(layer_desc.bucket_name);
|
||||
if (bucket_it != style->buckets.end()) {
|
||||
const BucketDescription &bucket_desc = bucket_it->second;
|
||||
|
||||
// Abort early if we can already deduce from the bucket type that
|
||||
// we're not going to render anything anyway during this pass.
|
||||
switch (bucket_desc.type) {
|
||||
case BucketType::Fill:
|
||||
if (is_invisible(style->computed.fills, layer_desc)) return;
|
||||
break;
|
||||
case BucketType::Line:
|
||||
if (pass == Opaque) return;
|
||||
if (is_invisible(style->computed.lines, layer_desc)) return;
|
||||
break;
|
||||
case BucketType::Icon:
|
||||
if (pass == Opaque) return;
|
||||
if (is_invisible(style->computed.icons, layer_desc)) return;
|
||||
break;
|
||||
case BucketType::Text:
|
||||
if (pass == Opaque) return;
|
||||
if (is_invisible(style->computed.texts, layer_desc)) return;
|
||||
break;
|
||||
case BucketType::Raster:
|
||||
if (pass == Translucent) return;
|
||||
if (is_invisible(style->computed.rasters, layer_desc)) return;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Find the source and render all tiles in it.
|
||||
auto source_it = sources.find(bucket_desc.source_name);
|
||||
if (source_it != sources.end()) {
|
||||
if (debug::renderTree) {
|
||||
std::cout << std::string(indent * 4, ' ') << "- " << layer_desc.name << " ("
|
||||
<< bucket_desc.type << ")" << std::endl;
|
||||
}
|
||||
|
||||
const std::unique_ptr<Source> &source = source_it->second;
|
||||
source->render(layer_desc, bucket_desc);
|
||||
} else {
|
||||
if (debug::renderWarnings) {
|
||||
fprintf(stderr, "[WARNING] can't find source '%s' required for bucket '%s'\n",
|
||||
bucket_desc.source_name.c_str(), layer_desc.bucket_name.c_str());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (debug::renderWarnings) {
|
||||
fprintf(stderr, "[WARNING] can't find bucket '%s' required for layer '%s'\n",
|
||||
layer_desc.bucket_name.c_str(), layer_desc.name.c_str());
|
||||
}
|
||||
// This is a singular layer.
|
||||
if (!layer_desc->bucket) {
|
||||
fprintf(stderr, "[WARNING] layer '%s' is missing bucket\n", layer_desc->id.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!layer_desc->bucket->source) {
|
||||
fprintf(stderr, "[WARNING] can't find source for layer '%s'\n", layer_desc->id.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// Abort early if we can already deduce from the bucket type that
|
||||
// we're not going to render anything anyway during this pass.
|
||||
switch (layer_desc->bucket->type) {
|
||||
case BucketType::Fill:
|
||||
if (!layer_desc->getProperties<FillProperties>().isVisible()) return;
|
||||
break;
|
||||
case BucketType::Line:
|
||||
if (pass == Opaque) return;
|
||||
if (!layer_desc->getProperties<LineProperties>().isVisible()) return;
|
||||
break;
|
||||
case BucketType::Icon:
|
||||
if (pass == Opaque) return;
|
||||
if (!layer_desc->getProperties<IconProperties>().isVisible()) return;
|
||||
break;
|
||||
case BucketType::Text:
|
||||
if (pass == Opaque) return;
|
||||
if (!layer_desc->getProperties<TextProperties>().isVisible()) return;
|
||||
break;
|
||||
case BucketType::Raster:
|
||||
if (pass == Translucent) return;
|
||||
if (!layer_desc->getProperties<RasterProperties>().isVisible()) return;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (debug::renderTree) {
|
||||
std::cout << std::string(indent * 4, ' ') << "- " << layer_desc->id << " ("
|
||||
<< layer_desc->bucket->type << ")" << std::endl;
|
||||
}
|
||||
|
||||
layer_desc->bucket->source->render(painter, layer_desc);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user