From 79b1af52c004469dbad6b2fc8ba8ff239b48112f Mon Sep 17 00:00:00 2001
From: Stijn Buys <ingar@osirion.org>
Date: Sun, 23 Dec 2012 23:11:43 +0000
Subject: Use bitmaps to draw on-screen HUD targets, improved HUD target health
 bars.

---
 src/client/hud.cc | 174 ++++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 135 insertions(+), 39 deletions(-)

(limited to 'src/client')

diff --git a/src/client/hud.cc b/src/client/hud.cc
index 7db0398..bcbc3a8 100644
--- a/src/client/hud.cc
+++ b/src/client/hud.cc
@@ -16,6 +16,7 @@
 #include "render/render.h"
 #include "render/renderext.h"
 #include "ui/ui.h"
+#include "ui/paint.h"
 
 namespace client
 {
@@ -118,6 +119,10 @@ void HUD::draw_offscreen_target(core::Entity *entity, bool is_active_target)
 	gl::enable(GL_TEXTURE_2D);
 }
 
+/*
+ * This function is called to draw on-screen targets
+ * if is_active_target is set, the target is the currently selected target
+ * */
 void HUD::draw_target(core::Entity *entity, bool is_active_target)
 {
 	using math::Vector3f;
@@ -133,6 +138,8 @@ void HUD::draw_target(core::Entity *entity, bool is_active_target)
 		return;
 	}
 
+	// calculate target screen position
+	
 	// transform the target into the camera coordinate system
 	target = render::Camera::axis().transpose() * target;
 
@@ -147,57 +154,138 @@ void HUD::draw_target(core::Entity *entity, bool is_active_target)
 		draw_offscreen_target(entity, is_active_target);
 		return;
 	}
+	
+	// target bitmap properties
+	float		bitmap_radius =  32.0f;
+	if (is_active_target) {
+		bitmap_radius *= 2.0f;
+	}	
+	math::Vector2f	bitmap_location(cx - bitmap_radius, cy - bitmap_radius);
+	math::Vector2f	bitmap_size(2.0f * bitmap_radius, 2.0f * bitmap_radius);
+	math::Color bitmap_color;	
+	std:: string 	bitmap_material;	
+	
+	if (entity->type() == core::Entity::Controlable) {
+		if (is_active_target) {
+			bitmap_material.assign("bitmaps/hud/target_controlable");
+		} else {
+			bitmap_material.assign("bitmaps/hud/target_default");
+		}
+		bitmap_color.assign(palette()->fancy());
+		
+	} else if (entity->has_flag(core::Entity::Dockable)) {
+		bitmap_material.assign("bitmaps/hud/target_dockable");
+		bitmap_color.assign(palette()->foreground());
+		
+	} else {
+		bitmap_material.assign("bitmaps/hud/target_default");
+		bitmap_color.assign(palette()->text());
+	}
+	
+	if (entity == core::localplayer()->mission_target()) {
+		bitmap_color.assign(palette()->mission());
+	}
 
-	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();
+	ui::Paint::draw_bitmap(bitmap_location, bitmap_size, bitmap_color, bitmap_material);
+	
 
-	if (entity->has_flag(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();
+	// labels	
+	std::string label_text;
+	
+	if (entity->type() == core::Entity::Controlable) {
+		const core::EntityControlable *ec = static_cast<core::EntityControlable *>(entity);
+		if (ec->owner()) {
+			label_text.append("^B");
+			label_text.append(ec->owner()->name());
+		} else {
+			label_text.append("^B");
+			label_text.append(entity->name());
+		}
+	} else {
+		if (entity->has_flag(core::Entity::Dockable)) {
+			label_text.append("^B");
+		} else {
+			label_text.append("^N");
+		}
+		label_text.append(entity->name());
+	}
+	
+	const ui::Font *label_font;
+	if (is_active_target) {
+		label_font = ui::root()->font_small();
+	} else {
+		label_font = ui::root()->font_tiny();
 	}
+	
+	math::Vector2f label_size(2.0f * bitmap_radius, label_font->height());
+	math::Vector2f label_location(cx - bitmap_radius, cy + bitmap_radius);
+	ui::Paint::draw_label(label_location, label_size,label_font, label_text);
 
-	if (entity == core::localplayer()->mission_target()) {
-		gl::color(palette()->mission());
+	if (is_active_target) {
 		
-	} else if (entity->type() == core::Entity::Controlable) {
-		gl::color(0, 1, 0, 1); // FIXME faction color
+		// draw distance
+		std::ostringstream strdistance;
 		
-	} else {
-		gl::color(palette()->foreground());
+		if (entity->type() == core::Entity::Controlable) {
+			strdistance << "^B";
+		} else if (entity->has_flag(core::Entity::Dockable)) {
+			strdistance << "^B";
+		} else {
+			strdistance << "^N";
+		}
+		
+		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 << "--";
+		}
+		
+		label_location[1] +=  - label_size.height();
+		ui::Paint::draw_label(label_location, label_size, label_font, strdistance.str());
 	}
+	
+	if (entity->type() == core::Entity::Controlable) {
+		const core::EntityControlable *ec = static_cast<core::EntityControlable *>(entity);		
+		
+		// health bar size
+		const float hb_width = bitmap_radius;
+		float hb_height = ui::root()->font_tiny()->width();
+		if (!is_active_target) {
+			hb_height *= 0.5f;
+		}
+		const float hb_f = hb_width * ec->health() / 100.0f;
 
-	// 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();
+		math::Vector2f pos;
+		pos[0] = cx - bitmap_radius;
+		pos[0] += bitmap_radius - 0.5f * hb_width;
+		pos[1] = cy - bitmap_radius;
+
+		// health bar
+		gl::color(0, 1, 0, 1);
+		gl::begin(gl::Quads);
+		gl::vertex(pos[0], pos[1]);
+		gl::vertex(pos[0] + hb_f, pos[1]);
+		gl::vertex(pos[0] + hb_f, pos[1] + hb_height);
+		gl::vertex(pos[0], pos[1] + hb_height);
+		gl::end();
 
-	if (entity->has_flag(core::Entity::Dockable)) {
+		// health bar frame
+		gl::color(palette()->foreground());
 		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::vertex(pos[0], pos[1]);
+		gl::vertex(pos[0] + hb_width, pos[1]);
+		gl::vertex(pos[0] + hb_width, pos[1] + hb_height);
+		gl::vertex(pos[0], pos[1] + hb_height);
 		gl::end();
+
 	}
 	
+	/*
 	if (is_active_target) {
 		
 		gl::color(palette()->foreground());
@@ -270,6 +358,7 @@ void HUD::draw_target(core::Entity *entity, bool is_active_target)
 			   cy + r + 4 + render::Text::fontheight(), strdistance.str()
 		);
 	}
+	*/
 }
 
 bool HUD::on_keypress(const int key, const unsigned int modifier)
@@ -309,13 +398,20 @@ void HUD::draw()
 		core::Entity *entity = (*it);
 
 		if (entity == targets::current()) {
+			// draw current HUD target
 			draw_target(entity, true);
 
 		} else 	if (entity == core::localplayer()->mission_target()) {
+			// draw current mission target
 			draw_target(entity, false);
 
 		} else if ((entity->type() == core::Entity::Controlable) && (targets::is_valid_hud_target(entity))) {
-			draw_target(entity, false);
+			const core::EntityControlable *ec = static_cast<core::EntityControlable *>(entity);
+			
+			if (ec->owner()) {
+				// draw other players
+				draw_target(entity, false);
+			}
 		}
 	}
 	
-- 
cgit v1.2.3