Index: code/branches/presentationHS12/src/modules/overlays/hud/HUDNavigation.cc
===================================================================
--- code/branches/presentationHS12/src/modules/overlays/hud/HUDNavigation.cc	(revision 9481)
+++ code/branches/presentationHS12/src/modules/overlays/hud/HUDNavigation.cc	(revision 9498)
@@ -37,6 +37,9 @@
 #include <OgrePanelOverlayElement.h>
 
+#include <typeinfo>
+
 #include "util/Math.h"
 #include "util/Convert.h"
+#include "core/command/ConsoleCommand.h"
 #include "core/CoreIncludes.h"
 #include "core/XMLPort.h"
@@ -55,21 +58,35 @@
 namespace orxonox
 {
-    bool compareDistance(std::pair<RadarViewable*, unsigned int> a, std::pair<RadarViewable*, unsigned int> b)
+
+    SetConsoleCommand("HUDNavigation","selectClosest", &HUDNavigation::selectClosestTarget).addShortcut().keybindMode(KeybindMode::OnPress);
+    SetConsoleCommand("HUDNavigation","selectNext", &HUDNavigation::selectNextTarget).addShortcut().keybindMode(KeybindMode::OnPress);
+
+    static bool compareDistance(std::pair<RadarViewable*, unsigned int> a,
+            std::pair<RadarViewable*, unsigned int> b)
     {
         return a.second < b.second;
     }
-
     CreateFactory ( HUDNavigation );
 
-    HUDNavigation::HUDNavigation(BaseObject* creator) : OrxonoxOverlay(creator)
-    {
-        RegisterObject(HUDNavigation);
-        this->setConfigValues();
+    HUDNavigation* HUDNavigation::localHUD_s = 0;
+
+    HUDNavigation::HUDNavigation(BaseObject* creator) :
+        OrxonoxOverlay(creator)
+    {
+        RegisterObject(HUDNavigation)
+;        this->setConfigValues();
 
         // Set default values
         this->setFont("Monofur");
         this->setTextSize(0.05f);
-        this->setNavMarkerSize(0.05f);
+        this->setNavMarkerSize(0.03f);
+        this->setAimMarkerSize(0.02f);
+
         this->setDetectionLimit(10000.0f);
+        this->currentMunitionSpeed_ = 2500.0f;
+
+        this->closestTarget_ = true;
+        this->nextTarget_ = false;
+        HUDNavigation::localHUD_s = this;
     }
 
@@ -79,5 +96,5 @@
         {
             for (std::map<RadarViewable*, ObjectInfo>::iterator it = this->activeObjectList_.begin(); it != this->activeObjectList_.end();)
-                removeObject((it++)->first);
+            removeObject((it++)->first);
         }
         this->sortedObjectList_.clear();
@@ -94,8 +111,9 @@
         SUPER(HUDNavigation, XMLPort, xmlelement, mode);
 
-        XMLPortParam(HUDNavigation, "font",           setFont,           getFont,           xmlelement, mode);
-        XMLPortParam(HUDNavigation, "textSize",       setTextSize,       getTextSize,       xmlelement, mode);
-        XMLPortParam(HUDNavigation, "navMarkerSize",  setNavMarkerSize,  getNavMarkerSize,  xmlelement, mode);
+        XMLPortParam(HUDNavigation, "font", setFont, getFont, xmlelement, mode);
+        XMLPortParam(HUDNavigation, "textSize", setTextSize, getTextSize, xmlelement, mode);
+        XMLPortParam(HUDNavigation, "navMarkerSize", setNavMarkerSize, getNavMarkerSize, xmlelement, mode);
         XMLPortParam(HUDNavigation, "detectionLimit", setDetectionLimit, getDetectionLimit, xmlelement, mode);
+        XMLPortParam(HUDNavigation, "aimMarkerSize", setAimMarkerSize, getAimMarkerSize, xmlelement, mode);
     }
 
@@ -112,5 +130,5 @@
         {
             if (it->second.text_ != NULL)
-                it->second.text_->setFontName(this->fontName_);
+            it->second.text_->setFontName(this->fontName_);
         }
     }
