diff options
Diffstat (limited to 'src/client/hud.cc')
| -rw-r--r-- | src/client/hud.cc | 371 | 
1 files changed, 371 insertions, 0 deletions
| 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); +} + +} | 
