Rigs of Rods 2026.01
Soft-body Physics Simulation
Loading...
Searching...
No Matches
OverlayWrapper.cpp
Go to the documentation of this file.
1/*
2 This source file is part of Rigs of Rods
3 Copyright 2005-2012 Pierre-Michel Ricordel
4 Copyright 2007-2012 Thomas Fischer
5 Copyright 2013-2020 Petr Ohlidal
6
7 For more information, see http://www.rigsofrods.org/
8
9 Rigs of Rods is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License version 3, as
11 published by the Free Software Foundation.
12
13 Rigs of Rods 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 Rigs of Rods. If not, see <http://www.gnu.org/licenses/>.
20*/
21
25
26#include <Ogre.h>
27#include <Overlay/OgreOverlayManager.h>
28#include <Overlay/OgreOverlay.h>
29#include <Overlay/OgreFontManager.h>
30#include "OverlayWrapper.h"
31
32#include "AeroEngine.h"
33#include "AppContext.h"
34#include "AutoPilot.h"
35#include "Actor.h"
36#include "ActorManager.h"
37#include "Character.h"
38#include "DashBoardManager.h"
39#include "ErrorUtils.h"
40#include "FlexAirfoil.h"
41#include "GameContext.h"
42#include "GfxActor.h"
43#include "GfxScene.h"
44#include "Language.h"
45#include "RoRVersion.h"
46#include "ScrewProp.h"
47#include "SoundScriptManager.h"
48#include "Terrain.h"
49#include "TurboProp.h"
50#include "Utils.h"
51
52using namespace Ogre;
53using namespace RoR;
54
55bool g_is_scaled = false;
56
62
68
69void OverlayWrapper::resizePanel(OverlayElement* oe)
70{
71 if (g_is_scaled)
72 return;
73 oe->setHeight(oe->getHeight() * (Real)win->getWidth() / (Real)win->getHeight());
74 oe->setTop(oe->getTop() * (Real)win->getWidth() / (Real)win->getHeight());
75}
76
77void OverlayWrapper::reposPanel(OverlayElement* oe)
78{
79 if (g_is_scaled)
80 return;
81 oe->setTop(oe->getTop() * (Real)win->getWidth() / (Real)win->getHeight());
82}
83
84void OverlayWrapper::placeNeedle(SceneNode* node, float x, float y, float len)
85{
86 node->setPosition((x - 640.0) / 444.0, (512 - y) / 444.0, -2.0);
87 node->setScale(0.0025, 0.007 * len, 0.007);
88}
89
90Overlay* OverlayWrapper::loadOverlay(String name, bool autoResizeRation)
91{
92 Overlay* o = OverlayManager::getSingleton().getByName(name);
93 if (!o)
94 return NULL;
95
96 if (autoResizeRation)
97 {
98 struct LoadedOverlay lo;
99 lo.o = o;
100 lo.orgScaleX = o->getScaleX();
101 lo.orgScaleY = o->getScaleY();
102
103 m_loaded_overlays.push_back(lo);
104 resizeOverlay(lo);
105 }
106 return o;
107}
108
110{
111 // enforce 4:3 for overlays
112 float w = win->getWidth();
113 float h = win->getHeight();
114 float s = (4.0f / 3.0f) / (w / h);
115
116 // window is higher than wide
117 if (s > 1)
118 s = (3.0f / 4.0f) / (h / w);
119
120 // originals
121 lo.o->setScale(lo.orgScaleX, lo.orgScaleY);
122 lo.o->setScroll(0, 0);
123
124 // now the new values
125 lo.o->setScale(s, s);
126 lo.o->scroll(1 - s, s - 1);
127}
128
130{
131 for (auto it = m_loaded_overlays.begin(); it != m_loaded_overlays.end(); it++)
132 {
133 resizeOverlay(*it);
134 }
135}
136
137OverlayElement* OverlayWrapper::loadOverlayElement(String name)
138{
139 return OverlayManager::getSingleton().getOverlayElement(name);
140}
141
142Ogre::TextureUnitState* GetTexUnit(Ogre::String material_name) // Internal helper
143{
144 return MaterialManager::getSingleton().getByName(material_name)->getTechnique(0)->getPass(0)->getTextureUnitState(0);
145}
146
148{
149 m_machine_dashboard_overlay = loadOverlay("tracks/MachineDashboardOverlay");
150 m_aerial_dashboard.dash_overlay = loadOverlay("tracks/AirDashboardOverlay", false);
151 m_aerial_dashboard.needles_overlay = loadOverlay("tracks/AirNeedlesOverlay", false);
152 m_marine_dashboard_overlay = loadOverlay("tracks/BoatDashboardOverlay");
153 m_marine_dashboard_needles_overlay = loadOverlay("tracks/BoatNeedlesOverlay");
154
155
156 //adjust dashboard size for screen ratio
157 resizePanel(loadOverlayElement("tracks/pressureo"));
158 resizePanel(loadOverlayElement("tracks/pressureneedle"));
159 MaterialPtr m = MaterialManager::getSingleton().getByName("tracks/pressureneedle_mat");
160 if (m)
161 pressuretexture = m->getTechnique(0)->getPass(0)->getTextureUnitState(0);
162 else
163 pressuretexture = nullptr;
164
165 resizePanel(loadOverlayElement("tracks/machineinstructions"));
166 resizePanel(loadOverlayElement("tracks/machinehelppanel"));
167
168 resizePanel(OverlayManager::getSingleton().getOverlayElement("tracks/machinedashbar"));
169 resizePanel(OverlayManager::getSingleton().getOverlayElement("tracks/machinedashfiller"));
170
171 resizePanel(OverlayManager::getSingleton().getOverlayElement("tracks/airdashbar"));
172 resizePanel(OverlayManager::getSingleton().getOverlayElement("tracks/airdashfiller"));
173
174 OverlayElement* tempoe;
175 resizePanel(tempoe = OverlayManager::getSingleton().getOverlayElement("tracks/thrusttrack1"));
176
177 resizePanel(OverlayManager::getSingleton().getOverlayElement("tracks/thrusttrack2"));
178 resizePanel(OverlayManager::getSingleton().getOverlayElement("tracks/thrusttrack3"));
179 resizePanel(OverlayManager::getSingleton().getOverlayElement("tracks/thrusttrack4"));
180
185
186 thrtop = 1.0f + tempoe->getTop() + m_aerial_dashboard.engines[0].thr_element->getHeight() * 0.5f;
187 thrheight = tempoe->getHeight() - m_aerial_dashboard.engines[0].thr_element->getHeight() * 2.0f;
188 throffset = m_aerial_dashboard.engines[0].thr_element->getHeight() * 0.5f;
189
192
193 m_aerial_dashboard.engines[0].Setup("tracks/engfire1", "tracks/thrust1");
194 m_aerial_dashboard.engines[1].Setup("tracks/engfire2", "tracks/thrust2");
195 m_aerial_dashboard.engines[2].Setup("tracks/engfire3", "tracks/thrust3");
196 m_aerial_dashboard.engines[3].Setup("tracks/engfire4", "tracks/thrust4");
197 m_aerial_dashboard.engstarts[0].Setup("tracks/engstart1", "tracks/engstart-on", "tracks/engstart-off");
198 m_aerial_dashboard.engstarts[1].Setup("tracks/engstart2", "tracks/engstart-on", "tracks/engstart-off");
199 m_aerial_dashboard.engstarts[2].Setup("tracks/engstart3", "tracks/engstart-on", "tracks/engstart-off");
200 m_aerial_dashboard.engstarts[3].Setup("tracks/engstart4", "tracks/engstart-on", "tracks/engstart-off");
201 resizePanel(loadOverlayElement("tracks/airrpm1"));
202 resizePanel(loadOverlayElement("tracks/airrpm2"));
203 resizePanel(loadOverlayElement("tracks/airrpm3"));
204 resizePanel(loadOverlayElement("tracks/airrpm4"));
205 resizePanel(loadOverlayElement("tracks/airpitch1"));
206 resizePanel(loadOverlayElement("tracks/airpitch2"));
207 resizePanel(loadOverlayElement("tracks/airpitch3"));
208 resizePanel(loadOverlayElement("tracks/airpitch4"));
209 resizePanel(loadOverlayElement("tracks/airtorque1"));
210 resizePanel(loadOverlayElement("tracks/airtorque2"));
211 resizePanel(loadOverlayElement("tracks/airtorque3"));
212 resizePanel(loadOverlayElement("tracks/airtorque4"));
213 resizePanel(loadOverlayElement("tracks/airspeed"));
214 resizePanel(loadOverlayElement("tracks/vvi"));
215 resizePanel(loadOverlayElement("tracks/altimeter"));
216 resizePanel(loadOverlayElement("tracks/altimeter_val"));
217 m_aerial_dashboard.alt_value_textarea = (TextAreaOverlayElement*)loadOverlayElement("tracks/altimeter_val");
218 boat_depth_value_taoe = (TextAreaOverlayElement*)loadOverlayElement("tracks/boatdepthmeter_val");
219 resizePanel(loadOverlayElement("tracks/adi-tape"));
220 resizePanel(loadOverlayElement("tracks/adi"));
221 resizePanel(loadOverlayElement("tracks/adi-bugs"));
222 m_aerial_dashboard.adibugstexture = GetTexUnit("tracks/adi-bugs");
223 m_aerial_dashboard.aditapetexture = GetTexUnit("tracks/adi-tape");
224 resizePanel(loadOverlayElement("tracks/aoa"));
225 resizePanel(loadOverlayElement("tracks/hsi"));
226 resizePanel(loadOverlayElement("tracks/hsi-rose"));
227 resizePanel(loadOverlayElement("tracks/hsi-bug"));
228 resizePanel(loadOverlayElement("tracks/hsi-v"));
229 resizePanel(loadOverlayElement("tracks/hsi-h"));
230 m_aerial_dashboard.hsirosetexture = GetTexUnit("tracks/hsi-rose");
231 m_aerial_dashboard.hsibugtexture = GetTexUnit("tracks/hsi-bug");
232 m_aerial_dashboard.hsivtexture = GetTexUnit("tracks/hsi-v");
233 m_aerial_dashboard.hsihtexture = GetTexUnit("tracks/hsi-h");
234 //autopilot
235 reposPanel(loadOverlayElement("tracks/ap_hdg_pack"));
236 reposPanel(loadOverlayElement("tracks/ap_wlv_but"));
237 reposPanel(loadOverlayElement("tracks/ap_nav_but"));
238 reposPanel(loadOverlayElement("tracks/ap_alt_pack"));
239 reposPanel(loadOverlayElement("tracks/ap_vs_pack"));
240 reposPanel(loadOverlayElement("tracks/ap_ias_pack"));
241 reposPanel(loadOverlayElement("tracks/ap_gpws_but"));
242 reposPanel(loadOverlayElement("tracks/ap_brks_but"));
243 m_aerial_dashboard.hdg.Setup("tracks/ap_hdg_but", "tracks/hdg-on", "tracks/hdg-off");
244 m_aerial_dashboard.hdg_trim.Setup("tracks/ap_hdg_up", "tracks/ap_hdg_dn", "tracks/ap_hdg_val");
245 m_aerial_dashboard.wlv.Setup("tracks/ap_wlv_but", "tracks/wlv-on", "tracks/wlv-off");
246 m_aerial_dashboard.nav.Setup("tracks/ap_nav_but", "tracks/nav-on", "tracks/nav-off");
247 m_aerial_dashboard.alt.Setup("tracks/ap_alt_but", "tracks/hold-on", "tracks/hold-off");
248 m_aerial_dashboard.alt_trim.Setup("tracks/ap_alt_up", "tracks/ap_alt_dn", "tracks/ap_alt_val");
249 m_aerial_dashboard.vs.Setup("tracks/ap_vs_but", "tracks/vs-on", "tracks/vs-off");
250 m_aerial_dashboard.vs_trim.Setup("tracks/ap_vs_up", "tracks/ap_vs_dn", "tracks/ap_vs_val");
251 m_aerial_dashboard.ias.Setup("tracks/ap_ias_but", "tracks/athr-on", "tracks/athr-off");
252 m_aerial_dashboard.ias_trim.Setup("tracks/ap_ias_up", "tracks/ap_ias_dn", "tracks/ap_ias_val");
253 m_aerial_dashboard.gpws.Setup("tracks/ap_gpws_but", "tracks/gpws-on", "tracks/gpws-off");
254 m_aerial_dashboard.brks.Setup("tracks/ap_brks_but", "tracks/brks-on", "tracks/brks-off");
255
256 //boat
257 resizePanel(loadOverlayElement("tracks/boatdashbar"));
258 resizePanel(loadOverlayElement("tracks/boatdashfiller"));
259 resizePanel(loadOverlayElement("tracks/boatthrusttrack1"));
260 resizePanel(loadOverlayElement("tracks/boatthrusttrack2"));
261
262 //resizePanel(boatmapo=loadOverlayElement("tracks/boatmap"));
263 //resizePanel(boatmapdot=loadOverlayElement("tracks/boatreddot"));
264
265 resizePanel(bthro1 = loadOverlayElement("tracks/boatthrust1"));
266 resizePanel(bthro2 = loadOverlayElement("tracks/boatthrust2"));
267
268 resizePanel(loadOverlayElement("tracks/boatspeed"));
269 resizePanel(loadOverlayElement("tracks/boatsteer"));
270 resizePanel(loadOverlayElement("tracks/boatspeedneedle"));
271 resizePanel(loadOverlayElement("tracks/boatsteer/fg"));
272 boatspeedtexture = ((MaterialPtr)(MaterialManager::getSingleton().getByName("tracks/boatspeedneedle_mat")))->getTechnique(0)->getPass(0)->getTextureUnitState(0);
273 boatsteertexture = ((MaterialPtr)(MaterialManager::getSingleton().getByName("tracks/boatsteer/fg_mat")))->getTechnique(0)->getPass(0)->getTextureUnitState(0);
274
275 //prepare needles
276 speedotexture = ((MaterialPtr)(MaterialManager::getSingleton().getByName("tracks/speedoneedle_mat")))->getTechnique(0)->getPass(0)->getTextureUnitState(0);
277 tachotexture = ((MaterialPtr)(MaterialManager::getSingleton().getByName("tracks/tachoneedle_mat"))) ->getTechnique(0)->getPass(0)->getTextureUnitState(0);
278
279 resizePanel(loadOverlayElement("tracks/airspeedneedle"));
280 m_aerial_dashboard.airspeedtexture = GetTexUnit("tracks/airspeedneedle_mat");
281
282 resizePanel(loadOverlayElement("tracks/altimeterneedle"));
283 m_aerial_dashboard.altimetertexture = GetTexUnit("tracks/altimeterneedle_mat");
284
285 resizePanel(loadOverlayElement("tracks/vvineedle"));
286 m_aerial_dashboard.vvitexture = GetTexUnit("tracks/vvineedle_mat");
287
288 resizePanel(loadOverlayElement("tracks/aoaneedle"));
289 m_aerial_dashboard.aoatexture = GetTexUnit("tracks/aoaneedle_mat");
290
291 resizePanel(loadOverlayElement("tracks/airrpm1needle"));
292 m_aerial_dashboard.engines[0].rpm_texture = GetTexUnit("tracks/airrpm1needle_mat");
293 resizePanel(loadOverlayElement("tracks/airrpm2needle"));
294 m_aerial_dashboard.engines[1].rpm_texture = GetTexUnit("tracks/airrpm2needle_mat");
295 resizePanel(loadOverlayElement("tracks/airrpm3needle"));
296 m_aerial_dashboard.engines[2].rpm_texture = GetTexUnit("tracks/airrpm3needle_mat");
297 resizePanel(loadOverlayElement("tracks/airrpm4needle"));
298 m_aerial_dashboard.engines[3].rpm_texture = GetTexUnit("tracks/airrpm4needle_mat");
299
300 resizePanel(loadOverlayElement("tracks/airpitch1needle"));
301 m_aerial_dashboard.engines[0].pitch_texture = GetTexUnit("tracks/airpitch1needle_mat");
302 resizePanel(loadOverlayElement("tracks/airpitch2needle"));
303 m_aerial_dashboard.engines[1].pitch_texture = GetTexUnit("tracks/airpitch2needle_mat");
304 resizePanel(loadOverlayElement("tracks/airpitch3needle"));
305 m_aerial_dashboard.engines[2].pitch_texture = GetTexUnit("tracks/airpitch3needle_mat");
306 resizePanel(loadOverlayElement("tracks/airpitch4needle"));
307 m_aerial_dashboard.engines[3].pitch_texture = GetTexUnit("tracks/airpitch4needle_mat");
308
309 resizePanel(loadOverlayElement("tracks/airtorque1needle"));
310 m_aerial_dashboard.engines[0].torque_texture = GetTexUnit("tracks/airtorque1needle_mat");
311 resizePanel(loadOverlayElement("tracks/airtorque2needle"));
312 m_aerial_dashboard.engines[1].torque_texture = GetTexUnit("tracks/airtorque2needle_mat");
313 resizePanel(loadOverlayElement("tracks/airtorque3needle"));
314 m_aerial_dashboard.engines[2].torque_texture = GetTexUnit("tracks/airtorque3needle_mat");
315 resizePanel(loadOverlayElement("tracks/airtorque4needle"));
316 m_aerial_dashboard.engines[3].torque_texture = GetTexUnit("tracks/airtorque4needle_mat");
317
318 guiGear = loadOverlayElement("tracks/Gear");
319
320 guiAuto[0] = (TextAreaOverlayElement*)loadOverlayElement("tracks/AGearR");
321 guiAuto[1] = (TextAreaOverlayElement*)loadOverlayElement("tracks/AGearN");
322 guiAuto[2] = (TextAreaOverlayElement*)loadOverlayElement("tracks/AGearD");
323 guiAuto[3] = (TextAreaOverlayElement*)loadOverlayElement("tracks/AGear2");
324 guiAuto[4] = (TextAreaOverlayElement*)loadOverlayElement("tracks/AGear1");
325
326 m_truck_pressure_overlay = loadOverlay("tracks/PressureOverlay");
327 m_truck_pressure_needle_overlay = loadOverlay("tracks/PressureNeedleOverlay");
328
329 m_racing_overlay = loadOverlay("tracks/Racing", false);
330 laptime = (TextAreaOverlayElement*)loadOverlayElement("tracks/Racing/LapTime");
331 bestlaptime = (TextAreaOverlayElement*)loadOverlayElement("tracks/Racing/BestLapTime");
332
333 g_is_scaled = true;
335
336 return 0;
337}
338
340{
341 if (mTimeUntilNextToggle > 0)
343}
344
346{
348 {
349 if (show)
350 {
353 }
354 else
355 {
358 }
359 }
360}
361
366
368{
369 m_dashboard_visible = show;
370
371 // check if we use the new style dashboards
372 if (actor && actor->ar_dashboard && actor->ar_dashboard->wasDashboardHudLoaded())
373 {
374 actor->ar_dashboard->setVisible(show);
375 return;
376 }
377
378 if (show)
379 {
380 int mode = actor ? actor->ar_driveable : -1;
381
382 if (mode == AIRPLANE)
383 {
386 }
387 else if (mode == BOAT)
388 {
391 }
392 else if (mode == MACHINE)
393 {
394 Ogre::OverlayElement* help_elem = OverlayManager::getSingleton().getOverlayElement("tracks/machinehelppanel");
395 if (actor->GetGfxActor()->GetHelpMat())
396 {
397 help_elem->setMaterial(actor->GetGfxActor()->GetHelpMat());
398 }
399 else
400 {
401 help_elem->setMaterialName("tracks/black");
402 }
404 }
405 }
406 else
407 {
410
413
415 }
416}
417
419{
420 static std::string currFps = _L("Current FPS: ");
421 static std::string avgFps = _L("Average FPS: ");
422 static std::string bestFps = _L("Best FPS: ");
423 static std::string worstFps = _L("Worst FPS: ");
424 static std::string tris = _L("Triangle Count: ");
425 const RenderTarget::FrameStats& stats = win->getStatistics();
426
427 // update stats when necessary
428 try
429 {
430 OverlayElement* guiAvg = OverlayManager::getSingleton().getOverlayElement("Core/AverageFps");
431 OverlayElement* guiCurr = OverlayManager::getSingleton().getOverlayElement("Core/CurrFps");
432 OverlayElement* guiBest = OverlayManager::getSingleton().getOverlayElement("Core/BestFps");
433 OverlayElement* guiWorst = OverlayManager::getSingleton().getOverlayElement("Core/WorstFps");
434
435 guiAvg->setCaption(avgFps + TOSTRING(stats.avgFPS));
436 guiCurr->setCaption(currFps + TOSTRING(stats.lastFPS));
437 guiBest->setCaption(bestFps + TOSTRING(stats.bestFPS) + (" ") + TOSTRING(stats.bestFrameTime) + (" ms"));
438 guiWorst->setCaption(worstFps + TOSTRING(stats.worstFPS) + (" ") + TOSTRING(stats.worstFrameTime) + (" ms"));
439
440 OverlayElement* guiTris = OverlayManager::getSingleton().getOverlayElement("Core/NumTris");
441 std::string triss = tris + TOSTRING(stats.triangleCount);
442 if (stats.triangleCount > 1000000)
443 triss = tris + TOSTRING(stats.triangleCount/1000000.0f) + (" M");
444 else if (stats.triangleCount > 1000)
445 triss = tris + TOSTRING(stats.triangleCount/1000.0f) + (" k");
446 guiTris->setCaption(triss);
447
448 // create some memory texts
449 std::string memoryText;
450 if (TextureManager::getSingleton().getMemoryUsage() > 1)
451 memoryText = memoryText + _L("Textures: ") + formatBytes(TextureManager::getSingleton().getMemoryUsage()) + (" / ") + formatBytes(TextureManager::getSingleton().getMemoryBudget()) + ("\n");
452 if (CompositorManager::getSingleton().getMemoryUsage() > 1)
453 memoryText = memoryText + _L("Compositors: ") + formatBytes(CompositorManager::getSingleton().getMemoryUsage()) + (" / ") + formatBytes(CompositorManager::getSingleton().getMemoryBudget()) + ("\n");
454 if (FontManager::getSingleton().getMemoryUsage() > 1)
455 memoryText = memoryText + _L("Fonts: ") + formatBytes(FontManager::getSingleton().getMemoryUsage()) + (" / ") + formatBytes(FontManager::getSingleton().getMemoryBudget()) + ("\n");
456 if (GpuProgramManager::getSingleton().getMemoryUsage() > 1)
457 memoryText = memoryText + _L("GPU Program: ") + formatBytes(GpuProgramManager::getSingleton().getMemoryUsage()) + (" / ") + formatBytes(GpuProgramManager::getSingleton().getMemoryBudget()) + ("\n");
458 if (HighLevelGpuProgramManager::getSingleton().getMemoryUsage() > 1)
459 memoryText = memoryText + _L("HL GPU Program: ") + formatBytes(HighLevelGpuProgramManager::getSingleton().getMemoryUsage()) + (" / ") + formatBytes(HighLevelGpuProgramManager::getSingleton().getMemoryBudget()) + ("\n");
460 if (MaterialManager::getSingleton().getMemoryUsage() > 1)
461 memoryText = memoryText + _L("Materials: ") + formatBytes(MaterialManager::getSingleton().getMemoryUsage()) + (" / ") + formatBytes(MaterialManager::getSingleton().getMemoryBudget()) + ("\n");
462 if (MeshManager::getSingleton().getMemoryUsage() > 1)
463 memoryText = memoryText + _L("Meshes: ") + formatBytes(MeshManager::getSingleton().getMemoryUsage()) + (" / ") + formatBytes(MeshManager::getSingleton().getMemoryBudget()) + ("\n");
464 if (SkeletonManager::getSingleton().getMemoryUsage() > 1)
465 memoryText = memoryText + _L("Skeletons: ") + formatBytes(SkeletonManager::getSingleton().getMemoryUsage()) + (" / ") + formatBytes(SkeletonManager::getSingleton().getMemoryBudget()) + ("\n");
466 if (MaterialManager::getSingleton().getMemoryUsage() > 1)
467 memoryText = memoryText + _L("Materials: ") + formatBytes(MaterialManager::getSingleton().getMemoryUsage()) + (" / ") + formatBytes(MaterialManager::getSingleton().getMemoryBudget()) + ("\n");
468 memoryText = memoryText + ("\n");
469
470 OverlayElement* memoryDbg = OverlayManager::getSingleton().getOverlayElement("Core/MemoryText");
471 memoryDbg->setCaption(memoryText);
472
473 float sumMem = TextureManager::getSingleton().getMemoryUsage() + CompositorManager::getSingleton().getMemoryUsage() + FontManager::getSingleton().getMemoryUsage() + GpuProgramManager::getSingleton().getMemoryUsage() + HighLevelGpuProgramManager::getSingleton().getMemoryUsage() + MaterialManager::getSingleton().getMemoryUsage() + MeshManager::getSingleton().getMemoryUsage() + SkeletonManager::getSingleton().getMemoryUsage() + MaterialManager::getSingleton().getMemoryUsage();
474 String sumMemoryText = _L("Memory (Ogre): ") + formatBytes(sumMem) + ("\n");
475
476 OverlayElement* memorySumDbg = OverlayManager::getSingleton().getOverlayElement("Core/CurrMemory");
477 memorySumDbg->setCaption(sumMemoryText);
478 }
479 catch (...)
480 {
481 // ignore
482 }
483}
484
486{
487 ActorPtr player_actor = App::GetGameContext()->GetPlayerActor();
488 if (!player_actor
489 || !m_aerial_dashboard.needles_overlay->isVisible()
491 return false;
492
493 // IMPORTANT: get mouse button state from InputEngine, not from OIS directly
494 // - that state may be dirty, see commentary in `InputEngine::getMouseState()`
495 const OIS::MouseState ms = App::GetInputEngine()->getMouseState();
496 bool res = false;
497 if (player_actor->ar_driveable == AIRPLANE && ms.buttonDown(OIS::MB_Left))
498 {
499 const int num_engines = std::min(4, player_actor->ar_num_aeroengines);
500
501 OverlayElement* element = m_aerial_dashboard.hovered_widget->GetHoveredElement();
502 if (element)
503 {
504 res = true;
505 for (int i = 0; i < num_engines; ++i)
506 {
507 if (element == m_aerial_dashboard.engines[i].thr_element)
508 {
510 }
511 }
512
513 for (int i = 0; i < num_engines; ++i)
514 {
515 if (element == m_aerial_dashboard.engstarts[i].element)
516 {
517 player_actor->ar_aeroengines[i]->flipStart();
518 }
519 }
520
521 if (player_actor->ar_autopilot && mTimeUntilNextToggle <= 0)
522 {
523 //heading group
524 if (element == m_aerial_dashboard.hdg.element)
525 {
528 }
529 if (element == m_aerial_dashboard.wlv.element)
530 {
533 }
534 if (element == m_aerial_dashboard.nav.element)
535 {
538 }
539 //altitude group
540 if (element == m_aerial_dashboard.alt.element)
541 {
544 }
545 if (element == m_aerial_dashboard.vs.element)
546 {
549 }
550 //IAS
551 if (element == m_aerial_dashboard.ias.element)
552 {
554 player_actor->ar_autopilot->toggleIAS();
555 }
556 //GPWS
557 if (element == m_aerial_dashboard.gpws.element)
558 {
560 player_actor->ar_autopilot->toggleGPWS();
561 }
562 //BRKS
563 if (element == m_aerial_dashboard.brks.element)
564 {
566 player_actor->parkingbrakeToggle();
567 }
568 //trims
570 {
572 player_actor->ar_autopilot->adjHDG(1);
573 }
575 {
577 player_actor->ar_autopilot->adjHDG(-1);
578 }
580 {
582 player_actor->ar_autopilot->adjALT(100);
583 }
585 {
587 player_actor->ar_autopilot->adjALT(-100);
588 }
589 if (element == m_aerial_dashboard.vs_trim.up_button)
590 {
592 player_actor->ar_autopilot->adjVS(100);
593 }
594 if (element == m_aerial_dashboard.vs_trim.dn_button)
595 {
597 player_actor->ar_autopilot->adjVS(-100);
598 }
600 {
602 player_actor->ar_autopilot->adjIAS(1);
603 }
605 {
607 player_actor->ar_autopilot->adjIAS(-1);
608 }
609 }
610 }
611 }
612 return res;
613}
614
616{
617 ActorPtr player_actor = App::GetGameContext()->GetPlayerActor();
618 if (!player_actor || !m_aerial_dashboard.needles_overlay->isVisible())
619 return false;
620
621 const Ogre::Vector2 mousepos = App::GetInputEngine()->getMouseNormalizedScreenPos();
622
623 // Update mouse drag if ongoing
625 {
626 const int num_engines = std::min(4, player_actor->ar_num_aeroengines);
627 float thr_value = 1.0f - ((mousepos.y - thrtop - throffset) / thrheight);
628 for (int i = 0; i < num_engines; ++i)
629 {
631 {
632 player_actor->ar_aeroengines[i]->setThrottle(thr_value);
633 }
634 }
635 return true;
636 }
637
638 // Just detect mouse hover
640
641 return false;
642}
643
645{
646 // IMPORTANT: get mouse button state from InputEngine, not from OIS directly
647 // - that state may be dirty, see commentary in `InputEngine::getMouseState()`
648 const OIS::MouseState ms = App::GetInputEngine()->getMouseState();
649
650 if (!ms.buttonDown(OIS::MB_Left))
651 {
653 }
654
655 return false;
656}
657
659{
661 {
662 this->showPressureOverlay(true);
663 const float pressure = ga->GetSimDataBuffer().simbuf_tyre_pressure;
664 Real angle = 135.0 - pressure * 2.7;
665 pressuretexture->setTextureRotate(Degree(angle));
666 }
667 else
668 {
669 this->showPressureOverlay(false);
670 }
671}
672
674{
675 // gears
676 int vehicle_getgear = ga->GetSimDataBuffer().simbuf_gear;
677 if (vehicle_getgear > 0)
678 {
679 size_t numgears = ga->GetSimDataBuffer().simbuf_num_gears;
680 String gearstr = TOSTRING(vehicle_getgear) + "/" + TOSTRING(numgears);
681 guiGear->setCaption(gearstr);
682 }
683 else if (vehicle_getgear == 0)
684 {
685 guiGear->setCaption("N");
686 }
687 else
688 {
689 guiGear->setCaption("R");
690 }
691
692 //autogears
693 int cg = ga->GetSimDataBuffer().simbuf_autoshift;
694 for (int i = 0; i < 5; i++)
695 {
696 if (i == cg)
697 {
698 if (i == 1)
699 {
700 guiAuto[i]->setColourTop(ColourValue(1.0, 0.2, 0.2, 1.0));
701 guiAuto[i]->setColourBottom(ColourValue(0.8, 0.1, 0.1, 1.0));
702 }
703 else
704 {
705 guiAuto[i]->setColourTop(ColourValue(1.0, 1.0, 1.0, 1.0));
706 guiAuto[i]->setColourBottom(ColourValue(0.8, 0.8, 0.8, 1.0));
707 }
708 }
709 else
710 {
711 if (i == 1)
712 {
713 guiAuto[i]->setColourTop(ColourValue(0.4, 0.05, 0.05, 1.0));
714 guiAuto[i]->setColourBottom(ColourValue(0.3, 0.02, 0.2, 1.0));
715 }
716 else
717 {
718 guiAuto[i]->setColourTop(ColourValue(0.4, 0.4, 0.4, 1.0));
719 guiAuto[i]->setColourBottom(ColourValue(0.3, 0.3, 0.3, 1.0));
720 }
721 }
722 }
723
724 // speedo / calculate speed
725 Real guiSpeedFactor = 7.0 * (140.0 / ga->GetSimDataBuffer().simbuf_speedo_highest_kph);
726 Real angle = 140 - fabs(ga->GetSimDataBuffer().simbuf_wheel_speed * guiSpeedFactor);
727 angle = std::max(-140.0f, angle);
728 speedotexture->setTextureRotate(Degree(angle));
729
730 // calculate tach stuff
731 Real tachoFactor = 0.072;
733 {
734 tachoFactor = 0.072 * (3500 / ga->GetSimDataBuffer().simbuf_engine_max_rpm);
735 }
736 angle = 126.0 - fabs(ga->GetSimDataBuffer().simbuf_engine_rpm * tachoFactor);
737 angle = std::max(-120.0f, angle);
738 angle = std::min(angle, 121.0f);
739 tachotexture->setTextureRotate(Degree(angle));
740}
741
743{
744 RoR::ActorSB& simbuf = gfx_actor->GetSimDataBuffer();
745 RoR::NodeSB* nodes = gfx_actor->GetSimNodeBuffer();
746
747 auto const& simbuf_ae = simbuf.simbuf_aeroengines;
748 int num_ae = static_cast<int>( simbuf_ae.size() );
749
750 //throttles
751 m_aerial_dashboard.SetThrottle(0, true, simbuf_ae[0].simbuf_ae_throttle);
752 m_aerial_dashboard.SetThrottle(1, (num_ae > 1), (num_ae > 1) ? simbuf_ae[1].simbuf_ae_throttle : 0.f);
753 m_aerial_dashboard.SetThrottle(2, (num_ae > 2), (num_ae > 2) ? simbuf_ae[2].simbuf_ae_throttle : 0.f);
754 m_aerial_dashboard.SetThrottle(3, (num_ae > 3), (num_ae > 3) ? simbuf_ae[3].simbuf_ae_throttle : 0.f);
755
756 //fire
757 m_aerial_dashboard.SetEngineFailed(0, simbuf_ae[0].simbuf_ae_failed);
758 m_aerial_dashboard.SetEngineFailed(1, num_ae > 1 && simbuf_ae[1].simbuf_ae_failed);
759 m_aerial_dashboard.SetEngineFailed(2, num_ae > 2 && simbuf_ae[2].simbuf_ae_failed);
760 m_aerial_dashboard.SetEngineFailed(3, num_ae > 3 && simbuf_ae[3].simbuf_ae_failed);
761
762 //airspeed
763 float angle = 0.0;
764 float ground_speed_kt = simbuf.simbuf_node0_velo.length() * 1.9438; // 1.943 = m/s in knots/s
765
766 //tropospheric model valid up to 11.000m (33.000ft)
767 float altitude = nodes[0].AbsPosition.y;
768 //float sea_level_temperature=273.15+15.0; //in Kelvin
769 float sea_level_pressure = 101325; //in Pa
770 //float airtemperature=sea_level_temperature-altitude*0.0065; //in Kelvin
771 float airpressure = sea_level_pressure * pow(1.0 - 0.0065 * altitude / 288.15, 5.24947); //in Pa
772 float airdensity = airpressure * 0.0000120896;//1.225 at sea level
773
774 float kt = ground_speed_kt * sqrt(airdensity / 1.225); //KIAS
775 if (kt > 23.0)
776 {
777 if (kt < 50.0)
778 angle = ((kt - 23.0) / 1.111);
779 else if (kt < 100.0)
780 angle = (24.0 + (kt - 50.0) / 0.8621);
781 else if (kt < 300.0)
782 angle = (82.0 + (kt - 100.0) / 0.8065);
783 else
784 angle = 329.0;
785 }
786 m_aerial_dashboard.airspeedtexture->setTextureRotate(Degree(-angle));
787
788 // AOA
789 angle = simbuf.simbuf_wing4_aoa;
790 if (kt < 10.0)
791 angle = 0;
792 float absangle = angle;
793 if (absangle < 0)
794 absangle = -absangle;
795
796 const int actor_id = gfx_actor->GetActorId();
797 SOUND_MODULATE(actor_id, SS_MOD_AOA, absangle);
798 if (absangle > 18.0) // TODO: magicccc
799 SOUND_START(actor_id, SS_TRIG_AOA);
800 else
801 SOUND_STOP(actor_id, SS_TRIG_AOA);
802
803 if (angle > 25.0)
804 angle = 25.0;
805 if (angle < -25.0)
806 angle = -25.0;
807 m_aerial_dashboard.aoatexture->setTextureRotate(Degree(-angle * 4.7 + 90.0));
808
809 // altimeter
810 angle = nodes[0].AbsPosition.y * 1.1811;
811 m_aerial_dashboard.altimetertexture->setTextureRotate(Degree(-angle));
812 char altc[10];
813 sprintf(altc, "%03u", (int)(nodes[0].AbsPosition.y / 30.48));
814 m_aerial_dashboard.alt_value_textarea->setCaption(altc);
815
816 //adi
817 //roll
818 Vector3 rollv = nodes[simbuf.simbuf_camera0_pos_node].AbsPosition - nodes[simbuf.simbuf_camera0_roll_node].AbsPosition;
819 rollv.normalise();
820 float rollangle = asin(rollv.dotProduct(Vector3::UNIT_Y));
821
822 //pitch
823 Vector3 dirv = simbuf.simbuf_direction;
824 float pitchangle = asin(dirv.dotProduct(Vector3::UNIT_Y));
825 Vector3 upv = dirv.crossProduct(-rollv);
826 if (upv.y < 0)
827 rollangle = 3.14159 - rollangle;
828 m_aerial_dashboard.adibugstexture->setTextureRotate(Radian(-rollangle));
829 m_aerial_dashboard.aditapetexture->setTextureVScroll(-pitchangle * 0.25);
830 m_aerial_dashboard.aditapetexture->setTextureRotate(Radian(-rollangle));
831
832 //hsi
833 float dirangle = atan2(dirv.dotProduct(Vector3::UNIT_X), dirv.dotProduct(-Vector3::UNIT_Z));
834 m_aerial_dashboard.hsirosetexture->setTextureRotate(Radian(dirangle));
835
836 //autopilot
837 m_aerial_dashboard.hsibugtexture->setTextureRotate(Radian(dirangle) - Degree(simbuf.simbuf_ap_heading_value));
838
839 float vdev = 0;
840 float hdev = 0;
841 if (simbuf.simbuf_ap_ils_available)
842 {
843 vdev = simbuf.simbuf_ap_ils_vdev;
844 hdev = simbuf.simbuf_ap_ils_hdev;
845 }
846 if (hdev > 15)
847 hdev = 15;
848 if (hdev < -15)
849 hdev = -15;
850 m_aerial_dashboard.hsivtexture->setTextureUScroll(-hdev * 0.02);
851 if (vdev > 15)
852 vdev = 15;
853 if (vdev < -15)
854 vdev = -15;
855 m_aerial_dashboard.hsihtexture->setTextureVScroll(-vdev * 0.02);
856
857 //vvi
858 float vvi = simbuf.simbuf_node0_velo.y * 196.85;
859 if (vvi < 1000.0 && vvi > -1000.0)
860 angle = vvi * 0.047;
861 if (vvi > 1000.0 && vvi < 6000.0)
862 angle = 47.0 + (vvi - 1000.0) * 0.01175;
863 if (vvi > 6000.0)
864 angle = 105.75;
865 if (vvi < -1000.0 && vvi > -6000.0)
866 angle = -47.0 + (vvi + 1000.0) * 0.01175;
867 if (vvi < -6000.0)
868 angle = -105.75;
869 m_aerial_dashboard.vvitexture->setTextureRotate(Degree(-angle + 90.0));
870
871 const bool is_prop = simbuf_ae[0].simbuf_ae_type == AeroEngineType::AE_XPROP;
872
873 //rpm
874 m_aerial_dashboard.SetEngineRpm(0, simbuf_ae[0].simbuf_ae_rpmpc);
875 m_aerial_dashboard.SetEngineRpm(1, (num_ae > 1) ? simbuf_ae[1].simbuf_ae_rpmpc : 0.f);
876 m_aerial_dashboard.SetEngineRpm(2, (num_ae > 2) ? simbuf_ae[2].simbuf_ae_rpmpc : 0.f);
877 m_aerial_dashboard.SetEngineRpm(3, (num_ae > 3) ? simbuf_ae[3].simbuf_ae_rpmpc : 0.f);
878
879 //turboprops - pitch
880 m_aerial_dashboard.SetEnginePitch(0, (is_prop) ? simbuf_ae[0].simbuf_tp_aepitch : 0.f);
881 m_aerial_dashboard.SetEnginePitch(1, (num_ae > 1 && is_prop) ? simbuf_ae[1].simbuf_tp_aepitch : 0.f);
882 m_aerial_dashboard.SetEnginePitch(2, (num_ae > 2 && is_prop) ? simbuf_ae[2].simbuf_tp_aepitch : 0.f);
883 m_aerial_dashboard.SetEnginePitch(3, (num_ae > 3 && is_prop) ? simbuf_ae[3].simbuf_tp_aepitch : 0.f);
884
885 //turboprops - torque
886 m_aerial_dashboard.SetEngineTorque(0, (is_prop) ? simbuf_ae[0].simbuf_tp_aetorque : 0.f);
887 m_aerial_dashboard.SetEngineTorque(1, (num_ae > 1 && is_prop) ? simbuf_ae[1].simbuf_tp_aetorque : 0.f);
888 m_aerial_dashboard.SetEngineTorque(2, (num_ae > 2 && is_prop) ? simbuf_ae[2].simbuf_tp_aetorque : 0.f);
889 m_aerial_dashboard.SetEngineTorque(3, (num_ae > 3 && is_prop) ? simbuf_ae[3].simbuf_tp_aetorque : 0.f);
890
891 //starters
892 m_aerial_dashboard.SetIgnition(0, true, simbuf_ae[0].simbuf_ae_ignition);
893 m_aerial_dashboard.SetIgnition(1, num_ae > 1, num_ae > 1 && simbuf_ae[1].simbuf_ae_ignition);
894 m_aerial_dashboard.SetIgnition(2, num_ae > 2, num_ae > 2 && simbuf_ae[2].simbuf_ae_ignition);
895 m_aerial_dashboard.SetIgnition(3, num_ae > 3, num_ae > 3 && simbuf_ae[3].simbuf_ae_ignition);
896
897 //autopilot - heading
901
902 //autopilot - altitude
905
906 //autopilot - other buttons
910
911 //autopilot - trims
915 if (simbuf.simbuf_ap_vs_value == 0)
916 m_aerial_dashboard.vs_trim.display->setCaption("000");
917 else if (simbuf.simbuf_ap_vs_value < 0)
919 else
921}
922
924{
925 // throttles
926 bthro1->setTop(thrtop + thrheight * (0.5 - vehicle->ar_screwprops[0]->getThrottle() / 2.0) - 1.0);
927 if (vehicle->ar_num_screwprops > 1)
928 {
929 bthro2->setTop(thrtop + thrheight * (0.5 - vehicle->ar_screwprops[1]->getThrottle() / 2.0) - 1.0);
930 }
931
932 // depth
933 char tmp[50] = "";
934 float height = vehicle->getHeightAboveGround();
935 if (height > 0.1 && height < 99.9)
936 {
937 sprintf(tmp, "%2.1f", height);
938 boat_depth_value_taoe->setCaption(tmp);
939 }
940 else
941 {
942 boat_depth_value_taoe->setCaption("--.-");
943 }
944
945 // water speed
946 Vector3 cam_dir = vehicle->getDirection();
947 Vector3 velocity = vehicle->ar_nodes[vehicle->ar_main_camera_node_pos].Velocity;
948 float kt = cam_dir.dotProduct(velocity) * 1.9438;
949 float angle = kt * 4.2;
950 boatspeedtexture->setTextureRotate(Degree(-angle));
951 boatsteertexture->setTextureRotate(Degree(vehicle->ar_screwprops[0]->getRudder() * 170));
952}
953
958
963
965{
966 float time = gs->GetSimDataBuffer().simbuf_race_time;
967 std::string txt = StringUtil::format("%.2i'%.2i.%.2i", (int)(time) / 60, (int)(time) % 60, (int)(time * 100.0) % 100);
968 this->laptime->setCaption(txt);
970 {
972 txt = StringUtil::format("%.2i'%.2i.%.2i", (int)(time) / 60, (int)(time) % 60, (int)(time * 100.0) % 100);
973 this->bestlaptime->setCaption(txt);
974 this->bestlaptime->show();
975 }
976 else
977 {
978 this->bestlaptime->hide();
979 }
980
981 float time_diff = gs->GetSimDataBuffer().simbuf_race_time_diff;
982 Ogre::ColourValue colour = Ogre::ColourValue::White;
983 if (time_diff > 0.0f)
984 {
985 colour = ColourValue(0.8, 0.0, 0.0);
986 }
987 else if (time_diff < 0.0f)
988 {
989 colour = ColourValue(0.0, 0.8, 0.0);
990 }
991 this->laptime->setColourTop(colour);
992 this->laptime->setColourBottom(colour);
993}
994
995void AeroDashOverlay::SetThrottle(int engine, bool visible, float value)
996{
997 if (visible)
998 {
999 engines[engine].thr_element->show();
1000 engines[engine].thr_element->setTop(
1001 thrust_track_top + thrust_track_height * (1.0 - value) - 1.0);
1002 }
1003 else
1004 {
1005 engines[engine].thr_element->hide();
1006 }
1007}
1008
1009void AeroDashOverlay::SetEngineFailed(int engine, bool value)
1010{
1011 engines[engine].engfire_element->setMaterialName(
1012 value ? "tracks/engfire-on" : "tracks/engfire-off");
1013}
1014
1015void AeroDashOverlay::SetEngineRpm(int engine, float pcent)
1016{
1017 float angle;
1018 if (pcent < 60.0)
1019 angle = -5.0 + pcent * 1.9167;
1020 else if (pcent < 110.0)
1021 angle = 110.0 + (pcent - 60.0) * 4.075;
1022 else
1023 angle = 314.0;
1024 engines[engine].rpm_texture->setTextureRotate(Ogre::Degree(-angle));
1025}
1026
1027void AeroDashOverlay::SetEnginePitch(int engine, float value)
1028{
1029 engines[engine].pitch_texture->setTextureRotate(Degree(-value * 2.0));
1030}
1031
1032void AeroDashOverlay::SetEngineTorque(int engine, float pcent)
1033{
1034 float angle;
1035 if (pcent < 60.0)
1036 angle = -5.0 + pcent * 1.9167;
1037 else if (pcent < 110.0)
1038 angle = 110.0 + (pcent - 60.0) * 4.075;
1039 else
1040 angle = 314.0;
1041 engines[engine].torque_texture->setTextureRotate(Degree(-angle));
1042}
1043
1044void AeroDashOverlay::SetIgnition(int engine, bool visible, bool ignited)
1045{
1046 if (visible)
1047 {
1048 engstarts[engine].element->show();
1049 engstarts[engine].SetActive(ignited);
1050 }
1051 else
1052 {
1053 engstarts[engine].element->hide();
1054 }
1055}
1056
1057// -----------------
1058// AeroEngineOverlay
1059
1060void AeroEngineWidget::Setup(std::string const& engfire_elemname, std::string const& thr_elemname)
1061{
1062 // Because highlighting works on per-material basis, we must clone the material for each element
1063 engfire_element = Ogre::OverlayManager::getSingleton().getOverlayElement(engfire_elemname);
1064 thr_element = Ogre::OverlayManager::getSingleton().getOverlayElement(thr_elemname);
1065 thr_material = thr_element->getMaterial()->clone(thr_element->getMaterial()->getName() + "@" + thr_elemname);
1066 thr_element->setMaterial(thr_material);
1067}
1068
1070{
1071 // Remove cloned materials
1072 Ogre::MaterialManager::getSingleton().remove(thr_material);
1073}
1074
1076{
1077 const Ogre::Vector2 mouse_pos = App::GetInputEngine()->getMouseNormalizedScreenPos();
1078 bool retval = false;
1079 if (retval = thr_element->contains(mouse_pos.x, mouse_pos.y))
1080 {
1082 }
1083 else
1084 {
1086 }
1087 return retval;
1088}
1089
1090Ogre::OverlayElement* AeroEngineWidget::GetHoveredElement() const
1091{
1092 return thr_element;
1093}
1094
1095// ---------------
1096// AeroSwitchOverlay
1097
1099{
1100 element->setMaterial(value ? on_material : off_material);
1101}
1102
1103void AeroSwitchWidget::Setup(std::string const & elem_name, std::string const & mat_on, std::string const & mat_off)
1104{
1105 // Because highlighting works on per-material basis, we must clone the material for each element
1106 element = Ogre::OverlayManager::getSingleton().getOverlayElement(elem_name);
1107 on_material = Ogre::MaterialManager::getSingleton().getByName(mat_on)->clone(elem_name + "@" + mat_on);
1108 off_material = Ogre::MaterialManager::getSingleton().getByName(mat_off)->clone(elem_name + "@" + mat_off);
1109}
1110
1112{
1113 // Remove cloned materials
1114 Ogre::MaterialManager::getSingleton().remove(on_material);
1115 Ogre::MaterialManager::getSingleton().remove(off_material);
1116}
1117
1119{
1120 // Element's current material switches dynamically based on game state, we must always sync both variants.
1121 const Ogre::Vector2 mouse_pos = App::GetInputEngine()->getMouseNormalizedScreenPos();
1122 bool retval = false;
1123 if (retval = element->contains(mouse_pos.x, mouse_pos.y))
1124 {
1127 }
1128 else
1129 {
1132 }
1133 return retval;
1134}
1135
1136Ogre::OverlayElement* AeroSwitchWidget::GetHoveredElement() const
1137{
1138 return element;
1139}
1140
1141// ---------------
1142// AeroTrimOverlay
1143
1144void AeroTrimWidget::Setup(std::string const & up, std::string const & dn, std::string const & disp)
1145{
1146 // Because highlighting works on per-material basis, we must clone the material for each element
1147 display = Ogre::OverlayManager::getSingleton().getOverlayElement(disp);
1148 up_button = Ogre::OverlayManager::getSingleton().getOverlayElement(up);
1149 up_material = up_button->getMaterial()->clone(up + "$" + disp);
1150 up_button->setMaterial(up_material);
1151 dn_button = Ogre::OverlayManager::getSingleton().getOverlayElement(dn);
1152 down_material = dn_button->getMaterial()->clone(dn + "$" + disp);
1153 dn_button->setMaterial(down_material);
1154}
1155
1157{
1158 // Remove cloned materials
1159 Ogre::MaterialManager::getSingleton().remove(up_material);
1160 Ogre::MaterialManager::getSingleton().remove(down_material);
1161}
1162
1164{
1165 const Ogre::Vector2 mouse_pos = App::GetInputEngine()->getMouseNormalizedScreenPos();
1166
1167 bool retval = false;
1168 if (retval = up_button->contains(mouse_pos.x, mouse_pos.y))
1169 {
1173 }
1174 else if (retval = dn_button->contains(mouse_pos.x, mouse_pos.y))
1175 {
1179 }
1180 else
1181 {
1182 hovered_button = nullptr;
1185 }
1186 return retval;
1187}
1188
1189Ogre::OverlayElement* AeroTrimWidget::GetHoveredElement() const
1190{
1191 return hovered_button;
1192}
1193
1194void AeroTrimWidget::DisplayFormat(const char* fmt, ...)
1195{
1196 char buffer[500] = {};
1197
1198 va_list args;
1199 va_start(args, fmt);
1200 vsprintf(buffer, fmt, args);
1201 va_end(args);
1202
1203 display->setCaption(buffer);
1204}
1205
1206// ---------------------
1207// AeroDashOverlay
1208
1209void AeroDashOverlay::SetMaterialHighlighted(Ogre::MaterialPtr mat, bool val)
1210{
1211 // Use texture blending to 'highlight' the hovered element
1212 // doc: https://ogrecave.github.io/ogre/api/13/_material-_scripts.html#autotoc_md169
1213 // -------------------------------------------------------
1214
1215 if (!val)
1216 {
1217 // reset to defaults
1218 mat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setColourOperationEx(
1219 Ogre::LBX_MODULATE, Ogre::LBS_TEXTURE, Ogre::LBS_CURRENT);
1220 }
1221 else
1222 {
1223 // set blend mode to 'add' with a custom colour
1224 mat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setColourOperationEx(
1225 Ogre::LBX_ADD, Ogre::LBS_TEXTURE, Ogre::LBS_MANUAL, Ogre::ColourValue::White, ColourValue(0.32, 0.3, 0.25));
1226 }
1227}
1228
1230{
1231 // Throttles
1232 aero_widgets.push_back(&engines[0]);
1233 aero_widgets.push_back(&engines[1]);
1234 aero_widgets.push_back(&engines[2]);
1235 aero_widgets.push_back(&engines[3]);
1236
1237 // Engine start switches
1238 aero_widgets.push_back(&engstarts[0]);
1239 aero_widgets.push_back(&engstarts[1]);
1240 aero_widgets.push_back(&engstarts[2]);
1241 aero_widgets.push_back(&engstarts[3]);
1242
1243 // Switches
1244 aero_widgets.push_back(&hdg );
1245 aero_widgets.push_back(&wlv );
1246 aero_widgets.push_back(&nav );
1247 aero_widgets.push_back(&alt );
1248 aero_widgets.push_back(&vs );
1249 aero_widgets.push_back(&ias );
1250 aero_widgets.push_back(&gpws );
1251 aero_widgets.push_back(&brks );
1252
1253 // Trims
1254 aero_widgets.push_back(&hdg_trim);
1255 aero_widgets.push_back(&alt_trim);
1256 aero_widgets.push_back(&vs_trim);
1257 aero_widgets.push_back(&ias_trim);
1258}
1259
1261{
1262 hovered_widget = nullptr;
1263 for (auto elem : aero_widgets)
1264 {
1265 if (elem->UpdateMouseHover())
1266 {
1267 hovered_widget = elem;
1268 }
1269 }
1270}
1271
1272
System integration layer; inspired by OgreBites::ApplicationContext.
#define TOSTRING(x)
Definition Application.h:58
#define _L
Game state manager and message-queue provider.
Manager for all visuals belonging to a single actor.
bool g_is_scaled
Ogre::TextureUnitState * GetTexUnit(Ogre::String material_name)
#define SOUND_START(_ACTOR_, _TRIG_)
#define SOUND_STOP(_ACTOR_, _TRIG_)
#define SOUND_MODULATE(_ACTOR_, _MOD_, _VALUE_)
int ar_num_screwprops
Definition Actor.h:426
DashBoardManagerPtr ar_dashboard
Gfx state; Dashboard manager (HUD element manager)
Definition Actor.h:563
node_t * ar_nodes
Definition Actor.h:365
GfxActor * GetGfxActor()
Definition Actor.h:344
ScrewpropPtr ar_screwprops[MAX_SCREWPROPS]
Definition Actor.h:425
NodeNum_t ar_main_camera_node_pos
Sim attr; ar_camera_node_pos[0] >= 0 ? ar_camera_node_pos[0] : 0.
Definition Actor.h:476
float getHeightAboveGround(bool skip_virtual_nodes=true)
Definition Actor.cpp:1594
Ogre::Vector3 getDirection()
average actor velocity, calculated using the actor positions of the last two frames
Definition Actor.cpp:365
AeroEnginePtr ar_aeroengines[MAX_AEROENGINES]
Definition Actor.h:423
int ar_num_aeroengines
Definition Actor.h:424
void parkingbrakeToggle()
Definition Actor.cpp:3952
AutopilotPtr ar_autopilot
Definition Actor.h:470
ActorType ar_driveable
Sim attr; marks vehicle type and features.
Definition Actor.h:466
virtual void setThrottle(float val)=0
virtual void flipStart()=0
Ogre::RenderWindow * GetRenderWindow()
Definition AppContext.h:70
int toggleHeading(int mode)
int adjALT(int d)
int adjIAS(int d)
int adjVS(int d)
int adjHDG(int d)
int toggleAlt(int mode)
void setVisible(bool visibility)
bool wasDashboardHudLoaded() const
const ActorPtr & GetPlayerActor()
Ogre::MaterialPtr GetHelpMat()
Definition GfxActor.h:147
ActorSB & GetSimDataBuffer()
Definition GfxActor.h:125
NodeSB * GetSimNodeBuffer()
Definition GfxActor.h:126
int GetActorId() const
Provides a 3D graphical representation of the simulation Idea: simulation runs at it's own constant r...
Definition GfxScene.h:47
GameContextSB & GetSimDataBuffer()
Definition GfxScene.h:80
OIS::MouseState getMouseState()
Ogre::Vector2 getMouseNormalizedScreenPos()
Returns XY position in range from 0 (top/left) to 1 (bottom/right)
void resizeOverlay(LoadedOverlay &overlay)
Ogre::TextAreaOverlayElement * boat_depth_value_taoe
Marine.
std::vector< LoadedOverlay > m_loaded_overlays
Ogre::RenderWindow * win
Ogre::Overlay * loadOverlay(Ogre::String name, bool autoResizeRation=true)
void UpdateMarineHUD(ActorPtr vehicle)
Ogre::Overlay * m_racing_overlay
Ogre::TextureUnitState * speedotexture
void showPressureOverlay(bool show)
void UpdatePressureOverlay(RoR::GfxActor *ga)
Ogre::TextureUnitState * boatspeedtexture
void UpdateRacingGui(RoR::GfxScene *gs)
void UpdateLandVehicleHUD(RoR::GfxActor *ga)
void placeNeedle(Ogre::SceneNode *node, float x, float y, float len)
Ogre::TextureUnitState * boatsteertexture
Ogre::OverlayElement * guiGear
Ogre::Overlay * m_marine_dashboard_needles_overlay
Ogre::OverlayElement * bthro2
Ogre::Overlay * m_truck_pressure_needle_overlay
Ogre::OverlayElement * bthro1
AeroDashOverlay m_aerial_dashboard
Ogre::TextureUnitState * tachotexture
Ogre::OverlayElement * loadOverlayElement(Ogre::String name)
void showDashboardOverlays(bool show, ActorPtr actor)
Ogre::TextAreaOverlayElement * bestlaptime
Ogre::TextAreaOverlayElement * guiAuto[5]
Ogre::Overlay * m_marine_dashboard_overlay
Ogre::TextAreaOverlayElement * laptime
Ogre::Overlay * m_truck_pressure_overlay
Ogre::Overlay * m_machine_dashboard_overlay
Ogre::TextureUnitState * pressuretexture
void reposPanel(Ogre::OverlayElement *oe)
void resizePanel(Ogre::OverlayElement *oe)
void UpdateAerialHUD(RoR::GfxActor *ga)
void updateStats(bool detailed=false)
void ToggleDashboardOverlays(ActorPtr actor)
float getRudder()
float getThrottle()
@ MACHINE
its a machine
Definition SimData.h:88
@ BOAT
its a boat
Definition SimData.h:87
@ AIRPLANE
its an airplane
Definition SimData.h:86
AppContext * GetAppContext()
InputEngine * GetInputEngine()
GameContext * GetGameContext()
std::string formatBytes(double bytes)
Definition Utils.cpp:67
int simbuf_ap_alt_value
Definition SimBuffers.h:184
int simbuf_num_gears
Gearbox.
Definition SimBuffers.h:157
int simbuf_ap_ias_value
Definition SimBuffers.h:186
bool simbuf_ap_ias_mode
Definition SimBuffers.h:185
Ogre::Vector3 simbuf_node0_velo
Definition SimBuffers.h:124
bool simbuf_tyre_pressurizing
Definition SimBuffers.h:163
int simbuf_ap_heading_mode
Definition SimBuffers.h:181
float simbuf_ap_ils_vdev
Definition SimBuffers.h:189
float simbuf_engine_rpm
Definition SimBuffers.h:148
int simbuf_ap_heading_value
Definition SimBuffers.h:182
int simbuf_ap_vs_value
Definition SimBuffers.h:191
float simbuf_ap_ils_hdev
Definition SimBuffers.h:190
float simbuf_wheel_speed
Definition SimBuffers.h:127
float simbuf_wing4_aoa
Definition SimBuffers.h:177
float simbuf_speedo_highest_kph
Definition SimBuffers.h:194
bool simbuf_speedo_use_engine_max_rpm
Definition SimBuffers.h:195
std::vector< AeroEngineSB > simbuf_aeroengines
Definition SimBuffers.h:138
bool simbuf_ap_ils_available
Definition SimBuffers.h:188
float simbuf_tyre_pressure
Definition SimBuffers.h:162
float simbuf_engine_max_rpm
Definition SimBuffers.h:158
NodeNum_t simbuf_camera0_pos_node
Definition SimBuffers.h:130
bool simbuf_parking_brake
Definition SimBuffers.h:168
NodeNum_t simbuf_camera0_roll_node
Definition SimBuffers.h:131
Ogre::Vector3 simbuf_direction
Output of Actor::getDirection()
Definition SimBuffers.h:126
bool simbuf_ap_gpws_mode
Definition SimBuffers.h:187
int simbuf_ap_alt_mode
Definition SimBuffers.h:183
int simbuf_autoshift
Definition SimBuffers.h:147
void SetIgnition(int engine, bool visible, bool ignited)
AeroTrimWidget alt_trim
AeroSwitchWidget wlv
Ogre::TextureUnitState * adibugstexture
AeroSwitchWidget alt
Ogre::TextureUnitState * airspeedtexture
AeroSwitchWidget vs
AeroSwitchWidget brks
void SetEngineRpm(int engine, float pcent)
AeroSwitchWidget ias
Ogre::TextureUnitState * altimetertexture
void SetThrottle(int engine, bool visible, float value)
AeroSwitchWidget engstarts[4]
void SetEngineTorque(int engine, float pcent)
Ogre::TextureUnitState * aoatexture
Ogre::TextAreaOverlayElement * alt_value_textarea
Ogre::TextureUnitState * hsivtexture
AeroTrimWidget ias_trim
AeroSwitchWidget gpws
Ogre::TextureUnitState * hsibugtexture
Ogre::TextureUnitState * hsihtexture
Ogre::TextureUnitState * hsirosetexture
Ogre::Overlay * dash_overlay
AeroEngineWidget engines[4]
AeroSwitchWidget hdg
Ogre::Overlay * needles_overlay
AeroTrimWidget vs_trim
static void SetMaterialHighlighted(Ogre::MaterialPtr, bool value)
void SetEngineFailed(int engine, bool value)
std::vector< AeroInteractiveWidget * > aero_widgets
AeroSwitchWidget nav
AeroTrimWidget hdg_trim
void SetEnginePitch(int engine, float value)
Ogre::TextureUnitState * vvitexture
Ogre::TextureUnitState * aditapetexture
AeroInteractiveWidget * hovered_widget
Ogre::OverlayElement * thr_element
Ogre::TextureUnitState * torque_texture
Ogre::TextureUnitState * pitch_texture
Ogre::OverlayElement * GetHoveredElement() const override
Ogre::OverlayElement * engfire_element
bool UpdateMouseHover() override
Ogre::MaterialPtr thr_material
void Setup(std::string const &engfire_elemname, std::string const &thr_elemname)
Ogre::TextureUnitState * rpm_texture
virtual Ogre::OverlayElement * GetHoveredElement() const =0
void Setup(std::string const &elem_name, std::string const &mat_on, std::string const &mat_off)
Ogre::OverlayElement * element
bool UpdateMouseHover() override
void SetActive(bool value)
Ogre::MaterialPtr off_material
Ogre::OverlayElement * GetHoveredElement() const override
Ogre::MaterialPtr on_material
void DisplayFormat(const char *fmt,...)
Ogre::OverlayElement * GetHoveredElement() const override
void Setup(std::string const &up, std::string const &dn, std::string const &disp)
Ogre::OverlayElement * display
bool UpdateMouseHover() override
Ogre::MaterialPtr down_material
Ogre::OverlayElement * hovered_button
Ogre::MaterialPtr up_material
Ogre::OverlayElement * dn_button
Ogre::OverlayElement * up_button
float simbuf_race_time_diff
Definition SimBuffers.h:214
float simbuf_race_best_time
Definition SimBuffers.h:213
Ogre::Vector3 AbsPosition
Definition SimBuffers.h:69
Ogre::Vector3 Velocity
Definition SimData.h:268