@@ -132,5 +150,5 @@
         {
             if (it->second.text_)
-                it->second.text_->setCharHeight(size);
+            it->second.text_->setCharHeight(size);
         }
     }
@@ -144,5 +162,5 @@
     {
         if (dist < 600)
-            dist = 600;
+        dist = 600;
         return this->getActualSize().x * 900 * this->navMarkerSize_ / dist;
     }
@@ -151,5 +169,5 @@
     {
         if (dist < 600)
-            dist = 600;
+        dist = 600;
         return this->getActualSize().y * 900 * this->navMarkerSize_ / dist;
     }
@@ -161,10 +179,9 @@
         Camera* cam = CameraManager::getInstance().getActiveCamera();
         if (cam == NULL)
-            return;
+        return;
         const Matrix4& camTransform = cam->getOgreCamera()->getProjectionMatrix() * cam->getOgreCamera()->getViewMatrix();
 
-
         for (std::list<std::pair<RadarViewable*, unsigned int> >::iterator listIt = this->sortedObjectList_.begin(); listIt != this->sortedObjectList_.end(); ++listIt)
-            listIt->second = (int)((listIt->first->getRVWorldPosition() - HumanController::getLocalControllerSingleton()->getControllableEntity()->getWorldPosition()).length() + 0.5f);
+        listIt->second = (int)((listIt->first->getRVWorldPosition() - HumanController::getLocalControllerSingleton()->getControllableEntity()->getWorldPosition()).length() + 0.5f);
 
         this->sortedObjectList_.sort(compareDistance);
@@ -172,4 +189,18 @@
         unsigned int markerCount = 0;
         bool closeEnough = false; // only display objects that are close enough to be relevant for the player
+
+        // if the selected object doesn't exist any more or is now out of range select the closest object
+        std::map<RadarViewable*, ObjectInfo>::iterator selectedActiveObject = this->activeObjectList_.find(this->selectedTarget_);
+        if(selectedActiveObject == this->activeObjectList_.end())
+        {
+            this->closestTarget_ = true;
+        }
+        else if(this->detectionLimit_ < (this->selectedTarget_->getRVWorldPosition() - HumanController::getLocalControllerSingleton()->getControllableEntity()->getWorldPosition()).length() + 0.5f)
+        {
+            this->closestTarget_ = true;
+            selectedActiveObject->second.selected_ = false;
+        }
+
+        bool nextHasToBeSelected = false;
 
         for (std::list<std::pair<RadarViewable*, unsigned int> >::iterator listIt = this->sortedObjectList_.begin(); listIt != this->sortedObjectList_.end(); ++markerCount, ++listIt)
@@ -178,5 +209,5 @@
             closeEnough = listIt->second < this->detectionLimit_;
             // display radarviewables on HUD if the marker limit and max-distance is not exceeded
-            if (markerCount < this->markerLimit_ && (closeEnough ||  this->detectionLimit_ < 0))
+            if (markerCount < this->markerLimit_ && (closeEnough || this->detectionLimit_ < 0))
             {
                 // Get Distance to HumanController and save it in the TextAreaOverlayElement.
@@ -196,4 +227,51 @@
                     textLength = it->first->getRadarName().size() * it->second.text_->getCharHeight() * 0.3f;
                 }
