/* 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 "client/video.h" #include "client/input.h" #include "client/view.h" #include "client/client.h" #include "client/targets.h" #include "render/render.h" #include "render/gl.h" #include "core/core.h" #include "core/gameserver.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_fullscreen = 0; core::Cvar *draw_ui = 0; core::Cvar *draw_stats = 0; core::Cvar *draw_devinfo = 0; core::Cvar *draw_keypress = 0; namespace video { float fullscreen = 0; int bpp = 0; int flags = 0; int width = 0; int height = 0; int width_prev = 0; int height_prev = 0; const int width_default = 1024; const int height_default = 768; std::string loader_message; bool is_loading = false; 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_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_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; } const SDL_VideoInfo* sdl_videoinfo = SDL_GetVideoInfo(); if( !sdl_videoinfo) { con_error << "SDL_GetVideoInfo() failed: " << SDL_GetError() << std::endl; return false; } width_prev = width; height_prev = height; width = (int) r_width->value(); height = (int) r_height->value(); bpp = sdl_videoinfo->vfmt->BitsPerPixel; if (bpp == 32) { 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); } else if (bpp == 24) { SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 6); SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 6); SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 6); SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 6); } else if (bpp == 16) { SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 4); SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 4); SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 4); SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 4); } else { con_warn << "Display depth " << bpp << " is not supported!" << std::endl; } SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1); fullscreen = r_fullscreen->value(); if (r_fullscreen->value()) { flags = SDL_OPENGL | SDL_FULLSCREEN; } else { flags = SDL_OPENGL; #ifndef _WIN32 flags |= SDL_RESIZABLE; #endif } if(!SDL_SetVideoMode(width, height, bpp, flags )) { con_warn << "Failed to set video mode " << width << "x" << height << "x" << bpp << "bpp" << std::endl; if (width_prev && height_prev) { width = width_prev; height = height_prev; if(!SDL_SetVideoMode(width, height, bpp, flags )) { con_error << "Failed to restore video mode " << width << "x" << height << "x" << bpp << "bpp" << std::endl; return false; } } else return false; } con_print << " video mode " << width << "x" << height << "x" << bpp << "bpp " << (fullscreen ? "fullscreen " : "window") << std::endl; #ifdef HAVE_DEBUG_MESSAGES int red, green, blue, alpha, depth; SDL_GL_GetAttribute( SDL_GL_RED_SIZE, &red); SDL_GL_GetAttribute( SDL_GL_GREEN_SIZE, &green); SDL_GL_GetAttribute( SDL_GL_RED_SIZE, &blue); SDL_GL_GetAttribute( SDL_GL_ALPHA_SIZE, &alpha); SDL_GL_GetAttribute( SDL_GL_DEPTH_SIZE, &depth); con_debug << " visual r: " << red << " g: " << green << " blue: " << blue << " alpha: " << alpha << " depth: " << depth << std::endl; #endif // HAVE_DEBUG_MESSAGES // set window caption set_caption(); // save r_width and r_height variables (*r_width) = width; (*r_height) = height; // resize user interface ui::root()->set_size((float) width, (float) height); ui::root()->event_resize(); // to grab or not to grab if (ui::console()->visible()) { SDL_WM_GrabInput(SDL_GRAB_OFF); SDL_ShowCursor(SDL_ENABLE); } else { SDL_WM_GrabInput(SDL_GRAB_ON); SDL_ShowCursor(SDL_DISABLE); } // initialize renderer render::init(width, height); // apply render options ui::root()->apply_render_options(); // initialize target drawer targets::init(); return true; } void set_caption() { // set window caption std::string version; if (core::server() && core::server()->module()) { version.assign(core::server()->module()->name()); } else { version.assign(core::name() + ' ' + core::version()); } SDL_WM_SetCaption(version.c_str(), 0); } void resize(int w, int h) { if (fullscreen) return; if (w < 320) w = 320; if (h < 200) h = 200; if (SDL_SetVideoMode(w, h, bpp, flags )) { render::resize(w, h); ui::root()->set_size(w, h); ui::root()->event_resize(); } else { con_warn << "Could not resize window!" << std::endl; } } void restart() { shutdown(); if (!init()) { client()->quit(1); } input::reset(); } void set_cursor() { if (ui::console()->visible()) { ui::root()->set_pointer(); } else if(core::localplayer()->view() || ui::root()->active()) { ui::root()->set_pointer("pointer"); } else if (!core::localcontrol()) { ui::root()->set_pointer(); } else if (client()->view()->map()->hover()) { ui::root()->set_pointer("pointer"); } else if (render::Camera::mode() == render::Camera::Overview) { ui::root()->set_pointer("aim"); } else if (targets::hover()) { ui::root()->set_pointer("target", ui::Palette::Active, true); if (input::joystick_lastmoved_time() > input::mouse_lastmoved_time()) { ui::root()->input_mouse(render::State::width()/2, render::State::height() /2); } } else if (input::mouse_control) { ui::root()->set_pointer("control", ui::Palette::Pointer); if (input::mouse_deadzone) { ui::root()->input_mouse(render::State::width()/2, render::State::height() /2); } } else if ((input::joystick_lastmoved_time() > input::mouse_lastmoved_time()) && (render::Camera::mode() == render::Camera::Cockpit || render::Camera::mode() == render::Camera::Track)) { ui::root()->set_pointer(); } else { ui::root()->set_pointer("aim", ui::Palette::Foreground); } } 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 draw_loader() { render::Camera::ortho(); gl::enable(GL_BLEND); gl::color(1.0f, 1.0f, 1.0f, 1.0f); math::Vector2f pos; math::Vector2f size(render::State::width(), render::State::height()); ui::paint::bitmap(pos, size, "loader"); 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); } void frame_loader() { // Clear the color and depth buffers. gl::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); draw_loader(); is_loading = true; SDL_GL_SwapBuffers(); } void frame(float elapsed) { // detect fullscreen/windowed mode switch if (fullscreen != r_fullscreen->value()) 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::Camera::frame(elapsed); render::Camera::frustum(); 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()->view()->show(); } else { draw_loader(); client()->view()->hide(); } } else { client()->view()->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()) { set_cursor(); ui::root()->frame(); } else if (ui::console()->visible()) { ui::console()->event_draw(); } gl::disable(GL_TEXTURE_2D); gl::disable(GL_BLEND); SDL_GL_SwapBuffers(); } void shutdown() { con_print << "^BShutting down video..." << std::endl; targets::shutdown(); render::shutdown(); width = 0; height = 0; SDL_QuitSubSystem(SDL_INIT_VIDEO); } } // namespace video } // namespace client