summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2014-03-14 11:33:45 +0100
committerKonstantin Käfer <mail@kkaefer.com>2014-03-14 11:33:45 +0100
commitbdfa761c39218234d9ce7419b3b323e8f25a1476 (patch)
tree4d6ef181a483a6787bb86cc0e5fd15ac187a8584 /common
parent4f03b43ab24cc91dea8028ea71b58d6e52f842ed (diff)
downloadqtlocation-mapboxgl-bdfa761c39218234d9ce7419b3b323e8f25a1476.tar.gz
remove code duplication between osx/glfw and linux/glfw programs
Diffstat (limited to 'common')
-rw-r--r--common/map_view.cpp236
1 files changed, 236 insertions, 0 deletions
diff --git a/common/map_view.cpp b/common/map_view.cpp
new file mode 100644
index 0000000000..5119b3134f
--- /dev/null
+++ b/common/map_view.cpp
@@ -0,0 +1,236 @@
+#include <GLFW/glfw3.h>
+#include <llmr/llmr.hpp>
+#include <llmr/map/settings.hpp>
+
+class MapView {
+public:
+ MapView(llmr::Settings& settings, bool fullscreen = false) :
+ fullscreen(fullscreen),
+ settings(settings),
+ map(settings) {
+ }
+
+ void init() {
+ if (!glfwInit()) {
+ fprintf(stderr, "Failed to initialize glfw\n");
+ exit(1);
+ }
+
+ GLFWmonitor *monitor = nullptr;
+ if (fullscreen) {
+ monitor = glfwGetPrimaryMonitor();
+ }
+
+#ifdef GL_ES_VERSION_2_0
+ glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
+#endif
+
+ glfwWindowHint(GLFW_RED_BITS, 8);
+ glfwWindowHint(GLFW_GREEN_BITS, 8);
+ glfwWindowHint(GLFW_BLUE_BITS, 8);
+ glfwWindowHint(GLFW_ALPHA_BITS, 8);
+ glfwWindowHint(GLFW_STENCIL_BITS, 8);
+ glfwWindowHint(GLFW_DEPTH_BITS, 16);
+
+ window = glfwCreateWindow(1024, 768, "llmr", monitor, NULL);
+ if (!window) {
+ glfwTerminate();
+ fprintf(stderr, "Failed to initialize window\n");
+ exit(1);
+ }
+
+ glfwSetWindowUserPointer(window, this);
+ glfwMakeContextCurrent(window);
+
+
+ int width, height;
+ glfwGetWindowSize(window, &width, &height);
+ int fb_width, fb_height;
+ glfwGetFramebufferSize(window, &fb_width, &fb_height);
+
+ settings.load();
+ map.setup((double)fb_width / width);
+
+ resize(window, 0, 0);
+
+ glfwSwapInterval(1);
+
+ map.loadSettings();
+
+ glfwSetCursorPosCallback(window, mousemove);
+ glfwSetMouseButtonCallback(window, mouseclick);
+ glfwSetWindowSizeCallback(window, resize);
+ glfwSetFramebufferSizeCallback(window, resize);
+ glfwSetScrollCallback(window, scroll);
+ glfwSetCharCallback(window, character);
+ glfwSetKeyCallback(window, key);
+ }
+
+
+ static void character(GLFWwindow *window, unsigned int codepoint) {
+
+ }
+
+
+ static void key(GLFWwindow *window, int key, int scancode, int action, int mods) {
+ MapView *mapView = (MapView *)glfwGetWindowUserPointer(window);
+
+ if (action == GLFW_RELEASE) {
+ switch (key) {
+ case GLFW_KEY_ESCAPE:
+ glfwSetWindowShouldClose(window, true);
+ break;
+ case GLFW_KEY_TAB:
+ mapView->map.toggleDebug();
+ break;
+ case GLFW_KEY_R:
+ if (!mods) mapView->map.resetPosition();
+ break;
+ case GLFW_KEY_N:
+ if (!mods) mapView->map.resetNorth();
+ break;
+ }
+ }
+ }
+
+
+ static void scroll(GLFWwindow *window, double xoffset, double yoffset) {
+ MapView *mapView = (MapView *)glfwGetWindowUserPointer(window);
+ double delta = yoffset * 40;
+
+ bool is_wheel = delta != 0 && fmod(delta, 4.000244140625) == 0;
+
+ double absdelta = delta < 0 ? -delta : delta;
+ double scale = 2.0 / (1.0 + exp(-absdelta / 100.0));
+
+ // Make the scroll wheel a bit slower.
+ if (!is_wheel) {
+ scale = (scale - 1.0) / 2.0 + 1.0;
+ }
+
+ // Zooming out.
+ if (delta < 0 && scale != 0) {
+ scale = 1.0 / scale;
+ }
+
+ mapView->map.startScaling();
+ mapView->map.scaleBy(scale, mapView->last_x, mapView->last_y);
+ }
+
+ static void resize(GLFWwindow *window, int, int) {
+ MapView *mapView = (MapView *)glfwGetWindowUserPointer(window);
+
+ int width, height;
+ glfwGetWindowSize(window, &width, &height);
+ int fb_width, fb_height;
+ glfwGetFramebufferSize(window, &fb_width, &fb_height);
+
+ mapView->map.resize(width, height, fb_width, fb_height);
+ }
+
+ static void mouseclick(GLFWwindow *window, int button, int action, int modifiers) {
+ MapView *mapView = (MapView *)glfwGetWindowUserPointer(window);
+
+ if (button == GLFW_MOUSE_BUTTON_RIGHT || (button == GLFW_MOUSE_BUTTON_LEFT && modifiers & GLFW_MOD_CONTROL)) {
+ mapView->rotating = action == GLFW_PRESS;
+ if (mapView->rotating) {
+ mapView->start_x = mapView->last_x;
+ mapView->start_y = mapView->last_y;
+ } else {
+ mapView->map.stopRotating();
+ }
+ } else if (button == GLFW_MOUSE_BUTTON_LEFT) {
+ mapView->tracking = action == GLFW_PRESS;
+
+ if (action == GLFW_RELEASE) {
+ mapView->map.stopPanning();
+ double now = glfwGetTime();
+ if (now - mapView->last_click < 0.4) {
+ mapView->map.scaleBy(2.0, mapView->last_x, mapView->last_y);
+ }
+ mapView->last_click = now;
+ }
+ }
+ }
+
+ static void mousemove(GLFWwindow *window, double x, double y) {
+ MapView *mapView = (MapView *)glfwGetWindowUserPointer(window);
+ if (mapView->tracking) {
+ double dx = x - mapView->last_x;
+ double dy = y - mapView->last_y;
+ if (dx || dy) {
+ mapView->map.startPanning();
+ mapView->map.moveBy(dx, dy);
+ }
+ } else if (mapView->rotating) {
+ mapView->map.startRotating();
+ mapView->map.rotateBy(mapView->start_x, mapView->start_y, mapView->last_x, mapView->last_y, x, y);
+ }
+ mapView->last_x = x;
+ mapView->last_y = y;
+ }
+
+ int run() {
+ while (!glfwWindowShouldClose(window)) {
+ llmr::platform::cleanup();
+
+ if (dirty) {
+ try {
+ dirty = render();
+ } catch (std::exception& ex) {
+ fprintf(stderr, "exception: %s\n", ex.what());
+ }
+ glfwSwapBuffers(window);
+ fps();
+ }
+
+ if (dirty) {
+ glfwPollEvents();
+ } else {
+ glfwWaitEvents();
+ }
+ }
+
+ return 0;
+ }
+
+ bool render() {
+ return map.render();
+ }
+
+ void fps() {
+ static int frames = 0;
+ static double time_elapsed = 0;
+
+ frames++;
+ double current_time = glfwGetTime();
+
+ if (current_time - time_elapsed >= 1) {
+ fprintf(stderr, "FPS: %4.2f\n", frames / (current_time - time_elapsed));
+ time_elapsed = current_time;
+ frames = 0;
+ }
+ }
+
+ ~MapView() {
+ glfwTerminate();
+ }
+
+public:
+ bool fullscreen = false;
+
+ bool dirty = true;
+ double last_x = 0, last_y = 0;
+ bool tracking = false;
+
+ double start_x = 0, start_y = 0;
+ bool rotating = false;
+
+ double last_click = -1;
+
+ GLFWwindow *window = nullptr;
+ llmr::Settings& settings;
+ llmr::Map map;
+};