#pragma once #include #include #include #include #include #include #include #include namespace mbgl { class SymbolBucket; class SymbolInstance; using SymbolInstanceReferences = std::vector>; class UpdateParameters; enum class PlacedSymbolOrientation : bool; class OpacityState { public: OpacityState(bool placed, bool skipFade); OpacityState(const OpacityState& prevState, float increment, bool placed); bool isHidden() const; float opacity; bool placed; }; class JointOpacityState { public: JointOpacityState(bool placedText, bool placedIcon, bool skipFade); JointOpacityState(const JointOpacityState& prevOpacityState, float increment, bool placedText, bool placedIcon); bool isHidden() const; OpacityState icon; OpacityState text; }; class VariableOffset { public: std::array offset; float width; float height; style::TextVariableAnchorType anchor; float textBoxScale; optional prevAnchor; }; class JointPlacement { public: JointPlacement(bool text_, bool icon_, bool skipFade_) : text(text_), icon(icon_), skipFade(skipFade_) {} bool placed() const { return text || icon; } const bool text; const bool icon; // 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 skipFade; }; struct RetainedQueryData { uint32_t bucketInstanceId; std::shared_ptr featureIndex; OverscaledTileID tileID; mutable FeatureSortOrder featureSortOrder; RetainedQueryData(uint32_t bucketInstanceId_, std::shared_ptr featureIndex_, OverscaledTileID tileID_) : bucketInstanceId(bucketInstanceId_), featureIndex(std::move(featureIndex_)), tileID(tileID_) {} }; class CollisionGroups { public: using Predicate = std::function; using CollisionGroup = std::pair>; CollisionGroups(const bool crossSourceCollisions_) : maxGroupID(0) , crossSourceCollisions(crossSourceCollisions_) {} const CollisionGroup& get(const std::string& sourceID); private: std::map collisionGroups; uint16_t maxGroupID; bool crossSourceCollisions; }; class Placement; class PlacementContext; class PlacementController { public: PlacementController(); void setPlacement(Immutable); const Immutable& getPlacement() const { return placement; } void setPlacementStale() { stale = true; } bool placementIsRecent(TimePoint now, float zoom, optional periodOverride = nullopt) const; bool hasTransitions(TimePoint now) const; private: Immutable placement; bool stale = false; }; class Placement { public: /** * @brief creates a new placement instance, from the given update parameters and the previous placement instance. * * Different placement implementations are created based on `updateParameters->mapMode`. * In Continuous map mode, `prevPlacement` must be provided. */ static Mutable create(std::shared_ptr updateParameters, optional> prevPlacement = nullopt); virtual ~Placement(); virtual void placeLayers(const RenderLayerReferences&); void updateLayerBuckets(const RenderLayer&, const TransformState&, bool updateOpacities) const; virtual float symbolFadeChange(TimePoint now) const; virtual bool hasTransitions(TimePoint now) const; virtual bool transitionsEnabled() const; virtual void collectPlacedSymbolData(bool /*enable*/) {} virtual const std::vector& getPlacedSymbolsData() const; const CollisionIndex& getCollisionIndex() const; TimePoint getCommitTime() const { return commitTime; } Duration getUpdatePeriod(float zoom) const; float zoomAdjustment(float zoom) const; const JointPlacement* getSymbolPlacement(const SymbolInstance&) const; const RetainedQueryData& getQueryData(uint32_t bucketInstanceId) const; // Public constructors are required for makeMutable(), shall not be called directly. Placement(); Placement(std::shared_ptr, optional> prevPlacement); protected: friend SymbolBucket; virtual void placeSymbolBucket(const BucketPlacementData&, std::set& seenCrossTileIDs); JointPlacement placeSymbol(const SymbolInstance& symbolInstance, const PlacementContext&); void placeLayer(const RenderLayer&, std::set&); virtual void commit(); virtual void newSymbolPlaced(const SymbolInstance&, const PlacementContext&, const JointPlacement&, style::SymbolPlacementType, const std::vector& /*textBoxes*/, const std::vector& /*iconBoxes*/) {} // Implentation specific hooks, which get called during a symbol bucket placement. virtual optional getAvoidEdges(const SymbolBucket&, const mat4& /*posMatrix*/) { return nullopt; } SymbolInstanceReferences getSortedSymbols(const BucketPlacementData&, float pixelRatio); virtual bool canPlaceAtVariableAnchor(const CollisionBox&, style::TextVariableAnchorType, Point /*shift*/, std::vector&, const mat4& /*posMatrix*/, float /*textPixelRatio*/) { return true; } // Returns `true` if bucket vertices were updated; returns `false` otherwise. bool updateBucketDynamicVertices(SymbolBucket&, const TransformState&, const RenderTile& tile) const; void updateBucketOpacities(SymbolBucket&, const TransformState&, std::set&) const; void markUsedJustification(SymbolBucket&, style::TextVariableAnchorType, const SymbolInstance&, style::TextWritingModeType orientation) const; void markUsedOrientation(SymbolBucket&, style::TextWritingModeType, const SymbolInstance&) const; const Placement* getPrevPlacement() const { return prevPlacement ? prevPlacement->get() : nullptr; } bool isTiltedView() const; std::shared_ptr updateParameters; CollisionIndex collisionIndex; style::TransitionOptions transitionOptions; TimePoint fadeStartTime; TimePoint commitTime; float placementZoom = 0.0f; float prevZoomAdjustment = 0.0f; std::unordered_map placements; std::unordered_map opacities; std::unordered_map variableOffsets; std::unordered_map placedOrientations; std::unordered_map retainedQueryData; CollisionGroups collisionGroups; mutable optional> prevPlacement; bool showCollisionBoxes = false; // Cache being used by placeSymbol() std::vector textBoxes; std::vector iconBoxes; // Used for debug purposes. std::unordered_map> collisionCircles; }; } // namespace mbgl