+
+                // select the object that aim-assistant indicates
+                if(this->closestTarget_)
+                // select the closest object
+                {
+                    if(listIt == this->sortedObjectList_.begin())
+                    {
+                        it->second.selected_ = true;
+                        this->selectedTarget_ = it->first;
+                    }
+                    else if(it->second.selected_)
+                    {
+                        it->second.selected_ = false;
+                    }
+
+                }
+                else if(this->nextTarget_)
+                // select the next object in sortedObjectList
+                {
+                    if(nextHasToBeSelected){
+                        it->second.selected_ = true;
+                        this->selectedTarget_ = it->first;
+                        nextHasToBeSelected = false;
+                    }
+                    else if(it->second.selected_)
+                    {
+                        nextHasToBeSelected = true;
+                        it->second.selected_ = false;
+
+                        // check if there's a next object
+                        listIt++;
+                        if(listIt != this->sortedObjectList_.end())
+                        {
+                            // and if the marker limit and max-distance are not exceeded for it
+                            if (markerCount + 1 >= this->markerLimit_ ||
+                                    (listIt->second > this->detectionLimit_ && detectionLimit_ >= 0))
+                            {
+                                // otherwise select the closest object
+                                this->activeObjectList_.find(this->sortedObjectList_.begin()->first)->second.selected_ = true;
+                                this->selectedTarget_ = it->first;
+                                nextHasToBeSelected = false;
+                            }
+                        }
+                        listIt--;
+                    }
+                }
+
 
                 // Transform to screen coordinates
@@ -222,4 +300,5 @@
                         it->second.panel_->setMaterialName(TextureGenerator::getMaterialName("arrows.png", it->first->getRadarObjectColour()));
                         it->second.wasOutOfView_ = true;
+                        it->second.target_->hide();
                     }
 
@@ -284,4 +363,5 @@
                         it->second.panel_->setMaterialName(TextureGenerator::getMaterialName("tdc.png", it->first->getRadarObjectColour()));
                         it->second.panel_->setDimensions(this->navMarkerSize_ * this->getActualSize().x, this->navMarkerSize_ * this->getActualSize().y);
+                        it->second.target_->setDimensions(this->aimMarkerSize_ * this->getActualSize().x, this->aimMarkerSize_ * this->getActualSize().y);
                         it->second.wasOutOfView_ = false;
                     }
@@ -295,23 +375,63 @@
                     it->second.text_->setLeft((pos.x + 1.0f + it->second.panel_->getWidth()) * 0.5f);
                     it->second.text_->setTop((-pos.y + 1.0f + it->second.panel_->getHeight()) * 0.5f);
-                }
-
-                // Make sure the overlays are shown
-                it->second.panel_->show();
-                it->second.text_->show();
+
+                    // Make sure the overlays are shown
+                    it->second.panel_->show();
+                    it->second.text_->show();
+
+                    // Target marker
+                    const Pawn* pawn = dynamic_cast<const Pawn*>(it->first->getWorldEntity());
+                    /* Pawn* humanPawn = HumanController::getLocalControllerEntityAsPawn();*/
+                    if(!it->second.selected_
+                            || it->first->getRVVelocity().squaredLength() == 0
+                            || pawn == NULL
+                            /* TODO : improve getTeam in such a way that it works
+                             * || humanPawn == NULL
+                             * || pawn->getTeam() == humanPawn->getTeam()*/)
+                    {
+                        // don't show marker for not selected enemies nor if the selected doesn't move
+                        it->second.target_->hide();
+                    }
+                    else // object is selected and moves
+                    {
+                        // get the aim position
+                        Vector3* targetPos = this->toAimPosition(it->first);
+                        // Transform to screen coordinates
+                        Vector3 screenPos = camTransform * (*targetPos);
+                        // Check if the target marker is in view too
+                        if(screenPos.z > 1 || screenPos.x < -1.0 || screenPos.x > 1.0
+                                || screenPos.y < -1.0 || screenPos.y > 1.0)
+                        {
+                            it->second.target_->hide();
+                        }
+                        else
+                        {
+                            it->second.target_->setLeft((screenPos.x + 1.0f - it->second.target_->getWidth()) * 0.5f);
+                            it->second.target_->setTop((-screenPos.y + 1.0f - it->second.target_->getHeight()) * 0.5f);
+                            it->second.target_->show();
+                        }
+                        delete targetPos;
+                    }
+
+                }
             }
             else // do not display on HUD
