From ac3ca340c9502e2e0c83c75d5aba5211429e25ae Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sun, 20 Jul 2008 23:10:08 +0000 Subject: targetting --- src/client/input.cc | 63 +++++++++++++++----------- src/client/input.h | 3 +- src/client/keyboard.cc | 2 +- src/client/targets.cc | 117 +++++++++++++++++++++++++++++++++++++++---------- src/client/targets.h | 7 +++ src/client/view.cc | 69 +++++++++++++++++------------ 6 files changed, 183 insertions(+), 78 deletions(-) (limited to 'src/client') diff --git a/src/client/input.cc b/src/client/input.cc index 3d9caa5..8075058 100644 --- a/src/client/input.cc +++ b/src/client/input.cc @@ -11,6 +11,7 @@ #include "client/chat.h" #include "client/console.h" #include "client/keyboard.h" +#include "client/targets.h" #include "client/video.h" #include "render/camera.h" #include "math/functions.h" @@ -21,7 +22,7 @@ namespace client { -core::Cvar *cl_mousecontrol = 0; +core::Cvar *input_mousecontrol = 0; namespace input { @@ -31,7 +32,7 @@ namespace input Keyboard *keyboard = 0; //bool free_control = true; -bool cl_mousecontrol_override = false; + // local controls float local_direction = 0.0f; @@ -51,7 +52,9 @@ float mouse_direction = 0; // true if the mouse is in the deadzone bool mouse_deadzone = false; + // true if the mouse has control +bool mouse_control_override = false; bool mouse_control = false; const float thruster_offset = 0.05f; @@ -71,13 +74,13 @@ void func_ui_control(std::string const &args) if (!core::localcontrol()) return; - if (cl_mousecontrol->value() > 0) { - (*cl_mousecontrol) = 0.0f; + if (input_mousecontrol->value() > 0) { + (*input_mousecontrol) = 0.0f; } else { - (*cl_mousecontrol) = 1.0f; + (*input_mousecontrol) = 1.0f; } - if (!cl_mousecontrol->value()) { + if (!input_mousecontrol->value()) { local_direction = 0.0f; local_pitch = 0.0f; local_roll = 0.0f; @@ -169,8 +172,8 @@ void init() SDL_WM_GrabInput(SDL_GRAB_ON); // SDL_EnableUNICODE(1); - cl_mousecontrol = core::Cvar::get("cl_mousecontrol", "1", core::Cvar::Archive); - cl_mousecontrol->set_info("[bool] set mouse control on or off"); + input_mousecontrol = core::Cvar::get("input_mousecontrol", "1", core::Cvar::Archive); + input_mousecontrol->set_info("[bool] enable or disable mouse control"); core::Func *func = 0; @@ -181,10 +184,10 @@ void init() func->set_info("toggle chatbox on or of"); func = core::Func::add("ui_view", func_ui_view); - func->set_info("switch view mode"); + func->set_info("switch camera view"); func = core::Func::add("ui_control",func_ui_control); - func->set_info("toggle mouse control on or off"); + func->set_info("toggle mouse control"); func = core::Func::add("list_keys", func_list_keys); func->set_info("list keyboard key names"); @@ -251,7 +254,7 @@ void action_press(std::string const &action) /* -- mouse control ------------------------------- */ } else if (action.compare("+control") == 0) { - cl_mousecontrol_override = true; + mouse_control_override = true; /* -- directional control ------------------------- */ } else if (action.compare("+left") == 0) { @@ -299,8 +302,8 @@ void action_release(std::string const &action) /* -- mouse control ------------------------------- */ } else if (action.compare("+control") == 0) { - cl_mousecontrol_override = false; - if (!cl_mousecontrol->value()) { + mouse_control_override = false; + if (!input_mousecontrol->value()) { local_direction = 0.0f; local_pitch = 0.0f; local_roll = 0.0f; @@ -357,8 +360,8 @@ void frame(float seconds) mouse_x = video::width / 2; mouse_y = video::height / 2; render::Camera::reset(); - cl_mousecontrol_override = false; - + mouse_control_override = false; + targets::reset(); render::reset(); } @@ -379,6 +382,7 @@ void frame(float seconds) break; case SDL_MOUSEBUTTONDOWN: + // override for gui mouse down key = keyboard->press(512 + event.button.button); pressed = true; break; @@ -411,8 +415,10 @@ void frame(float seconds) if (keysym.mod & KMOD_CAPS) capslock = true; else capslock = false; if ((keysym.mod & KMOD_LSHIFT) || (keysym.mod & KMOD_RSHIFT)) capslock != capslock; */ - // console key is always captured - if (key->bind().compare("ui_console") == 0) { + // FIXME console key is always captured + // FIXME ESC should escape to gui + + if ((key->sym() == SDLK_ESCAPE) || (key->bind().compare("ui_console") == 0)) { console()->toggle(); local_direction = 0.0f; local_pitch = 0.0f; @@ -433,15 +439,22 @@ void frame(float seconds) } else if (core::application()->connected() && core::localcontrol()) { - char c = key->bind().c_str()[0]; - if (c == '+' || c == '-') { - // action bind - action_press(key->bind()); + if ((key->sym() == 512 + SDL_BUTTON_LEFT) && targets::hover()) { + // hovering target selected + targets::select_target(targets::hover()); - } else if (c) { - // normal bind - core::cmd() << key->bind() << "\n"; + } else { + char c = key->bind().c_str()[0]; + if (c == '+' || c == '-') { + // action bind + action_press(key->bind()); + + } else if (c) { + // normal bind + core::cmd() << key->bind() << "\n"; + } } + } else if (core::application()->connected()) { char c = key->bind().c_str()[0]; @@ -470,7 +483,7 @@ void frame(float seconds) if (core::application()->connected() && core::localcontrol()) { - mouse_control = !console()->visible() && ((cl_mousecontrol->value() > 0) || cl_mousecontrol_override); + mouse_control = !console()->visible() && ((input_mousecontrol->value() > 0) || mouse_control_override); if (mouse_control) { // the mouse will not react if it is in the deadzone diff --git a/src/client/input.h b/src/client/input.h index 201f4e9..96192f8 100644 --- a/src/client/input.h +++ b/src/client/input.h @@ -29,10 +29,11 @@ extern int mouse_y; extern bool mouse_deadzone; extern bool mouse_control; +extern bool mouse_control_override; } // namespace input -extern core::Cvar *cl_mousecontrol; +extern core::Cvar *input_mousecontrol; } // namespace client diff --git a/src/client/keyboard.cc b/src/client/keyboard.cc index 4237b20..8295fce 100644 --- a/src/client/keyboard.cc +++ b/src/client/keyboard.cc @@ -32,7 +32,7 @@ Keyboard::Keyboard() add_key("clear", SDLK_CLEAR); add_key("enter", SDLK_RETURN); add_key("pause", SDLK_PAUSE); - add_key("escape", SDLK_ESCAPE); + add_key("esc", SDLK_ESCAPE); add_key("space", SDLK_SPACE, ' ', "ui_control"); add_key("!", SDLK_EXCLAIM, '!'); add_key("\"", SDLK_QUOTEDBL, '"'); diff --git a/src/client/targets.cc b/src/client/targets.cc index 418ca47..1264cbb 100644 --- a/src/client/targets.cc +++ b/src/client/targets.cc @@ -14,14 +14,16 @@ #include "audio/audio.h" #include "audio/sources.h" +#include "client/input.h" #include "client/view.h" +#include "client/video.h" #include "core/application.h" -#include "core/gameinterface.h" #include "core/entity.h" #include "core/func.h" +#include "core/gameinterface.h" #include "math/vector3f.h" -#include "render/render.h" #include "render/gl.h" +#include "render/render.h" #include "render/text.h" namespace client { @@ -30,9 +32,12 @@ namespace targets { const float TARGETBOXRADIUS = 0.025f; unsigned int current_target_id = 0; +unsigned int current_hover = 0; + core::Entity *current_target = 0; core::Cvar *snd_engines = 0; + bool is_legal_target(core::Entity *entity) { if (entity->id() == core::localcontrol()->id()) @@ -41,6 +46,31 @@ bool is_legal_target(core::Entity *entity) return true; } +core::Entity* current() +{ + return current_target; +} + +unsigned int hover() +{ + return current_hover; +} + +void select_target(core::Entity *entity) +{ + current_target = entity; + current_target_id = current_target->id(); + core::application()->notify_sound("ui/target"); +} + +void select_target(unsigned int id) +{ + // FIXME validate + core::Entity * entity = core::Entity::find(id); + if (entity) + select_target(entity); +} + void func_target_next(std::string const &args) { if (!core::localcontrol()) @@ -83,9 +113,7 @@ void func_target_next(std::string const &args) } if (it != core::Entity::registry.end()) { - current_target = (*it).second; - current_target_id = current_target->id(); - core::application()->notify_sound("ui/target"); + select_target((*it).second); } else { current_target = 0; current_target_id = 0; @@ -134,19 +162,20 @@ void func_target_prev(std::string const &args) } if (rit != core::Entity::registry.rend()) { - current_target = (*rit).second; - current_target_id = current_target->id(); - core::application()->notify_sound("ui/target"); + select_target((*rit).second); + } else { current_target = 0; current_target_id = 0; - } } -core::Entity* current() +void reset() { - return current_target; + current_target = 0; + current_target_id = 0; + current_hover = 0; + } void init() @@ -162,25 +191,17 @@ void init() core::Func::add("target_prev", func_target_prev); func->set_info("select previous target"); - current_target = 0; - current_target_id = 0; + reset(); } void shutdown() { - current_target = 0; - current_target_id = 0; + reset(); core::Func::remove("target_next"); core::Func::remove("target_prev"); } -void reset() -{ - current_target = 0; - current_target_id = 0; -} - void render_listener_sound() { if (!(snd_engines && snd_engines->value())) @@ -238,11 +259,26 @@ void render_entity_sound(core::Entity *entity) void draw() { + /* Notes + http://en.wikipedia.org/wiki/Line-plane_intersection + http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html + */ using math::Vector3f; render_listener_sound(); current_target = 0; + current_hover = 0; + + float z = -1; + + // mouse cursor location in 3d world space + float x = (float)(input::mouse_x - video::width /2) / (float)video::width * render::Camera::aspect(); + float y = (float)(input::mouse_y - video::height /2) / (float)video::height; + + Vector3f cursor = render::Camera::eye() + render::Camera::axis().forward() * (render::frustum_front + 0.001); + cursor -= render::Camera::axis().left() * x; + cursor -= render::Camera::axis().up() * y; math::Vector3f center = render::Camera::eye() + (render::Camera::axis().forward() * (render::frustum_front +0.01f)); for (std::map::iterator it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { @@ -251,10 +287,30 @@ void draw() // render entity sound render_entity_sound(entity); - // calculate target information + // find the current target if (entity->id() == current_target_id) { current_target = entity; + } + + // check if the mouse is hovering the entity + if (core::localcontrol() && entity->state()->visible()) { + Vector3f v(entity->state()->location() - render::Camera::eye()); + v.normalize(); + if (is_legal_target(entity) && (math::dotproduct(render::Camera::axis().forward(), v) > 0.75 )) { + + // caculate the distance from entity location to the line [eye - cursor] + float d = math::Vector3f::length(math::crossproduct( (cursor - render::Camera::eye()) , (render::Camera::eye() - entity->location()))) / math::Vector3f::length(cursor - render::Camera::eye()); + + // if the cursor-beam hits the entity sphere + if (d < entity->radius() * 0.5f) { + float myz = math::distance(cursor, entity->location()); + if (z < 0 || myz < z) { + current_hover = entity->id(); + z = myz; + } + } + } } } @@ -294,6 +350,23 @@ void draw() render::gl::end(); } } + +/* + math::Color color(1, 1, 1, 1); + core::Cvar *cl_crosshaircolor = core::Cvar::get("cl_crosshaircolor", "1 1 1"); + if (cl_crosshaircolor) { + std::stringstream colorstr(cl_crosshaircolor->str()); + colorstr >> color; + } + const float r = 0.05; + render::gl::color(color); + render::gl::begin(render::gl::LineLoop); + render::gl::vertex(cursorposition + render::Camera::axis().up() * r); + render::gl::vertex(cursorposition + render::Camera::axis().left() * r); + render::gl::vertex(cursorposition - render::Camera::axis().up() * r); + render::gl::vertex(cursorposition - render::Camera::axis().left() * r); + render::gl::end(); +*/ } } diff --git a/src/client/targets.h b/src/client/targets.h index 32ea7cd..c1f78c7 100644 --- a/src/client/targets.h +++ b/src/client/targets.h @@ -20,6 +20,7 @@ void init(); void shutdown(); +void reset(); /// render client side entity properties void draw(); @@ -33,6 +34,12 @@ void render_entity_sound(core::Entity *Entity); /// current selected target, 0 if there is no current targer core::Entity *current(); +/// id if target the mouse is currently hovering, 0 if none +unsigned int hover(); + +/// target a specific entity +void select_target(unsigned int id); + } } diff --git a/src/client/view.cc b/src/client/view.cc index 1ee50ed..db0fa64 100644 --- a/src/client/view.cc +++ b/src/client/view.cc @@ -33,8 +33,8 @@ core::Cvar *draw_ui = 0; core::Cvar *draw_stats = 0; core::Cvar *draw_location = 0; -core::Cvar *cl_crosshaircolor = 0; - +core::Cvar *ui_pointercolor = 0; +core::Cvar *ui_pointerhovercolor =0; namespace view { @@ -51,8 +51,11 @@ void init() draw_ui = core::Cvar::get("draw_ui", "1", core::Cvar::Archive); draw_ui->set_info("[bool] draw the user interface"); - cl_crosshaircolor = core::Cvar::get("cl_crosshaircolor", "1 1 1", core::Cvar::Archive); - cl_crosshaircolor->set_info("[r g b] crosshairs color"); + ui_pointercolor = core::Cvar::get("ui_pointercolor", "0 .5 0", core::Cvar::Archive); + ui_pointercolor->set_info("[r g b] mouse pointer color"); + + ui_pointerhovercolor = core::Cvar::get("ui_pointerhovercolor", "0 1 0", core::Cvar::Archive); + ui_pointerhovercolor->set_info("[r g b] mouse pointer hover color"); targets::init(); } @@ -157,9 +160,9 @@ void draw_cursor() if (!core::localcontrol() || console()->visible()) return; - float crosshair_size = 48.0f; - float x = input::mouse_x - (crosshair_size /2); - float y = input::mouse_y - (crosshair_size /2); + float pointer_size = 48.0f; + float x = input::mouse_x - (pointer_size /2); + float y = input::mouse_y - (pointer_size /2); using namespace render; @@ -167,24 +170,32 @@ void draw_cursor() color.a = 0.5f; if (render::Camera::mode() == render::Camera::Overview) { - render::Textures::bind("bitmaps/crosshairs/aim"); + render::Textures::bind("bitmaps/pointers/aim"); } else { - if (input::mouse_control) { + if (!input::mouse_control_override && targets::hover()) { + + if (ui_pointerhovercolor) { + std::stringstream colorstr(ui_pointerhovercolor->str()); + colorstr >> color; + } + render::Textures::bind("bitmaps/pointers/target"); + + } else if (input::mouse_control) { - if (cl_crosshaircolor) { - std::stringstream colorstr(cl_crosshaircolor->str()); + if (ui_pointercolor) { + std::stringstream colorstr(ui_pointercolor->str()); colorstr >> color; } if (render::Camera::mode() == render::Camera::Cockpit || render::Camera::mode() == render::Camera::Track) { - render::Textures::bind("bitmaps/crosshairs/center"); + render::Textures::bind("bitmaps/pointers/center"); - x = (video::width - crosshair_size) /2; - y = (video::height - crosshair_size) /2; + x = (video::width - pointer_size) /2; + y = (video::height - pointer_size) /2; gl::color(color); gl::begin(gl::Quads); @@ -193,32 +204,32 @@ void draw_cursor() gl::vertex(x,y,0.0f); glTexCoord2f(1, 0); - gl::vertex(x+crosshair_size, y, 0.0f); + gl::vertex(x+pointer_size, y, 0.0f); glTexCoord2f(1, 1); - gl::vertex(x+crosshair_size, y+crosshair_size, 0.0f); + gl::vertex(x+pointer_size, y+pointer_size, 0.0f); glTexCoord2f(0, 1); - gl::vertex(x, y+crosshair_size, 0.0f); + gl::vertex(x, y+pointer_size, 0.0f); gl::end(); } - render::Textures::bind("bitmaps/crosshairs/control"); + render::Textures::bind("bitmaps/pointers/control"); - if (!input::mouse_deadzone) { - x = input::mouse_x - (crosshair_size /2); - y = input::mouse_y - (crosshair_size /2); +// if (!input::mouse_deadzone) { + x = input::mouse_x - (pointer_size /2); + y = input::mouse_y - (pointer_size /2); - } else { - x = (video::width - crosshair_size) /2; - y = (video::height - crosshair_size) /2; - } +// } else { +// x = (video::width - pointer_size) /2; +// y = (video::height - pointer_size) /2; +// } } else { - render::Textures::bind("bitmaps/crosshairs/aim"); + render::Textures::bind("bitmaps/pointers/aim"); } } @@ -230,13 +241,13 @@ void draw_cursor() gl::vertex(x,y,0.0f); glTexCoord2f(1, 0); - gl::vertex(x+crosshair_size, y, 0.0f); + gl::vertex(x+pointer_size, y, 0.0f); glTexCoord2f(1, 1); - gl::vertex(x+crosshair_size, y+crosshair_size, 0.0f); + gl::vertex(x+pointer_size, y+pointer_size, 0.0f); glTexCoord2f(0, 1); - gl::vertex(x, y+crosshair_size, 0.0f); + gl::vertex(x, y+pointer_size, 0.0f); gl::end(); } -- cgit v1.2.3