[core] fix symbol flickering after data updates
This commit is contained in:
committed by
Ansis Brammanis
parent
fff33ed7e7
commit
6782d7af37
@@ -130,6 +130,7 @@ public:
|
||||
} collisionCircle;
|
||||
|
||||
uint32_t bucketInstanceId = 0;
|
||||
bool justReloaded = false;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -86,6 +86,7 @@ private:
|
||||
ImageMap imageMap;
|
||||
|
||||
bool showCollisionBoxes;
|
||||
bool firstLoad = true;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
Reference in New Issue
Block a user