From 1f9df7f9b6877ab457fe92682487711edbe3fe54 Mon Sep 17 00:00:00 2001
From: Allanis <allanis.saracraft.studios@gmail.com>
Date: Fri, 17 Nov 2017 20:51:44 +0000
Subject: [PATCH] [Add] Added targets to ships.

---
 src/body.cpp       |  7 +++++++
 src/body.h         |  7 +++++++
 src/frame.cpp      |  1 +
 src/player.cpp     | 41 ++++++++++++++++++++++++++++++++++-------
 src/player.h       |  1 +
 src/ship.cpp       |  4 ++++
 src/ship.h         |  3 +++
 src/world_view.cpp | 33 +++++++++++++++++++++++++++++++++
 src/world_view.h   |  6 +++++-
 9 files changed, 95 insertions(+), 8 deletions(-)

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<Body*>::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<Body*>::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;
 };