/** * Copyright (c) 2022 Dominic Masters * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ #include "DawnGLFWHost.hpp" #include "game/DawnGame.hpp" #include "dawnopengl.hpp" #include "display/BackBufferRenderTarget.hpp" using namespace Dawn; // Static declaration of the host, needed due to GLFW events being C-like DawnHost *DAWN_HOST = nullptr; // Host DawnHost::DawnHost() { this->data = std::make_unique(); this->data->window = nullptr; } int32_t DawnHost::init(DawnGame &game) { // Update values this->game = &game; DAWN_HOST = this; // Init GLFW if(!glfwInit()) return DAWN_GLFW_INIT_RESULT_INIT_FAILED; glfwSetErrorCallback(&glfwOnError); // Setup window hints glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, false); // Create Window this->data->window = glfwCreateWindow( DAWN_GLFW_WINDOW_WIDTH_DEFAULT, DAWN_GLFW_WINDOW_HEIGHT_DEFAULT, "Dawn", NULL, NULL ); if(this->data->window == nullptr) { glfwTerminate(); return DAWN_GLFW_INIT_RESULT_WINDOW_CREATE_FAILED; } // Load GLAD glfwMakeContextCurrent(this->data->window); glfwSwapInterval(0); gladLoadGLLoader((GLADloadproc)glfwGetProcAddress); // Initialize the game auto result = game.init(); if(result != DAWN_GAME_INIT_RESULT_SUCCESS) return result; game.renderManager.backBuffer.setSize( DAWN_GLFW_WINDOW_WIDTH_DEFAULT, DAWN_GLFW_WINDOW_HEIGHT_DEFAULT ); // Set up event listeners glfwSetWindowSizeCallback(this->data->window, &glfwOnResize); return DAWN_HOST_INIT_RESULT_SUCCESS; } int32_t DawnHost::start(DawnGame &game) { double_t time, newTime; float_t fDelta; int32_t updateResult; // Main Render Loop time = 0.0f; while(!glfwWindowShouldClose(this->data->window)) { // Determine the delta. newTime = glfwGetTime(); fDelta = (float_t)(newTime - time); time = newTime; // Perform update updateResult = this->update(game, fDelta); // Did the update complete successfully? if(updateResult == DAWN_HOST_UPDATE_RESULT_EXIT) { break; } else if(updateResult != DAWN_HOST_UPDATE_RESULT_SUCCESS) { return DAWN_GLFW_START_RESULT_UPDATE_FAILED; } // Tick the engine. glfwSwapBuffers(this->data->window); // Update events glfwPollEvents(); } return DAWN_HOST_START_RESULT_EXIT_SUCCESS; } int32_t DawnHost::update(DawnGame &game, float_t delta) { auto ret = game.update(delta); switch(ret) { case DAWN_GAME_UPDATE_RESULT_SUCCESS: return DAWN_HOST_UPDATE_RESULT_SUCCESS; case DAWN_GAME_UPDATE_RESULT_EXIT: return DAWN_HOST_UPDATE_RESULT_EXIT; default: return ret; } } void DawnHost::unload(DawnGame &game) { glfwDestroyWindow(this->data->window); this->data->window = nullptr; glfwTerminate(); } DawnHost::~DawnHost() { DAWN_HOST = nullptr; } // GLFW Callbacks void glfwOnError(int error, const char* description) { fputs(description, stderr); } void glfwOnResize( GLFWwindow *window, int32_t width, int32_t height ) { if(DAWN_HOST == nullptr) return; // TODO: I may throttle this, it calls for every frame the window's resized. DAWN_HOST->game->renderManager.backBuffer.setSize( (float_t)width, (float_t)height ); }