248 lines
8.5 KiB
C++
248 lines
8.5 KiB
C++
#ifndef MBGL_MAP_MAP
|
|
#define MBGL_MAP_MAP
|
|
|
|
#include <mbgl/map/transform.hpp>
|
|
#include <mbgl/util/geo.hpp>
|
|
#include <mbgl/util/projection.hpp>
|
|
#include <mbgl/util/noncopyable.hpp>
|
|
#include <mbgl/util/uv.hpp>
|
|
#include <mbgl/util/ptr.hpp>
|
|
#include <mbgl/util/vec.hpp>
|
|
|
|
#include <cstdint>
|
|
#include <atomic>
|
|
#include <thread>
|
|
#include <iosfwd>
|
|
#include <set>
|
|
#include <vector>
|
|
#include <mutex>
|
|
#include <condition_variable>
|
|
#include <functional>
|
|
#include <chrono>
|
|
|
|
namespace mbgl {
|
|
|
|
class Painter;
|
|
class GlyphStore;
|
|
class LayerDescription;
|
|
class Sprite;
|
|
class Style;
|
|
class StyleLayer;
|
|
class StyleLayerGroup;
|
|
class StyleSource;
|
|
class TexturePool;
|
|
class FileSource;
|
|
class View;
|
|
class GlyphAtlas;
|
|
class SpriteAtlas;
|
|
class LineAtlas;
|
|
|
|
class Map : private util::noncopyable {
|
|
public:
|
|
explicit Map(View&, FileSource&);
|
|
~Map();
|
|
|
|
// Start the map render thread. It is asynchronous.
|
|
void start(bool startPaused = false);
|
|
|
|
// Stop the map render thread. This call will block until the map rendering thread stopped.
|
|
// The optional callback function will be invoked repeatedly until the map thread is stopped.
|
|
// The callback function should wait until it is woken up again by view.notify(), otherwise
|
|
// this will be a busy waiting loop.
|
|
void stop(std::function<void ()> callback = std::function<void ()>());
|
|
|
|
// Pauses the render thread. The render thread will stop running but will not be terminated and will not lose state until resumed.
|
|
void pause(bool waitForPause = false);
|
|
|
|
// Resumes a paused render thread
|
|
void resume();
|
|
|
|
// Runs the map event loop. ONLY run this function when you want to get render a single frame
|
|
// with this map object. It will *not* spawn a separate thread and instead block until the
|
|
// frame is completely rendered.
|
|
void run();
|
|
|
|
// Triggers a lazy rerender: only performs a render when the map is not clean.
|
|
void rerender();
|
|
|
|
// Forces a map update: always triggers a rerender.
|
|
void update();
|
|
|
|
// Releases resources immediately
|
|
void terminate();
|
|
|
|
// Controls buffer swapping.
|
|
bool needsSwap();
|
|
void swapped();
|
|
|
|
// Size
|
|
void resize(uint16_t width, uint16_t height, float ratio = 1);
|
|
void resize(uint16_t width, uint16_t height, float ratio, uint16_t fbWidth, uint16_t fbHeight);
|
|
|
|
// Styling
|
|
void addClass(const std::string&);
|
|
void removeClass(const std::string&);
|
|
bool hasClass(const std::string&) const;
|
|
void setClasses(const std::vector<std::string>&);
|
|
std::vector<std::string> getClasses() const;
|
|
|
|
void setDefaultTransitionDuration(std::chrono::steady_clock::duration duration = std::chrono::steady_clock::duration::zero());
|
|
std::chrono::steady_clock::duration getDefaultTransitionDuration();
|
|
void setStyleURL(const std::string &url);
|
|
void setStyleJSON(std::string newStyleJSON, const std::string &base = "");
|
|
std::string getStyleJSON() const;
|
|
|
|
// Transition
|
|
void cancelTransitions();
|
|
|
|
// Position
|
|
void moveBy(double dx, double dy, std::chrono::steady_clock::duration duration = std::chrono::steady_clock::duration::zero());
|
|
void setLatLng(LatLng latLng, std::chrono::steady_clock::duration duration = std::chrono::steady_clock::duration::zero());
|
|
inline const LatLng getLatLng() const { return state.getLatLng(); }
|
|
void startPanning();
|
|
void stopPanning();
|
|
void resetPosition();
|
|
|
|
// Scale
|
|
void scaleBy(double ds, double cx = -1, double cy = -1, std::chrono::steady_clock::duration duration = std::chrono::steady_clock::duration::zero());
|
|
void setScale(double scale, double cx = -1, double cy = -1, std::chrono::steady_clock::duration duration = std::chrono::steady_clock::duration::zero());
|
|
double getScale() const;
|
|
void setZoom(double zoom, std::chrono::steady_clock::duration duration = std::chrono::steady_clock::duration::zero());
|
|
double getZoom() const;
|
|
void setLatLngZoom(LatLng latLng, double zoom, std::chrono::steady_clock::duration duration = std::chrono::steady_clock::duration::zero());
|
|
void resetZoom();
|
|
void startScaling();
|
|
void stopScaling();
|
|
double getMinZoom() const;
|
|
double getMaxZoom() const;
|
|
|
|
// Rotation
|
|
void rotateBy(double sx, double sy, double ex, double ey, std::chrono::steady_clock::duration duration = std::chrono::steady_clock::duration::zero());
|
|
void setBearing(double degrees, std::chrono::steady_clock::duration duration = std::chrono::steady_clock::duration::zero());
|
|
void setBearing(double degrees, double cx, double cy);
|
|
double getBearing() const;
|
|
void resetNorth();
|
|
void startRotating();
|
|
void stopRotating();
|
|
|
|
// API
|
|
void setAccessToken(const std::string &token);
|
|
const std::string &getAccessToken() const;
|
|
|
|
// Projection
|
|
inline void getWorldBoundsMeters(ProjectedMeters &sw, ProjectedMeters &ne) const { Projection::getWorldBoundsMeters(sw, ne); }
|
|
inline void getWorldBoundsLatLng(LatLng &sw, LatLng &ne) const { Projection::getWorldBoundsLatLng(sw, ne); }
|
|
inline double getMetersPerPixelAtLatitude(const double lat, const double zoom) const { return Projection::getMetersPerPixelAtLatitude(lat, zoom); }
|
|
inline const ProjectedMeters projectedMetersForLatLng(const LatLng latLng) const { return Projection::projectedMetersForLatLng(latLng); }
|
|
inline const LatLng latLngForProjectedMeters(const ProjectedMeters projectedMeters) const { return Projection::latLngForProjectedMeters(projectedMeters); }
|
|
inline const vec2<double> pixelForLatLng(const LatLng latLng) const { return state.pixelForLatLng(latLng); }
|
|
inline const LatLng latLngForPixel(const vec2<double> pixel) const { return state.latLngForPixel(pixel); }
|
|
|
|
// Debug
|
|
void setDebug(bool value);
|
|
void toggleDebug();
|
|
bool getDebug() const;
|
|
|
|
inline const TransformState &getState() const { return state; }
|
|
inline std::chrono::steady_clock::time_point getTime() const { return animationTime; }
|
|
|
|
private:
|
|
util::ptr<Sprite> getSprite();
|
|
uv::worker& getWorker();
|
|
|
|
// Checks if render thread needs to pause
|
|
void checkForPause();
|
|
|
|
// Setup
|
|
void setup();
|
|
|
|
void updateTiles();
|
|
void updateSources();
|
|
void updateSources(const util::ptr<StyleLayerGroup> &group);
|
|
|
|
// Prepares a map render by updating the tiles we need for the current view, as well as updating
|
|
// the stylesheet.
|
|
void prepare();
|
|
|
|
// Unconditionally performs a render with the current map state.
|
|
void render();
|
|
|
|
enum class Mode : uint8_t {
|
|
None, // we're not doing any processing
|
|
Continuous, // continually updating map
|
|
Static, // a once-off static image.
|
|
};
|
|
|
|
Mode mode = Mode::None;
|
|
|
|
public: // TODO: make private again
|
|
std::unique_ptr<uv::loop> loop;
|
|
|
|
private:
|
|
std::unique_ptr<uv::worker> workers;
|
|
std::thread thread;
|
|
std::unique_ptr<uv::async> asyncTerminate;
|
|
std::unique_ptr<uv::async> asyncRender;
|
|
|
|
bool terminating = false;
|
|
bool pausing = false;
|
|
bool isPaused = false;
|
|
std::mutex mutexRun;
|
|
std::condition_variable condRun;
|
|
std::mutex mutexPause;
|
|
std::condition_variable condPause;
|
|
|
|
// If cleared, the next time the render thread attempts to render the map, it will *actually*
|
|
// render the map.
|
|
std::atomic_flag isClean = ATOMIC_FLAG_INIT;
|
|
|
|
// If this flag is cleared, the current back buffer is ready for being swapped with the front
|
|
// buffer (i.e. it has rendered data).
|
|
std::atomic_flag isSwapped = ATOMIC_FLAG_INIT;
|
|
|
|
// This is cleared once the current front buffer has been presented and the back buffer is
|
|
// ready for rendering.
|
|
std::atomic_flag isRendered = ATOMIC_FLAG_INIT;
|
|
|
|
// Stores whether the map thread has been stopped already.
|
|
std::atomic_bool isStopped;
|
|
|
|
View &view;
|
|
|
|
#ifdef DEBUG
|
|
const std::thread::id mainThread;
|
|
std::thread::id mapThread;
|
|
#endif
|
|
|
|
Transform transform;
|
|
TransformState state;
|
|
|
|
FileSource& fileSource;
|
|
|
|
util::ptr<Style> style;
|
|
const std::unique_ptr<GlyphAtlas> glyphAtlas;
|
|
util::ptr<GlyphStore> glyphStore;
|
|
const std::unique_ptr<SpriteAtlas> spriteAtlas;
|
|
util::ptr<Sprite> sprite;
|
|
const std::unique_ptr<LineAtlas> lineAtlas;
|
|
util::ptr<TexturePool> texturePool;
|
|
|
|
const std::unique_ptr<Painter> painter;
|
|
|
|
std::string styleURL;
|
|
std::string styleJSON = "";
|
|
std::vector<std::string> classes;
|
|
std::string accessToken;
|
|
|
|
std::chrono::steady_clock::duration defaultTransitionDuration;
|
|
|
|
bool debug = false;
|
|
std::chrono::steady_clock::time_point animationTime = std::chrono::steady_clock::time_point::min();
|
|
|
|
std::set<util::ptr<StyleSource>> activeSources;
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|