/* client/video.cc This file is part of the Osirion project and is distributed under the terms and conditions of the GNU General Public License version 2 */ #include "core/core.h" #include "core/gameserver.h" #include "client/video.h" #include "client/input.h" #include "client/client.h" #include "client/targets.h" #include "render/render.h" #include "render/gl.h" #include "filesystem/filesystem.h" #include "sys/sys.h" #include "ui/ui.h" #include "ui/paint.h" #include using namespace render; namespace client { /* -- engine variables --------------------------------------------- */ core::Cvar *r_width = 0; core::Cvar *r_height = 0; core::Cvar *r_windowwidth = 0; core::Cvar *r_windowheight = 0; core::Cvar *r_fullscreen = 0; core::Cvar *draw_ui = 0; core::Cvar *draw_stats = 0; core::Cvar *draw_devinfo = 0; core::Cvar *draw_keypress = 0; core::Cvar *draw_clock = 0; namespace video { bool fullscreen = 0; int width = 0; int height = 0; // default resolution and window size const int width_default = 1024; const int height_default = 768; SDL_Window* sdlwindow = 0; Uint32 sdlwindow_flags = 0; SDL_GLContext glcontext = 0; std::string loader_message; bool is_loading = false; void draw_loader() { render::Camera::ortho(); gl::enable(GL_BLEND); gl::color(1.0f, 1.0f, 1.0f, 1.0f); const std::string loader_texture("bitmaps/loader"); const math::Vector2f size(render::State::width(), render::State::height()); const math::Vector2f pos; ui::Paint::draw_bitmap(pos, size, loader_texture, true); if (loader_message.size()) { using render::Text; gl::enable(GL_TEXTURE_2D); Text::setfont("gui", 12, 18); Text::setcolor('N'); //set normal color Text::draw(Text::fontwidth(), Text::fontheight(), loader_message); gl::disable(GL_TEXTURE_2D); } gl::disable(GL_BLEND); swap_buffers(); is_loading = true; } bool init() { con_print << "^BInitializing video..." << std::endl; // initialize engine variables r_width = core::Cvar::get("r_width", width_default, core::Cvar::Archive); r_width->set_info("[int] video resolution width"); r_height = core::Cvar::get("r_height", height_default, core::Cvar::Archive); r_height->set_info("[int] video resolution height"); r_windowwidth = core::Cvar::get("r_windowwidth", width_default, core::Cvar::Archive); r_windowwidth->set_info("[int] window width in windowed mode"); r_windowheight = core::Cvar::get("r_windowheight", height_default, core::Cvar::Archive); r_windowheight->set_info("[int] window height in windowed mode"); r_fullscreen = core::Cvar::get("r_fullscreen", "0", core::Cvar::Archive); r_fullscreen->set_info("[bool] enable or disable fullscreen video"); draw_devinfo = core::Cvar::get("draw_devinfo", "0", core::Cvar::Archive); draw_devinfo->set_info("[bool] draw developer information"); draw_stats = core::Cvar::get("draw_stats", "0", core::Cvar::Archive); draw_stats->set_info("[bool] draw network and render statistics"); draw_keypress = core::Cvar::get("draw_keypress", "0", core::Cvar::Archive); draw_keypress->set_info("[bool] draw keypress key names"); draw_clock = core::Cvar::get("draw_clock", "0", core::Cvar::Archive); draw_clock->set_info("[int] draw clock (0=Off, 1=12hr, 2=24hr)"); draw_ui = core::Cvar::get("draw_ui", "1", core::Cvar::Archive); draw_ui->set_info("[bool] draw the user interface"); if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) { con_error << "SDL_InitSubSystem() failed: " << SDL_GetError() << std::endl; return false; } // window caption std::string sdlwindow_title(core::name()); sdlwindow_title += ' '; sdlwindow_title.append(core::version()); // window icon /* * FIXME * store the icon as binary data * and use SDL_CreateRGBSurfaceFrom to create the icon */ /* * filesystem::File *iconfile = filesystem::open("bitmaps/icon.bmp"); if (iconfile) { std::string iconfilename = iconfile->path(); iconfilename.append(iconfile->name()); filesystem::close(iconfile); con_debug << " setting window icon " << iconfilename << std::endl; SDL_Surface *image = SDL_LoadBMP(iconfilename.c_str()); if (image) { Uint32 colorkey = SDL_MapRGB(image->format, 255, 0, 255); SDL_SetColorKey(image, SDL_SRCCOLORKEY, colorkey); SDL_WM_SetIcon(image, NULL); } } */ SDL_InitSubSystem(SDL_INIT_VIDEO); fullscreen = (r_fullscreen->value() > 0.0f); if (fullscreen) { sdlwindow_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_BORDERLESS; sdlwindow = SDL_CreateWindow(sdlwindow_title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 0, 0, sdlwindow_flags); } else { if ((r_windowwidth->value() > 0.0f) && (r_windowheight->value() > 0.0f)) { width = (int) r_windowwidth->value(); height = (int) r_windowheight->value(); } else { width = width_default; height = height_default; } sdlwindow_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; sdlwindow = SDL_CreateWindow(sdlwindow_title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, sdlwindow_flags); } if (!sdlwindow) { con_error << "Failed to initialize SDL window: " << SDL_GetError() << std::endl; return false; } glcontext = SDL_GL_CreateContext(sdlwindow); if (!glcontext) { con_error << "Failed to initialize OpenGL context: " << SDL_GetError() << std::endl; return false; } SDL_GetWindowSize(sdlwindow, &width, &height); // save window width and height if (fullscreen) { (*r_width) = width; (*r_height) = height; } else { (*r_windowwidth) = (float) width; (*r_windowheight) = (float) height; } // resize user interface ui::root()->set_size((float) width, (float) height); ui::root()->event_resize(); // grab input core::Cvar *input_grab = core::Cvar::find("input_grab"); if (!ui::console()->visible() || (input_grab && input_grab->value())) { SDL_SetRelativeMouseMode(SDL_TRUE); } else { SDL_SetRelativeMouseMode(SDL_FALSE); } // initialize renderer render::init(width, height); // apply render options ui::root()->load_settings(); // initialize target drawer targets::init(); // draw loader screen draw_loader(); return true; } void resize(const Uint32 sdlwindow_id, int w, int h) { if (fullscreen) { return; } if (SDL_GetWindowID(sdlwindow) != sdlwindow_id) { return; } if (w < 320) w = 320; if (h < 200) h = 200; render::resize(w, h); ui::root()->set_size(w, h); ui::root()->event_resize(); (*r_windowwidth) = (float) w; (*r_windowheight) = (float) h; } void restart() { shutdown(); // clear models and materials /* resetting the rednder subsystem will force a reload of all materials */ model::Model::clear(); model::Material::clear(); if (!init()) { client()->quit(1); } model::Material::init(); render::load(); input::reset(); } void set_loader_message(const std::string message) { loader_message.assign(message); if (is_loading) frame_loader(); } void set_loader_message(const char *message) { if (message) loader_message.assign(message); else loader_message.clear(); if (is_loading) frame_loader(); } void swap_buffers() { SDL_GL_SwapWindow(sdlwindow); } void frame_loader() { // Clear the color and depth buffers. gl::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); draw_loader(); swap_buffers(); } void frame(float elapsed) { // detect fullscreen/windowed mode switch if (fullscreen != (r_fullscreen->value() > 0.0f)) restart(); using namespace render; is_loading = false; // Clear the color and depth buffers. gl::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); render::Stats::clear(); if (core::application()->connected()) { if (core::game()->time() && core::localplayer()->zone()) { render::draw(elapsed); // draw the world targets::frame(); // validate current target, render sound /* if (!core::localplayer()->view() && targets::current()) // draw target docks etc render::draw_target(targets::current()); */ render::Camera::ortho(); client()->mainwindow()->show(); } else { draw_loader(); client()->mainwindow()->hide(); } } else { client()->mainwindow()->hide(); render::Camera::ortho(); } gl::color(1.0f, 1.0f, 1.0f, 1.0f); gl::disable(GL_TEXTURE_2D); gl::enable(GL_BLEND); // draw the user interface if (draw_ui->value()) { ui::root()->frame(); } else if (ui::console()->visible()) { ui::console()->event_draw(); } gl::disable(GL_TEXTURE_2D); gl::disable(GL_BLEND); swap_buffers(); } void shutdown() { con_print << "^BShutting down video..." << std::endl; targets::shutdown(); render::shutdown(); SDL_SetRelativeMouseMode(SDL_FALSE); SDL_GL_DeleteContext(glcontext); glcontext = 0; SDL_DestroyWindow(sdlwindow); sdlwindow = 0; SDL_QuitSubSystem(SDL_INIT_VIDEO); width = 0; height = 0; } } // namespace video } // namespace client