+
             {
                 it->second.panel_->hide();
                 it->second.text_->hide();
+                it->second.target_->hide();
             }
         }
+
+        this->closestTarget_ = false;
+        this->nextTarget_ = false;
     }
 
     /** Overridden method of OrxonoxOverlay.
-    @details
-        Usually the entire overlay scales with scale().
-        Here we obviously have to adjust this.
-    */
+     @details
+     Usually the entire overlay scales with scale().
+     Here we obviously have to adjust this.
+     */
     void HUDNavigation::sizeChanged()
     {
@@ -326,4 +446,6 @@
             if (it->second.text_ != NULL)
                 it->second.text_->setCharHeight(it->second.text_->getCharHeight() * yScale);
+            if (it->second.target_ != NULL)
+                it->second.target_->setDimensions(this->aimMarkerSize_ * xScale, this->aimMarkerSize_ * yScale);
         }
     }
@@ -332,9 +454,9 @@
     {
         if (showObject(object) == false)
-            return;
+        return;
 
         if (this->activeObjectList_.size() >= this->markerLimit_)
-            if (object == NULL)
-                return;
+        if (object == NULL)
+        return;
 
         // Object hasn't been added yet (we know that)
@@ -349,5 +471,5 @@
         // Create arrow/marker
         Ogre::PanelOverlayElement* panel = static_cast<Ogre::PanelOverlayElement*>( Ogre::OverlayManager::getSingleton()
-                                           .createOverlayElement("Panel", "HUDNavigation_navMarker_" + getUniqueNumberString()));
+                .createOverlayElement("Panel", "HUDNavigation_navMarker_" + getUniqueNumberString()));
         //panel->setMaterialName("Orxonox/NavTDC");
         panel->setMaterialName(TextureGenerator::getMaterialName("tdc.png", object->getRadarObjectColour()));
@@ -355,6 +477,13 @@
         //panel->setColour(object->getRadarObjectColour());
 
+        // Create target marker
+        Ogre::PanelOverlayElement* target = static_cast<Ogre::PanelOverlayElement*>(Ogre::OverlayManager::getSingleton()
+                    .createOverlayElement("Panel", "HUDNavigation_targetMarker_" + getUniqueNumberString()));
+        target->setMaterialName(TextureGenerator::getMaterialName("target.png", object->getRadarObjectColour()));
+        target->setDimensions(this->aimMarkerSize_ * xScale, this->aimMarkerSize_ * yScale);
+
+        // Create text
         Ogre::TextAreaOverlayElement* text = static_cast<Ogre::TextAreaOverlayElement*>( Ogre::OverlayManager::getSingleton()
-                                             .createOverlayElement("TextArea", "HUDNavigation_navText_" + getUniqueNumberString()));
+                .createOverlayElement("TextArea", "HUDNavigation_navText_" + getUniqueNumberString()));
         text->setFontName(this->fontName_);
         text->setCharHeight(text->getCharHeight() * yScale);
@@ -362,10 +491,13 @@
 
         panel->hide();
+        target->hide();
         text->hide();
 
-        ObjectInfo tempStruct = {panel, text, false /*, TODO: initialize wasOutOfView_ */};
+        ObjectInfo tempStruct =
+        {   panel, target, text, false, false, false};
         this->activeObjectList_[object] = tempStruct;
 
         this->background_->addChild(panel);
+        this->background_->addChild(target);
         this->background_->addChild(text);
 
@@ -381,7 +513,9 @@
             // Detach overlays
             this->background_->removeChild(it->second.panel_->getName());
+            this->background_->removeChild(it->second.target_->getName());
             this->background_->removeChild(it->second.text_->getName());
             // Properly destroy the overlay elements (do not use delete!)
             Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.panel_);
+            Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.target_);
             Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.text_);
             // Remove from the list
