From 272d229094309bc5875287a5063f818c58c5f4f8 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sat, 10 Jan 2009 15:36:15 +0000 Subject: hud widget, drawing code reorganization --- src/client/hud.cc | 371 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 371 insertions(+) create mode 100644 src/client/hud.cc (limited to 'src/client/hud.cc') diff --git a/src/client/hud.cc b/src/client/hud.cc new file mode 100644 index 0000000..1eb2591 --- /dev/null +++ b/src/client/hud.cc @@ -0,0 +1,371 @@ +/* + client/hud.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 "client/hud.h" +#include "client/input.h" +#include "client/targets.h" +#include "render/render.h" +#include "render/renderext.h" + +namespace client +{ + +HUD::HUD(ui::Widget *parent) : Widget(parent) +{ + set_label("hud"); + set_border(false); + set_background(false); + + /*hud_toolbar = new ui::Toolbar(this); + + hud_toolbar->add_button("", "Menu", "ui_menu"); + hud_toolbar->add_button("", "Chat", "ui_chat"); + hud_toolbar->add_button("", "Map", "ui_map"); + */ + hud_center = new ui::Bitmap(this, "pointers/center"); + hud_center->set_color(palette()->pointer()); + +} + +void HUD::resize() +{ + //hud_toolbar->set_geometry(0.0f, 0.0f, width(), font()->height() *2 ); + + hud_center->set_size(ui::pointer_size, ui::pointer_size); + hud_center->set_location((size() - hud_center->size()) * 0.5f); +} + +void HUD::draw_offscreen_target(core::Entity *entity, bool is_active_target) +{ + + math::Vector3f target(entity->location() - render::Camera::eye()); + target = render::Camera::axis().transpose() * target; + + float cx = 0; + float cy = 0; + + if ( target.y*target.y + target.z*target.z < 0.0001 ) { + // X - bound, behind (front is visible) + cx = 0.0f; + cy = -0.5f; + + } else if (fabs(target.y) > fabs(target.z)) { + // Y-bound + cx = math::sgnf(target.y) * 0.5f; + cy = 0.5f * target.z / fabs(target.y); + } else { + // Z-bound + cx = 0.5f * target.y / fabs(target.z); + cy = math::sgnf(target.z) * 0.5f; + } + + const float r = 16; + const float margin = 24; + cx = (0.5f - cx) * ((float) render::State::width() - margin*2); + cx += margin; + cy = (0.5f - cy) * ((float) render::State::height() - margin*2); + cy += margin; + + gl::disable(GL_TEXTURE_2D); + gl::color(0, 0, 0, 1); + gl::begin(gl::LineLoop); + glVertex3f(cx+r, cy+2, 0); + glVertex3f(cx, cy+r+2, 0); + glVertex3f(cx-r, cy+2, 0); + glVertex3f(cx, cy-r+2, 0); + gl::end(); + + if (entity == core::localplayer()->mission_target()) { + gl::color(palette()->mission()); + } else if (entity->type() == core::Entity::Controlable) { + gl::color(0, 1, 0, 1); // FIXME allegiance color + } else { + gl::color(1, 1, 1, 1); // FIXME neutral color + } + + gl::begin(gl::LineLoop); + glVertex3f(cx+r, cy, 0); + glVertex3f(cx, cy+r, 0); + glVertex3f(cx-r, cy, 0); + glVertex3f(cx, cy-r, 0); + gl::end(); + gl::enable(GL_TEXTURE_2D); +} + +void HUD::draw_target(core::Entity *entity, bool is_active_target) +{ + using math::Vector3f; + + // don't draw target if we're very close to it + if (render::ext_render(entity)->distance() < 0.001f) + return; + + // don't draw target if it is outside the visible cone + Vector3f target(entity->location() - render::Camera::eye()); + if (math::dotproduct(render::Camera::axis().forward(), Vector3f::normalized(target)) < 0.75 ) { + draw_offscreen_target(entity, is_active_target); + return; + } + + // transform the target into the camera coordinate system + target = render::Camera::axis().transpose() * target; + + // calculate the intersection between the line (0,0,0)-target and the frustum front + float t = (render::Camera::frustum_front() + 0.001f) / target.x; + Vector3f center(target *t); + + float cx = render::State::width() * (0.5 - center.y); + float cy = render::State::height() * (0.5 - center.z * render::State::aspect()); + + if ((cx < 0 ) || (cy < 0) || (cx > render::State::width()) || (cy > render::State::height())) { + draw_offscreen_target(entity, is_active_target); + return; + } + + float r = ui::pointer_size; + if (!is_active_target) + r *= 0.5; + + gl::disable(GL_TEXTURE_2D); + // outer square shadow + gl::color(0, 0, 0, 1); + gl::begin(gl::LineLoop); + gl::vertex(cx+r, cy+2); + gl::vertex(cx, cy+r+2); + gl::vertex(cx-r, cy+2); + gl::vertex(cx, cy-r+2); + gl::end(); + + if ((entity->flags() & core::Entity::Dockable) == core::Entity::Dockable) { + gl::begin(gl::LineLoop); + gl::vertex(cx+ (r*0.25f), cy+2); + gl::vertex(cx, cy+(r*0.25f)+2); + gl::vertex(cx-(r*0.25f), cy+2); + gl::vertex(cx, cy-(r*0.25f)+2); + gl::end(); + } + + if (entity == core::localplayer()->mission_target()) { + gl::color(palette()->mission()); + } else if (entity->type() == core::Entity::Controlable) { + gl::color(0, 1, 0, 1); // FIXME allegiance color + } else { + gl::color(1, 1, 1, 1); // FIXME neutral color + } + + // outer square0 + gl::begin(gl::LineLoop); + gl::vertex(cx+r, cy); + gl::vertex(cx, cy+r); + gl::vertex(cx-r, cy); + gl::vertex(cx, cy-r); + gl::end(); + + if ((entity->flags() & core::Entity::Dockable) == core::Entity::Dockable) { + gl::begin(gl::LineLoop); + gl::vertex(cx+(r*0.25f), cy); + gl::vertex(cx, cy+(r*0.25f)); + gl::vertex(cx-(r*0.25f), cy); + gl::vertex(cx, cy-(r*0.25f)); + gl::end(); + } + + gl::enable(GL_TEXTURE_2D); + if (is_active_target) { + + // entity name and distance + std::stringstream strdistance; + float d = math::distance(core::localcontrol()->location(), entity->location()) - entity->radius() - core::localcontrol()->radius(); + if (d > 0 ) { + if (d > 100.0f) { + strdistance << roundf(d * 0.1f) << "km"; + } else { + strdistance << roundf(d * 100.0f) << "m"; + } + } else { + strdistance << "--"; + } + if (entity->type() == core::Entity::Controlable) { + render::Text::setcolor('B'); + } else { + render::Text::setcolor('N'); + } + render::Text::draw(cx-aux::text_length(entity->name()) * render::Text::fontwidth()*0.5f, + cy-r-4-render::Text::fontheight(), entity->name()); + + render::Text::draw(cx - aux::text_length(strdistance.str()) * render::Text::fontwidth() * 0.5f, + cy+r+4, strdistance); + } +} + +void HUD::draw() +{ + using namespace render; + std::stringstream status; + + if (core::localcontrol() && (input::mouse_control || input::joystick_control) && + (render::Camera::mode() == render::Camera::Cockpit || render::Camera::mode() == render::Camera::Track)) { + hud_center->set_visible(true); + } else { + hud_center->set_visible(false); + } + + gl::enable(GL_TEXTURE_2D); + Text::setfont("gui", 12, 18); + Text::setcolor('N'); //set normal color + + // draw a basic HUD + if(core::localplayer()->view()) { + Text::setcolor('N'); //set normal color + Text::draw(render::State::width()-4-Text::fontwidth()*32, render::State::height()-Text::fontheight()*3-4, core::localcontrol()->zone()->name()); + + Text::setcolor('B'); //set bold color + Text::draw(render::State::width() - 4-Text::fontwidth()*32, render::State::height() - Text::fontheight()*2 -4, core::localplayer()->view()->name()); + + } else if (core::localcontrol() && core::localcontrol()->zone()) { + core::Zone *zone = core::localcontrol()->zone(); + + // draw targets + for (core::Zone::Content::iterator it=zone->content().begin(); it != zone->content().end(); it++) { + core::Entity *entity = (*it); + + if (targets::is_legal_target(entity)) { + if (entity == core::localplayer()->mission_target()) { + draw_target(entity, true); + } else if (entity == targets::current()) { + draw_target(entity, true); + } else if (entity->type() == core::Entity::Controlable) { + draw_target(entity, false); + } + } + } + + unsigned int state = core::localcontrol()->eventstate(); + if (state) { + std::stringstream statestr; + statestr.clear(); + if (state == core::Entity::ImpulseInitiate) { + statestr << "^FInitializing kinetic impulse drive " << core::localcontrol()->timer(); + } else if (state == core::Entity::Impulse) { + //statestr << "^FKinetic impulse"; + } else if (state == core::Entity::JumpInitiate) { + statestr << "^FInitializing hyperspace jump drive "<< core::localcontrol()->timer(); + } else if (state == core::Entity::Jump) { + statestr << "^FJumping..."; + } + + Text::draw(4, render::State::height() - Text::fontheight()*3-4, statestr); + } + + core::Entity *target = targets::current(); + std::stringstream strdistance; + float d = 0; + float y = 1.0f; + + if (target) { + std::stringstream strtarget; + strtarget << "^B" << target->name() << "\n^B"; + + d = math::distance(core::localcontrol()->location(), target->location()) + - target->radius() - core::localcontrol()->radius(); + + if (d > 0 ) { + strtarget << "^Ndist:^B "; + if (d > 100.0f) { + strtarget << roundf(d * 0.1f) << "km"; + } else { + strtarget << roundf(d * 100.0f) << "m"; + } + + if (core::localcontrol()->speed() > 0.1f) { + strtarget << "^N eta:^B "; + float eta = floorf(d / core::localcontrol()->speed() ); + if (eta > 60.0f) { + float etamin = floorf(eta / 60.0f); + strtarget << etamin << "min "; + eta -= etamin * 60; + } + strtarget << eta << "sec"; + } + } else { + strtarget << " --"; + } + strtarget << '\n'; + Text::draw(render::State::width() - 4-Text::fontwidth()*32, render::State::height() - Text::fontheight()*2 -4, strtarget); + y += 2.0f; + } + + Text::setcolor('N'); //set normal color + Text::draw(render::State::width()-4-Text::fontwidth()*32, render::State::height()-Text::fontheight()*y-4, core::localcontrol()->zone()->name()); + + Textures::bind("bitmaps/hud/thruster_base"); // 316 x 32 bitmap + gl::color(1, 1, 1, 1); + gl::begin(gl::Quads); + + glTexCoord2f(0, 0); + gl::vertex(4, render::State::height() - 4 - 32, 0); + + glTexCoord2f(1, 0); + gl::vertex(4 + 316, render::State::height() - 4 - 32, 0); + + glTexCoord2f(1, 1); + gl::vertex(4 + 316, render::State::height() - 4 , 0); + + glTexCoord2f(0, 1); + gl::vertex(4, render::State::height() - 4 , 0); + + gl::end(); + + float u = core::localcontrol()->thrust(); + if (core::localcontrol()->eventstate() == core::Entity::Impulse) { + u = 1.0; + } + + if (( u > 0) || (core::localcontrol()->eventstate() == core::Entity::Impulse)) { + + if (core::localcontrol()->eventstate() == core::Entity::Impulse) { + gl::color(0, .8, 0); + } else { + float d = math::absf(input::local_thrust - u); + if (d > 0.1) { + d = 0.1f; + } + gl::color(1, 1, .5f + d * 5.0f); + } + Textures::bind("bitmaps/hud/thruster_indicator"); // 316 x 32 bitmap + gl::begin(gl::Quads); + glTexCoord2f(0, 0); + gl::vertex(4, render::State::height() - 4 - 32, 0); + + glTexCoord2f(u, 0); + gl::vertex(4.0f + u * 316.0f, render::State::height() - 4 - 32, 0); + + glTexCoord2f(u, 1); + gl::vertex(4.0f + u * 316.0f, render::State::height() - 4 , 0); + + glTexCoord2f(0, 1); + gl::vertex(4, render::State::height() - 4 , 0); + + gl::end(); + } + + Text::setfont("gui", 14, 24); + Text::setcolor('B'); //set normal color + + std::stringstream speedstr; + speedstr << "^B" << roundf(core::localcontrol()->speed() * 100.0f); + Text::draw( 316+4+10, render::State::height() - 6 -16 - render::Text::fontwidth() /2, speedstr); + + Text::setfont("gui", 12, 18); + Text::setcolor('N'); //set normal color + } + + gl::disable(GL_TEXTURE_2D); +} + +} -- cgit v1.2.3