Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStijn Buys <ingar@osirion.org>2009-01-10 15:36:15 +0000
committerStijn Buys <ingar@osirion.org>2009-01-10 15:36:15 +0000
commit272d229094309bc5875287a5063f818c58c5f4f8 (patch)
treefb9a84748c0a88bfa0e59f63be51455fc239becc
parent44500292f5a964036e9d915a38a2773bf5aa765d (diff)
hud widget, drawing code reorganization
-rw-r--r--src/client/Makefile.am10
-rw-r--r--src/client/client.cc31
-rw-r--r--src/client/client.h1
-rw-r--r--src/client/hud.cc371
-rw-r--r--src/client/hud.h48
-rw-r--r--src/client/input.cc2
-rw-r--r--src/client/video.cc128
-rw-r--r--src/client/video.h11
-rw-r--r--src/client/view.cc548
-rw-r--r--src/client/view.h26
10 files changed, 599 insertions, 577 deletions
diff --git a/src/client/Makefile.am b/src/client/Makefile.am
index 4f78bbe..ad011d0 100644
--- a/src/client/Makefile.am
+++ b/src/client/Makefile.am
@@ -7,13 +7,13 @@ else
noinst_LTLIBRARIES = libclient.la
endif
-libclient_la_SOURCES = action.cc chat.cc client.cc clientext.cc input.cc \
- joystick.cc key.cc keyboard.cc map.cc notifications.cc soundext.cc targets.cc \
- video.cc view.cc
+libclient_la_SOURCES = action.cc chat.cc client.cc clientext.cc hud.cc \
+ input.cc joystick.cc key.cc keyboard.cc map.cc notifications.cc soundext.cc targets.cc video.cc view.cc
libclient_la_CFLAGS = $(LIBSDL_CFLAGS) $(GL_CFLAGS)
libclient_la_LDFLAGS = -avoid-version -no-undefined $(GL_LIBS) $(LIBSDL_LIBS)
-noinst_HEADERS = action.h chat.h client.h clientext.h input.h joystick.h key.h \
- keyboard.h map.h notifications.h soundext.h targets.h video.h view.h
+noinst_HEADERS = action.h chat.h client.h clientext.h hud.h input.h joystick.h \
+ key.h keyboard.h map.h notifications.h soundext.h targets.h video.h \
+ view.h
libclient_la_LIBADD = $(top_builddir)/src/core/libcore.la $(top_builddir)/src/audio/libaudio.la \
$(top_builddir)/src/render/librender.la $(top_builddir)/src/ui/libui.la
diff --git a/src/client/client.cc b/src/client/client.cc
index bb6fb55..b897480 100644
--- a/src/client/client.cc
+++ b/src/client/client.cc
@@ -110,7 +110,10 @@ void Client::init(int count, char **arguments)
func = core::Func::add("r_restart", Client::func_r_restart);
func->set_info("restart render subsystem");
-
+
+ func = core::Func::add("snd_restart", Client::func_snd_restart);
+ func->set_info("restart audio subsystem");
+
func = core::Func::add("ui_chat", Client::func_ui_chat);
func->set_info("toggle chat window");
@@ -120,8 +123,8 @@ void Client::init(int count, char **arguments)
func = core::Func::add("ui_map", Client::func_ui_map);
func->set_info("toggle map");
- func = core::Func::add("snd_restart", Client::func_snd_restart);
- func->set_info("restart audio subsystem");
+ func = core::Func::add("ui_menu", Client::func_ui_menu);
+ func->set_info("toggle main menu");
previous_timestamp = 0;
}
@@ -228,9 +231,11 @@ void Client::shutdown()
if (connected()) disconnect();
core::Func::remove("r_restart");
+ core::Func::remove("snd_restart");
core::Func::remove("ui_chat");
core::Func::remove("ui_chatsmall");
- core::Func::remove("snd_restart");
+ core::Func::remove("ui_map");
+ core::Func::remove("ui_menu");
audio::shutdown();
@@ -374,5 +379,23 @@ void Client::func_ui_map(std::string const &args)
}
}
+void Client::func_ui_menu(std::string const &args)
+{
+ if (client()->connected()) {
+ if (ui::root()->active()) {
+ ui::root()->hide_menu();
+ } else {
+ // show the main menu on non-interactive modules
+ if (!core::game()->interactive()) {
+ ui::root()->show_menu("main");
+ } else {
+ ui::root()->show_menu("game");
+ }
+ }
+ } else {
+ con_print << "Not connected." << std::endl;
+ }
+}
+
} // namespace client
diff --git a/src/client/client.h b/src/client/client.h
index 607c7f0..e98eaf4 100644
--- a/src/client/client.h
+++ b/src/client/client.h
@@ -72,6 +72,7 @@ private:
static void func_ui_chat(std::string const &args);
static void func_ui_chatsmall(std::string const &args);
static void func_ui_map(std::string const &args);
+ static void func_ui_menu(std::string const &args);
View *client_view;
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);
+}
+
+}
diff --git a/src/client/hud.h b/src/client/hud.h
new file mode 100644
index 0000000..6882239
--- /dev/null
+++ b/src/client/hud.h
@@ -0,0 +1,48 @@
+/*
+ client/hud.h
+ This file is part of the Osirion project and is distributed under
+ the terms and conditions of the GNU General Public License version 2
+*/
+
+#ifndef __INCLUDED_CLIENT_HUD_H__
+#define __INCLUDED_CLIENT_HUD_H__
+
+#include "ui/bitmap.h"
+#include "ui/toolbar.h"
+#include "ui/widget.h"
+
+namespace client
+{
+
+/// widget that contains HUD elements
+/**
+ * The contains all user interface elements
+ * that are only visible if the client is connected
+ * and the core is running an interactive module
+ **/
+class HUD : public ui::Widget {
+public:
+ /// create a new HUD widget
+ HUD(ui::Widget *parent=0);
+
+protected:
+ /// draw hud elements
+ virtual void draw();
+
+ /// rearrange child widgets
+ virtual void resize();
+
+private:
+
+ void draw_offscreen_target(core::Entity *entity, bool is_active_target);
+
+ void draw_target(core::Entity *entity, bool is_active_target);
+
+ ui::Bitmap *hud_center;
+ ui::Toolbar *hud_toolbar;
+};
+
+}
+
+#endif // __INCLUDED_CLIENT_HUD_H__
+
diff --git a/src/client/input.cc b/src/client/input.cc
index a5af430..9293404 100644
--- a/src/client/input.cc
+++ b/src/client/input.cc
@@ -782,7 +782,7 @@ void frame()
for (Keyboard::iterator it = keyboard->begin(); it != keyboard->end(); it++) {
key = (*it).second;
- if (key && key->pressed()) {
+ if (key && (key->sym() < 512) && key->pressed()) {
if ((key->pressed()+delay < core::application()->time()) && (key->lastpressed()+repeat < core::application()->time())) {
key->key_lastpressed = core::application()->time();
key_pressed(key);
diff --git a/src/client/video.cc b/src/client/video.cc
index 1db1ba4..57efa96 100644
--- a/src/client/video.cc
+++ b/src/client/video.cc
@@ -8,6 +8,7 @@
#include "client/input.h"
#include "client/view.h"
#include "client/client.h"
+#include "client/targets.h"
#include "render/render.h"
#include "core/core.h"
#include "core/gameserver.h"
@@ -21,6 +22,18 @@ 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;
@@ -37,17 +50,11 @@ int height_prev = 0;
const int width_default = 1024;
const int height_default = 768;
-/* -- engine variables --------------------------------------------- */
-
-core::Cvar *r_width;
-core::Cvar *r_height;
-core::Cvar *r_fullscreen;
-
bool init()
{
con_print << "^BInitializing video..." << std::endl;
- // initialize cvars
+ // initialize engine variables
r_width = core::Cvar::get("r_width", width_default, core::Cvar::Archive);
r_width->set_info("[int] video resolution width");
@@ -57,6 +64,18 @@ bool init()
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;
@@ -160,7 +179,8 @@ bool init()
// apply render options
ui::root()->apply_render_options();
- view::init();
+ // initialize target drawer
+ targets::init();
return true;
}
@@ -204,14 +224,100 @@ void restart()
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 frame(float elapsed)
{
// detect fullscreen/windowed mode switch
if (fullscreen != r_fullscreen->value())
restart();
- // render a client frame
- view::frame(elapsed);
+ using namespace render;
+
+ // Clear the color and depth buffers.
+ gl::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ render::Stats::clear();
+
+ if (core::application()->connected() && 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();
+
+ } else {
+ 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();
}
@@ -220,7 +326,7 @@ void shutdown()
{
con_print << "^BShutting down video..." << std::endl;
- view::shutdown();
+ targets::shutdown();
render::shutdown();
diff --git a/src/client/video.h b/src/client/video.h
index 833ebc4..d085f03 100644
--- a/src/client/video.h
+++ b/src/client/video.h
@@ -7,6 +7,8 @@
#ifndef __INCLUDED_CLIENT_VIDEO_H__
#define __INCLUDED_CLIENT_VIDEO_H__
+#include "core/cvar.h"
+
namespace client {
/// the video subsystem
@@ -35,6 +37,15 @@ namespace video
} // namespace video
+extern core::Cvar *r_width;
+extern core::Cvar *r_height;
+extern core::Cvar *r_fullscreen;
+
+extern core::Cvar *draw_ui;
+extern core::Cvar *draw_stats;
+extern core::Cvar *draw_devinfo;
+extern core::Cvar *draw_keypress;
+
} // namespace client
#endif // __INCLUDED_CLIENT_VIDEO_H__
diff --git a/src/client/view.cc b/src/client/view.cc
index 1c1b108..d8346cb 100644
--- a/src/client/view.cc
+++ b/src/client/view.cc
@@ -29,13 +29,6 @@
namespace client
{
-core::Cvar *draw_ui = 0;
-core::Cvar *draw_stats = 0;
-core::Cvar *draw_devinfo = 0;
-core::Cvar *draw_keypress = 0;
-
-unsigned long previousframe = 0;
-
void time_to_stream(std::stringstream &str, float time)
{
int minutes = (int) floorf(time / 60.0f);
@@ -193,24 +186,14 @@ View::View(ui::Widget *parent) : ui::Widget(parent)
set_label("view");
set_border(false);
- // initialize client variables
- 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");
-
// add child widgets
- view_center = new ui::Bitmap(this, "pointers/center");
view_devinfo = new DevInfo(this);
view_stats = new Stats(this);
view_keypress = new KeyPress(this);
view_notify = new Notifications(this);
view_chat = new Chat(this);
view_map = new Map(this);
+ view_hud = new HUD(this);
// make sure the view is at the bottom of the draw stack
lower();
@@ -220,6 +203,10 @@ void View::resize()
{
set_size(parent()->size());
+ // set hud geometry
+ view_hud->set_geometry(0,0, width(), height());
+ view_hud->event_resize();
+
// reposition devinfo widget
view_devinfo->set_size(font()->width()*32, font()->height()*5);
view_devinfo->set_location(font()->width() * 0.5f, font()->height() * 0.5f);
@@ -237,11 +224,6 @@ void View::resize()
view_map->set_size(width() - font()->width() * 8, height() - font()->height() * 8);
view_map->set_location(font()->width() * 4, font()->height() * 4);
- // reposition center
- view_center->set_size(ui::pointer_size, ui::pointer_size);
- view_center->set_location((size() - view_center->size()) * 0.5f);
- view_center->set_color(palette()->pointer());
-
// reposition notifications
view_notify->set_location(ui::UI::elementsize.width()*2.0f+ font()->width(), view_devinfo->top() + view_devinfo->height() + font()->height());
view_notify->set_size(width() - ui::UI::elementsize.width()*2.0f - font()->width() * 2, height() * 0.5f - view_notify->top());
@@ -249,6 +231,13 @@ void View::resize()
void View::draw()
{
+ // draw hud only when connected and controlling a spacecraft
+ if (core::application()->connected() && core::localcontrol() && !ui::root()->active()) {
+ view_hud->set_visible(true);
+ } else {
+ view_hud->set_visible(false);
+ }
+
// reposition chat widget
if (!view_chat->small_view()) {
view_chat->set_location(font()->width(), view_devinfo->top() + view_devinfo->height() + font()->height());
@@ -279,520 +268,7 @@ void View::draw()
if (!core::localcontrol()) {
view_map->set_visible(false);
}
-
- if (core::localcontrol() && (input::mouse_control || input::joystick_control) &&
- (render::Camera::mode() == render::Camera::Cockpit || render::Camera::mode() == render::Camera::Track)) {
- view_center->set_visible(true);
- } else {
- view_center->set_visible(false);
- }
-}
-
-/* -- namespace view ----------------------------------------------- */
-
-namespace view
-{
-
-void init()
-{
- // FIXME integrate with libui
- draw_ui = core::Cvar::get("draw_ui", "1", core::Cvar::Archive);
- draw_ui->set_info("[bool] draw the user interface");
-
- targets::init();
-
- previousframe = 0;
-}
-
-void shutdown()
-{
- targets::shutdown();
-}
-
-/*
- FIXME should be merged with the render passes
- and in the bbox pass
-*/
-
-void draw_entity_world_target(core::Entity *entity)
-{
- model::Model *model = entity->model();
- if (!model)
- return;
-
- if (!model->docks().size())
- return;
-
- float d = math::distance(core::localcontrol()->location(), entity->location()) - entity->radius() - core::localcontrol()->radius();
- if (d > 100.0f)
- return;
-
- gl::enable(GL_DEPTH_TEST);
- gl::push();
- gl::translate(entity->location());
- gl::multmatrix(entity->axis());
-
- gl::color(0, 1.0f, 1.0f, 1.0f);
-
- for (model::Model::Docks::iterator dit = model->docks().begin(); dit != model->docks().end(); dit++) {
- model::Dock *dock = (*dit);
- math::Vector3f maxbox(dock->location());
- math::Vector3f minbox(dock->location());
-
- for (size_t i=0; i < 3; i++) {
- maxbox[i] += 0.025;
- minbox[i] -= 0.025;
- }
-
- // top
- gl::begin(gl::LineLoop);
- gl::vertex(maxbox.x, maxbox.y, maxbox.z);
- gl::vertex(minbox.x, maxbox.y, maxbox.z);
- gl::vertex(minbox.x, minbox.y, maxbox.z);
- gl::vertex(maxbox.x, minbox.y, maxbox.z);
- gl::end();
-
- // bottom
- gl::begin(gl::LineLoop);
- gl::vertex(maxbox.x, maxbox.y, minbox.z);
- gl::vertex(minbox.x, maxbox.y, minbox.z);
- gl::vertex(minbox.x, minbox.y, minbox.z);
- gl::vertex(maxbox.x, minbox.y, minbox.z);
- gl::end();
-
- gl::begin(gl::Lines);
- gl::vertex(maxbox.x, maxbox.y, maxbox.z);
- gl::vertex(maxbox.x, maxbox.y, minbox.z);
- gl::vertex(minbox.x, maxbox.y, maxbox.z);
- gl::vertex(minbox.x, maxbox.y, minbox.z);
- gl::vertex(minbox.x, minbox.y, maxbox.z);
- gl::vertex(minbox.x, minbox.y, minbox.z);
- gl::vertex(maxbox.x, minbox.y, maxbox.z);
- gl::vertex(maxbox.x, minbox.y, minbox.z);
- gl::end();
- }
-
- gl::pop();
- gl::disable(GL_DEPTH_TEST);
-
-}
-
-void draw_entity_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(ui::root()->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 draw_entity_target(core::Entity *entity, bool is_active_target)
-{
- using math::Vector3f;
-
- // don't draw target if we're very close to it
- if (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_entity_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_entity_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(ui::root()->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 draw_hud()
-{
- using namespace render;
- std::stringstream status;
-
- // 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_entity_target(entity, true);
- } else if (entity == targets::current()) {
- draw_entity_target(entity, true);
- } else if (entity->type() == core::Entity::Controlable) {
- draw_entity_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
- }
-}
-
-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 frame(float elapsed)
-{
- using namespace render;
-
- // Clear the color and depth buffers.
- gl::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- render::Stats::clear();
-
- if (core::application()->connected() && 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
- draw_entity_world_target(targets::current());
-
- render::Camera::ortho();
-
- } else {
- 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()) {
- // draw the hud - TODO move as much as possible into ui::
- if (draw_ui->value() && !ui::root()->active()) {
- gl::enable(GL_TEXTURE_2D);
- gl::color(1.0f, 1.0f, 1.0f, 1.0f);
- Text::setfont("gui", 12, 18);
-
- // draw the hud
- draw_hud();
- }
-
- set_cursor();
- ui::root()->frame();
-
- } else if (ui::console()->visible()) {
- ui::console()->event_draw();
- }
-
- gl::disable(GL_TEXTURE_2D);
- gl::disable(GL_BLEND);
-}
-
-} //namespace view
-
} // namespace client
diff --git a/src/client/view.h b/src/client/view.h
index 250fa2d..499f6ec 100644
--- a/src/client/view.h
+++ b/src/client/view.h
@@ -9,6 +9,7 @@
#include "core/zone.h"
#include "client/chat.h"
+#include "client/hud.h"
#include "client/map.h"
#include "client/notifications.h"
#include "ui/widget.h"
@@ -29,7 +30,7 @@ public:
protected:
/// draw developer info
- void draw();
+ virtual void draw();
};
/// a widget that shows engine statistics
@@ -75,7 +76,6 @@ public:
inline Map *map() { return view_map; }
inline Chat *chat() { return view_chat; }
-
inline Notifications *notify() { return view_notify; }
protected:
@@ -84,34 +84,20 @@ protected:
virtual void resize();
private:
+ HUD *view_hud;
Chat *view_chat;
DevInfo *view_devinfo;
Stats *view_stats;
KeyPress *view_keypress;
Notifications *view_notify;
Map *view_map;
- ui::Bitmap *view_center;
};
-/// functions to draw the client view
-namespace view
-{
- /// intialize the view
- void init();
-
- /// shutdown the view
- void shutdown();
-
- /// draw the next frame
- void frame(float elapsed);
-
- /// reset OpenGL state
- void reset();
+namespace view {
- /// clear client-side assets of a zone
- void clear_zone(core::Zone *zone);
+void draw_hud();
-} // namespace view
+}
} // namespace client