@@ -409,8 +543,8 @@
     {
         if (rv == orxonox_cast<RadarViewable*>(this->getOwner()))
-            return false;
+        return false;
         assert(rv->getWorldEntity());
         if (rv->getWorldEntity()->isVisible() == false || rv->getRadarVisibility() == false)
-            return false;
+        return false;
         return true;
     }
@@ -422,5 +556,35 @@
         {
             if (!(*it)->isHumanShip_)
-                this->addObject(*it);
+            this->addObject(*it);
+        }
+    }
+
+    Vector3* HUDNavigation::toAimPosition(RadarViewable* target) const
+    {
+        Vector3 wePosition = HumanController::getLocalControllerSingleton()->getControllableEntity()->getWorldPosition();
+        Vector3 targetPosition = target->getRVWorldPosition();
+        Vector3 targetSpeed = target->getRVVelocity();
+        Vector3 relativePosition = targetPosition - wePosition; //Vector from attacker to target
+
+        float p_half = relativePosition.dotProduct(targetSpeed)/(targetSpeed.squaredLength() - this->currentMunitionSpeed_ * this->currentMunitionSpeed_);
+        float time1 = -p_half + sqrt(p_half * p_half - relativePosition.squaredLength()/(targetSpeed.squaredLength() - this->currentMunitionSpeed_ * this->currentMunitionSpeed_));
+
+        Vector3* result = new Vector3(targetPosition + targetSpeed * time1);
+        return result;
+    }
+
+    void HUDNavigation::selectClosestTarget()
+    {
+        if(HUDNavigation::localHUD_s)
+        {
+            HUDNavigation::localHUD_s->closestTarget_ = true;
+        }
+    }
+
+    void HUDNavigation::selectNextTarget()
+    {
+        if(HUDNavigation::localHUD_s)
+        {
+            HUDNavigation::localHUD_s->nextTarget_ = true;
         }
     }
Index: code/branches/presentationHS12/src/modules/overlays/hud/HUDNavigation.h
===================================================================
--- code/branches/presentationHS12/src/modules/overlays/hud/HUDNavigation.h	(revision 9481)
+++ code/branches/presentationHS12/src/modules/overlays/hud/HUDNavigation.h	(revision 9498)
@@ -71,11 +71,16 @@
                 { return this->markerLimit_; }
 
+            static void selectClosestTarget();
+            static void selectNextTarget();
+
         private:
             struct ObjectInfo
             {
                 Ogre::PanelOverlayElement* panel_;
+                Ogre::PanelOverlayElement* target_;
                 Ogre::TextAreaOverlayElement* text_;
                 bool outOfView_;
                 bool wasOutOfView_;
+                bool selected_;
             };
 
@@ -85,9 +90,16 @@
             inline void setNavMarkerSize(float size)
             {
-                navMarkerSize_ = size;
+                this->navMarkerSize_ = size;
                 this->sizeChanged();
             }
             inline float getNavMarkerSize() const
                 { return navMarkerSize_; }
+            inline void setAimMarkerSize(float size)
+            {
+                this->aimMarkerSize_ = size;
+                this->sizeChanged();
+            }
+            inline float getAimMarkerSize() const
+                { return aimMarkerSize_; }
             inline void setDetectionLimit(float limit)
                 { this->detectionLimit_ = limit; }
@@ -104,11 +116,24 @@
             float getArrowSizeY(int dist) const;
 
+            Vector3* toAimPosition(RadarViewable* target) const;
+
             std::map<RadarViewable*, ObjectInfo> activeObjectList_;
             std::list<std::pair<RadarViewable*, unsigned int> > sortedObjectList_;
 
             float navMarkerSize_;
+            float aimMarkerSize_;
             std::string fontName_;
             float textSize_;
             bool showDistance_;
+
+            RadarViewable* selectedTarget_;
+
+            bool closestTarget_;
+            bool nextTarget_;
+
+            static HUDNavigation* localHUD_s; //!< This is used as a filter. Only the local HUD should be influenced by the static Console Command functions.
+
+
+            float currentMunitionSpeed_;
 
             unsigned int markerLimit_;
