This repository has been archived by the owner on Aug 8, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
remove code duplication between osx/glfw and linux/glfw programs
- Loading branch information
Showing
6 changed files
with
325 additions
and
519 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.