| [1505] | 1 | /* | 
|---|
|  | 2 | *   ORXONOX - the hottest 3D action shooter ever to exist | 
|---|
|  | 3 | *                    > www.orxonox.net < | 
|---|
| [1454] | 4 | * | 
|---|
| [1505] | 5 | * | 
|---|
|  | 6 | *   License notice: | 
|---|
|  | 7 | * | 
|---|
|  | 8 | *   This program is free software; you can redistribute it and/or | 
|---|
|  | 9 | *   modify it under the terms of the GNU General Public License | 
|---|
|  | 10 | *   as published by the Free Software Foundation; either version 2 | 
|---|
|  | 11 | *   of the License, or (at your option) any later version. | 
|---|
|  | 12 | * | 
|---|
|  | 13 | *   This program is distributed in the hope that it will be useful, | 
|---|
|  | 14 | *   but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
|  | 15 | *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|---|
|  | 16 | *   GNU General Public License for more details. | 
|---|
|  | 17 | * | 
|---|
|  | 18 | *   You should have received a copy of the GNU General Public License | 
|---|
|  | 19 | *   along with this program; if not, write to the Free Software | 
|---|
|  | 20 | *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. | 
|---|
|  | 21 | * | 
|---|
| [1454] | 22 | *   Author: | 
|---|
|  | 23 | *      Felix Schulthess | 
|---|
|  | 24 | *   Co-authors: | 
|---|
| [1590] | 25 | *      Reto Grieder | 
|---|
| [7801] | 26 | *      Oliver Scheuss | 
|---|
| [9016] | 27 | *      Matthias Spalinger | 
|---|
| [1454] | 28 | * | 
|---|
|  | 29 | */ | 
|---|
| [1393] | 30 |  | 
|---|
| [1601] | 31 | #include "HUDNavigation.h" | 
|---|
| [1410] | 32 |  | 
|---|
| [6417] | 33 | #include <OgreCamera.h> | 
|---|
| [7163] | 34 | #include <OgreFontManager.h> | 
|---|
| [1393] | 35 | #include <OgreOverlayManager.h> | 
|---|
| [1614] | 36 | #include <OgreTextAreaOverlayElement.h> | 
|---|
|  | 37 | #include <OgrePanelOverlayElement.h> | 
|---|
| [1410] | 38 |  | 
|---|
| [9526] | 39 | #include <typeinfo> | 
|---|
|  | 40 |  | 
|---|
| [1614] | 41 | #include "util/Math.h" | 
|---|
| [1616] | 42 | #include "util/Convert.h" | 
|---|
| [10624] | 43 | #include "core/command/ConsoleCommandIncludes.h" | 
|---|
| [1616] | 44 | #include "core/CoreIncludes.h" | 
|---|
|  | 45 | #include "core/XMLPort.h" | 
|---|
| [6417] | 46 | #include "CameraManager.h" | 
|---|
| [5929] | 47 | #include "Scene.h" | 
|---|
| [5735] | 48 | #include "Radar.h" | 
|---|
| [6417] | 49 | #include "graphics/Camera.h" | 
|---|
|  | 50 | #include "controllers/HumanController.h" | 
|---|
|  | 51 | #include "worldentities/pawns/Pawn.h" | 
|---|
| [7163] | 52 | #include "worldentities/WorldEntity.h" | 
|---|
| [9667] | 53 | #include "core/config/ConfigValueIncludes.h" | 
|---|
| [7163] | 54 | #include "tools/TextureGenerator.h" | 
|---|
| [1393] | 55 |  | 
|---|
| [7163] | 56 |  | 
|---|
| [1393] | 57 | namespace orxonox | 
|---|
|  | 58 | { | 
|---|
| [9526] | 59 |  | 
|---|
|  | 60 | SetConsoleCommand("HUDNavigation","selectClosest", &HUDNavigation::selectClosestTarget).addShortcut().keybindMode(KeybindMode::OnPress); | 
|---|
|  | 61 | SetConsoleCommand("HUDNavigation","selectNext", &HUDNavigation::selectNextTarget).addShortcut().keybindMode(KeybindMode::OnPress); | 
|---|
|  | 62 |  | 
|---|
|  | 63 | static bool compareDistance(std::pair<RadarViewable*, unsigned int> a, | 
|---|
|  | 64 | std::pair<RadarViewable*, unsigned int> b) | 
|---|
| [9348] | 65 | { | 
|---|
|  | 66 | return a.second < b.second; | 
|---|
|  | 67 | } | 
|---|
| [9667] | 68 | RegisterClass ( HUDNavigation ); | 
|---|
| [2087] | 69 |  | 
|---|
| [11054] | 70 | HUDNavigation* HUDNavigation::localHUD_s = nullptr; | 
|---|
| [9526] | 71 |  | 
|---|
| [9667] | 72 | HUDNavigation::HUDNavigation(Context* context) : | 
|---|
|  | 73 | OrxonoxOverlay(context) | 
|---|
| [9348] | 74 | { | 
|---|
| [9939] | 75 | RegisterObject(HUDNavigation); | 
|---|
|  | 76 | this->setConfigValues(); | 
|---|
| [2087] | 77 |  | 
|---|
| [9348] | 78 | // Set default values | 
|---|
|  | 79 | this->setFont("Monofur"); | 
|---|
|  | 80 | this->setTextSize(0.05f); | 
|---|
| [9526] | 81 | this->setNavMarkerSize(0.03f); | 
|---|
|  | 82 | this->setAimMarkerSize(0.02f); | 
|---|
| [10258] | 83 | this->setHealthMarkerSize(0.06f); | 
|---|
|  | 84 | this->setHealthLevelMarkerSize(0.06f); | 
|---|
| [9526] | 85 |  | 
|---|
| [9348] | 86 | this->setDetectionLimit(10000.0f); | 
|---|
| [10294] | 87 | this->currentMunitionSpeed_ = 750.0f; | 
|---|
| [9526] | 88 |  | 
|---|
|  | 89 | this->closestTarget_ = true; | 
|---|
|  | 90 | this->nextTarget_ = false; | 
|---|
|  | 91 | HUDNavigation::localHUD_s = this; | 
|---|
| [9348] | 92 | } | 
|---|
| [2087] | 93 |  | 
|---|
| [9348] | 94 | HUDNavigation::~HUDNavigation() | 
|---|
|  | 95 | { | 
|---|
|  | 96 | if (this->isInitialized()) | 
|---|
|  | 97 | { | 
|---|
|  | 98 | for (std::map<RadarViewable*, ObjectInfo>::iterator it = this->activeObjectList_.begin(); it != this->activeObjectList_.end();) | 
|---|
| [9526] | 99 | removeObject((it++)->first); | 
|---|
| [9348] | 100 | } | 
|---|
|  | 101 | this->sortedObjectList_.clear(); | 
|---|
|  | 102 | } | 
|---|
| [2087] | 103 |  | 
|---|
| [9348] | 104 | void HUDNavigation::setConfigValues() | 
|---|
|  | 105 | { | 
|---|
|  | 106 | SetConfigValue(markerLimit_, 3); | 
|---|
|  | 107 | SetConfigValue(showDistance_, false); | 
|---|
|  | 108 | } | 
|---|
| [2087] | 109 |  | 
|---|
| [9348] | 110 | void HUDNavigation::XMLPort(Element& xmlelement, XMLPort::Mode mode) | 
|---|
| [7163] | 111 | { | 
|---|
| [9348] | 112 | SUPER(HUDNavigation, XMLPort, xmlelement, mode); | 
|---|
| [2087] | 113 |  | 
|---|
| [9526] | 114 | XMLPortParam(HUDNavigation, "font", setFont, getFont, xmlelement, mode); | 
|---|
|  | 115 | XMLPortParam(HUDNavigation, "textSize", setTextSize, getTextSize, xmlelement, mode); | 
|---|
|  | 116 | XMLPortParam(HUDNavigation, "navMarkerSize", setNavMarkerSize, getNavMarkerSize, xmlelement, mode); | 
|---|
| [9348] | 117 | XMLPortParam(HUDNavigation, "detectionLimit", setDetectionLimit, getDetectionLimit, xmlelement, mode); | 
|---|
| [9526] | 118 | XMLPortParam(HUDNavigation, "aimMarkerSize", setAimMarkerSize, getAimMarkerSize, xmlelement, mode); | 
|---|
| [10258] | 119 | XMLPortParam(HUDNavigation, "healthMarkerSize", setHealthMarkerSize, getHealthMarkerSize, xmlelement, mode); | 
|---|
|  | 120 | XMLPortParam(HUDNavigation, "healthLevelMarkerSize", setHealthLevelMarkerSize, getHealthLevelMarkerSize, xmlelement, mode); | 
|---|
|  | 121 |  | 
|---|
| [1393] | 122 | } | 
|---|
|  | 123 |  | 
|---|
| [9348] | 124 | void HUDNavigation::setFont(const std::string& font) | 
|---|
|  | 125 | { | 
|---|
|  | 126 | const Ogre::ResourcePtr& fontPtr = Ogre::FontManager::getSingleton().getByName(font); | 
|---|
|  | 127 | if (fontPtr.isNull()) | 
|---|
|  | 128 | { | 
|---|
|  | 129 | orxout(internal_warning) << "HUDNavigation: Font '" << font << "' not found" << endl; | 
|---|
|  | 130 | return; | 
|---|
|  | 131 | } | 
|---|
|  | 132 | this->fontName_ = font; | 
|---|
| [11054] | 133 | for (const auto& mapEntry : this->activeObjectList_) | 
|---|
| [9348] | 134 | { | 
|---|
| [11054] | 135 | if (mapEntry.second.text_ != nullptr) | 
|---|
|  | 136 | mapEntry.second.text_->setFontName(this->fontName_); | 
|---|
| [9348] | 137 | } | 
|---|
|  | 138 | } | 
|---|
| [1564] | 139 |  | 
|---|
| [9348] | 140 | const std::string& HUDNavigation::getFont() const | 
|---|
| [1590] | 141 | { | 
|---|
| [9348] | 142 | return this->fontName_; | 
|---|
| [1590] | 143 | } | 
|---|
| [9348] | 144 |  | 
|---|
|  | 145 | void HUDNavigation::setTextSize(float size) | 
|---|
| [1590] | 146 | { | 
|---|
| [9348] | 147 | if (size <= 0.0f) | 
|---|
|  | 148 | { | 
|---|
|  | 149 | orxout(internal_warning) << "HUDNavigation: Negative font size not allowed" << endl; | 
|---|
|  | 150 | return; | 
|---|
|  | 151 | } | 
|---|
|  | 152 | this->textSize_ = size; | 
|---|
| [11054] | 153 | for (const auto& mapEntry : this->activeObjectList_) | 
|---|
| [9348] | 154 | { | 
|---|
| [11054] | 155 | if (mapEntry.second.text_) | 
|---|
|  | 156 | mapEntry.second.text_->setCharHeight(size); | 
|---|
| [9348] | 157 | } | 
|---|
| [1590] | 158 | } | 
|---|
|  | 159 |  | 
|---|
| [9348] | 160 | float HUDNavigation::getTextSize() const | 
|---|
| [1590] | 161 | { | 
|---|
| [9348] | 162 | return this->textSize_; | 
|---|
| [1590] | 163 | } | 
|---|
| [9348] | 164 |  | 
|---|
|  | 165 | float HUDNavigation::getArrowSizeX(int dist) const | 
|---|
| [7163] | 166 | { | 
|---|
| [9348] | 167 | if (dist < 600) | 
|---|
| [9526] | 168 | dist = 600; | 
|---|
| [9348] | 169 | return this->getActualSize().x * 900 * this->navMarkerSize_ / dist; | 
|---|
| [7163] | 170 | } | 
|---|
| [1590] | 171 |  | 
|---|
| [9348] | 172 | float HUDNavigation::getArrowSizeY(int dist) const | 
|---|
| [1590] | 173 | { | 
|---|
| [9348] | 174 | if (dist < 600) | 
|---|
| [9526] | 175 | dist = 600; | 
|---|
| [9348] | 176 | return this->getActualSize().y * 900 * this->navMarkerSize_ / dist; | 
|---|
| [1590] | 177 | } | 
|---|
|  | 178 |  | 
|---|
| [9348] | 179 | void HUDNavigation::tick(float dt) | 
|---|
| [1590] | 180 | { | 
|---|
| [9348] | 181 | SUPER(HUDNavigation, tick, dt); | 
|---|
| [1400] | 182 |  | 
|---|
| [9348] | 183 | Camera* cam = CameraManager::getInstance().getActiveCamera(); | 
|---|
| [11054] | 184 | if (cam == nullptr) | 
|---|
| [9526] | 185 | return; | 
|---|
| [9348] | 186 | const Matrix4& camTransform = cam->getOgreCamera()->getProjectionMatrix() * cam->getOgreCamera()->getViewMatrix(); | 
|---|
| [1399] | 187 |  | 
|---|
| [11054] | 188 | for (std::pair<RadarViewable*, unsigned int>& pair : this->sortedObjectList_) | 
|---|
|  | 189 | pair.second = (int)((pair.first->getRVWorldPosition() - HumanController::getLocalControllerSingleton()->getControllableEntity()->getWorldPosition()).length() + 0.5f); | 
|---|
| [1564] | 190 |  | 
|---|
| [9348] | 191 | this->sortedObjectList_.sort(compareDistance); | 
|---|
| [9016] | 192 |  | 
|---|
| [9348] | 193 | unsigned int markerCount = 0; | 
|---|
|  | 194 | bool closeEnough = false; // only display objects that are close enough to be relevant for the player | 
|---|
| [1399] | 195 |  | 
|---|
| [9526] | 196 | // if the selected object doesn't exist any more or is now out of range select the closest object | 
|---|
|  | 197 | std::map<RadarViewable*, ObjectInfo>::iterator selectedActiveObject = this->activeObjectList_.find(this->selectedTarget_); | 
|---|
|  | 198 | if(selectedActiveObject == this->activeObjectList_.end()) | 
|---|
|  | 199 | { | 
|---|
|  | 200 | this->closestTarget_ = true; | 
|---|
|  | 201 | } | 
|---|
|  | 202 | else if(this->detectionLimit_ < (this->selectedTarget_->getRVWorldPosition() - HumanController::getLocalControllerSingleton()->getControllableEntity()->getWorldPosition()).length() + 0.5f) | 
|---|
|  | 203 | { | 
|---|
|  | 204 | this->closestTarget_ = true; | 
|---|
|  | 205 | selectedActiveObject->second.selected_ = false; | 
|---|
|  | 206 | } | 
|---|
|  | 207 |  | 
|---|
|  | 208 | bool nextHasToBeSelected = false; | 
|---|
|  | 209 |  | 
|---|
| [11054] | 210 | for (std::list<std::pair<RadarViewable*, unsigned int>>::iterator listIt = this->sortedObjectList_.begin(); listIt != this->sortedObjectList_.end(); ++markerCount, ++listIt) | 
|---|
| [9348] | 211 | { | 
|---|
| [10258] | 212 |  | 
|---|
| [9348] | 213 | std::map<RadarViewable*, ObjectInfo>::iterator it = this->activeObjectList_.find(listIt->first); | 
|---|
|  | 214 | closeEnough = listIt->second < this->detectionLimit_; | 
|---|
|  | 215 | // display radarviewables on HUD if the marker limit and max-distance is not exceeded | 
|---|
| [9526] | 216 | if (markerCount < this->markerLimit_ && (closeEnough || this->detectionLimit_ < 0)) | 
|---|
| [1580] | 217 | { | 
|---|
| [9348] | 218 | // Get Distance to HumanController and save it in the TextAreaOverlayElement. | 
|---|
|  | 219 | int dist = listIt->second; | 
|---|
|  | 220 | float textLength = 0.0f; | 
|---|
| [1590] | 221 |  | 
|---|
| [9348] | 222 | if (this->showDistance_) | 
|---|
| [1580] | 223 | { | 
|---|
| [9348] | 224 | //display distance next to cursor | 
|---|
|  | 225 | it->second.text_->setCaption(multi_cast<std::string>(dist)); | 
|---|
|  | 226 | textLength = multi_cast<std::string>(dist).size() * it->second.text_->getCharHeight() * 0.3f; | 
|---|
| [1399] | 227 | } | 
|---|
| [9348] | 228 | else | 
|---|
|  | 229 | { | 
|---|
|  | 230 | //display name next to cursor | 
|---|
|  | 231 | it->second.text_->setCaption(it->first->getRadarName()); | 
|---|
|  | 232 | textLength = it->first->getRadarName().size() * it->second.text_->getCharHeight() * 0.3f; | 
|---|
|  | 233 | } | 
|---|
| [7163] | 234 |  | 
|---|
| [9526] | 235 | // select the object that aim-assistant indicates | 
|---|
|  | 236 | if(this->closestTarget_) | 
|---|
|  | 237 | // select the closest object | 
|---|
|  | 238 | { | 
|---|
|  | 239 | if(listIt == this->sortedObjectList_.begin()) | 
|---|
|  | 240 | { | 
|---|
|  | 241 | it->second.selected_ = true; | 
|---|
|  | 242 | this->selectedTarget_ = it->first; | 
|---|
|  | 243 | } | 
|---|
|  | 244 | else if(it->second.selected_) | 
|---|
|  | 245 | { | 
|---|
|  | 246 | it->second.selected_ = false; | 
|---|
|  | 247 | } | 
|---|
|  | 248 |  | 
|---|
|  | 249 | } | 
|---|
|  | 250 | else if(this->nextTarget_) | 
|---|
|  | 251 | // select the next object in sortedObjectList | 
|---|
|  | 252 | { | 
|---|
|  | 253 | if(nextHasToBeSelected){ | 
|---|
|  | 254 | it->second.selected_ = true; | 
|---|
|  | 255 | this->selectedTarget_ = it->first; | 
|---|
|  | 256 | nextHasToBeSelected = false; | 
|---|
|  | 257 | } | 
|---|
|  | 258 | else if(it->second.selected_) | 
|---|
|  | 259 | { | 
|---|
|  | 260 | nextHasToBeSelected = true; | 
|---|
|  | 261 | it->second.selected_ = false; | 
|---|
|  | 262 |  | 
|---|
|  | 263 | // check if there's a next object | 
|---|
|  | 264 | listIt++; | 
|---|
|  | 265 | if(listIt != this->sortedObjectList_.end()) | 
|---|
|  | 266 | { | 
|---|
|  | 267 | // and if the marker limit and max-distance are not exceeded for it | 
|---|
|  | 268 | if (markerCount + 1 >= this->markerLimit_ || | 
|---|
|  | 269 | (listIt->second > this->detectionLimit_ && detectionLimit_ >= 0)) | 
|---|
|  | 270 | { | 
|---|
|  | 271 | // otherwise select the closest object | 
|---|
|  | 272 | this->activeObjectList_.find(this->sortedObjectList_.begin()->first)->second.selected_ = true; | 
|---|
|  | 273 | this->selectedTarget_ = it->first; | 
|---|
|  | 274 | nextHasToBeSelected = false; | 
|---|
|  | 275 | } | 
|---|
|  | 276 | } | 
|---|
|  | 277 | listIt--; | 
|---|
|  | 278 | } | 
|---|
|  | 279 | } | 
|---|
|  | 280 |  | 
|---|
|  | 281 |  | 
|---|
| [10258] | 282 |  | 
|---|
|  | 283 |  | 
|---|
| [9348] | 284 | // Transform to screen coordinates | 
|---|
|  | 285 | Vector3 pos = camTransform * it->first->getRVWorldPosition(); | 
|---|
| [9016] | 286 |  | 
|---|
| [9348] | 287 | bool outOfView = true; | 
|---|
|  | 288 | if (pos.z > 1.0) | 
|---|
|  | 289 | { | 
|---|
|  | 290 | // z > 1.0 means that the object is behind the camera | 
|---|
|  | 291 | outOfView = true; | 
|---|
|  | 292 | // we have to switch all coordinates (if you don't know why, | 
|---|
|  | 293 | // try linear algebra lectures, because I can't explain..) | 
|---|
|  | 294 | pos.x = -pos.x; | 
|---|
|  | 295 | pos.y = -pos.y; | 
|---|
|  | 296 | } | 
|---|
|  | 297 | else | 
|---|
|  | 298 | outOfView = pos.x < -1.0 || pos.x > 1.0 || pos.y < -1.0 || pos.y > 1.0; | 
|---|
| [9016] | 299 |  | 
|---|
| [9348] | 300 | if (outOfView) | 
|---|
| [7163] | 301 | { | 
|---|
| [9348] | 302 | // Object is not in view | 
|---|
|  | 303 |  | 
|---|
|  | 304 | // Change material only if outOfView changed | 
|---|
|  | 305 | if (!it->second.wasOutOfView_) | 
|---|
| [7163] | 306 | { | 
|---|
| [10258] | 307 | it->second.health_->hide(); | 
|---|
|  | 308 | it->second.healthLevel_->hide(); | 
|---|
| [9348] | 309 | it->second.panel_->setMaterialName(TextureGenerator::getMaterialName("arrows.png", it->first->getRadarObjectColour())); | 
|---|
|  | 310 | it->second.wasOutOfView_ = true; | 
|---|
| [9526] | 311 | it->second.target_->hide(); | 
|---|
| [7163] | 312 | } | 
|---|
| [9348] | 313 |  | 
|---|
|  | 314 | //float xDistScale = this->getActualSize().x * 1000.0f * this->navMarkerSize_ / dist; | 
|---|
|  | 315 | //float yDistScale = this->getActualSize().y * 1000.0f * this->navMarkerSize_ / dist; | 
|---|
|  | 316 |  | 
|---|
|  | 317 | // Adjust Arrowsize according to distance | 
|---|
|  | 318 | it->second.panel_->setDimensions(getArrowSizeX(dist), getArrowSizeY(dist)); | 
|---|
|  | 319 |  | 
|---|
|  | 320 | // Switch between top, bottom, left and right position of the arrow at the screen border | 
|---|
|  | 321 | if (pos.x < pos.y) | 
|---|
|  | 322 | { | 
|---|
|  | 323 | if (pos.y > -pos.x) | 
|---|
|  | 324 | { | 
|---|
|  | 325 | // Top | 
|---|
|  | 326 | float position = pos.x / pos.y + 1.0f; | 
|---|
|  | 327 | it->second.panel_->setPosition((position - it->second.panel_->getWidth()) * 0.5f, 0.0f); | 
|---|
|  | 328 | it->second.panel_->setUV(0.5f, 0.0f, 1.0f, 0.5f); | 
|---|
|  | 329 | it->second.text_->setLeft((position - textLength) * 0.5f); | 
|---|
|  | 330 | it->second.text_->setTop(it->second.panel_->getHeight()); | 
|---|
|  | 331 | } | 
|---|
|  | 332 | else | 
|---|
|  | 333 | { | 
|---|
|  | 334 | // Left | 
|---|
|  | 335 | float position = pos.y / pos.x + 1.0f; | 
|---|
|  | 336 | it->second.panel_->setPosition(0.0f, (position - it->second.panel_->getWidth()) * 0.5f); | 
|---|
|  | 337 | it->second.panel_->setUV(0.0f, 0.0f, 0.5f, 0.5f); | 
|---|
|  | 338 | it->second.text_->setLeft(it->second.panel_->getWidth() + 0.01f); | 
|---|
|  | 339 | it->second.text_->setTop((position - it->second.text_->getCharHeight()) * 0.5f); | 
|---|
|  | 340 | } | 
|---|
|  | 341 | } | 
|---|
| [7163] | 342 | else | 
|---|
|  | 343 | { | 
|---|
| [9348] | 344 | if (pos.y < -pos.x) | 
|---|
|  | 345 | { | 
|---|
|  | 346 | // Bottom | 
|---|
|  | 347 | float position = -pos.x / pos.y + 1.0f; | 
|---|
|  | 348 | it->second.panel_->setPosition((position - it->second.panel_->getWidth()) * 0.5f, 1.0f - it->second.panel_->getHeight()); | 
|---|
|  | 349 | it->second.panel_->setUV(0.0f, 0.5f, 0.5f, 1.0f ); | 
|---|
|  | 350 | it->second.text_->setLeft((position - textLength) * 0.5f); | 
|---|
|  | 351 | it->second.text_->setTop(1.0f - it->second.panel_->getHeight() - it->second.text_->getCharHeight()); | 
|---|
|  | 352 | } | 
|---|
|  | 353 | else | 
|---|
|  | 354 | { | 
|---|
|  | 355 | // Right | 
|---|
|  | 356 | float position = -pos.y / pos.x + 1.0f; | 
|---|
|  | 357 | it->second.panel_->setPosition(1.0f - it->second.panel_->getWidth(), (position - it->second.panel_->getHeight()) * 0.5f); | 
|---|
|  | 358 | it->second.panel_->setUV(0.5f, 0.5f, 1.0f, 1.0f); | 
|---|
|  | 359 | it->second.text_->setLeft(1.0f - it->second.panel_->getWidth() - textLength - 0.01f); | 
|---|
|  | 360 | it->second.text_->setTop((position - it->second.text_->getCharHeight()) * 0.5f); | 
|---|
|  | 361 | } | 
|---|
| [7163] | 362 | } | 
|---|
|  | 363 | } | 
|---|
| [1580] | 364 | else | 
|---|
|  | 365 | { | 
|---|
| [9348] | 366 | // Object is in view | 
|---|
| [7163] | 367 |  | 
|---|
| [10258] | 368 | //calculate the health of the actual selected radarViewable (relativHealthScale: while (0) is no health left, (1) is the initial health) | 
|---|
| [11023] | 369 | const Pawn* pawnPtr = orxonox_cast<const Pawn*>(it->first->getWorldEntity()); | 
|---|
|  | 370 | if (pawnPtr) | 
|---|
|  | 371 | { | 
|---|
|  | 372 | float health = pawnPtr->getHealth(); | 
|---|
|  | 373 | float initHealth = pawnPtr->getMaxHealth(); | 
|---|
|  | 374 | float relativHealthScale = health/initHealth; | 
|---|
| [10258] | 375 |  | 
|---|
| [11023] | 376 | //integer values from 0 to 10 (0 is no health and 10 is full health) | 
|---|
|  | 377 | int discreteHealthScale = (int)(10*relativHealthScale); | 
|---|
| [10258] | 378 |  | 
|---|
| [11023] | 379 | //calculate the HealthLevel (= OponentLevel or Strength) there are 5 Levels | 
|---|
|  | 380 | //Level 1, Level 2,... , Level 5 | 
|---|
|  | 381 | int HealthLevel = 1; | 
|---|
| [10258] | 382 |  | 
|---|
| [11023] | 383 | if(initHealth < 200) | 
|---|
|  | 384 | HealthLevel = 1; | 
|---|
|  | 385 | if(200 <= initHealth && initHealth < 500) | 
|---|
|  | 386 | HealthLevel = 2; | 
|---|
|  | 387 | if(500 <= initHealth && initHealth < 1000) | 
|---|
|  | 388 | HealthLevel = 3; | 
|---|
|  | 389 | if(1000 <= initHealth && initHealth < 2500) | 
|---|
|  | 390 | HealthLevel = 4; | 
|---|
|  | 391 | if(2500 <= initHealth) | 
|---|
|  | 392 | HealthLevel = 5; | 
|---|
| [10258] | 393 |  | 
|---|
| [11023] | 394 | // Change material only if outOfView changed | 
|---|
|  | 395 | if (it->second.wasOutOfView_) | 
|---|
|  | 396 | { | 
|---|
|  | 397 | //it->second.health_->setMaterialName(TextureGenerator::getMaterialName("bar2_1.png", it->first->getRadarObjectColour())); | 
|---|
|  | 398 | it->second.health_->setMaterialName(TextureGenerator::getMaterialName("barSquare.png", it->first->getRadarObjectColour())); | 
|---|
|  | 399 | it->second.health_->setDimensions(this->healthMarkerSize_ * this->getActualSize().x , 0.75f*this->healthMarkerSize_ * this->getActualSize().y); | 
|---|
| [10258] | 400 |  | 
|---|
| [11023] | 401 | // because as soon as relative health drops below 10% (0.1) the descrete value is 0 but as long as the | 
|---|
|  | 402 | // spaceship is still intact there should be at least one part of the bar left. | 
|---|
|  | 403 | if(1<=discreteHealthScale){ | 
|---|
|  | 404 | it->second.health_->setTiling((float)discreteHealthScale , 1 ,0); | 
|---|
|  | 405 | it->second.health_->setDimensions(this->healthMarkerSize_ * this->getActualSize().x *0.1f*discreteHealthScale, 0.75f*this->healthMarkerSize_ * this->getActualSize().y); | 
|---|
|  | 406 | } | 
|---|
| [10258] | 407 |  | 
|---|
| [11023] | 408 | //healthLevel | 
|---|
|  | 409 | it->second.healthLevel_->setMaterialName(TextureGenerator::getMaterialName("barSquare.png", it->first->getRadarObjectColour())); | 
|---|
|  | 410 | it->second.healthLevel_->setDimensions(this->healthLevelMarkerSize_ * this->getActualSize().x , 0.75f*this->healthLevelMarkerSize_ * this->getActualSize().y); | 
|---|
|  | 411 | it->second.healthLevel_->setTiling((float)HealthLevel , 1 ,0); | 
|---|
|  | 412 | it->second.healthLevel_->setDimensions(this->healthLevelMarkerSize_ * this->getActualSize().x *0.1f*HealthLevel, 0.25f*this->healthLevelMarkerSize_ * this->getActualSize().y); | 
|---|
|  | 413 | } | 
|---|
| [10258] | 414 |  | 
|---|
| [11023] | 415 | // sets Position and Dimensions (amount) health | 
|---|
|  | 416 | it->second.health_->setUV(0.0f, 0.0f, 1.0f, 1.0f); | 
|---|
|  | 417 | it->second.health_->setLeft((pos.x + 0.975f - it->second.panel_->getWidth()) * 0.5f); | 
|---|
|  | 418 | it->second.health_->setTop((-pos.y + 1.04f - it->second.panel_->getHeight()) * 0.5f); | 
|---|
| [10258] | 419 |  | 
|---|
|  | 420 | // because as soon as relative health drops below 10% (0.1) the descrete value is 0 but as long as the | 
|---|
|  | 421 | // spaceship is still intact there should be at least one part of the bar left. | 
|---|
|  | 422 | if(1<=discreteHealthScale){ | 
|---|
|  | 423 | it->second.health_->setTiling((float)discreteHealthScale , 1 ,0); | 
|---|
|  | 424 | it->second.health_->setDimensions(this->healthMarkerSize_ * this->getActualSize().x *0.1f*discreteHealthScale, 0.75f*this->healthMarkerSize_ * this->getActualSize().y); | 
|---|
|  | 425 | } | 
|---|
|  | 426 |  | 
|---|
| [11023] | 427 | //sets Position and Dimensions (level) of healthLevel | 
|---|
|  | 428 | it->second.healthLevel_->setMaterialName(TextureGenerator::getMaterialName("barSquare.png", it->first->getRadarObjectColour())); | 
|---|
|  | 429 | it->second.healthLevel_->setUV(0.0f, 0.0f, 1.0f, 1.0f); | 
|---|
|  | 430 | it->second.healthLevel_->setLeft((pos.x + 0.975f - it->second.panel_->getWidth()) * 0.5f); | 
|---|
|  | 431 | it->second.healthLevel_->setTop((-pos.y + 1.125f - it->second.panel_->getHeight()) * 0.5f); | 
|---|
| [10258] | 432 |  | 
|---|
|  | 433 | it->second.healthLevel_->setTiling((float)HealthLevel , 1 ,0); | 
|---|
|  | 434 | it->second.healthLevel_->setDimensions(this->healthLevelMarkerSize_ * this->getActualSize().x *0.1f*HealthLevel, 0.25f*this->healthLevelMarkerSize_ * this->getActualSize().y); | 
|---|
| [11023] | 435 |  | 
|---|
|  | 436 | // Make sure the overlays are shown | 
|---|
|  | 437 | it->second.health_->show(); | 
|---|
|  | 438 | it->second.healthLevel_->show(); | 
|---|
| [7163] | 439 | } | 
|---|
| [9348] | 440 |  | 
|---|
| [10258] | 441 |  | 
|---|
| [11023] | 442 | // Change material only if outOfView changed | 
|---|
|  | 443 | if (it->second.wasOutOfView_) | 
|---|
|  | 444 | { | 
|---|
|  | 445 | //it->second.panel_->setMaterialName("Orxonox/NavTDC"); | 
|---|
|  | 446 | it->second.panel_->setMaterialName(TextureGenerator::getMaterialName("tdc.png", it->first->getRadarObjectColour())); | 
|---|
|  | 447 | it->second.panel_->setDimensions(this->navMarkerSize_ * this->getActualSize().x, this->navMarkerSize_ * this->getActualSize().y); | 
|---|
|  | 448 | it->second.target_->setDimensions(this->aimMarkerSize_ * this->getActualSize().x, this->aimMarkerSize_ * this->getActualSize().y); | 
|---|
|  | 449 | it->second.wasOutOfView_ = false; | 
|---|
| [10258] | 450 | } | 
|---|
|  | 451 |  | 
|---|
| [9348] | 452 | // Position marker | 
|---|
|  | 453 | it->second.panel_->setUV(0.0f, 0.0f, 1.0f, 1.0f); | 
|---|
|  | 454 | it->second.panel_->setLeft((pos.x + 1.0f - it->second.panel_->getWidth()) * 0.5f); | 
|---|
|  | 455 | it->second.panel_->setTop((-pos.y + 1.0f - it->second.panel_->getHeight()) * 0.5f); | 
|---|
|  | 456 |  | 
|---|
|  | 457 | // Position text | 
|---|
|  | 458 | it->second.text_->setLeft((pos.x + 1.0f + it->second.panel_->getWidth()) * 0.5f); | 
|---|
|  | 459 | it->second.text_->setTop((-pos.y + 1.0f + it->second.panel_->getHeight()) * 0.5f); | 
|---|
| [9526] | 460 |  | 
|---|
|  | 461 | // Make sure the overlays are shown | 
|---|
|  | 462 | it->second.panel_->show(); | 
|---|
|  | 463 | it->second.text_->show(); | 
|---|
|  | 464 |  | 
|---|
|  | 465 | // Target marker | 
|---|
|  | 466 | const Pawn* pawn = dynamic_cast<const Pawn*>(it->first->getWorldEntity()); | 
|---|
|  | 467 | /* Pawn* humanPawn = HumanController::getLocalControllerEntityAsPawn();*/ | 
|---|
|  | 468 | if(!it->second.selected_ | 
|---|
|  | 469 | || it->first->getRVVelocity().squaredLength() == 0 | 
|---|
| [11054] | 470 | || pawn == nullptr | 
|---|
| [9526] | 471 | /* TODO : improve getTeam in such a way that it works | 
|---|
| [11054] | 472 | * || humanPawn == nullptr | 
|---|
| [9526] | 473 | * || pawn->getTeam() == humanPawn->getTeam()*/) | 
|---|
|  | 474 | { | 
|---|
|  | 475 | // don't show marker for not selected enemies nor if the selected doesn't move | 
|---|
|  | 476 | it->second.target_->hide(); | 
|---|
|  | 477 | } | 
|---|
|  | 478 | else // object is selected and moves | 
|---|
|  | 479 | { | 
|---|
|  | 480 | // get the aim position | 
|---|
| [10291] | 481 | const Vector3& targetPos = this->toAimPosition(it->first); | 
|---|
| [9526] | 482 | // Transform to screen coordinates | 
|---|
| [10291] | 483 | Vector3 screenPos = camTransform * targetPos; | 
|---|
| [9526] | 484 | // Check if the target marker is in view too | 
|---|
|  | 485 | if(screenPos.z > 1 || screenPos.x < -1.0 || screenPos.x > 1.0 | 
|---|
|  | 486 | || screenPos.y < -1.0 || screenPos.y > 1.0) | 
|---|
|  | 487 | { | 
|---|
|  | 488 | it->second.target_->hide(); | 
|---|
|  | 489 | } | 
|---|
|  | 490 | else | 
|---|
|  | 491 | { | 
|---|
|  | 492 | it->second.target_->setLeft((screenPos.x + 1.0f - it->second.target_->getWidth()) * 0.5f); | 
|---|
|  | 493 | it->second.target_->setTop((-screenPos.y + 1.0f - it->second.target_->getHeight()) * 0.5f); | 
|---|
|  | 494 | it->second.target_->show(); | 
|---|
|  | 495 | } | 
|---|
|  | 496 | } | 
|---|
|  | 497 |  | 
|---|
| [1411] | 498 | } | 
|---|
|  | 499 | } | 
|---|
| [9348] | 500 | else // do not display on HUD | 
|---|
| [9526] | 501 |  | 
|---|
| [1580] | 502 | { | 
|---|
| [10258] | 503 | it->second.health_->hide(); | 
|---|
|  | 504 | it->second.healthLevel_->hide(); | 
|---|
| [9348] | 505 | it->second.panel_->hide(); | 
|---|
|  | 506 | it->second.text_->hide(); | 
|---|
| [9526] | 507 | it->second.target_->hide(); | 
|---|
| [9348] | 508 | } | 
|---|
|  | 509 | } | 
|---|
| [9526] | 510 |  | 
|---|
|  | 511 | this->closestTarget_ = false; | 
|---|
|  | 512 | this->nextTarget_ = false; | 
|---|
| [9348] | 513 | } | 
|---|
| [7163] | 514 |  | 
|---|
| [9348] | 515 | /** Overridden method of OrxonoxOverlay. | 
|---|
| [9526] | 516 | @details | 
|---|
|  | 517 | Usually the entire overlay scales with scale(). | 
|---|
|  | 518 | Here we obviously have to adjust this. | 
|---|
|  | 519 | */ | 
|---|
| [9348] | 520 | void HUDNavigation::sizeChanged() | 
|---|
|  | 521 | { | 
|---|
|  | 522 | // Use size to compensate for aspect ratio if enabled. | 
|---|
|  | 523 | float xScale = this->getActualSize().x; | 
|---|
|  | 524 | float yScale = this->getActualSize().y; | 
|---|
| [7163] | 525 |  | 
|---|
| [11054] | 526 | for (const auto& mapEntry : this->activeObjectList_) | 
|---|
| [1580] | 527 | { | 
|---|
| [11054] | 528 | if (mapEntry.second.health_ != nullptr) | 
|---|
|  | 529 | mapEntry.second.health_->setDimensions(this->healthMarkerSize_ * xScale, this->healthMarkerSize_ * yScale); | 
|---|
|  | 530 | if (mapEntry.second.healthLevel_ != nullptr) | 
|---|
|  | 531 | mapEntry.second.healthLevel_->setDimensions(this->healthLevelMarkerSize_ * xScale, this->healthLevelMarkerSize_ * yScale); | 
|---|
|  | 532 | if (mapEntry.second.panel_ != nullptr) | 
|---|
|  | 533 | mapEntry.second.panel_->setDimensions(this->navMarkerSize_ * xScale, this->navMarkerSize_ * yScale); | 
|---|
|  | 534 | if (mapEntry.second.text_ != nullptr) | 
|---|
|  | 535 | mapEntry.second.text_->setCharHeight(this->textSize_ * yScale); | 
|---|
|  | 536 | if (mapEntry.second.target_ != nullptr) | 
|---|
|  | 537 | mapEntry.second.target_->setDimensions(this->aimMarkerSize_ * xScale, this->aimMarkerSize_ * yScale); | 
|---|
| [7163] | 538 | } | 
|---|
|  | 539 | } | 
|---|
| [1566] | 540 |  | 
|---|
| [9348] | 541 | void HUDNavigation::addObject(RadarViewable* object) | 
|---|
| [7163] | 542 | { | 
|---|
| [9348] | 543 | if (showObject(object) == false) | 
|---|
| [9526] | 544 | return; | 
|---|
| [7163] | 545 |  | 
|---|
| [9348] | 546 | if (this->activeObjectList_.size() >= this->markerLimit_) | 
|---|
| [11054] | 547 | if (object == nullptr) | 
|---|
| [9526] | 548 | return; | 
|---|
| [7163] | 549 |  | 
|---|
| [9348] | 550 | // Object hasn't been added yet (we know that) | 
|---|
|  | 551 | assert(this->activeObjectList_.find(object) == this->activeObjectList_.end()); | 
|---|
| [7163] | 552 |  | 
|---|
| [9348] | 553 | // Scales used for dimensions and text size | 
|---|
|  | 554 | float xScale = this->getActualSize().x; | 
|---|
|  | 555 | float yScale = this->getActualSize().y; | 
|---|
| [7163] | 556 |  | 
|---|
| [9348] | 557 | // Create everything needed to display the object on the radar and add it to the map | 
|---|
| [7163] | 558 |  | 
|---|
| [10258] | 559 | // Create health | 
|---|
|  | 560 | Ogre::PanelOverlayElement* health = static_cast<Ogre::PanelOverlayElement*>( Ogre::OverlayManager::getSingleton().createOverlayElement("Panel", "HUDNavigation_healthMarker_" + getUniqueNumberString())); | 
|---|
|  | 561 | //panel->setMaterialName("Orxonox/NavTDC"); | 
|---|
|  | 562 | health->setMaterialName(TextureGenerator::getMaterialName("barSquare.png", object->getRadarObjectColour())); | 
|---|
|  | 563 | health->setDimensions(this->healthMarkerSize_ * xScale, this->healthMarkerSize_ * yScale); | 
|---|
|  | 564 | //panel->setColour(object->getRadarObjectColour()); | 
|---|
|  | 565 |  | 
|---|
|  | 566 | // Create healthLevel | 
|---|
|  | 567 | Ogre::PanelOverlayElement* healthLevel = static_cast<Ogre::PanelOverlayElement*>( Ogre::OverlayManager::getSingleton().createOverlayElement("Panel", "HUDNavigation_healthLevelMarker_" + getUniqueNumberString())); | 
|---|
|  | 568 | //panel->setMaterialName("Orxonox/NavTDC"); | 
|---|
|  | 569 | health->setMaterialName(TextureGenerator::getMaterialName("barSquare.png", object->getRadarObjectColour())); | 
|---|
|  | 570 | health->setDimensions(this->healthLevelMarkerSize_ * xScale, this->healthLevelMarkerSize_ * yScale); | 
|---|
|  | 571 |  | 
|---|
|  | 572 |  | 
|---|
| [9348] | 573 | // Create arrow/marker | 
|---|
|  | 574 | Ogre::PanelOverlayElement* panel = static_cast<Ogre::PanelOverlayElement*>( Ogre::OverlayManager::getSingleton() | 
|---|
| [9526] | 575 | .createOverlayElement("Panel", "HUDNavigation_navMarker_" + getUniqueNumberString())); | 
|---|
| [9348] | 576 | //panel->setMaterialName("Orxonox/NavTDC"); | 
|---|
|  | 577 | panel->setMaterialName(TextureGenerator::getMaterialName("tdc.png", object->getRadarObjectColour())); | 
|---|
|  | 578 | panel->setDimensions(this->navMarkerSize_ * xScale, this->navMarkerSize_ * yScale); | 
|---|
|  | 579 | //panel->setColour(object->getRadarObjectColour()); | 
|---|
| [7163] | 580 |  | 
|---|
| [9526] | 581 | // Create target marker | 
|---|
|  | 582 | Ogre::PanelOverlayElement* target = static_cast<Ogre::PanelOverlayElement*>(Ogre::OverlayManager::getSingleton() | 
|---|
|  | 583 | .createOverlayElement("Panel", "HUDNavigation_targetMarker_" + getUniqueNumberString())); | 
|---|
|  | 584 | target->setMaterialName(TextureGenerator::getMaterialName("target.png", object->getRadarObjectColour())); | 
|---|
|  | 585 | target->setDimensions(this->aimMarkerSize_ * xScale, this->aimMarkerSize_ * yScale); | 
|---|
|  | 586 |  | 
|---|
|  | 587 | // Create text | 
|---|
| [9348] | 588 | Ogre::TextAreaOverlayElement* text = static_cast<Ogre::TextAreaOverlayElement*>( Ogre::OverlayManager::getSingleton() | 
|---|
| [9526] | 589 | .createOverlayElement("TextArea", "HUDNavigation_navText_" + getUniqueNumberString())); | 
|---|
| [9348] | 590 | text->setFontName(this->fontName_); | 
|---|
| [10292] | 591 | text->setCharHeight(this->textSize_ * yScale); | 
|---|
| [9348] | 592 | text->setColour(object->getRadarObjectColour()); | 
|---|
| [7163] | 593 |  | 
|---|
| [10258] | 594 | health->hide(); | 
|---|
|  | 595 | healthLevel->hide(); | 
|---|
| [9348] | 596 | panel->hide(); | 
|---|
| [9526] | 597 | target->hide(); | 
|---|
| [9348] | 598 | text->hide(); | 
|---|
| [7163] | 599 |  | 
|---|
| [9526] | 600 | ObjectInfo tempStruct = | 
|---|
| [10258] | 601 | {   health, healthLevel, panel, target, text, false, false, false}; | 
|---|
| [9348] | 602 | this->activeObjectList_[object] = tempStruct; | 
|---|
| [7163] | 603 |  | 
|---|
| [10258] | 604 | this->background_->addChild(health); | 
|---|
|  | 605 | this->background_->addChild(healthLevel); | 
|---|
| [9348] | 606 | this->background_->addChild(panel); | 
|---|
| [9526] | 607 | this->background_->addChild(target); | 
|---|
| [9348] | 608 | this->background_->addChild(text); | 
|---|
| [7163] | 609 |  | 
|---|
| [9348] | 610 | this->sortedObjectList_.push_front(std::make_pair(object, (unsigned int)0)); | 
|---|
|  | 611 | } | 
|---|
| [7163] | 612 |  | 
|---|
| [9348] | 613 | void HUDNavigation::removeObject(RadarViewable* viewable) | 
|---|
| [1580] | 614 | { | 
|---|
| [9348] | 615 | std::map<RadarViewable*, ObjectInfo>::iterator it = this->activeObjectList_.find(viewable); | 
|---|
| [7163] | 616 |  | 
|---|
| [9348] | 617 | if (this->activeObjectList_.find(viewable) != this->activeObjectList_.end()) | 
|---|
|  | 618 | { | 
|---|
|  | 619 | // Detach overlays | 
|---|
| [10258] | 620 | this->background_->removeChild(it->second.health_->getName()); | 
|---|
|  | 621 | this->background_->removeChild(it->second.healthLevel_->getName()); | 
|---|
| [9348] | 622 | this->background_->removeChild(it->second.panel_->getName()); | 
|---|
| [9526] | 623 | this->background_->removeChild(it->second.target_->getName()); | 
|---|
| [9348] | 624 | this->background_->removeChild(it->second.text_->getName()); | 
|---|
|  | 625 | // Properly destroy the overlay elements (do not use delete!) | 
|---|
| [10258] | 626 | Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.health_); | 
|---|
|  | 627 | Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.healthLevel_); | 
|---|
| [9348] | 628 | Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.panel_); | 
|---|
| [9526] | 629 | Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.target_); | 
|---|
| [9348] | 630 | Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.text_); | 
|---|
|  | 631 | // Remove from the list | 
|---|
|  | 632 | this->activeObjectList_.erase(viewable); | 
|---|
|  | 633 | } | 
|---|
| [7163] | 634 |  | 
|---|
| [11054] | 635 | for (std::list<std::pair<RadarViewable*, unsigned int>>::iterator listIt = this->sortedObjectList_.begin(); listIt != this->sortedObjectList_.end(); ++listIt) | 
|---|
| [9348] | 636 | { | 
|---|
|  | 637 | if ((listIt->first) == viewable) | 
|---|
|  | 638 | { | 
|---|
|  | 639 | this->sortedObjectList_.erase(listIt); | 
|---|
|  | 640 | break; | 
|---|
|  | 641 | } | 
|---|
|  | 642 | } | 
|---|
| [1410] | 643 | } | 
|---|
| [1590] | 644 |  | 
|---|
| [9348] | 645 | void HUDNavigation::objectChanged(RadarViewable* viewable) | 
|---|
| [1590] | 646 | { | 
|---|
| [9348] | 647 | // TODO: niceification neccessary ;) | 
|---|
|  | 648 | removeObject(viewable); | 
|---|
|  | 649 | addObject(viewable); | 
|---|
|  | 650 | } | 
|---|
| [7163] | 651 |  | 
|---|
| [9348] | 652 | bool HUDNavigation::showObject(RadarViewable* rv) | 
|---|
|  | 653 | { | 
|---|
|  | 654 | if (rv == orxonox_cast<RadarViewable*>(this->getOwner())) | 
|---|
| [9526] | 655 | return false; | 
|---|
| [9348] | 656 | assert(rv->getWorldEntity()); | 
|---|
|  | 657 | if (rv->getWorldEntity()->isVisible() == false || rv->getRadarVisibility() == false) | 
|---|
| [9526] | 658 | return false; | 
|---|
| [9348] | 659 | return true; | 
|---|
| [1590] | 660 | } | 
|---|
| [7163] | 661 |  | 
|---|
| [9348] | 662 | void HUDNavigation::changedOwner() | 
|---|
| [7163] | 663 | { | 
|---|
| [9348] | 664 | const std::set<RadarViewable*>& respawnObjects = this->getOwner()->getScene()->getRadar()->getRadarObjects(); | 
|---|
| [11054] | 665 | for (RadarViewable* respawnObject : respawnObjects) | 
|---|
| [9348] | 666 | { | 
|---|
| [11054] | 667 | if (!respawnObject->isHumanShip_) | 
|---|
|  | 668 | this->addObject(respawnObject); | 
|---|
| [9348] | 669 | } | 
|---|
| [7163] | 670 | } | 
|---|
| [9526] | 671 |  | 
|---|
| [10291] | 672 | Vector3 HUDNavigation::toAimPosition(RadarViewable* target) const | 
|---|
| [9526] | 673 | { | 
|---|
|  | 674 | Vector3 wePosition = HumanController::getLocalControllerSingleton()->getControllableEntity()->getWorldPosition(); | 
|---|
|  | 675 | Vector3 targetPosition = target->getRVWorldPosition(); | 
|---|
|  | 676 | Vector3 targetSpeed = target->getRVVelocity(); | 
|---|
|  | 677 |  | 
|---|
| [10291] | 678 | return getPredictedPosition(wePosition, this->currentMunitionSpeed_, targetPosition, targetSpeed); | 
|---|
| [9526] | 679 | } | 
|---|
|  | 680 |  | 
|---|
|  | 681 | void HUDNavigation::selectClosestTarget() | 
|---|
|  | 682 | { | 
|---|
|  | 683 | if(HUDNavigation::localHUD_s) | 
|---|
|  | 684 | { | 
|---|
|  | 685 | HUDNavigation::localHUD_s->closestTarget_ = true; | 
|---|
|  | 686 | } | 
|---|
|  | 687 | } | 
|---|
|  | 688 |  | 
|---|
|  | 689 | void HUDNavigation::selectNextTarget() | 
|---|
|  | 690 | { | 
|---|
|  | 691 | if(HUDNavigation::localHUD_s) | 
|---|
|  | 692 | { | 
|---|
|  | 693 | HUDNavigation::localHUD_s->nextTarget_ = true; | 
|---|
|  | 694 | } | 
|---|
|  | 695 | } | 
|---|
| [7163] | 696 | } | 
|---|