forked from Kolyah35/minecraft-pe-0.6.1
235 lines
6.7 KiB
C++
235 lines
6.7 KiB
C++
#include "PlatformGlfw.h"
|
|
#include <IPlatform.h>
|
|
#include "platform/input/Keyboard.h"
|
|
#include "platform/input/Mouse.h"
|
|
|
|
#include "platform/log.h"
|
|
#include <GLFW/glfw3.h>
|
|
#include <png.h>
|
|
|
|
#include "platform/HttpClient.h"
|
|
#include "util/StringUtils.h"
|
|
#include <fstream>
|
|
#include <ctime>
|
|
#include <vector>
|
|
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#include <shellapi.h>
|
|
#endif
|
|
|
|
#include "App.h"
|
|
|
|
|
|
bool PlatformGlfw::init() {
|
|
glfwSetErrorCallback(PlatformGlfw::error_callback);
|
|
|
|
if (!glfwInit()) {
|
|
return false;
|
|
}
|
|
|
|
glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_NATIVE_CONTEXT_API);
|
|
#ifndef __EMSCRIPTEN__
|
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
|
|
#else
|
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 1);
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
|
#endif
|
|
|
|
m_window = glfwCreateWindow(getScreenWidth(), getScreenHeight(), "Minecraft PE 0.6.1", NULL, NULL);
|
|
|
|
if (m_window == nullptr) {
|
|
return false;
|
|
}
|
|
|
|
glfwSetKeyCallback(m_window, key_callback);
|
|
glfwSetCharCallback(m_window, character_callback);
|
|
glfwSetCursorPosCallback(m_window, cursor_position_callback);
|
|
glfwSetMouseButtonCallback(m_window, mouse_button_callback);
|
|
glfwSetScrollCallback(m_window, scroll_callback);
|
|
glfwSetWindowSizeCallback(m_window, window_size_callback);
|
|
|
|
glfwSetWindowUserPointer(m_window, this);
|
|
|
|
glfwMakeContextCurrent(m_window);
|
|
|
|
#ifndef __EMSCRIPTEN__
|
|
gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);
|
|
glfwSwapInterval(0);
|
|
#endif
|
|
}
|
|
|
|
void PlatformGlfw::finish() {
|
|
glfwDestroyWindow(m_window);
|
|
glfwTerminate();
|
|
}
|
|
|
|
int PlatformGlfw::transformKey(int glfwkey) {
|
|
if (glfwkey >= GLFW_KEY_F1 && glfwkey <= GLFW_KEY_F12) {
|
|
return glfwkey - 178;
|
|
}
|
|
|
|
switch (glfwkey) {
|
|
case GLFW_KEY_ESCAPE: return Keyboard::KEY_ESCAPE;
|
|
case GLFW_KEY_TAB: return Keyboard::KEY_TAB;
|
|
case GLFW_KEY_BACKSPACE: return Keyboard::KEY_BACKSPACE;
|
|
case GLFW_KEY_LEFT_SHIFT: return Keyboard::KEY_LSHIFT;
|
|
case GLFW_KEY_ENTER: return Keyboard::KEY_RETURN;
|
|
case GLFW_KEY_LEFT_CONTROL: return Keyboard::KEY_LEFT_CTRL;
|
|
default: return glfwkey;
|
|
}
|
|
}
|
|
|
|
void PlatformGlfw::cursor_position_callback(GLFWwindow* window, double xpos, double ypos) {
|
|
static double lastX = 0.0, lastY = 0.0;
|
|
static bool firstMouse = true;
|
|
|
|
if (firstMouse) {
|
|
lastX = xpos;
|
|
lastY = ypos;
|
|
firstMouse = false;
|
|
}
|
|
|
|
double deltaX = xpos - lastX;
|
|
double deltaY = ypos - lastY;
|
|
|
|
lastX = xpos;
|
|
lastY = ypos;
|
|
|
|
if (glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED) {
|
|
Mouse::feed(0, 0, xpos, ypos, deltaX, deltaY);
|
|
} else {
|
|
Mouse::feed( MouseAction::ACTION_MOVE, 0, xpos, ypos);
|
|
}
|
|
|
|
// Multitouch::feed(0, 0, xpos, ypos, 0);
|
|
}
|
|
|
|
void PlatformGlfw::mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {
|
|
if(action == GLFW_REPEAT) return;
|
|
|
|
double xpos, ypos;
|
|
glfwGetCursorPos(window, &xpos, &ypos);
|
|
|
|
if (button == GLFW_MOUSE_BUTTON_LEFT) {
|
|
Mouse::feed( MouseAction::ACTION_LEFT, action, xpos, ypos);
|
|
// Multitouch::feed(1, action, xpos, ypos, 0);
|
|
}
|
|
|
|
if (button == GLFW_MOUSE_BUTTON_RIGHT) {
|
|
Mouse::feed( MouseAction::ACTION_RIGHT, action, xpos, ypos);
|
|
}
|
|
}
|
|
|
|
void PlatformGlfw::character_callback(GLFWwindow* window, unsigned int codepoint) {
|
|
Keyboard::feedText(codepoint);
|
|
}
|
|
|
|
void PlatformGlfw::scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {
|
|
double xpos, ypos;
|
|
glfwGetCursorPos(window, &xpos, &ypos);
|
|
|
|
Mouse::feed(3, 0, xpos, ypos, 0, yoffset);
|
|
}
|
|
|
|
void PlatformGlfw::error_callback(int error, const char* desc) {
|
|
LOGE("GLFW Error (%d): %s", error, desc);
|
|
}
|
|
|
|
void PlatformGlfw::window_size_callback(GLFWwindow* window, int width, int height) {
|
|
PlatformGlfw* app = (PlatformGlfw*)glfwGetWindowUserPointer(window);
|
|
|
|
app->windowSizeChanged = true;
|
|
}
|
|
|
|
|
|
float PlatformGlfw::getPixelsPerMillimeter() {
|
|
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
|
|
|
|
int width_mm, height_mm;
|
|
glfwGetMonitorPhysicalSize(monitor, &width_mm, &height_mm);
|
|
|
|
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
|
|
|
|
return (float)mode->width / (float)width_mm;
|
|
}
|
|
|
|
TextureData PlatformGlfw::loadTexture(const std::string& filename_, bool textureFolder) {
|
|
// Support fetching PNG textures via HTTP/HTTPS (for skins, etc)
|
|
if (Util::startsWith(filename_, "http://") || Util::startsWith(filename_, "https://")) {
|
|
std::vector<unsigned char> body;
|
|
if (HttpClient::download(filename_, body) && !body.empty()) {
|
|
return loadTextureFromMemory(body.data(), body.size());
|
|
}
|
|
return TextureData();
|
|
}
|
|
|
|
TextureData out;
|
|
|
|
std::string filename = textureFolder? "data/images/" + filename_
|
|
: filename_;
|
|
std::ifstream source(filename.c_str(), std::ios::binary);
|
|
|
|
if (!source) {
|
|
LOGI("Couldn't find file: %s\n", filename.c_str());
|
|
return out;
|
|
}
|
|
|
|
std::vector<unsigned char> fileData((std::istreambuf_iterator<char>(source)), std::istreambuf_iterator<char>());
|
|
source.close();
|
|
|
|
if (fileData.empty()) {
|
|
LOGI("Couldn't read file: %s\n", filename.c_str());
|
|
return out;
|
|
}
|
|
|
|
return loadTextureFromMemory(fileData.data(), fileData.size());
|
|
}
|
|
|
|
std::string PlatformGlfw::getDateString(int s) {
|
|
time_t tm = s;
|
|
|
|
char mbstr[100];
|
|
std::strftime(mbstr, sizeof(mbstr), "%F %T", std::localtime(&tm));
|
|
|
|
return std::string(mbstr);
|
|
}
|
|
|
|
void PlatformGlfw::hideCursor(bool hide) {
|
|
int isHide = hide ? GLFW_CURSOR_NORMAL : GLFW_CURSOR_HIDDEN;
|
|
glfwSetInputMode(m_window, GLFW_CURSOR, isHide);
|
|
}
|
|
|
|
void PlatformGlfw::openURL(const std::string& url) {
|
|
#ifdef _WIN32
|
|
ShellExecuteA(NULL, "open", url.c_str(), NULL, NULL, SW_SHOWNORMAL);
|
|
#elif __linux__
|
|
std::string command = "xdg-open " + url;
|
|
system(command.c_str());
|
|
#elif __EMSCRIPTEN__
|
|
emscripten_run_script(std::string("window.open('" + url + "', '_blank')").c_str());
|
|
#endif
|
|
}
|
|
|
|
void PlatformGlfw::swapBuffers() {
|
|
glfwSwapBuffers(m_window);
|
|
glfwPollEvents();
|
|
|
|
// @todo
|
|
// if(((MAIN_CLASS*)g_app)->options.getBooleanValue(OPTIONS_LIMIT_FRAMERATE)) {
|
|
// auto frameEnd = clock::now();
|
|
// auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(frameEnd - frameStart);
|
|
// auto target = std::chrono::microseconds(33333); // ~30 fps
|
|
// if(elapsed < target)
|
|
// std::this_thread::sleep_for(target - elapsed);
|
|
// }
|
|
}
|
|
|
|
void PlatformGlfw::setVSync(bool on) {
|
|
IPlatform::setVSync(on);
|
|
|
|
glfwSwapInterval(on);
|
|
} |