Code Sampe – SDL + OpenGL App
//START OF HEADER FILE (INTERFACE)
//----------------------------------------------------------
class App
{
public:
Signal<void, unsigned, unsigned> OnResized;
Signal<void> OnActivated;
Signal<void> OnDeactivated;
Signal<void> OnQuit;
App(unsigned width = 800, unsigned height = 600);
virtual ~App(void);
int Execute(void);
//metrics
unsigned Width (void) const;
unsigned Height(void) const;
//input
const InputState &Input(void) const;
protected:
virtual void Init(void);
virtual void Update(float dt);
virtual void Render(float dt);
virtual void CleanUp(void);
void SwapBuffers(void);
void Exit(void);
private:
void SDLEvent(SDL_Event *e);
bool SDLInit(void);
//video data
bool m_isRunning;
SDL_Surface *m_display;
//metrics
unsigned m_width, m_height;
//input state
InputState m_input;
};
//----------------------------------------------------------
//END OF HEADER FILE
//START OF SOURCE FILE (IMPLEMENTATION)
//----------------------------------------------------------
App::App(unsigned width, unsigned height)
: m_width(width), m_height(height)
, m_isRunning(false)
, m_display(nullptr)
{
m_input.WindowSize(m_width, m_height);
}
App::~App(void) { }
int App::Execute(void)
{
if (!SDLInit())
return -1;
SDL_Event e;
Init();
//start main loop
Stopwatch stopwatch;
stopwatch.Start();
m_isRunning = true;
while (m_isRunning)
{
//handle events
while (SDL_PollEvent(&e))
SDLEvent(&e);
//record delta time
float dt = stopwatch.Stop();
stopwatch.Start();
//update input
m_input.Update();
//update loop
Update(dt);
//render loop
Render(dt);
}
CleanUp();
return 0;
}
unsigned App::Width (void) const { return m_width ; }
unsigned App::Height(void) const { return m_height; }
const InputState & App::Input(void) const
{ return m_input; }
void App::Init(void)
{ }
void App::Update(float dt)
{ }
void App::Render(float dt)
{ }
void App::CleanUp(void)
{ }
void App::SwapBuffers(void)
{
SDL_GL_SwapBuffers();
}
void App::Exit(void)
{
m_isRunning = false;
}
void App::SDLEvent(SDL_Event *e)
{
switch (e->type)
{
//input events
//------------------------------------------
//mouse move
case SDL_MOUSEMOTION:
{
SDL_MouseMotionEvent * mme =
reinterpret_cast<SDL_MouseMotionEvent *>(e);
m_input.MoveMouse(mme->x, mme->y);
break;
}
//mouse button down
case SDL_MOUSEBUTTONDOWN:
{
SDL_MouseButtonEvent * mbe =
reinterpret_cast<SDL_MouseButtonEvent *>(e);
switch (mbe->button)
{
case InputCode::MOUSE_BUTTON_LEFT:
m_input.IsPressed(InputCode::MOUSE_BUTTON_LEFT);
break;
case InputCode::MOUSE_BUTTON_RIGHT:
m_input.IsPressed(InputCode::MOUSE_BUTTON_RIGHT);
break;
}
break;
}
//mouse button up
case SDL_MOUSEBUTTONUP:
{
SDL_MouseButtonEvent * mbe =
reinterpret_cast<SDL_MouseButtonEvent *>(e);
switch (mbe->button)
{
case InputCode::MOUSE_BUTTON_LEFT:
m_input.IsReleased(InputCode::MOUSE_BUTTON_LEFT);
break;
case InputCode::MOUSE_BUTTON_RIGHT:
m_input.IsReleased(InputCode::MOUSE_BUTTON_RIGHT);
break;
}
break;
}
//keyboard key down
case SDL_KEYDOWN:
{
//TODO
break;
}
//keyboard key up
case SDL_KEYUP:
{
//TODO
break;
}
//window events
//------------------------------------------
//video resize
case SDL_VIDEORESIZE:
{
SDL_ResizeEvent * re =
reinterpret_cast<SDL_ResizeEvent *>(e);
m_width = re->w; m_height= re->h;
m_input.WindowSize(m_width, m_height);
OnResized.Dispatch(m_width, m_height);
//TODO: fullscreen GL re-init
glViewport(0, 0, m_width, m_height);
break;
}
//system events
//------------------------------------------
//gain/lose focus
case SDL_ACTIVEEVENT:
{
SDL_ActiveEvent * ae =
reinterpret_cast<SDL_ActiveEvent *>(e);
if (ae->gain) OnActivated .Dispatch();
else OnDeactivated.Dispatch();
break;
}
//quit message
case SDL_QUIT:
{
OnQuit.Dispatch();
Exit();
break;
}
}
}
bool App::SDLInit(void)
{
if(SDL_Init(SDL_INIT_EVERYTHING) < 0)
return false;
//SDL attributes have to be set
//BEFORE calling SDL_SetVideoMode
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);
SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE , 8);
SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE , 8);
SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE , 32);
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 2);
//init SDL surface
m_display =
SDL_SetVideoMode
(
m_width, m_height, 32,
SDL_HWSURFACE
| SDL_DOUBLEBUF
| SDL_OPENGL
| SDL_RESIZABLE
);
if(!m_display)
return false;
//init OpenGL
glViewport(0, 0, m_width, m_height);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
//init GLEW
glewInit();
//print OpenGL info
std::cout << "OpenGL version: "
<< glGetString(GL_VERSION)
<< std::endl << std::endl;
return true;
}
//----------------------------------------------------------
//END OF SOURCE FILE