215 lines
4.1 KiB
C++
215 lines
4.1 KiB
C++
#include <psemek/app/app.hpp>
|
|
#include <psemek/gfx/gl.hpp>
|
|
#include <psemek/log/log.hpp>
|
|
|
|
#include <SDL2/SDL.h>
|
|
|
|
namespace
|
|
{
|
|
|
|
[[noreturn]] void sdl_fail(std::string const & message)
|
|
{
|
|
throw std::runtime_error(message + SDL_GetError());
|
|
}
|
|
|
|
struct sdl_initializer
|
|
{
|
|
sdl_initializer()
|
|
{
|
|
if (SDL_Init(SDL_INIT_VIDEO) != 0)
|
|
sdl_fail("Failed to initialize SDL2: ");
|
|
}
|
|
|
|
~sdl_initializer()
|
|
{
|
|
SDL_Quit();
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
namespace psemek::util::pimpl
|
|
{
|
|
|
|
template <>
|
|
struct impl<app::app>
|
|
{
|
|
sdl_initializer init;
|
|
SDL_Window * window = nullptr;
|
|
SDL_GLContext gl_context = nullptr;
|
|
|
|
bool running = false;
|
|
|
|
~impl()
|
|
{
|
|
if (gl_context) SDL_GL_DeleteContext(gl_context);
|
|
if (window) SDL_DestroyWindow(window);
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
namespace psemek::app
|
|
{
|
|
|
|
|
|
app::app(std::string const & name)
|
|
{
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, gl::sys::GetLeastMajorVersion());
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, gl::sys::GetLeastMinorVersion());
|
|
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
|
|
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
|
|
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
|
|
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
|
|
|
|
impl().window = SDL_CreateWindow(name.data(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 800, 600, SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL | SDL_WINDOW_MAXIMIZED);
|
|
if (!impl().window)
|
|
sdl_fail("Failed to create window: ");
|
|
|
|
impl().gl_context = SDL_GL_CreateContext(impl().window);
|
|
if (!impl().gl_context)
|
|
sdl_fail("Failed to create OpenGL context: ");
|
|
|
|
SDL_GL_MakeCurrent(impl().window, impl().gl_context);
|
|
|
|
if (!gl::sys::LoadFunctions())
|
|
throw std::runtime_error("Failed to load OpenGL functions");
|
|
|
|
log::info() << "Initialized OpenGL " << gl::sys::GetMajorVersion() << '.' << gl::sys::GetMinorVersion();
|
|
}
|
|
|
|
app::~app()
|
|
{}
|
|
|
|
bool app::running() const
|
|
{
|
|
return impl().running;
|
|
}
|
|
|
|
void app::on_resize(int width, int height)
|
|
{
|
|
gl::Viewport(0, 0, width, height);
|
|
}
|
|
|
|
void app::on_focus_gained() {}
|
|
|
|
void app::on_focus_lost() {}
|
|
|
|
void app::on_quit()
|
|
{
|
|
impl().running = false;
|
|
}
|
|
|
|
void app::on_mouse_move(int, int) {}
|
|
|
|
void app::on_mouse_wheel(int) {}
|
|
|
|
void app::on_left_button_down() {}
|
|
|
|
void app::on_left_button_up() {}
|
|
|
|
void app::on_middle_button_down() {}
|
|
|
|
void app::on_middle_button_up() {}
|
|
|
|
void app::on_right_button_down() {}
|
|
|
|
void app::on_right_button_up() {}
|
|
|
|
void app::on_key_down(SDL_Keycode) {}
|
|
|
|
void app::on_key_up(SDL_Keycode) {}
|
|
|
|
void app::poll_events()
|
|
{
|
|
for (SDL_Event e; SDL_PollEvent(&e);) switch (e.type)
|
|
{
|
|
case SDL_QUIT:
|
|
on_quit();
|
|
break;
|
|
case SDL_WINDOWEVENT: switch (e.window.event)
|
|
{
|
|
case SDL_WINDOWEVENT_RESIZED:
|
|
on_resize(e.window.data1, e.window.data2);
|
|
break;
|
|
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
|
on_focus_gained();
|
|
break;
|
|
case SDL_WINDOWEVENT_FOCUS_LOST:
|
|
on_focus_lost();
|
|
break;
|
|
}
|
|
break;
|
|
case SDL_MOUSEMOTION:
|
|
on_mouse_move(e.motion.x, e.motion.y);
|
|
break;
|
|
case SDL_MOUSEWHEEL:
|
|
on_mouse_wheel(e.wheel.y);
|
|
break;
|
|
case SDL_MOUSEBUTTONDOWN:
|
|
switch (e.button.button)
|
|
{
|
|
case SDL_BUTTON_LEFT:
|
|
on_left_button_down();
|
|
break;
|
|
case SDL_BUTTON_MIDDLE:
|
|
on_middle_button_down();
|
|
break;
|
|
case SDL_BUTTON_RIGHT:
|
|
on_right_button_down();
|
|
break;
|
|
}
|
|
break;
|
|
case SDL_MOUSEBUTTONUP:
|
|
switch (e.button.button)
|
|
{
|
|
case SDL_BUTTON_LEFT:
|
|
on_left_button_up();
|
|
break;
|
|
case SDL_BUTTON_MIDDLE:
|
|
on_middle_button_up();
|
|
break;
|
|
case SDL_BUTTON_RIGHT:
|
|
on_right_button_up();
|
|
break;
|
|
}
|
|
break;
|
|
case SDL_KEYDOWN:
|
|
on_key_down(e.key.keysym.sym);
|
|
break;
|
|
case SDL_KEYUP:
|
|
on_key_up(e.key.keysym.sym);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void app::update()
|
|
{}
|
|
|
|
void app::draw()
|
|
{
|
|
gl::ClearColor(0.7f, 0.7f, 1.f, 1.f);
|
|
gl::Clear(gl::COLOR_BUFFER_BIT);
|
|
}
|
|
|
|
void app::run()
|
|
{
|
|
impl().running = true;
|
|
while (running())
|
|
{
|
|
poll_events();
|
|
if (!running()) break;
|
|
update();
|
|
draw();
|
|
|
|
SDL_GL_SwapWindow(impl().window);
|
|
}
|
|
}
|
|
|
|
void app::show_cursor(bool show)
|
|
{
|
|
SDL_ShowCursor(show ? SDL_TRUE : SDL_FALSE);
|
|
}
|
|
|
|
}
|