Rigs of Rods 2023.09
Soft-body Physics Simulation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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); // Needed for dashboard-prop
277 tachotexture = ((MaterialPtr)(MaterialManager::getSingleton().getByName("tracks/tachoneedle_mat"))) ->getTechnique(0)->getPass(0)->getTextureUnitState(0); // Needed for dashboard-prop
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 guiGear3D = loadOverlayElement("tracks/3DGear");
320
321 guiAuto[0] = (TextAreaOverlayElement*)loadOverlayElement("tracks/AGearR");
322 guiAuto[1] = (TextAreaOverlayElement*)loadOverlayElement("tracks/AGearN");
323 guiAuto[2] = (TextAreaOverlayElement*)loadOverlayElement("tracks/AGearD");
324 guiAuto[3] = (TextAreaOverlayElement*)loadOverlayElement("tracks/AGear2");
325 guiAuto[4] = (TextAreaOverlayElement*)loadOverlayElement("tracks/AGear1");
326
327 guiAuto3D[0] = (TextAreaOverlayElement*)loadOverlayElement("tracks/3DAGearR");
328 guiAuto3D[1] = (TextAreaOverlayElement*)loadOverlayElement("tracks/3DAGearN");
329 guiAuto3D[2] = (TextAreaOverlayElement*)loadOverlayElement("tracks/3DAGearD");
330 guiAuto3D[3] = (TextAreaOverlayElement*)loadOverlayElement("tracks/3DAGear2");
331 guiAuto3D[4] = (TextAreaOverlayElement*)loadOverlayElement("tracks/3DAGear1");
332
333 m_truck_pressure_overlay = loadOverlay("tracks/PressureOverlay");
334 m_truck_pressure_needle_overlay = loadOverlay("tracks/PressureNeedleOverlay");
335
336 m_racing_overlay = loadOverlay("tracks/Racing", false);
337 laptime = (TextAreaOverlayElement*)loadOverlayElement("tracks/Racing/LapTime");
338 bestlaptime = (TextAreaOverlayElement*)loadOverlayElement("tracks/Racing/BestLapTime");
339
340 g_is_scaled = true;
342
343 return 0;
344}
345
347{
348 if (mTimeUntilNextToggle > 0)
350}
351
353{
355 {
356 if (show)
357 {
360 }
361 else
362 {
365 }
366 }
367}
368
373
375{
376 m_dashboard_visible = show;
377
378 // check if we use the new style dashboards
379 if (actor && actor->ar_dashboard && actor->ar_dashboard->wasDashboardHudLoaded())
380 {
381 actor->ar_dashboard->setVisible(show);
382 return;
383 }
384
385 if (show)
386 {
387 int mode = actor ? actor->ar_driveable : -1;
388
389 if (mode == AIRPLANE)
390 {
393 }
394 else if (mode == BOAT)
395 {
398 }
399 else if (mode == MACHINE)
400 {
401 Ogre::OverlayElement* help_elem = OverlayManager::getSingleton().getOverlayElement("tracks/machinehelppanel");
402 if (actor->GetGfxActor()->GetHelpMat())
403 {
404 help_elem->setMaterial(actor->GetGfxActor()->GetHelpMat());
405 }
406 else
407 {
408 help_elem->setMaterialName("tracks/black");
409 }
411 }
412 }
413 else
414 {
417
420
422 }
423}
424
426{
427 static std::string currFps = _L("Current FPS: ");
428 static std::string avgFps = _L("Average FPS: ");
429 static std::string bestFps = _L("Best FPS: ");
430 static std::string worstFps = _L("Worst FPS: ");
431 static std::string tris = _L("Triangle Count: ");
432 const RenderTarget::FrameStats& stats = win->getStatistics();
433
434 // update stats when necessary
435 try
436 {
437 OverlayElement* guiAvg = OverlayManager::getSingleton().getOverlayElement("Core/AverageFps");
438 OverlayElement* guiCurr = OverlayManager::getSingleton().getOverlayElement("Core/CurrFps");
439 OverlayElement* guiBest = OverlayManager::getSingleton().getOverlayElement("Core/BestFps");
440 OverlayElement* guiWorst = OverlayManager::getSingleton().getOverlayElement("Core/WorstFps");
441
442 guiAvg->setCaption(avgFps + TOSTRING(stats.avgFPS));
443 guiCurr->setCaption(currFps + TOSTRING(stats.lastFPS));
444 guiBest->setCaption(bestFps + TOSTRING(stats.bestFPS) + (" ") + TOSTRING(stats.bestFrameTime) + (" ms"));
445 guiWorst->setCaption(worstFps + TOSTRING(stats.worstFPS) + (" ") + TOSTRING(stats.worstFrameTime) + (" ms"));
446
447 OverlayElement* guiTris = OverlayManager::getSingleton().getOverlayElement("Core/NumTris");
448 std::string triss = tris + TOSTRING(stats.triangleCount);
449 if (stats.triangleCount > 1000000)
450 triss = tris + TOSTRING(stats.triangleCount/1000000.0f) + (" M");
451 else if (stats.triangleCount > 1000)
452 triss = tris + TOSTRING(stats.triangleCount/1000.0f) + (" k");
453 guiTris->setCaption(triss);
454
455 // create some memory texts
456 std::string memoryText;
457 if (TextureManager::getSingleton().getMemoryUsage() > 1)
458 memoryText = memoryText + _L("Textures: ") + formatBytes(TextureManager::getSingleton().getMemoryUsage()) + (" / ") + formatBytes(TextureManager::getSingleton().getMemoryBudget()) + ("\n");
459 if (CompositorManager::getSingleton().getMemoryUsage() > 1)
460 memoryText = memoryText + _L("Compositors: ") + formatBytes(CompositorManager::getSingleton().getMemoryUsage()) + (" / ") + formatBytes(CompositorManager::getSingleton().getMemoryBudget()) + ("\n");
461 if (FontManager::getSingleton().getMemoryUsage() > 1)
462 memoryText = memoryText + _L("Fonts: ") + formatBytes(FontManager::getSingleton().getMemoryUsage()) + (" / ") + formatBytes(FontManager::getSingleton().getMemoryBudget()) + ("\n");
463 if (GpuProgramManager::getSingleton().getMemoryUsage() > 1)
464 memoryText = memoryText + _L("GPU Program: ") + formatBytes(GpuProgramManager::getSingleton().getMemoryUsage()) + (" / ") + formatBytes(GpuProgramManager::getSingleton().getMemoryBudget()) + ("\n");
465 if (HighLevelGpuProgramManager::getSingleton().getMemoryUsage() > 1)
466 memoryText = memoryText + _L("HL GPU Program: ") + formatBytes(HighLevelGpuProgramManager::getSingleton().getMemoryUsage()) + (" / ") + formatBytes(HighLevelGpuProgramManager::getSingleton().getMemoryBudget()) + ("\n");
467 if (MaterialManager::getSingleton().getMemoryUsage() > 1)
468 memoryText = memoryText + _L("Materials: ") + formatBytes(MaterialManager::getSingleton().getMemoryUsage()) + (" / ") + formatBytes(MaterialManager::getSingleton().getMemoryBudget()) + ("\n");
469 if (MeshManager::getSingleton().getMemoryUsage() > 1)
470 memoryText = memoryText + _L("Meshes: ") + formatBytes(MeshManager::getSingleton().getMemoryUsage()) + (" / ") + formatBytes(MeshManager::getSingleton().getMemoryBudget()) + ("\n");
471 if (SkeletonManager::getSingleton().getMemoryUsage() > 1)
472 memoryText = memoryText + _L("Skeletons: ") + formatBytes(SkeletonManager::getSingleton().getMemoryUsage()) + (" / ") + formatBytes(SkeletonManager::getSingleton().getMemoryBudget()) + ("\n");
473 if (MaterialManager::getSingleton().getMemoryUsage() > 1)
474 memoryText = memoryText + _L("Materials: ") + formatBytes(MaterialManager::getSingleton().getMemoryUsage()) + (" / ") + formatBytes(MaterialManager::getSingleton().getMemoryBudget()) + ("\n");
475 memoryText = memoryText + ("\n");
476
477 OverlayElement* memoryDbg = OverlayManager::getSingleton().getOverlayElement("Core/MemoryText");
478 memoryDbg->setCaption(memoryText);
479
480 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();
481 String sumMemoryText = _L("Memory (Ogre): ") + formatBytes(sumMem) + ("\n");
482
483 OverlayElement* memorySumDbg = OverlayManager::getSingleton().getOverlayElement("Core/CurrMemory");
484 memorySumDbg->setCaption(sumMemoryText);
485 }
486 catch (...)
487 {
488 // ignore
489 }
490}
491
493{
494 ActorPtr player_actor = App::GetGameContext()->GetPlayerActor();
495 if (!player_actor
496 || !m_aerial_dashboard.needles_overlay->isVisible()
498 return false;
499
500 // IMPORTANT: get mouse button state from InputEngine, not from OIS directly
501 // - that state may be dirty, see commentary in `InputEngine::getMouseState()`
502 const OIS::MouseState ms = App::GetInputEngine()->getMouseState();
503 bool res = false;
504 if (player_actor->ar_driveable == AIRPLANE && ms.buttonDown(OIS::MB_Left))
505 {
506 const int num_engines = std::min(4, player_actor->ar_num_aeroengines);
507
508 OverlayElement* element = m_aerial_dashboard.hovered_widget->GetHoveredElement();
509 if (element)
510 {
511 res = true;
512 for (int i = 0; i < num_engines; ++i)
513 {
514 if (element == m_aerial_dashboard.engines[i].thr_element)
515 {
517 }
518 }
519
520 for (int i = 0; i < num_engines; ++i)
521 {
522 if (element == m_aerial_dashboard.engstarts[i].element)
523 {
524 player_actor->ar_aeroengines[i]->flipStart();
525 }
526 }
527
528 if (player_actor->ar_autopilot && mTimeUntilNextToggle <= 0)
529 {
530 //heading group
531 if (element == m_aerial_dashboard.hdg.element)
532 {
535 }
536 if (element == m_aerial_dashboard.wlv.element)
537 {
540 }
541 if (element == m_aerial_dashboard.nav.element)
542 {
545 }
546 //altitude group
547 if (element == m_aerial_dashboard.alt.element)
548 {
551 }
552 if (element == m_aerial_dashboard.vs.element)
553 {
556 }
557 //IAS
558 if (element == m_aerial_dashboard.ias.element)
559 {
561 player_actor->ar_autopilot->toggleIAS();
562 }
563 //GPWS
564 if (element == m_aerial_dashboard.gpws.element)
565 {
567 player_actor->ar_autopilot->toggleGPWS();
568 }
569 //BRKS
570 if (element == m_aerial_dashboard.brks.element)
571 {
573 player_actor->parkingbrakeToggle();
574 }
575 //trims
577 {
579 player_actor->ar_autopilot->adjHDG(1);
580 }
582 {
584 player_actor->ar_autopilot->adjHDG(-1);
585 }
587 {
589 player_actor->ar_autopilot->adjALT(100);
590 }
592 {
594 player_actor->ar_autopilot->adjALT(-100);
595 }
596 if (element == m_aerial_dashboard.vs_trim.up_button)
597 {
599 player_actor->ar_autopilot->adjVS(100);
600 }
601 if (element == m_aerial_dashboard.vs_trim.dn_button)
602 {
604 player_actor->ar_autopilot->adjVS(-100);
605 }
607 {
609 player_actor->ar_autopilot->adjIAS(1);
610 }
612 {
614 player_actor->ar_autopilot->adjIAS(-1);
615 }
616 }
617 }
618 }
619 return res;
620}
621
623{
624 ActorPtr player_actor = App::GetGameContext()->GetPlayerActor();
625 if (!player_actor || !m_aerial_dashboard.needles_overlay->isVisible())
626 return false;
627
628 const Ogre::Vector2 mousepos = App::GetInputEngine()->getMouseNormalizedScreenPos();
629
630 // Update mouse drag if ongoing
632 {
633 const int num_engines = std::min(4, player_actor->ar_num_aeroengines);
634 float thr_value = 1.0f - ((mousepos.y - thrtop - throffset) / thrheight);
635 for (int i = 0; i < num_engines; ++i)
636 {
638 {
639 player_actor->ar_aeroengines[i]->setThrottle(thr_value);
640 }
641 }
642 return true;
643 }
644
645 // Just detect mouse hover
647
648 return false;
649}
650
652{
653 // IMPORTANT: get mouse button state from InputEngine, not from OIS directly
654 // - that state may be dirty, see commentary in `InputEngine::getMouseState()`
655 const OIS::MouseState ms = App::GetInputEngine()->getMouseState();
656
657 if (!ms.buttonDown(OIS::MB_Left))
658 {
660 }
661
662 return false;
663}
664
666{
668 {
669 this->showPressureOverlay(true);
670 const float pressure = ga->GetSimDataBuffer().simbuf_tyre_pressure;
671 Real angle = 135.0 - pressure * 2.7;
672 pressuretexture->setTextureRotate(Degree(angle));
673 }
674 else
675 {
676 this->showPressureOverlay(false);
677 }
678}
679
681{
682 // gears
683 int vehicle_getgear = ga->GetSimDataBuffer().simbuf_gear;
684 if (vehicle_getgear > 0)
685 {
686 size_t numgears = ga->GetSimDataBuffer().simbuf_num_gears;
687 String gearstr = TOSTRING(vehicle_getgear) + "/" + TOSTRING(numgears);
688 guiGear->setCaption(gearstr);
689 guiGear3D->setCaption(gearstr);
690 }
691 else if (vehicle_getgear == 0)
692 {
693 guiGear->setCaption("N");
694 guiGear3D->setCaption("N");
695 }
696 else
697 {
698 guiGear->setCaption("R");
699 guiGear3D->setCaption("R");
700 }
701
702 //autogears
703 int cg = ga->GetSimDataBuffer().simbuf_autoshift;
704 for (int i = 0; i < 5; i++)
705 {
706 if (i == cg)
707 {
708 if (i == 1)
709 {
710 guiAuto[i]->setColourTop(ColourValue(1.0, 0.2, 0.2, 1.0));
711 guiAuto[i]->setColourBottom(ColourValue(0.8, 0.1, 0.1, 1.0));
712 guiAuto3D[i]->setColourTop(ColourValue(1.0, 0.2, 0.2, 1.0));
713 guiAuto3D[i]->setColourBottom(ColourValue(0.8, 0.1, 0.1, 1.0));
714 }
715 else
716 {
717 guiAuto[i]->setColourTop(ColourValue(1.0, 1.0, 1.0, 1.0));
718 guiAuto[i]->setColourBottom(ColourValue(0.8, 0.8, 0.8, 1.0));
719 guiAuto3D[i]->setColourTop(ColourValue(1.0, 1.0, 1.0, 1.0));
720 guiAuto3D[i]->setColourBottom(ColourValue(0.8, 0.8, 0.8, 1.0));
721 }
722 }
723 else
724 {
725 if (i == 1)
726 {
727 guiAuto[i]->setColourTop(ColourValue(0.4, 0.05, 0.05, 1.0));
728 guiAuto[i]->setColourBottom(ColourValue(0.3, 0.02, 0.2, 1.0));
729 guiAuto3D[i]->setColourTop(ColourValue(0.4, 0.05, 0.05, 1.0));
730 guiAuto3D[i]->setColourBottom(ColourValue(0.3, 0.02, 0.2, 1.0));
731 }
732 else
733 {
734 guiAuto[i]->setColourTop(ColourValue(0.4, 0.4, 0.4, 1.0));
735 guiAuto[i]->setColourBottom(ColourValue(0.3, 0.3, 0.3, 1.0));
736 guiAuto3D[i]->setColourTop(ColourValue(0.4, 0.4, 0.4, 1.0));
737 guiAuto3D[i]->setColourBottom(ColourValue(0.3, 0.3, 0.3, 1.0));
738 }
739 }
740 }
741
742 // speedo / calculate speed
743 Real guiSpeedFactor = 7.0 * (140.0 / ga->GetSimDataBuffer().simbuf_speedo_highest_kph);
744 Real angle = 140 - fabs(ga->GetSimDataBuffer().simbuf_wheel_speed * guiSpeedFactor);
745 angle = std::max(-140.0f, angle);
746 speedotexture->setTextureRotate(Degree(angle));
747
748 // calculate tach stuff
749 Real tachoFactor = 0.072;
751 {
752 tachoFactor = 0.072 * (3500 / ga->GetSimDataBuffer().simbuf_engine_max_rpm);
753 }
754 angle = 126.0 - fabs(ga->GetSimDataBuffer().simbuf_engine_rpm * tachoFactor);
755 angle = std::max(-120.0f, angle);
756 angle = std::min(angle, 121.0f);
757 tachotexture->setTextureRotate(Degree(angle));
758}
759
761{
762 RoR::ActorSB& simbuf = gfx_actor->GetSimDataBuffer();
763 RoR::NodeSB* nodes = gfx_actor->GetSimNodeBuffer();
764
765 auto const& simbuf_ae = simbuf.simbuf_aeroengines;
766 int num_ae = static_cast<int>( simbuf_ae.size() );
767
768 //throttles
769 m_aerial_dashboard.SetThrottle(0, true, simbuf_ae[0].simbuf_ae_throttle);
770 m_aerial_dashboard.SetThrottle(1, (num_ae > 1), (num_ae > 1) ? simbuf_ae[1].simbuf_ae_throttle : 0.f);
771 m_aerial_dashboard.SetThrottle(2, (num_ae > 2), (num_ae > 2) ? simbuf_ae[2].simbuf_ae_throttle : 0.f);
772 m_aerial_dashboard.SetThrottle(3, (num_ae > 3), (num_ae > 3) ? simbuf_ae[3].simbuf_ae_throttle : 0.f);
773
774 //fire
775 m_aerial_dashboard.SetEngineFailed(0, simbuf_ae[0].simbuf_ae_failed);
776 m_aerial_dashboard.SetEngineFailed(1, num_ae > 1 && simbuf_ae[1].simbuf_ae_failed);
777 m_aerial_dashboard.SetEngineFailed(2, num_ae > 2 && simbuf_ae[2].simbuf_ae_failed);
778 m_aerial_dashboard.SetEngineFailed(3, num_ae > 3 && simbuf_ae[3].simbuf_ae_failed);
779
780 //airspeed
781 float angle = 0.0;
782 float ground_speed_kt = simbuf.simbuf_node0_velo.length() * 1.9438; // 1.943 = m/s in knots/s
783
784 //tropospheric model valid up to 11.000m (33.000ft)
785 float altitude = nodes[0].AbsPosition.y;
786 //float sea_level_temperature=273.15+15.0; //in Kelvin
787 float sea_level_pressure = 101325; //in Pa
788 //float airtemperature=sea_level_temperature-altitude*0.0065; //in Kelvin
789 float airpressure = sea_level_pressure * pow(1.0 - 0.0065 * altitude / 288.15, 5.24947); //in Pa
790 float airdensity = airpressure * 0.0000120896;//1.225 at sea level
791
792 float kt = ground_speed_kt * sqrt(airdensity / 1.225); //KIAS
793 if (kt > 23.0)
794 {
795 if (kt < 50.0)
796 angle = ((kt - 23.0) / 1.111);
797 else if (kt < 100.0)
798 angle = (24.0 + (kt - 50.0) / 0.8621);
799 else if (kt < 300.0)
800 angle = (82.0 + (kt - 100.0) / 0.8065);
801 else
802 angle = 329.0;
803 }
804 m_aerial_dashboard.airspeedtexture->setTextureRotate(Degree(-angle));
805
806 // AOA
807 angle = simbuf.simbuf_wing4_aoa;
808 if (kt < 10.0)
809 angle = 0;
810 float absangle = angle;
811 if (absangle < 0)
812 absangle = -absangle;
813
814 const int actor_id = gfx_actor->GetActorId();
815 SOUND_MODULATE(actor_id, SS_MOD_AOA, absangle);
816 if (absangle > 18.0) // TODO: magicccc
817 SOUND_START(actor_id, SS_TRIG_AOA);
818 else
819 SOUND_STOP(actor_id, SS_TRIG_AOA);
820
821 if (angle > 25.0)
822 angle = 25.0;
823 if (angle < -25.0)
824 angle = -25.0;
825 m_aerial_dashboard.aoatexture->setTextureRotate(Degree(-angle * 4.7 + 90.0));
826
827 // altimeter
828 angle = nodes[0].AbsPosition.y * 1.1811;
829 m_aerial_dashboard.altimetertexture->setTextureRotate(Degree(-angle));
830 char altc[10];
831 sprintf(altc, "%03u", (int)(nodes[0].AbsPosition.y / 30.48));
832 m_aerial_dashboard.alt_value_textarea->setCaption(altc);
833
834 //adi
835 //roll
836 Vector3 rollv = nodes[simbuf.simbuf_camera0_pos_node].AbsPosition - nodes[simbuf.simbuf_camera0_roll_node].AbsPosition;
837 rollv.normalise();
838 float rollangle = asin(rollv.dotProduct(Vector3::UNIT_Y));
839
840 //pitch
841 Vector3 dirv = simbuf.simbuf_direction;
842 float pitchangle = asin(dirv.dotProduct(Vector3::UNIT_Y));
843 Vector3 upv = dirv.crossProduct(-rollv);
844 if (upv.y < 0)
845 rollangle = 3.14159 - rollangle;
846 m_aerial_dashboard.adibugstexture->setTextureRotate(Radian(-rollangle));
847 m_aerial_dashboard.aditapetexture->setTextureVScroll(-pitchangle * 0.25);
848 m_aerial_dashboard.aditapetexture->setTextureRotate(Radian(-rollangle));
849
850 //hsi
851 float dirangle = atan2(dirv.dotProduct(Vector3::UNIT_X), dirv.dotProduct(-Vector3::UNIT_Z));
852 m_aerial_dashboard.hsirosetexture->setTextureRotate(Radian(dirangle));
853
854 //autopilot
855 m_aerial_dashboard.hsibugtexture->setTextureRotate(Radian(dirangle) - Degree(simbuf.simbuf_ap_heading_value));
856
857 float vdev = 0;
858 float hdev = 0;
859 if (simbuf.simbuf_ap_ils_available)
860 {
861 vdev = simbuf.simbuf_ap_ils_vdev;
862 hdev = simbuf.simbuf_ap_ils_hdev;
863 }
864 if (hdev > 15)
865 hdev = 15;
866 if (hdev < -15)
867 hdev = -15;
868 m_aerial_dashboard.hsivtexture->setTextureUScroll(-hdev * 0.02);
869 if (vdev > 15)
870 vdev = 15;
871 if (vdev < -15)
872 vdev = -15;
873 m_aerial_dashboard.hsihtexture->setTextureVScroll(-vdev * 0.02);
874
875 //vvi
876 float vvi = simbuf.simbuf_node0_velo.y * 196.85;
877 if (vvi < 1000.0 && vvi > -1000.0)
878 angle = vvi * 0.047;
879 if (vvi > 1000.0 && vvi < 6000.0)
880 angle = 47.0 + (vvi - 1000.0) * 0.01175;
881 if (vvi > 6000.0)
882 angle = 105.75;
883 if (vvi < -1000.0 && vvi > -6000.0)
884 angle = -47.0 + (vvi + 1000.0) * 0.01175;
885 if (vvi < -6000.0)
886 angle = -105.75;
887 m_aerial_dashboard.vvitexture->setTextureRotate(Degree(-angle + 90.0));
888
889 const bool is_prop = simbuf_ae[0].simbuf_ae_type == AeroEngineType::AE_XPROP;
890
891 //rpm
892 m_aerial_dashboard.SetEngineRpm(0, simbuf_ae[0].simbuf_ae_rpmpc);
893 m_aerial_dashboard.SetEngineRpm(1, (num_ae > 1) ? simbuf_ae[1].simbuf_ae_rpmpc : 0.f);
894 m_aerial_dashboard.SetEngineRpm(2, (num_ae > 2) ? simbuf_ae[2].simbuf_ae_rpmpc : 0.f);
895 m_aerial_dashboard.SetEngineRpm(3, (num_ae > 3) ? simbuf_ae[3].simbuf_ae_rpmpc : 0.f);
896
897 //turboprops - pitch
898 m_aerial_dashboard.SetEnginePitch(0, (is_prop) ? simbuf_ae[0].simbuf_tp_aepitch : 0.f);
899 m_aerial_dashboard.SetEnginePitch(1, (num_ae > 1 && is_prop) ? simbuf_ae[1].simbuf_tp_aepitch : 0.f);
900 m_aerial_dashboard.SetEnginePitch(2, (num_ae > 2 && is_prop) ? simbuf_ae[2].simbuf_tp_aepitch : 0.f);
901 m_aerial_dashboard.SetEnginePitch(3, (num_ae > 3 && is_prop) ? simbuf_ae[3].simbuf_tp_aepitch : 0.f);
902
903 //turboprops - torque
904 m_aerial_dashboard.SetEngineTorque(0, (is_prop) ? simbuf_ae[0].simbuf_tp_aetorque : 0.f);
905 m_aerial_dashboard.SetEngineTorque(1, (num_ae > 1 && is_prop) ? simbuf_ae[1].simbuf_tp_aetorque : 0.f);
906 m_aerial_dashboard.SetEngineTorque(2, (num_ae > 2 && is_prop) ? simbuf_ae[2].simbuf_tp_aetorque : 0.f);
907 m_aerial_dashboard.SetEngineTorque(3, (num_ae > 3 && is_prop) ? simbuf_ae[3].simbuf_tp_aetorque : 0.f);
908
909 //starters
910 m_aerial_dashboard.SetIgnition(0, true, simbuf_ae[0].simbuf_ae_ignition);
911 m_aerial_dashboard.SetIgnition(1, num_ae > 1, num_ae > 1 && simbuf_ae[1].simbuf_ae_ignition);
912 m_aerial_dashboard.SetIgnition(2, num_ae > 2, num_ae > 2 && simbuf_ae[2].simbuf_ae_ignition);
913 m_aerial_dashboard.SetIgnition(3, num_ae > 3, num_ae > 3 && simbuf_ae[3].simbuf_ae_ignition);
914
915 //autopilot - heading
919
920 //autopilot - altitude
923
924 //autopilot - other buttons
928
929 //autopilot - trims
933 if (simbuf.simbuf_ap_vs_value == 0)
934 m_aerial_dashboard.vs_trim.display->setCaption("000");
935 else if (simbuf.simbuf_ap_vs_value < 0)
937 else
939}
940
942{
943 // throttles
944 bthro1->setTop(thrtop + thrheight * (0.5 - vehicle->ar_screwprops[0]->getThrottle() / 2.0) - 1.0);
945 if (vehicle->ar_num_screwprops > 1)
946 {
947 bthro2->setTop(thrtop + thrheight * (0.5 - vehicle->ar_screwprops[1]->getThrottle() / 2.0) - 1.0);
948 }
949
950 // depth
951 char tmp[50] = "";
952 float height = vehicle->getHeightAboveGround();
953 if (height > 0.1 && height < 99.9)
954 {
955 sprintf(tmp, "%2.1f", height);
956 boat_depth_value_taoe->setCaption(tmp);
957 }
958 else
959 {
960 boat_depth_value_taoe->setCaption("--.-");
961 }
962
963 // water speed
964 Vector3 cam_dir = vehicle->getDirection();
965 Vector3 velocity = vehicle->ar_nodes[vehicle->ar_main_camera_node_pos].Velocity;
966 float kt = cam_dir.dotProduct(velocity) * 1.9438;
967 float angle = kt * 4.2;
968 boatspeedtexture->setTextureRotate(Degree(-angle));
969 boatsteertexture->setTextureRotate(Degree(vehicle->ar_screwprops[0]->getRudder() * 170));
970}
971
976
981
983{
984 float time = gs->GetSimDataBuffer().simbuf_race_time;
985 std::string txt = StringUtil::format("%.2i'%.2i.%.2i", (int)(time) / 60, (int)(time) % 60, (int)(time * 100.0) % 100);
986 this->laptime->setCaption(txt);
988 {
990 txt = StringUtil::format("%.2i'%.2i.%.2i", (int)(time) / 60, (int)(time) % 60, (int)(time * 100.0) % 100);
991 this->bestlaptime->setCaption(txt);
992 this->bestlaptime->show();
993 }
994 else
995 {
996 this->bestlaptime->hide();
997 }
998
999 float time_diff = gs->GetSimDataBuffer().simbuf_race_time_diff;
1000 Ogre::ColourValue colour = Ogre::ColourValue::White;
1001 if (time_diff > 0.0f)
1002 {
1003 colour = ColourValue(0.8, 0.0, 0.0);
1004 }
1005 else if (time_diff < 0.0f)
1006 {
1007 colour = ColourValue(0.0, 0.8, 0.0);
1008 }
1009 this->laptime->setColourTop(colour);
1010 this->laptime->setColourBottom(colour);
1011}
1012
1013void AeroDashOverlay::SetThrottle(int engine, bool visible, float value)
1014{
1015 if (visible)
1016 {
1017 engines[engine].thr_element->show();
1018 engines[engine].thr_element->setTop(
1019 thrust_track_top + thrust_track_height * (1.0 - value) - 1.0);
1020 }
1021 else
1022 {
1023 engines[engine].thr_element->hide();
1024 }
1025}
1026
1027void AeroDashOverlay::SetEngineFailed(int engine, bool value)
1028{
1029 engines[engine].engfire_element->setMaterialName(
1030 value ? "tracks/engfire-on" : "tracks/engfire-off");
1031}
1032
1033void AeroDashOverlay::SetEngineRpm(int engine, float pcent)
1034{
1035 float angle;
1036 if (pcent < 60.0)
1037 angle = -5.0 + pcent * 1.9167;
1038 else if (pcent < 110.0)
1039 angle = 110.0 + (pcent - 60.0) * 4.075;
1040 else
1041 angle = 314.0;
1042 engines[engine].rpm_texture->setTextureRotate(Ogre::Degree(-angle));
1043}
1044
1045void AeroDashOverlay::SetEnginePitch(int engine, float value)
1046{
1047 engines[engine].pitch_texture->setTextureRotate(Degree(-value * 2.0));
1048}
1049
1050void AeroDashOverlay::SetEngineTorque(int engine, float pcent)
1051{
1052 float angle;
1053 if (pcent < 60.0)
1054 angle = -5.0 + pcent * 1.9167;
1055 else if (pcent < 110.0)
1056 angle = 110.0 + (pcent - 60.0) * 4.075;
1057 else
1058 angle = 314.0;
1059 engines[engine].torque_texture->setTextureRotate(Degree(-angle));
1060}
1061
1062void AeroDashOverlay::SetIgnition(int engine, bool visible, bool ignited)
1063{
1064 if (visible)
1065 {
1066 engstarts[engine].element->show();
1067 engstarts[engine].SetActive(ignited);
1068 }
1069 else
1070 {
1071 engstarts[engine].element->hide();
1072 }
1073}
1074
1075// -----------------
1076// AeroEngineOverlay
1077
1078void AeroEngineWidget::Setup(std::string const& engfire_elemname, std::string const& thr_elemname)
1079{
1080 // Because highlighting works on per-material basis, we must clone the material for each element
1081 engfire_element = Ogre::OverlayManager::getSingleton().getOverlayElement(engfire_elemname);
1082 thr_element = Ogre::OverlayManager::getSingleton().getOverlayElement(thr_elemname);
1083 thr_material = thr_element->getMaterial()->clone(thr_element->getMaterial()->getName() + "@" + thr_elemname);
1084 thr_element->setMaterial(thr_material);
1085}
1086
1088{
1089 // Remove cloned materials
1090 Ogre::MaterialManager::getSingleton().remove(thr_material);
1091}
1092
1094{
1095 const Ogre::Vector2 mouse_pos = App::GetInputEngine()->getMouseNormalizedScreenPos();
1096 bool retval = false;
1097 if (retval = thr_element->contains(mouse_pos.x, mouse_pos.y))
1098 {
1100 }
1101 else
1102 {
1104 }
1105 return retval;
1106}
1107
1108Ogre::OverlayElement* AeroEngineWidget::GetHoveredElement() const
1109{
1110 return thr_element;
1111}
1112
1113// ---------------
1114// AeroSwitchOverlay
1115
1117{
1118 element->setMaterial(value ? on_material : off_material);
1119}
1120
1121void AeroSwitchWidget::Setup(std::string const & elem_name, std::string const & mat_on, std::string const & mat_off)
1122{
1123 // Because highlighting works on per-material basis, we must clone the material for each element
1124 element = Ogre::OverlayManager::getSingleton().getOverlayElement(elem_name);
1125 on_material = Ogre::MaterialManager::getSingleton().getByName(mat_on)->clone(elem_name + "@" + mat_on);
1126 off_material = Ogre::MaterialManager::getSingleton().getByName(mat_off)->clone(elem_name + "@" + mat_off);
1127}
1128
1130{
1131 // Remove cloned materials
1132 Ogre::MaterialManager::getSingleton().remove(on_material);
1133 Ogre::MaterialManager::getSingleton().remove(off_material);
1134}
1135
1137{
1138 // Element's current material switches dynamically based on game state, we must always sync both variants.
1139 const Ogre::Vector2 mouse_pos = App::GetInputEngine()->getMouseNormalizedScreenPos();
1140 bool retval = false;
1141 if (retval = element->contains(mouse_pos.x, mouse_pos.y))
1142 {
1145 }
1146 else
1147 {
1150 }
1151 return retval;
1152}
1153
1154Ogre::OverlayElement* AeroSwitchWidget::GetHoveredElement() const
1155{
1156 return element;
1157}
1158
1159// ---------------
1160// AeroTrimOverlay
1161
1162void AeroTrimWidget::Setup(std::string const & up, std::string const & dn, std::string const & disp)
1163{
1164 // Because highlighting works on per-material basis, we must clone the material for each element
1165 display = Ogre::OverlayManager::getSingleton().getOverlayElement(disp);
1166 up_button = Ogre::OverlayManager::getSingleton().getOverlayElement(up);
1167 up_material = up_button->getMaterial()->clone(up + "$" + disp);
1168 up_button->setMaterial(up_material);
1169 dn_button = Ogre::OverlayManager::getSingleton().getOverlayElement(dn);
1170 down_material = dn_button->getMaterial()->clone(dn + "$" + disp);
1171 dn_button->setMaterial(down_material);
1172}
1173
1175{
1176 // Remove cloned materials
1177 Ogre::MaterialManager::getSingleton().remove(up_material);
1178 Ogre::MaterialManager::getSingleton().remove(down_material);
1179}
1180
1182{
1183 const Ogre::Vector2 mouse_pos = App::GetInputEngine()->getMouseNormalizedScreenPos();
1184
1185 bool retval = false;
1186 if (retval = up_button->contains(mouse_pos.x, mouse_pos.y))
1187 {
1191 }
1192 else if (retval = dn_button->contains(mouse_pos.x, mouse_pos.y))
1193 {
1197 }
1198 else
1199 {
1200 hovered_button = nullptr;
1203 }
1204 return retval;
1205}
1206
1207Ogre::OverlayElement* AeroTrimWidget::GetHoveredElement() const
1208{
1209 return hovered_button;
1210}
1211
1212void AeroTrimWidget::DisplayFormat(const char* fmt, ...)
1213{
1214 char buffer[500] = {};
1215
1216 va_list args;
1217 va_start(args, fmt);
1218 vsprintf(buffer, fmt, args);
1219 va_end(args);
1220
1221 display->setCaption(buffer);
1222}
1223
1224// ---------------------
1225// AeroDashOverlay
1226
1227void AeroDashOverlay::SetMaterialHighlighted(Ogre::MaterialPtr mat, bool val)
1228{
1229 // Use texture blending to 'highlight' the hovered element
1230 // doc: https://ogrecave.github.io/ogre/api/13/_material-_scripts.html#autotoc_md169
1231 // -------------------------------------------------------
1232
1233 if (!val)
1234 {
1235 // reset to defaults
1236 mat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setColourOperationEx(
1237 Ogre::LBX_MODULATE, Ogre::LBS_TEXTURE, Ogre::LBS_CURRENT);
1238 }
1239 else
1240 {
1241 // set blend mode to 'add' with a custom colour
1242 mat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setColourOperationEx(
1243 Ogre::LBX_ADD, Ogre::LBS_TEXTURE, Ogre::LBS_MANUAL, Ogre::ColourValue::White, ColourValue(0.32, 0.3, 0.25));
1244 }
1245}
1246
1248{
1249 // Throttles
1250 aero_widgets.push_back(&engines[0]);
1251 aero_widgets.push_back(&engines[1]);
1252 aero_widgets.push_back(&engines[2]);
1253 aero_widgets.push_back(&engines[3]);
1254
1255 // Engine start switches
1256 aero_widgets.push_back(&engstarts[0]);
1257 aero_widgets.push_back(&engstarts[1]);
1258 aero_widgets.push_back(&engstarts[2]);
1259 aero_widgets.push_back(&engstarts[3]);
1260
1261 // Switches
1262 aero_widgets.push_back(&hdg );
1263 aero_widgets.push_back(&wlv );
1264 aero_widgets.push_back(&nav );
1265 aero_widgets.push_back(&alt );
1266 aero_widgets.push_back(&vs );
1267 aero_widgets.push_back(&ias );
1268 aero_widgets.push_back(&gpws );
1269 aero_widgets.push_back(&brks );
1270
1271 // Trims
1272 aero_widgets.push_back(&hdg_trim);
1273 aero_widgets.push_back(&alt_trim);
1274 aero_widgets.push_back(&vs_trim);
1275 aero_widgets.push_back(&ias_trim);
1276}
1277
1279{
1280 for (auto elem : aero_widgets)
1281 {
1282 if (elem->UpdateMouseHover())
1283 {
1284 hovered_widget = elem;
1285 }
1286 }
1287}
1288
System integration layer; inspired by OgreBites::ApplicationContext.
#define TOSTRING(x)
Definition Application.h:57
#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:391
DashBoardManagerPtr ar_dashboard
Definition Actor.h:484
node_t * ar_nodes
Definition Actor.h:330
GfxActor * GetGfxActor()
Definition Actor.h:309
ScrewpropPtr ar_screwprops[MAX_SCREWPROPS]
Definition Actor.h:390
NodeNum_t ar_main_camera_node_pos
Sim attr; ar_camera_node_pos[0] >= 0 ? ar_camera_node_pos[0] : 0.
Definition Actor.h:441
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:388
int ar_num_aeroengines
Definition Actor.h:389
void parkingbrakeToggle()
Definition Actor.cpp:3816
AutopilotPtr ar_autopilot
Definition Actor.h:435
ActorType ar_driveable
Sim attr; marks vehicle type and features.
Definition Actor.h:431
virtual void setThrottle(float val)=0
virtual void flipStart()=0
Ogre::RenderWindow * GetRenderWindow()
Definition AppContext.h:67
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:150
ActorSB & GetSimDataBuffer()
Definition GfxActor.h:128
NodeSB * GetSimNodeBuffer()
Definition GfxActor.h:129
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)
Ogre::TextAreaOverlayElement * guiAuto3D[5]
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 * guiGear3D
truck
Ogre::OverlayElement * guiGear
truck
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:183
int simbuf_num_gears
Gearbox.
Definition SimBuffers.h:156
int simbuf_ap_ias_value
Definition SimBuffers.h:185
bool simbuf_ap_ias_mode
Definition SimBuffers.h:184
Ogre::Vector3 simbuf_node0_velo
Definition SimBuffers.h:124
bool simbuf_tyre_pressurizing
Definition SimBuffers.h:162
int simbuf_ap_heading_mode
Definition SimBuffers.h:180
float simbuf_ap_ils_vdev
Definition SimBuffers.h:188
float simbuf_engine_rpm
Definition SimBuffers.h:147
int simbuf_ap_heading_value
Definition SimBuffers.h:181
int simbuf_ap_vs_value
Definition SimBuffers.h:190
float simbuf_ap_ils_hdev
Definition SimBuffers.h:189
float simbuf_wheel_speed
Definition SimBuffers.h:127
float simbuf_wing4_aoa
Definition SimBuffers.h:176
float simbuf_speedo_highest_kph
Definition SimBuffers.h:193
bool simbuf_speedo_use_engine_max_rpm
Definition SimBuffers.h:194
std::vector< AeroEngineSB > simbuf_aeroengines
Definition SimBuffers.h:138
bool simbuf_ap_ils_available
Definition SimBuffers.h:187
float simbuf_tyre_pressure
Definition SimBuffers.h:161
float simbuf_engine_max_rpm
Definition SimBuffers.h:157
NodeNum_t simbuf_camera0_pos_node
Definition SimBuffers.h:130
bool simbuf_parking_brake
Definition SimBuffers.h:167
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:186
int simbuf_ap_alt_mode
Definition SimBuffers.h:182
int simbuf_autoshift
Definition SimBuffers.h:146
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:213
float simbuf_race_best_time
Definition SimBuffers.h:212
Ogre::Vector3 AbsPosition
Definition SimBuffers.h:69
Ogre::Vector3 Velocity
Definition SimData.h:268