Add app library

This commit is contained in:
Nikita Lisitsa 2020-08-28 11:01:56 +03:00
parent 0d4563638b
commit f69fb7299e
7 changed files with 313 additions and 1 deletions

8
libs/app/CMakeLists.txt Normal file
View file

@ -0,0 +1,8 @@
find_package(SDL2 REQUIRED)
file(GLOB_RECURSE PSEMEK_APP_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "include/*.hpp")
file(GLOB_RECURSE PSEMEK_APP_SOURCES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "source/*.cpp")
add_library(app ${PSEMEK_APP_HEADERS} ${PSEMEK_APP_SOURCES})
target_include_directories(app PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${SDL2_INCLUDE_DIRS}")
target_link_libraries(app PUBLIC log util gfx ${SDL2_LIBRARIES})

View file

@ -0,0 +1,44 @@
#pragma once
#include <SDL2/SDL_keycode.h>
#include <psemek/util/pimpl.hpp>
namespace psemek::app
{
struct app
: util::pimpl::dynamic<app>
{
app(std::string const & name);
virtual ~app();
virtual bool running() const;
virtual void on_resize(int width, int height);
virtual void on_focus_gained();
virtual void on_focus_lost();
virtual void on_quit();
virtual void on_mouse_move(int x, int y);
virtual void on_mouse_wheel(int delta);
virtual void on_left_button_down();
virtual void on_left_button_up();
virtual void on_middle_button_down();
virtual void on_middle_button_up();
virtual void on_right_button_down();
virtual void on_right_button_up();
virtual void on_key_down(SDL_Keycode key);
virtual void on_key_up(SDL_Keycode key);
void poll_events();
virtual void update();
virtual void draw();
void run();
void show_cursor(bool show);
};
}

View file

@ -0,0 +1,32 @@
#pragma once
#include <psemek/log/log.hpp>
namespace psemek::app
{
template <typename App>
int main() try
{
log::register_thread("main");
App app;
log::info() << "Running";
app.run();
log::info() << "Quitting";
return EXIT_SUCCESS;
}
catch (std::exception const & e)
{
log::error() << e.what();
return EXIT_FAILURE;
}
catch (...)
{
log::error() << "unknown exception";
return EXIT_FAILURE;
}
}

215
libs/app/source/app.cpp Normal file
View file

@ -0,0 +1,215 @@
#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);
}
}

View file

@ -1733,6 +1733,9 @@ namespace gl
exts::LoadTest LoadFunctions();
int GetLeastMinorVersion();
int GetLeastMajorVersion();
int GetMinorVersion();
int GetMajorVersion();
bool IsVersionGEQ(int majorVersion, int minorVersion);

View file

@ -1579,6 +1579,16 @@ namespace gl
return exts::LoadTest(true, numFailed);
}
int GetLeastMinorVersion()
{
return 3;
}
int GetLeastMajorVersion()
{
return 3;
}
static int g_major_version = 0;
static int g_minor_version = 0;

View file

@ -1,6 +1,6 @@
* Remove gfx::vertex, setup mesh using attributes directly
* Design affine transforms in geom & use them instead of matrices when appropriate
* Create an 'app' module that simplifies application creation
* Implement pixmap font rendering
* Create a simple generic primive painter
* Design ui system
* Add platform deployment tools