diff --git a/src/body.cpp b/src/body.cpp index 77b338e..d8d4eac 100644 --- a/src/body.cpp +++ b/src/body.cpp @@ -5,6 +5,8 @@ Body::Body(void) { m_frame = 0; m_flags = 0; + m_projectedPos = vector3d(0.0f, 0.0f, 0.0f); + m_onscreen = false; } /* f == NULL, then absolute position within system. */ @@ -12,3 +14,8 @@ vector3d Body::GetPositionRelTo(const Frame* relTo) { return m_frame->GetPosRelativeToOtherFrame(relTo) + GetPosition(); } +const vector3d& Body::GetProjectedPos(void) const { + assert(IsOnscreen()); + return m_projectedPos; +} + diff --git a/src/body.h b/src/body.h index 4f8ca3d..c8ac8e6 100644 --- a/src/body.h +++ b/src/body.h @@ -26,6 +26,11 @@ public: unsigned int GetFlags(void) { return m_flags; } /* Return true if we should apply damage. */ virtual bool OnCollision(Body* b) { return false; } + void SetProjectedPos(const vector3d& projectedPos) { m_projectedPos = projectedPos; } + /* Only valid if IsOnScreen() is true. */ + const vector3d& GetProjectedPos() const; + bool IsOnscreen() const { return m_onscreen; } + void SetOnscreen(const bool onscreen) { m_onscreen = onscreen; } enum { FLAG_CAN_MOVE_FRAME = 1 }; @@ -36,5 +41,7 @@ private: /* Frame of reference. */ Frame* m_frame; std::string m_label; + bool m_onscreen; + vector3d m_projectedPos; }; diff --git a/src/frame.cpp b/src/frame.cpp index 67ccb18..4416f58 100644 --- a/src/frame.cpp +++ b/src/frame.cpp @@ -21,6 +21,7 @@ void Frame::Init(Frame* parent, const char* label, unsigned int flags) { m_parent = parent; m_flags = flags; m_radius = 0; + m_pos = vector3d(0.0f); m_dSpaceID = dHashSpaceCreate(0); if(m_parent) { m_parent->m_children.push_back(this); diff --git a/src/player.cpp b/src/player.cpp index dc1f1e1..c0736e8 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -158,17 +158,20 @@ void Player::DrawHUD(const Frame* cam_frame) { { for(std::list::iterator i = Space::bodies.begin(); i != Space::bodies.end(); ++i) { Body* b = *i; - if(b == this) continue; vector3d _pos = b->GetPositionRelTo(cam_frame); vector3d cam_coord = rot*_pos; - - if(cam_coord.z < 0) - if(Gui::Screen::Project(_pos.x, _pos.y, _pos.z, modelMatrix, projMatrix, - viewport, &_pos.x, &_pos.y, &_pos.z)) { - Gui::Screen::RenderLabel(b->GetLabel(), _pos.x, _pos.y); - } + if(cam_coord.z < 0 + && Gui::Screen::Project(_pos.x,_pos.y,_pos.z,modelMatrix,projMatrix,viewport, + &_pos.x, &_pos.y, &_pos.z)) { + b->SetProjectedPos(_pos); + b->SetOnscreen(true); + } else + b->SetOnscreen(false); } } + + DrawTargetSquare(); + GLdouble pos[3]; const float sz = HUD_CROSSHAIR_SIZE; @@ -245,3 +248,27 @@ void Player::DrawHUD(const Frame* cam_frame) { Gui::Screen::LeaveOrtho(); } +void Player::DrawTargetSquare(void) { + if(GetTarget()) { + glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT); + glColor3f(0.0f, 1.0f, 0.0f); + glLineWidth(2.0f); + + const vector3d& _pos = GetTarget()->GetProjectedPos(); + const float x1 = _pos.x - WorldView::PICK_OBJECT_RECT_SIZE * 0.5f; + const float x2 = x1 + WorldView::PICK_OBJECT_RECT_SIZE; + const float y1 = _pos.y - WorldView::PICK_OBJECT_RECT_SIZE * 0.5f; + const float y2 = y1 + WorldView::PICK_OBJECT_RECT_SIZE; + + glBegin(GL_LINE_STRIP); + glVertex2f(x1, y1); + glVertex2f(x2, y1); + glVertex2f(x2, y2); + glVertex2f(x1, y2); + glVertex2f(x1, y1); + glEnd(); + + glPopAttrib(); + } +} + diff --git a/src/player.h b/src/player.h index e546c5b..37c010d 100644 --- a/src/player.h +++ b/src/player.h @@ -12,6 +12,7 @@ public: vector3d GetExternalViewTranslation(void); void ApplyExternalViewRotation(void); private: + void DrawTargetSquare(); float m_mouseCMov[2]; float m_external_view_rotx, m_external_view_roty; float m_external_view_dist; diff --git a/src/ship.cpp b/src/ship.cpp index b4ae744..e9a03e1 100644 --- a/src/ship.cpp +++ b/src/ship.cpp @@ -10,6 +10,7 @@ Ship::Ship(ShipType::Type shipType) : RigidBody() { m_wheelTransition = 0; m_wheelState = 0; m_dockedWith = 0; + m_target = 0; m_mesh = 0; m_shipType = shipType; m_angThrusters[0] = m_angThrusters[1] = m_angThrusters[2] = 0; @@ -143,12 +144,15 @@ void Ship::RenderLaserfire(void) { glDisable(GL_LIGHTING); for(int i = 0; i < ShipType::GUNMOUNT_MAX; i++) { if(!m_gunState[i]) continue; + glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT); glColor3f(1, 0, 0); glBegin(GL_LINES); + glLineWidth(2.0f); vector3f pos = stype.gunMount[i].pos; glVertex3f(pos.x, pos.y, pos.z); glVertex3fv(&((10000)*stype.gunMount[i].dir)[0]); glEnd(); + glPopAttrib(); } glEnable(GL_LIGHTING); } diff --git a/src/ship.h b/src/ship.h index a51cc73..a5e54d1 100644 --- a/src/ship.h +++ b/src/ship.h @@ -20,6 +20,8 @@ public: virtual Object::Type GetType(void) { return Object::SHIP; } virtual void SetDockedWith(SpaceStation*); SpaceStation* GetDockedWith(void) { return m_dockedWith; } + void SetTarget(Body* const target) { m_target = target; } + Body* GetTarget(void) const { return m_target; } virtual void Render(const Frame* camFrame); void SetMesh(ObjMesh* m); void SetThrusterState(enum ShipType::Thruster t, float level); @@ -54,5 +56,6 @@ private: dGeomID m_tempLaserGeom[ShipType::GUNMOUNT_MAX]; LaserObj m_laserCollisionObj; + Body* m_target; }; diff --git a/src/world_view.cpp b/src/world_view.cpp index 3ccdeca..ec5bdd1 100644 --- a/src/world_view.cpp +++ b/src/world_view.cpp @@ -5,6 +5,7 @@ #include "space.h" static const float lightCol[] = { 1, 1, .9, 0 }; +const float WorldView::PICK_OBJECT_RECT_SIZE = 20.0f; #define BG_STAR_MAX 2000 @@ -113,3 +114,35 @@ void WorldView::Update(void) { L3D::player->AITurn(); } +void WorldView::OnMouseDown(Gui::MouseButtonEvent* e) { + if(1 == e->button) { + /* Left click in view => Select target. */ + float screenPos[2]; + GetPosition(screenPos); + /* Put mouse coords into screen space. */ + screenPos[0] += e->x; + screenPos[1] += e->y; + L3D::player->SetTarget(PickBody(screenPos[0], screenPos[1])); + } +} + +Body* WorldView::PickBody(const float screenX, const float screenY) const { + Body* selected = 0; + + for(std::list::iterator i = Space::bodies.begin(); i != Space::bodies.end(); ++i) { + Body* b = *i; + if(b->IsOnscreen()) { + const vector3d& _pos = b->GetProjectedPos(); + const float x1 = _pos.x - PICK_OBJECT_RECT_SIZE * 0.5f; + const float x2 = x1 + PICK_OBJECT_RECT_SIZE; + const float y1 = _pos.y - PICK_OBJECT_RECT_SIZE * 0.5f; + const float y2 = y1 + PICK_OBJECT_RECT_SIZE; + if(screenX >= x1 && screenX <= x2 && screenY >= y1 && screenY <= y2) { + selected = b; + break; + } + } + } + return selected; +} + diff --git a/src/world_view.h b/src/world_view.h index 4fcaeb5..5d0e54a 100644 --- a/src/world_view.h +++ b/src/world_view.h @@ -3,16 +3,20 @@ #include "gui.h" #include "view.h" +class Body; + class WorldView: public View { public: WorldView(void); virtual void Update(void); virtual void Draw3D(void); matrix4x4d viewingRotation; - + static const float PICK_OBJECT_RECT_SIZE; private: void OnClickHyperspace(void); void OnChangeWheelsState(Gui::MultiStateImageButton* b); + virtual void OnMouseDown(Gui::MouseButtonEvent* e); + Body* PickBody(const float screenX, const float screenY) const; Gui::ImageButton* m_hyperspaceButton; GLuint m_bgstarsDlist; };