diff options
author | Konstantin Käfer <mail@kkaefer.com> | 2014-03-14 11:33:45 +0100 |
---|---|---|
committer | Konstantin Käfer <mail@kkaefer.com> | 2014-03-14 11:33:45 +0100 |
commit | bdfa761c39218234d9ce7419b3b323e8f25a1476 (patch) | |
tree | 4d6ef181a483a6787bb86cc0e5fd15ac187a8584 /common | |
parent | 4f03b43ab24cc91dea8028ea71b58d6e52f842ed (diff) | |
download | qtlocation-mapboxgl-bdfa761c39218234d9ce7419b3b323e8f25a1476.tar.gz |
remove code duplication between osx/glfw and linux/glfw programs
Diffstat (limited to 'common')
-rw-r--r-- | common/map_view.cpp | 236 |
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; +}; |