/*
* UltraStar Deluxe - Karaoke Game
*
* UltraStar Deluxe is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
*/
#include "application.hpp"
#include "event_manager.hpp"
#include <exception>
#include "software_mouse_pointer.hpp"
#include "frames/loading_frame.hpp"
#include <GL/gl.h>
#include <log4cpp/PropertyConfigurator.hh>
namespace usdx
{
log4cpp::Category& Application::log =
log4cpp::Category::getInstance("usdx.menu.application");
Application* Application::instance = NULL;
Application::Application(Container* parent)
: Container(parent), config(NULL), display(NULL), fps_manager(NULL),
running(false), frames_per_second(50)
{
log4cpp::PropertyConfigurator::configure("log4cpp.property");
config = new Config();
set_size(config->get_graphics_resolution());
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
}
Application::~Application()
{
if (config) {
delete config;
config = NULL;
}
if (fps_manager) {
delete fps_manager;
fps_manager = NULL;
}
SDL_Quit();
// reset instance to be able to recreate the singleton
instance = NULL;
}
Application* Application::get_instance(void)
{
if (! instance) {
instance = new Application(NULL);
}
return instance;
}
Config* Application::get_config(void)
{
return get_instance()->config;
}
bool Application::is_gl_thread(void)
{
return boost::this_thread::get_id() == get_instance()->gl_thread;
}
void Application::main_loop(SDL_Surface* display)
{
SDL_Event event;
EventManager event_manager;
boost::thread event_thread(boost::bind(&EventManager::handle_events, &event_manager));
SoftwareMousePointer pointer(this, &event_manager);
LoadingFrame frame(this);
running = true;
while (running) {
// repaint everything
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
repaint();
SDL_GL_SwapBuffers();
log << log4cpp::Priority::DEBUG << "repaint";
// poll current events
while (event_manager.available() && SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
running = false;
event_thread.interrupt();
break;
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_q) {
running = false;
event_thread.interrupt();
break;
}
if (event.key.keysym.sym == SDLK_d) {
config->set_debug_boxes(!config->get_debug_boxes());
break;
}
/* fall throught */
default:
event_manager.add_event(event);
break;
}
}
if (running) {
// limit frames
SDL_framerateDelay(fps_manager);
}
}
event_thread.join();
}
void Application::run(void)
{
if (! display) {
// opengl settings
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
// center screen
char env[] = "SDL_VIDEO_CENTERED=center";
SDL_putenv(env);
// fullscreen if requested from config
Uint32 flags = SDL_OPENGL;
if (config->get_graphics_fullscreen()) {
flags |= SDL_FULLSCREEN;
}
// create screen
display = SDL_SetVideoMode(get_width(), get_height(), 24, flags);
glViewport(0, 0, get_width(), get_height());
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
// save current thread, to be able to detect whether some method is
// called from the thread owning the OpenGL contect
gl_thread = boost::this_thread::get_id();
// set-up the opengl projection matrix
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0f, get_width(), get_height(), 0.0f, -1.0f, 1.0f);
// reset the modelview matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// the depth layer is not used, so disable the depth test for
// higher performance
glDisable(GL_DEPTH_TEST);
}
if (! display) {
log << log4cpp::Priority::ERROR << "SDL_SetVideoMode failed.";
throw new std::exception();
}
init_fps_manager();
SDL_setFramerate(fps_manager, frames_per_second);
SDL_ShowCursor(SDL_DISABLE);
main_loop(display);
SDL_ShowCursor(SDL_ENABLE);
}
const int Application::get_frames_per_second(void) const
{
return frames_per_second;
}
void Application::set_frames_per_second(int fps)
{
this->frames_per_second = fps;
if (fps_manager) {
SDL_setFramerate(fps_manager, frames_per_second);
}
}
void Application::init_fps_manager(void)
{
if (! fps_manager) {
fps_manager = new FPSmanager();
SDL_initFramerate(fps_manager);
}
}
};