293 lines
7.7 KiB
C++
293 lines
7.7 KiB
C++
#include "GameWindow.hpp"
|
|
|
|
#include <sstream>
|
|
|
|
#include <al.h>
|
|
#include <glm/detail/setup.hpp>
|
|
#include <glm/gtc/matrix_transform.hpp>
|
|
#include <glm/gtc/type_ptr.hpp>
|
|
|
|
#include "Game.hpp"
|
|
#include "GlobalProperties.hpp"
|
|
#include "GLFWHandler.hpp"
|
|
#include "GameState.hpp"
|
|
#include "MessageState.hpp"
|
|
#include "Audio.hpp"
|
|
|
|
namespace Diggler {
|
|
|
|
int GameWindow::InstanceCount = 0;
|
|
|
|
static void glfwErrorCallback(int error, const char *description) {
|
|
getErrorStream() << "GLFW Error " << error << ": " << description << std::endl;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
static void APIENTRY glDebugCallback(GLenum source, GLenum type, GLuint id,
|
|
GLenum severity, GLsizei length, const GLchar *message, const void *userParam) {
|
|
const char *sourceStr = "???";
|
|
switch (source) {
|
|
case GL_DEBUG_SOURCE_API:
|
|
sourceStr = "API";
|
|
break;
|
|
case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
|
|
sourceStr = "WIN";
|
|
break;
|
|
case GL_DEBUG_SOURCE_SHADER_COMPILER:
|
|
sourceStr = "SHC";
|
|
break;
|
|
case GL_DEBUG_SOURCE_THIRD_PARTY:
|
|
sourceStr = "3PT";
|
|
break;
|
|
case GL_DEBUG_SOURCE_APPLICATION:
|
|
sourceStr = "APP";
|
|
break;
|
|
case GL_DEBUG_SOURCE_OTHER:
|
|
sourceStr = "OTH";
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
const char *typeStr = "???";
|
|
switch (type) {
|
|
case GL_DEBUG_TYPE_ERROR:
|
|
typeStr = "ERR";
|
|
break;
|
|
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
|
|
typeStr = "DEP";
|
|
break;
|
|
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
|
|
typeStr = "UND";
|
|
break;
|
|
case GL_DEBUG_TYPE_PORTABILITY:
|
|
typeStr = "PRT";
|
|
break;
|
|
case GL_DEBUG_TYPE_PERFORMANCE:
|
|
typeStr = "PRF";
|
|
break;
|
|
case GL_DEBUG_TYPE_MARKER:
|
|
typeStr = "MKR";
|
|
break;
|
|
case GL_DEBUG_TYPE_PUSH_GROUP:
|
|
typeStr = "GP+";
|
|
break;
|
|
case GL_DEBUG_TYPE_POP_GROUP:
|
|
typeStr = "GP-";
|
|
break;
|
|
case GL_DEBUG_TYPE_OTHER:
|
|
typeStr = "OTH";
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
const char *severityStr = "??";
|
|
switch (severity) {
|
|
case GL_DEBUG_SEVERITY_HIGH:
|
|
severityStr = "HI";
|
|
break;
|
|
case GL_DEBUG_SEVERITY_MEDIUM:
|
|
severityStr = "MD";
|
|
break;
|
|
case GL_DEBUG_SEVERITY_LOW:
|
|
severityStr = "LO";
|
|
break;
|
|
case GL_DEBUG_SEVERITY_NOTIFICATION:
|
|
severityStr = "NT";
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
char line[3 + 1 + 3 + 1 + 2 + 2 + 1];
|
|
std::snprintf(line, sizeof(line)/sizeof(line[0]), "%3s %3s %2s] ", sourceStr, typeStr, severityStr);
|
|
getDebugStreamRaw() << line << message << std::endl;
|
|
}
|
|
#endif
|
|
|
|
GameWindow::GameWindow(Game *G) : G(G) {
|
|
if (InstanceCount++ == 0) {
|
|
glfwSetErrorCallback(glfwErrorCallback);
|
|
int glfwStatus = glfwInit();
|
|
if (glfwStatus != GLFW_TRUE) {
|
|
std::ostringstream err;
|
|
err << "GLFW init failed (" << glfwStatus << ')';
|
|
throw std::runtime_error(err.str());
|
|
}
|
|
getOutputStreamRaw() << "GLFW linked " << GLFW_VERSION_MAJOR << '.' << GLFW_VERSION_MINOR <<
|
|
'.' << GLFW_VERSION_REVISION << ", using " << glfwGetVersionString() << std::endl;
|
|
}
|
|
|
|
GLFWHandler::getInstance().setWindow(this, m_window);
|
|
|
|
m_w = 640; m_h = 480;
|
|
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API /*GLFW_OPENGL_ES_API*/);
|
|
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
|
|
glfwWindowHint(GLFW_SAMPLES, 0); // Gimme aliasing everywhere
|
|
//glfwWindowHint(GLFW_STENCIL_BITS, 8);
|
|
|
|
#ifdef DEBUG
|
|
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
|
|
#endif
|
|
|
|
m_window = glfwCreateWindow(m_w, m_h, "Diggler", nullptr, nullptr);
|
|
if (!m_window) {
|
|
glfwTerminate();
|
|
throw std::runtime_error("GLFW window creation failed");
|
|
}
|
|
glfwMakeContextCurrent(m_window);
|
|
|
|
Render::gl::OpenGL::init();
|
|
|
|
#ifdef DEBUG
|
|
glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE);
|
|
glDebugMessageCallback(glDebugCallback, nullptr);
|
|
#endif
|
|
glfwSetFramebufferSizeCallback(m_window, GLFWHandler::resize);
|
|
glfwSetCursorPosCallback(m_window, GLFWHandler::cursorPos);
|
|
glfwSetKeyCallback(m_window, GLFWHandler::key);
|
|
glfwSetMouseButtonCallback(m_window, GLFWHandler::mouseButton);
|
|
glfwSetScrollCallback(m_window, GLFWHandler::mouseScroll);
|
|
glfwSetCharCallback(m_window, GLFWHandler::unichar);
|
|
glfwSwapInterval(1);
|
|
/*GLint bits;
|
|
glGetIntegerv(GL_STENCIL_BITS, &bits);
|
|
getDebugStream() << bits << " stencil bits" << std::endl;*/
|
|
|
|
getOutputStreamRaw() << "GLM " << GLM_VERSION_MAJOR << '.' << GLM_VERSION_MINOR << '.' << GLM_VERSION_PATCH << ' '
|
|
#if GLM_ARCH & GLM_ARCH_AVX512_BIT
|
|
<< "AVX512 "
|
|
#endif
|
|
#if GLM_ARCH & GLM_ARCH_AVX2_BIT
|
|
<< "AVX2 "
|
|
#endif
|
|
#if GLM_ARCH & GLM_ARCH_AVX_BIT
|
|
<< "AVX "
|
|
#endif
|
|
#if GLM_ARCH & GLM_ARCH_SSE42_BIT
|
|
<< "SSE42 "
|
|
#endif
|
|
#if GLM_ARCH & GLM_ARCH_SSE41_BIT
|
|
<< "SSE41 "
|
|
#endif
|
|
#if GLM_ARCH & GLM_ARCH_SSSE3_BIT
|
|
<< "SSSE3 "
|
|
#endif
|
|
#if GLM_ARCH & GLM_ARCH_SSE3_BIT
|
|
<< "SSE3 "
|
|
#endif
|
|
#if GLM_ARCH & GLM_ARCH_SSE2_BIT
|
|
<< "SSE2 "
|
|
#endif
|
|
;
|
|
|
|
auto glver = Render::gl::OpenGL::version();
|
|
getOutputStreamRaw() << "-- " <<
|
|
Render::gl::OpenGL::loaderName() << ' ' <<
|
|
Render::gl::OpenGL::loaderVersion() << " -- GL" <<
|
|
(glver.isGLES ? "ES" : "") << ' ' <<
|
|
glver.major << '.' << glver.minor <<
|
|
(glver.isCore ? " Core" : "") <<
|
|
(glver.isForward ? " FC" : "") << ' ' << std::endl;
|
|
|
|
if (InstanceCount == 1) { // If we're the first instance
|
|
const uint8 *GL_version = glGetString(GL_VERSION);
|
|
//const uint8 *GL_vendor = glGetString(GL_VENDOR);
|
|
const uint8 *GL_renderer = glGetString(GL_RENDERER);
|
|
getOutputStreamRaw() << "GL " << GL_version << " / " << GL_renderer << std::endl;
|
|
}
|
|
|
|
UIM = new UI::Manager;
|
|
UIM->onResize(m_w, m_h);
|
|
|
|
G->init();
|
|
UIM->setup(G);
|
|
G->GW = this;
|
|
G->UIM = UIM;
|
|
G->A->loadSoundAssets();
|
|
|
|
G->FM->loadFont(getAssetPath("04b08.png"), "04b08");
|
|
G->FM->setDefaultFont("04b08");
|
|
|
|
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
}
|
|
|
|
GameWindow::~GameWindow() {
|
|
m_currentState.reset();
|
|
m_nextState.reset();
|
|
delete UIM;
|
|
|
|
glfwDestroyWindow(m_window);
|
|
|
|
if (--InstanceCount == 0) {
|
|
glfwTerminate();
|
|
}
|
|
}
|
|
|
|
bool GameWindow::shouldClose() const {
|
|
return glfwWindowShouldClose(m_window);
|
|
}
|
|
|
|
void GameWindow::setVisible(bool visible) {
|
|
return visible ? glfwShowWindow(m_window) : glfwHideWindow(m_window);
|
|
}
|
|
|
|
bool GameWindow::isVisible() const {
|
|
return glfwGetWindowAttrib(m_window, GLFW_VISIBLE);
|
|
}
|
|
|
|
void GameWindow::cbChar(char32 unichar) {
|
|
UIM->onChar(unichar);
|
|
m_currentState->onChar(unichar);
|
|
}
|
|
|
|
void GameWindow::cbKey(int key, int scancode, int action, int mods) {
|
|
UIM->onKey(key, scancode, action, mods);
|
|
m_currentState->onKey(key, scancode, action, mods);
|
|
}
|
|
|
|
void GameWindow::cbMouseButton(int key, int action, int mods) {
|
|
UIM->onMouseButton(key, action, mods);
|
|
m_currentState->onMouseButton(key, action, mods);
|
|
}
|
|
|
|
void GameWindow::cbCursorPos(double x, double y) {
|
|
UIM->onCursorPos(x, y);
|
|
m_currentState->onCursorPos(x, y);
|
|
}
|
|
|
|
void GameWindow::cbMouseScroll(double x, double y) {
|
|
UIM->onMouseScroll(x, y);
|
|
m_currentState->onMouseScroll(x, y);
|
|
}
|
|
|
|
void GameWindow::cbResize(int w, int h) {
|
|
m_w = w; m_h = h;
|
|
glViewport(0, 0, w, h);
|
|
UIM->onResize(w, h);
|
|
m_currentState->onResize(w, h);
|
|
}
|
|
|
|
void GameWindow::setNextState(std::unique_ptr<State> &&next) {
|
|
m_nextState = std::move(next);
|
|
}
|
|
|
|
void GameWindow::run() {
|
|
while (m_nextState != nullptr && !glfwWindowShouldClose(m_window)) {
|
|
m_currentState = std::move(m_nextState);
|
|
m_nextState = nullptr;
|
|
UIM->clear();
|
|
m_currentState->run();
|
|
m_currentState.reset();
|
|
}
|
|
}
|
|
|
|
void GameWindow::showMessage(const std::string &msg, const std::string &submsg) {
|
|
setNextState(std::make_unique<MessageState>(this, msg, submsg));
|
|
}
|
|
|
|
}
|