[core] fix symbol flickering after data updates

This commit is contained in:
Ansis Brammanis
2018-01-10 16:52:00 -05:00
committed by Ansis Brammanis
parent fff33ed7e7
commit 6782d7af37
5 changed files with 34 additions and 29 deletions

View File

@@ -130,6 +130,7 @@ public:
} collisionCircle;
uint32_t bucketInstanceId = 0;
bool justReloaded = false;
};
} // namespace mbgl

View File

@@ -8,8 +8,8 @@
namespace mbgl {
OpacityState::OpacityState(bool placed_, bool offscreen)
: opacity((offscreen && placed_) ? 1 : 0)
OpacityState::OpacityState(bool placed_, bool skipFade)
: opacity((skipFade && placed_) ? 1 : 0)
, placed(placed_)
{
}
@@ -22,11 +22,11 @@ bool OpacityState::isHidden() const {
return opacity == 0 && !placed;
}
JointOpacityState::JointOpacityState(bool placedIcon, bool placedText, bool offscreen) :
icon(OpacityState(placedIcon, offscreen)),
text(OpacityState(placedText, offscreen)) {}
JointOpacityState::JointOpacityState(bool placedText, bool placedIcon, bool skipFade) :
icon(OpacityState(placedIcon, skipFade)),
text(OpacityState(placedText, skipFade)) {}
JointOpacityState::JointOpacityState(const JointOpacityState& prevOpacityState, float increment, bool placedIcon, bool placedText) :
JointOpacityState::JointOpacityState(const JointOpacityState& prevOpacityState, float increment, bool placedText, bool placedIcon) :
icon(OpacityState(prevOpacityState.icon, increment, placedIcon)),
text(OpacityState(prevOpacityState.text, increment, placedText)) {}
@@ -165,10 +165,12 @@ void Placement::placeLayerBucket(
placements.erase(symbolInstance.crossTileID);
}
placements.emplace(symbolInstance.crossTileID, JointPlacement(placeText, placeIcon, offscreen));
placements.emplace(symbolInstance.crossTileID, JointPlacement(placeText, placeIcon, offscreen || bucket.justReloaded));
seenCrossTileIDs.insert(symbolInstance.crossTileID);
}
}
bucket.justReloaded = false;
}
bool Placement::commit(const Placement& prevPlacement, TimePoint now) {
@@ -184,12 +186,12 @@ bool Placement::commit(const Placement& prevPlacement, TimePoint now) {
for (auto& jointPlacement : placements) {
auto prevOpacity = prevPlacement.opacities.find(jointPlacement.first);
if (prevOpacity != prevPlacement.opacities.end()) {
opacities.emplace(jointPlacement.first, JointOpacityState(prevOpacity->second, increment, jointPlacement.second.icon, jointPlacement.second.text));
opacities.emplace(jointPlacement.first, JointOpacityState(prevOpacity->second, increment, jointPlacement.second.text, jointPlacement.second.icon));
placementChanged = placementChanged ||
jointPlacement.second.icon != prevOpacity->second.icon.placed ||
jointPlacement.second.text != prevOpacity->second.text.placed;
} else {
opacities.emplace(jointPlacement.first, JointOpacityState(jointPlacement.second.icon, jointPlacement.second.text, jointPlacement.second.offscreen));
opacities.emplace(jointPlacement.first, JointOpacityState(jointPlacement.second.text, jointPlacement.second.icon, jointPlacement.second.skipFade));
placementChanged = placementChanged || jointPlacement.second.icon || jointPlacement.second.text;
}
}
@@ -234,10 +236,17 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, std::set<uint32_t>&
true);
for (SymbolInstance& symbolInstance : bucket.symbolInstances) {
auto opacityState = seenCrossTileIDs.count(symbolInstance.crossTileID) == 0 ?
getOpacity(symbolInstance.crossTileID) :
bool isDuplicate = seenCrossTileIDs.count(symbolInstance.crossTileID) > 0;
auto it = opacities.find(symbolInstance.crossTileID);
auto opacityState = it != opacities.end() && !isDuplicate ?
it->second :
defaultOpacityState;
if (it == opacities.end()) {
opacities.emplace(symbolInstance.crossTileID, defaultOpacityState);
}
seenCrossTileIDs.insert(symbolInstance.crossTileID);
if (symbolInstance.hasText) {
@@ -293,16 +302,6 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, std::set<uint32_t>&
bucket.sortFeatures(state.getAngle());
}
JointOpacityState Placement::getOpacity(uint32_t crossTileSymbolID) const {
auto it = opacities.find(crossTileSymbolID);
if (it != opacities.end()) {
return it->second;
} else {
return JointOpacityState(false, false, false);
}
}
float Placement::symbolFadeChange(TimePoint now) const {
if (mapMode == MapMode::Continuous) {
return std::chrono::duration<float>(now - commitTime) / Duration(std::chrono::milliseconds(300));

View File

@@ -14,7 +14,7 @@ class SymbolBucket;
class OpacityState {
public:
OpacityState(bool placed, bool offscreen);
OpacityState(bool placed, bool skipFade);
OpacityState(const OpacityState& prevOpacityState, float increment, bool placed);
bool isHidden() const;
float opacity;
@@ -23,7 +23,7 @@ public:
class JointOpacityState {
public:
JointOpacityState(bool placedIcon, bool placedText, bool offscreen);
JointOpacityState(bool placedIcon, bool placedText, bool skipFade);
JointOpacityState(const JointOpacityState& prevOpacityState, float increment, bool placedIcon, bool placedText);
bool isHidden() const;
OpacityState icon;
@@ -32,17 +32,17 @@ public:
class JointPlacement {
public:
JointPlacement(bool text_, bool icon_, bool offscreen_)
: text(text_), icon(icon_), offscreen(offscreen_)
JointPlacement(bool text_, bool icon_, bool skipFade_)
: text(text_), icon(icon_), skipFade(skipFade_)
{}
const bool text;
const bool icon;
// offscreen = outside viewport, but within CollisionIndex::viewportPadding px of the edge
// skipFade = outside viewport, but within CollisionIndex::viewportPadding px of the edge
// Because these symbols aren't onscreen yet, we can skip the "fade in" animation,
// and if a subsequent viewport change brings them into view, they'll be fully
// visible right away.
const bool offscreen;
const bool skipFade;
};
class Placement {
@@ -51,7 +51,6 @@ public:
void placeLayer(RenderSymbolLayer&, const mat4&, bool showCollisionBoxes);
bool commit(const Placement& prevPlacement, TimePoint);
void updateLayerOpacities(RenderSymbolLayer&);
JointOpacityState getOpacity(uint32_t crossTileSymbolID) const;
float symbolFadeChange(TimePoint now) const;
bool hasTransitions(TimePoint now) const;

View File

@@ -425,12 +425,17 @@ void GeometryTileWorker::attemptPlacement() {
continue;
}
std::shared_ptr<Bucket> bucket = symbolLayout->place(showCollisionBoxes);
std::shared_ptr<SymbolBucket> bucket = symbolLayout->place(showCollisionBoxes);
for (const auto& pair : symbolLayout->layerPaintProperties) {
if (!firstLoad) {
bucket->justReloaded = true;
}
buckets.emplace(pair.first, bucket);
}
}
firstLoad = false;
parent.invoke(&GeometryTile::onPlacement, GeometryTile::PlacementResult {
std::move(buckets),
std::move(glyphAtlasImage),

View File

@@ -86,6 +86,7 @@ private:
ImageMap imageMap;
bool showCollisionBoxes;
bool firstLoad = true;
};
} // namespace mbgl