Dawn/src/dawnsdl2/host/DawnSDL2Host.cpp

172 lines
4.3 KiB
C++

/**
* Copyright (c) 2022 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "DawnSDL2Host.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 = new DawnHostData();
this->data->window = nullptr;
}
int32_t DawnHost::init(DawnGame *game) {
// Update values
this->game = game;
DAWN_HOST = this;
// Init SDL
if(SDL_Init(SDL_INIT_VIDEO) < 0) {
return DAWN_SDL2_INIT_RESULT_INIT_FAILED;
}
// Request OpenGL 4.5
SDL_GL_LoadLibrary(NULL);
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 5);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
// Create Window
game->host->data->window = SDL_CreateWindow(
"Dawn",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
DAWN_SDL2_WINDOW_WIDTH_DEFAULT, DAWN_SDL2_WINDOW_HEIGHT_DEFAULT,
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE
);
if(game->host->data->window == NULL) {
return DAWN_SDL2_INIT_RESULT_WINDOW_CREATE_FAILED;
}
// Create OpenGL Context and attach GLAD
game->host->data->glContext = SDL_GL_CreateContext(game->host->data->window);
gladLoadGLLoader(SDL_GL_GetProcAddress);
// Override engine defaults appropriately.
game->renderManager.backBuffer.setSize(
DAWN_SDL2_WINDOW_WIDTH_DEFAULT,
DAWN_SDL2_WINDOW_HEIGHT_DEFAULT
);
// Default keybinds
game->inputManager.bind(INPUT_BIND_ACCEPT, SDLK_RETURN);
game->inputManager.bind(INPUT_BIND_ACCEPT, SDLK_e);
game->inputManager.bind(INPUT_BIND_ACCEPT, SDLK_SPACE);
// Initialize the game
auto result = game->init();
if(result != DAWN_GAME_INIT_RESULT_SUCCESS) return result;
// Hard-Load the first scene assets.
if(game->scene != nullptr) {
auto assets = game->scene->getRequiredAssets();
game->assetManager.queueLoad(assets);
game->assetManager.syncLoad();
game->scene->stage();
}
// Use v-sync
SDL_GL_SetSwapInterval(1);
return DAWN_HOST_INIT_RESULT_SUCCESS;
}
int32_t DawnHost::start(DawnGame *game) {
uint32_t ticks;
int32_t updateResult;
SDL_Event event;
game->host->data->running = true;
// Main Render Loop
ticks = SDL_GetTicks();
while(game->host->data->running) {
// Ticks
uint32_t newTicks = SDL_GetTicks();
float_t delta = (newTicks - ticks) / 1000.0f;
ticks = newTicks;
// Perform update
updateResult = this->update(game, delta);
// Did the update complete successfully?
if(updateResult == DAWN_HOST_UPDATE_RESULT_EXIT) {
break;
} else if(updateResult != DAWN_HOST_UPDATE_RESULT_SUCCESS) {
return DAWN_SDL2_START_RESULT_UPDATE_FAILED;
}
// Swap buffers
SDL_GL_SwapWindow(game->host->data->window);
// Check events.
while (SDL_PollEvent(&event)) {
switch( event.type ){
case SDL_KEYDOWN:
game->inputManager.rawInputValues[event.key.keysym.sym] = 1.0f;
break;
case SDL_KEYUP:
game->inputManager.rawInputValues[event.key.keysym.sym] = 0.0f;
break;
case SDL_QUIT:
game->host->data->running = false;
break;
case SDL_WINDOWEVENT:
if(event.window.event == SDL_WINDOWEVENT_RESIZED) {
this->game->renderManager.backBuffer.setSize(
(float_t)event.window.data1, (float_t)event.window.data2
);
}
break;
default:
break;
}
}
}
return DAWN_HOST_START_RESULT_EXIT_SUCCESS;
}
int32_t DawnHost::update(DawnGame *game, float_t delta) {
// Tick game.
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) {
SDL_GL_DeleteContext(game->host->data->glContext);
SDL_DestroyWindow( game->host->data->window );
this->data->window = nullptr;
SDL_Quit();
}
DawnHost::~DawnHost() {
delete this->data;
DAWN_HOST = nullptr;
}