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
GUI_VehicleInfoTPanel.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-2024 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
23
24#include "Application.h"
25#include "Actor.h"
26#include "SimData.h"
27#include "Language.h"
28#include "Engine.h"
29#include "GameContext.h"
30#include "GfxActor.h"
31#include "GUIManager.h"
32#include "Utils.h"
33#include "GUIUtils.h"
34
35using namespace RoR;
36using namespace GUI;
37
38const float HELP_TEXTURE_WIDTH = 512.f;
39const float HELP_TEXTURE_HEIGHT = 80.f;
40const float HELP_TEXTURE_HEIGHT_FULL = 128.f;
41const ImVec2 MAX_PREVIEW_SIZE(100.f, 100.f);
42const float MIN_PANEL_WIDTH = 230.f;
43
48
50{
51 // === DETERMINE VISIBILITY ===
52
53 // Show only once for 5 sec, with a notice
54 bool show_translucent = false;
55 if (App::ui_show_vehicle_buttons->getBool() && actorx && !m_startupdemo_init)
56 {
57 m_startupdemo_timer.reset();
59 fmt::format(_LC("VehicleButtons", "Hover the mouse on the left to see controls")), "lightbulb.png");
60 m_startupdemo_init = true;
61 }
62 if (App::ui_show_vehicle_buttons->getBool() && m_startupdemo_timer.getMilliseconds() < 5000)
63 {
64 show_translucent = true;
65 }
66
67 // Show when mouse is on the left of screen
70 && App::GetGuiManager()->AreStaticMenusAllowed()
71 && (ImGui::GetIO().MousePos.x <= MIN_PANEL_WIDTH + ImGui::GetStyle().WindowPadding.x*2))
72 {
73 show_translucent = true;
74 }
75
76 if (show_translucent && m_visibility_mode != TPANELMODE_OPAQUE)
77 {
79 }
80 else if (!show_translucent && m_visibility_mode != TPANELMODE_OPAQUE)
81 {
83 }
84
86 {
87 return;
88 }
89
90 // === OPEN IMGUI WINDOW ===
91
93
94 ImGuiWindowFlags flags = ImGuiWindowFlags_NoCollapse |
95 ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoBringToFrontOnFocus;
96
97 ImGui::SetNextWindowPos(ImVec2(theme.screen_edge_padding.x, (theme.screen_edge_padding.y + 110)));
98
100 {
101 ImGui::SetNextWindowContentWidth(this->GetPanelWidth());
102 }
103 else
104 {
105 ImGui::SetNextWindowContentWidth(MIN_PANEL_WIDTH);
106 }
107
108 switch (m_visibility_mode)
109 {
111 ImGui::PushStyleColor(ImGuiCol_WindowBg, theme.semitransparent_window_bg);
112 ImGui::PushStyleColor(ImGuiCol_TextDisabled, ImGui::GetStyle().Colors[ImGuiCol_TextDisabled]);
113 break;
114
116 ImGui::PushStyleColor(ImGuiCol_WindowBg, m_panel_translucent_color);
117 ImGui::PushStyleColor(ImGuiCol_TextDisabled, m_transluc_textdis_color);
118 break;
119
120 default:
121 break;
122 }
123 ImGui::Begin("VehicleInfoTPanel", nullptr, flags);
124
125 // === DECIDE WHAT THE WINDOW WILL DISPLAY ===
126
127 int tabflags_basics = ImGuiTabItemFlags_None;
128 int tabflags_stats = ImGuiTabItemFlags_None;
129 int tabflags_commands = ImGuiTabItemFlags_None;
130 int tabflags_diag = ImGuiTabItemFlags_None;
132 {
133 switch (m_requested_focus)
134 {
135 case TPANELFOCUS_BASICS: tabflags_basics = ImGuiTabItemFlags_SetSelected; break;
136 case TPANELFOCUS_STATS: tabflags_stats = ImGuiTabItemFlags_SetSelected; break;
137 case TPANELFOCUS_DIAG: tabflags_diag = ImGuiTabItemFlags_SetSelected; break;
138 case TPANELFOCUS_COMMANDS: tabflags_commands = ImGuiTabItemFlags_SetSelected; break;
139 default:;
140 }
141
142 // Reset the request
144 }
145
146 // === DRAW THE WINDOW HEADER - MINI IMAGE (if available) AND VEHICLE NAME ===
147
148 ImVec2 name_pos = ImGui::GetCursorPos();
149 ImVec2 tabs_pos;
150 if (actorx->GetActor()->getUsedActorEntry()->filecachename != "")
151 {
152 Ogre::TexturePtr preview_tex = Ogre::TextureManager::getSingleton().load(
154 // Scale the image
155 ImVec2 MAX_PREVIEW_SIZE(100.f, 100.f);
156 ImVec2 size(preview_tex->getWidth(), preview_tex->getHeight());
157 size *= MAX_PREVIEW_SIZE.x / size.x; // Fit size along X
158 if (size.y > MAX_PREVIEW_SIZE.y) // Reduce size along Y if needed
159 {
160 size *= MAX_PREVIEW_SIZE.y / size.y;
161 }
162 // Draw the image
163 ImGui::Image(reinterpret_cast<ImTextureID>(preview_tex->getHandle()), size);
164 tabs_pos = ImGui::GetCursorPos();
165 // Move name to the right
166 name_pos.x += size.x + ImGui::GetStyle().ItemSpacing.x;
167 ImGui::SetCursorPos(name_pos);
168 }
169
171
172 // === DRAW TAB BAR ===
173
174 if (actorx->GetActor()->getUsedActorEntry()->filecachename != "")
175 {
176 ImGui::SetCursorPos(tabs_pos);
177 }
178 ImGui::BeginTabBar("VehicleInfoTPanelTabs", ImGuiTabBarFlags_None);
179 if (ImGui::BeginTabItem(_LC("TPanel", "Basics"), nullptr, tabflags_basics))
180 {
182 this->DrawVehicleBasicsUI(actorx);
183
184 ImGui::EndTabItem();
185 }
186 if (ImGui::BeginTabItem(_LC("TPanel", "Stats"), nullptr, tabflags_stats))
187 {
189 this->DrawVehicleStatsUI(actorx);
190
191 ImGui::EndTabItem();
192 }
193 if (ImGui::BeginTabItem(_LC("TPanel", "Commands"), nullptr, tabflags_commands))
194 {
196 this->DrawVehicleCommandsUI(actorx);
197
198 ImGui::EndTabItem();
199 }
200 if (ImGui::BeginTabItem(_LC("TPanel", "Diag"), nullptr, tabflags_diag))
201 {
203 this->DrawVehicleDiagUI(actorx);
204
205 ImGui::EndTabItem();
206 }
207
208 ImGui::EndTabBar();
209
210 ImGui::End();
211 ImGui::PopStyleColor(2); // WindowBg, TextDisabled
212
213 this->DrawVehicleCommandHighlights(actorx);
214}
215
217{
218 // === DRAW DESCRIPTION (if available) ===
219
220 if (!actorx->GetActor()->getDescription().empty())
221 {
222 ImGui::TextDisabled("%s", _LC("VehicleDescription", "Description text:"));
223 for (auto line : actorx->GetActor()->getDescription())
224 {
225 ImGui::TextWrapped("%s", line.c_str());
226 }
227 }
228
229 // === DRAW HELP TEXTURE (if available) ===
230
231 if (actorx->GetHelpTex())
232 {
233 ImGui::TextDisabled("%s", _LC("VehicleDescription", "Help image:"));
234 if (!App::ui_always_show_fullsize->getBool())
235 {
236 ImGui::SameLine();
237 ImGui::SetCursorPosX(this->GetPanelWidth() - (ImGui::CalcTextSize(_LC("VehicleDescription", "Full size")).x + 25.f));
238 ImGui::Checkbox(_LC("VehicleDescription", "Full size"), &m_helptext_fullsize);
239 }
240 else
241 {
242 m_helptext_fullsize = true;
243 }
245 {
246 m_helptext_fullsize_screenpos = ImGui::GetCursorScreenPos();
247 ImGui::Dummy(ImVec2(MIN_PANEL_WIDTH, HELP_TEXTURE_HEIGHT_FULL));
248 this->DrawVehicleHelpTextureFullsize(actorx);
249 }
250 else
251 {
252 ImTextureID im_tex = reinterpret_cast<ImTextureID>(actorx->GetHelpTex()->getHandle());
253 ImGui::Image(im_tex, ImVec2(MIN_PANEL_WIDTH, HELP_TEXTURE_HEIGHT));
254 }
255 }
256
257 // === DRAW COMMAND KEYS, WITH HIGHLIGHT ===
258
261
262 if (actorx->GetActor()->ar_unique_commandkey_pairs.size() > 0)
263 {
264 ImGui::TextDisabled("%s", _LC("VehicleDescription", "Command controls:"));
265 ImGui::PushStyleColor(ImGuiCol_Text, m_cmdbeam_highlight_color);
266 ImGui::Text("%s", _LC("VehicleDescription", "Hover controls for on-vehicle highlight"));
267 ImGui::PopStyleColor(1); // Text
268
269 for (const UniqueCommandKeyPair& qpair: actorx->GetActor()->ar_unique_commandkey_pairs)
270 {
271 // Calc key-button sizes for right alignment (also to check if they fit on the description line)
272 ImVec2 initial_cursor = ImGui::GetCursorScreenPos();
273 const RoR::events event1 = (RoR::events)RoR::InputEngine::resolveEventName(fmt::format("COMMANDS_{:02d}", qpair.uckp_key1));
274 const RoR::events event2 = (RoR::events)RoR::InputEngine::resolveEventName(fmt::format("COMMANDS_{:02d}", qpair.uckp_key2));
275 std::string desc = qpair.uckp_description;
276 if (qpair.uckp_description == "")
277 {
278 desc = _LC("VehicleDescription", "~unlabeled~");
279 }
280 ImVec2 key1_size = ImCalcEventHighlightedSize(event1);
281 ImVec2 key2_size = ImCalcEventHighlightedSize(event2);
282 ImVec2 desc_size = ImGui::CalcTextSize(desc.c_str());
283 const bool single_line = ImGui::GetWindowContentRegionMax().x > desc_size.x + key1_size.x + key2_size.x;
284 static const float BUMP_HEIGHT = 3.f;
285 static const float MOUSEHIGHLIGHT_MAGICPADRIGHT = 4.f;
286
287 // The line-highlighting: Done manually because `ImGui::Selectable()` blocks buttons under it (or gets blocked by buttons with the `_AllowItemOverlap` flag).
288 ImVec2 highlight_mouse_min = initial_cursor - ImGui::GetStyle().ItemSpacing/2;
289 ImVec2 highlight_mouse_max = highlight_mouse_min + ImVec2(ImGui::GetWindowContentRegionWidth()+MOUSEHIGHLIGHT_MAGICPADRIGHT, ImGui::GetTextLineHeightWithSpacing());
290 if (!single_line)
291 {
292 highlight_mouse_max.y += ImGui::GetTextLineHeightWithSpacing() - BUMP_HEIGHT;
293 }
294
295 if ((ImGui::GetMousePos().x > highlight_mouse_min.x && ImGui::GetMousePos().y > highlight_mouse_min.y)
296 && (ImGui::GetMousePos().x < highlight_mouse_max.x && ImGui::GetMousePos().y < highlight_mouse_max.y))
297 {
298 // This is only for the command-highlight HUD; key1/key2 both point to the same command beams.
299 m_hovered_commandkey = qpair.uckp_key1;
300
301 // Draw the highlight
302 ImVec4 col = m_cmdbeam_highlight_color;
303 col.w = 0.55f;
304 ImDrawList* draw_list = ImGui::GetWindowDrawList();
305 draw_list->AddRectFilled(highlight_mouse_min, highlight_mouse_max, ImColor(col));
306
307 // Description comes first - colored for contrast
308 ImGui::TextColored(m_command_hovered_text_color, "%s", desc.c_str());
309 }
310 else
311 {
312 // Description comes first
313 ImGui::Text("%s", desc.c_str());
314 }
315
316
317 if (single_line)
318 {
319 ImGui::SameLine(); // They fit!
320 }
321 else
322 {
323 ImGui::SetCursorPos(ImGui::GetCursorPos() + ImVec2(0.f, -BUMP_HEIGHT)); // They must go below, but bump them up a bit
324 }
325
326 // Key 1
327 bool key1_hovered = false;
328 bool key1_active = false;
329 ImGui::SetCursorPosX((ImGui::GetWindowContentRegionMax().x) - key1_size.x - key2_size.x - ImGui::GetStyle().ItemSpacing.x);
330 ImDrawEventHighlightedButton(event1, &key1_hovered, &key1_active);
331 if (key1_active)
332 {
333 m_active_commandkey = qpair.uckp_key1;
334 }
335 if (key1_hovered)
336 {
337 m_hovered_commandkey = qpair.uckp_key1;
338 }
339 ImGui::SameLine();
340
341 // Key 2
342 ImGui::SetCursorPosX((ImGui::GetWindowContentRegionMax().x) - key2_size.x);
343 bool key2_hovered = false;
344 bool key2_active = false;
345 ImDrawEventHighlightedButton(event2, &key2_hovered, &key2_active);
346 if (key2_active)
347 {
348 m_active_commandkey = qpair.uckp_key2;
349 }
350 if (key2_hovered)
351 {
352 m_hovered_commandkey = qpair.uckp_key2;
353 }
354 }
355 }
356}
357
358void DrawStatsLineColored(const char* name, const std::string& value, ImVec4 value_color)
359{
361 ImGui::TextColored(theme.value_blue_text_color, "%s", name);
362 // If the value is too long, move it to next line
363 ImVec2 label_size = ImGui::CalcTextSize(name);
364 ImVec2 value_size = ImGui::CalcTextSize(value.c_str());
365 float cursor_x_desired = - ImGui::CalcTextSize(value.c_str()).x;
366 if (label_size.x + value_size.x + ImGui::GetStyle().ItemSpacing.x < ImGui::GetWindowContentRegionWidth())
367 {
368 ImGui::SameLine();
369 }
370 ImGui::SetCursorPosX(ImGui::GetWindowContentRegionMax().x - value_size.x);
371 ImGui::TextColored(value_color, "%s", value.c_str());
372}
373
374void DrawStatsLine(const char* name, const std::string& value)
375{
376 DrawStatsLineColored(name, value, ImGui::GetStyle().Colors[ImGuiCol_Text]);
377}
378
379void DrawStatsBullet(const char* name, const std::string& value)
380{
382 ImGui::PushStyleColor(ImGuiCol_Text, theme.value_blue_text_color);
383 ImGui::Bullet();
384 ImGui::PopStyleColor(); // Text
385 ImGui::SameLine();
386 DrawStatsLineColored(name, value, ImGui::GetStyle().Colors[ImGuiCol_Text]);
387}
388
390{
392 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(ImGui::GetStyle().ItemSpacing.x, 0));
393
394 if (m_stat_health < 1.0f)
395 {
396 const float value = static_cast<float>( Round((1.0f - m_stat_health) * 100.0f, 2) );
397 DrawStatsLine(_LC("SimActorStats", "Vehicle health: "), fmt::format("{:.2f}%", value));
398 }
399 else if (m_stat_health >= 1.0f) //When this condition is true, it means that health is at 0% which means 100% of destruction.
400 {
401 DrawStatsLine(_LC("SimActorStats", "Vehicle destruction: "), "100%");
402 }
403
404 const int num_beams = actorx->GetActor()->ar_num_beams;
405 DrawStatsLine(_LC("SimActorStats", "Beam count: "), fmt::format("{}", num_beams));
406
407 const float broken_pct = static_cast<float>( Round((float)m_stat_broken_beams / (float)num_beams, 2) * 100.0f );
408 DrawStatsLine(_LC("SimActorStats", "Broken beams count: "), fmt::format("{} ({:.0f}%)", m_stat_broken_beams, broken_pct));
409
410 const float deform_pct = static_cast<float>( Round((float)m_stat_deformed_beams / (float)num_beams * 100.0f) );
411 DrawStatsLine(_LC("SimActorStats", "Deformed beams count: "), fmt::format("{} ({:.0f}%)", m_stat_deformed_beams, deform_pct));
412
413 const float avg_deform = static_cast<float>( Round((float)m_stat_avg_deform / (float)num_beams, 4) * 100.0f );
414 DrawStatsLine(_LC("SimActorStats", "Average deformation: "), fmt::format("{:.2f}", avg_deform));
415
416 const float avg_stress = 1.f - (float)m_stat_beam_stress / (float)num_beams;
417 DrawStatsLine(_LC("SimActorStats", "Average stress: "), fmt::format("{:+08.0f}", avg_stress));
418
419 ImGui::NewLine();
420
421 const int num_nodes = actorx->GetActor()->ar_num_nodes;
422 const int num_wheelnodes = actorx->GetActor()->getWheelNodeCount();
423 DrawStatsLine(_LC("SimActorStats", "Node count: "), fmt::format("{} (wheels: {})", num_nodes, num_wheelnodes));
424 if (App::gfx_speedo_imperial->getBool())
425 {
426 DrawStatsLine(_LC("SimActorStats", "Total mass: "), fmt::format("{:8.2f} lb", m_stat_mass_Kg * 2.205));
427 DrawStatsLine(_LC("SimActorStats", ""), fmt::format("{:8.2f} kg",m_stat_mass_Kg));
428 DrawStatsLine(_LC("SimActorStats", ""), fmt::format("{:.2f} tons", m_stat_mass_Kg / 1000.0f));
429 }
430 else
431 {
432 DrawStatsLine(_LC("SimActorStats", "Total mass: "), fmt::format("{:8.2f} kg", m_stat_mass_Kg));
433 DrawStatsLine(_LC("SimActorStats", ""), fmt::format("{:8.2f} lb", m_stat_mass_Kg * 2.205));
434 DrawStatsLine(_LC("SimActorStats", ""), fmt::format("{:.2f} tons", m_stat_mass_Kg / 1000.0f));
435 }
436
437 ImGui::NewLine();
438
439 const float n0_velo_len = actorx->GetSimDataBuffer().simbuf_node0_velo.length();
441 {
442 const double PI = 3.14159265358979323846;
443
444 const float max_rpm = actorx->GetSimDataBuffer().simbuf_engine_max_rpm;
445 const float torque = actorx->GetSimDataBuffer().simbuf_engine_torque;
446 const float turbo_psi = actorx->GetSimDataBuffer().simbuf_engine_turbo_psi;
447 const float cur_rpm = actorx->GetSimDataBuffer().simbuf_engine_rpm;
448 const float wheel_speed = actorx->GetSimDataBuffer().simbuf_wheel_speed;
449
450 const ImVec4 rpm_color = (cur_rpm > max_rpm) ? theme.value_red_text_color : ImGui::GetStyle().Colors[ImGuiCol_Text];
451 DrawStatsLineColored(_LC("SimActorStats", "Engine RPM: "), fmt::format("{:.2f} / {:.2f}", cur_rpm, max_rpm), rpm_color);
452
453 const float inputshaft_rpm = Round(std::max(0.0f, actorx->GetSimDataBuffer().simbuf_inputshaft_rpm));
454 DrawStatsLineColored(_LC("SimActorStats", "Input shaft RPM: "), fmt::format("{:.0f}", inputshaft_rpm), rpm_color);
455
456 DrawStatsLine(_LC("SimActorStats", "Current torque: "), fmt::format("{:.0f} Nm", Round(torque)));
457
458 const float currentKw = (((cur_rpm * (torque + ((turbo_psi * 6.8) * torque) / 100) * ( PI / 30)) / 1000));
459 if (App::gfx_speedo_imperial->getBool())
460 {
461 DrawStatsLine(_LC("SimActorStats", "Current power: "), fmt::format("{:.0f}hp ({:.0f}Kw)", Round(currentKw * 1.34102209), Round(currentKw)));
462 }
463 else
464 {
465 DrawStatsLine(_LC("SimActorStats", "Current power: "), fmt::format("{:.0f}Kw ({:.0f}hp)", Round(currentKw), Round(currentKw * 1.34102209)));
466 }
467
468 DrawStatsLine(_LC("SimActorStats", "Current gear: "), fmt::format("{}", actorx->GetSimDataBuffer().simbuf_gear));
469
470 DrawStatsLine(_LC("SimActorStats", "Drive ratio: "), fmt::format("{:.2f}:1", actorx->GetSimDataBuffer().simbuf_drive_ratio));
471
472 float velocityKPH = wheel_speed * 3.6f;
473 float velocityMPH = wheel_speed * 2.23693629f;
474 float carSpeedKPH = n0_velo_len * 3.6f;
475 float carSpeedMPH = n0_velo_len * 2.23693629f;
476
477 // apply a deadzone ==> no flickering +/-
478 if (fabs(wheel_speed) < 1.0f)
479 {
480 velocityKPH = velocityMPH = 0.0f;
481 }
482 if (fabs(n0_velo_len) < 1.0f)
483 {
484 carSpeedKPH = carSpeedMPH = 0.0f;
485 }
486
487 if (App::gfx_speedo_imperial->getBool())
488 {
489 DrawStatsLine(_LC("SimActorStats", "Wheel speed: "), fmt::format("{:.0f} mph ({:.0f} km/h)", Round(velocityMPH), Round(velocityKPH)));
490
491 DrawStatsLine(_LC("SimActorStats", "Vehicle speed: "), fmt::format("{:.0f} mph ({:.0f} km/h)", Round(carSpeedMPH), Round(carSpeedKPH)));
492 }
493 else
494 {
495 DrawStatsLine(_LC("SimActorStats", "Wheel speed: "), fmt::format("{:.0f} km/h ({:.0f} mph)", Round(velocityKPH), Round(velocityMPH)));
496
497 DrawStatsLine(_LC("SimActorStats", "Vehicle speed: "), fmt::format("{:.0f} km/h ({:.0f} mph)", Round(carSpeedKPH), Round(carSpeedMPH)));
498 }
499 }
500 else // Aircraft or boat
501 {
502 float speedKN = n0_velo_len * 1.94384449f;
503 if (App::gfx_speedo_imperial->getBool())
504 {
505 DrawStatsLine(_LC("SimActorStats", "Current speed: "), fmt::format("{:.0f} kn", Round(speedKN)));
506 DrawStatsLine(_LC("SimActorStats", ""), fmt::format("{:.0f} mph", Round(speedKN * 1.151)));
507 DrawStatsLine(_LC("SimActorStats", ""), fmt::format("{:.0f} km/h", Round(speedKN * 1.852)));
508 }
509 else
510 {
511 DrawStatsLine(_LC("SimActorStats", "Current speed: "), fmt::format("{:.0f} kn", Round(speedKN)));
512 DrawStatsLine(_LC("SimActorStats", ""), fmt::format("{:.0f} km/h", Round(speedKN * 1.852)));
513 DrawStatsLine(_LC("SimActorStats", ""), fmt::format("{:.0f} mph", Round(speedKN * 1.151)));
514 }
515
516 ImGui::NewLine();
517
519 {
520 const float altitude = actorx->GetSimNodeBuffer()[0].AbsPosition.y / 30.48 * 100;
521 DrawStatsLine(_LC("SimActorStats", "Altitude: "), fmt::format("{:.0f} feet ({:.0f} meters)", Round(altitude), Round(altitude * 0.30480)));
522
523 int engine_num = 1; // UI; count from 1
525 {
526 std::string label = fmt::format("{} #{}:", _LC("SimActorStats", "Engine "), engine_num);
527 if (ae.simbuf_ae_type == AeroEngineType::AE_XPROP) // Turboprop/pistonprop
528 {
529 DrawStatsLine(label.c_str(), fmt::format("{:.2f} RPM", ae.simbuf_ae_rpm));
530 }
531 else // Turbojet
532 {
533 DrawStatsLine(label.c_str(), fmt::format("{:.2f}", ae.simbuf_ae_rpm));
534 }
535 ++engine_num;
536 }
537 }
538 else if (actorx->GetSimDataBuffer().simbuf_driveable == BOAT)
539 {
540 int engine_num = 1; // UI; count from 1
541 for (ScrewpropSB& screw: actorx->GetSimDataBuffer().simbuf_screwprops)
542 {
543 std::string label = fmt::format("{} #{}:", _LC("SimActorStats", "Engine "), engine_num);
544 DrawStatsLine(label.c_str(), fmt::format("{:.2f}", screw.simbuf_sp_throttle));
545 ++engine_num;
546 }
547 }
548 }
549
550 ImGui::NewLine();
551
552 const float speedKPH = actorx->GetSimDataBuffer().simbuf_top_speed * 3.6f;
553 const float speedMPH = actorx->GetSimDataBuffer().simbuf_top_speed * 2.23693629f;
554 if (App::gfx_speedo_imperial->getBool())
555 {
556 DrawStatsLine(_LC("SimActorStats", "Top speed: "), fmt::format("{:.0f} mph ({:.0f} km/h)", Round(speedMPH), Round(speedKPH)));
557 }
558 else
559 {
560 DrawStatsLine(_LC("SimActorStats", "Top speed: "), fmt::format("{:.0f} km/h ({:.0f} mph)", Round(speedKPH), Round(speedMPH)));
561 }
562
563 ImGui::NewLine();
564
565 DrawStatsLine(_LC("SimActorStats", "G-Forces:"), "");
566 DrawStatsBullet("Vertical:", fmt::format("{: 6.2f}g ({:1.2f}g)", m_stat_gcur_x, m_stat_gmax_x));
567 DrawStatsBullet("Sagittal:", fmt::format("{: 6.2f}g ({:1.2f}g)", m_stat_gcur_y, m_stat_gmax_y));
568 DrawStatsBullet("Lateral:", fmt::format("{: 6.2f}g ({:1.2f}g)", m_stat_gcur_z, m_stat_gmax_z));
569
570 ImGui::PopStyleVar(); // ItemSpacing
571}
572
574{
575 ImGui::TextDisabled("%s", _LC("TopMenubar", "Live diagnostic views:"));
576 ImGui::TextDisabled("%s", fmt::format(_LC("TopMenubar", "(Toggle with {})"), App::GetInputEngine()->getEventCommandTrimmed(EV_COMMON_TOGGLE_DEBUG_VIEW)).c_str());
577 ImGui::TextDisabled("%s", fmt::format(_LC("TopMenubar", "(Cycle with {})"), App::GetInputEngine()->getEventCommandTrimmed(EV_COMMON_CYCLE_DEBUG_VIEWS)).c_str());
578
579 int debug_view_type = static_cast<int>(actorx->GetDebugView());
580 ImGui::RadioButton(_LC("TopMenubar", "Normal view"), &debug_view_type, static_cast<int>(DebugViewType::DEBUGVIEW_NONE));
581 ImGui::RadioButton(_LC("TopMenubar", "Skeleton view"), &debug_view_type, static_cast<int>(DebugViewType::DEBUGVIEW_SKELETON));
582 ImGui::RadioButton(_LC("TopMenubar", "Node details"), &debug_view_type, static_cast<int>(DebugViewType::DEBUGVIEW_NODES));
583 ImGui::RadioButton(_LC("TopMenubar", "Beam details"), &debug_view_type, static_cast<int>(DebugViewType::DEBUGVIEW_BEAMS));
585 {
586 ImGui::RadioButton(_LC("TopMenubar", "Wheel details"), &debug_view_type, static_cast<int>(DebugViewType::DEBUGVIEW_WHEELS));
587 }
589 {
590 ImGui::RadioButton(_LC("TopMenubar", "Shock details"), &debug_view_type, static_cast<int>(DebugViewType::DEBUGVIEW_SHOCKS));
591 }
593 {
594 ImGui::RadioButton(_LC("TopMenubar", "Rotator details"), &debug_view_type, static_cast<int>(DebugViewType::DEBUGVIEW_ROTATORS));
595 }
597 {
598 ImGui::RadioButton(_LC("TopMenubar", "Slidenode details"), &debug_view_type, static_cast<int>(DebugViewType::DEBUGVIEW_SLIDENODES));
599 }
601 {
602 ImGui::RadioButton(_LC("TopMenubar", "Submesh details"), &debug_view_type, static_cast<int>(DebugViewType::DEBUGVIEW_SUBMESH));
603 }
605 {
606 ImGui::RadioButton(_LC("TopMenubar", "Buoyancy details"), &debug_view_type, static_cast<int>(DebugViewType::DEBUGVIEW_BUOYANCY));
607 }
608
609 if (debug_view_type != static_cast<int>(actorx->GetDebugView()))
610 {
611 actorx->SetDebugView(static_cast<DebugViewType>(debug_view_type));
612 }
613
614 if (debug_view_type >= 1 && debug_view_type <= static_cast<int>(DebugViewType::DEBUGVIEW_BEAMS))
615 {
616 ImGui::Separator();
617 ImGui::TextDisabled("%s", _LC("TopMenubar", "Settings:"));
618 DrawGCheckbox(App::diag_hide_broken_beams, _LC("TopMenubar", "Hide broken beams"));
619 DrawGCheckbox(App::diag_hide_beam_stress, _LC("TopMenubar", "Hide beam stress"));
620 DrawGCheckbox(App::diag_hide_wheels, _LC("TopMenubar", "Hide wheels"));
621 DrawGCheckbox(App::diag_hide_nodes, _LC("TopMenubar", "Hide nodes"));
622 if (debug_view_type >= 2)
623 {
624 DrawGCheckbox(App::diag_hide_wheel_info, _LC("TopMenubar", "Hide wheel info"));
625 }
626 }
627}
628
630{
631 m_visibility_mode = mode;
632 m_requested_focus = focus; // Cannot be handled here, must be handled in Draw() while window is open.
633}
634
636{
637 //taken from TruckHUD.cpp (now removed)
638 beam_t* beam = actor->ar_beams;
639 float average_deformation = 0.0f;
640 float beamstress = 0.0f;
641 float mass = actor->getTotalMass();
642 int beambroken = 0;
643 int beamdeformed = 0;
644 Ogre::Vector3 gcur = actor->getGForces();
645 Ogre::Vector3 gmax = actor->getMaxGForces();
646
647 for (int i = 0; i < actor->ar_num_beams; i++ , beam++)
648 {
649 if (beam->bm_broken != 0)
650 {
651 beambroken++;
652 }
653 beamstress += std::abs(beam->stress);
654 float current_deformation = fabs(beam->L - beam->refL);
655 if (fabs(current_deformation) > 0.0001f && beam->bm_type != BEAM_HYDRO)
656 {
657 beamdeformed++;
658 }
659 average_deformation += current_deformation;
660 }
661
662 m_stat_health = ((float)beambroken / (float)actor->ar_num_beams) * 10.0f + ((float)beamdeformed / (float)actor->ar_num_beams);
663 m_stat_broken_beams = beambroken;
664 m_stat_deformed_beams = beamdeformed;
665 m_stat_beam_stress = beamstress;
666 m_stat_mass_Kg = mass;
667 m_stat_avg_deform = average_deformation;
668 m_stat_gcur_x = gcur.x;
669 m_stat_gcur_y = gcur.y;
670 m_stat_gcur_z = gcur.z;
671 m_stat_gmax_x = gmax.x;
672 m_stat_gmax_y = gmax.y;
673 m_stat_gmax_z = gmax.z;
674}
675
676const ImVec2 BUTTON_SIZE(18, 18);
677const ImVec2 BUTTON_OFFSET(0, 3.f);
678const float BUTTON_Y_OFFSET = 0.f;
679const ImVec2 BUTTONDUMMY_SIZE(18, 1);
680
681void DrawSingleBulletRow(const char* name, RoR::events ev)
682{
683 ImGui::Dummy(BUTTONDUMMY_SIZE); ImGui::SameLine(); ImGui::Bullet(); ImGui::Text("%s", name);
684 ImGui::SameLine();
685 const ImVec2 btn_size = ImCalcEventHighlightedSize(ev);
686 ImGui::SetCursorPosX(ImGui::GetWindowContentRegionWidth() - btn_size.x);
688}
689
691{
693
694 if (!m_icons_cached)
695 {
696 this->CacheIcons();
697 }
698
699 ImGui::TextDisabled("Simulation:");
700 this->DrawRepairButton(actorx);
701 this->DrawActorPhysicsButton(actorx);
702
703 int num_headlights = actorx->GetActor()->countFlaresByType(FlareType::HEADLIGHT);
704 int num_taillights = actorx->GetActor()->countFlaresByType(FlareType::TAIL_LIGHT);
705 int num_blinkleft = actorx->GetActor()->countFlaresByType(FlareType::BLINKER_LEFT);
706 int num_blinkright = actorx->GetActor()->countFlaresByType(FlareType::BLINKER_RIGHT);
707 int num_beacons = actorx->countBeaconProps();
708 bool has_horn = actorx->GetActor()->getTruckType() == TRUCK;
709 if (num_headlights || num_taillights || num_blinkleft || num_blinkright || num_beacons || has_horn)
710 {
711 ImGui::TextDisabled("Lights and signals:");
712 if (num_headlights || num_taillights)
713 {
714 this->DrawHeadLightButton(actorx);
715 }
716 if (num_blinkleft)
717 {
718 this->DrawLeftBlinkerButton(actorx);
719 }
720 if (num_blinkright)
721 {
722 this->DrawRightBlinkerButton(actorx);
723 }
724 if (num_blinkright || num_blinkleft)
725 {
726 this->DrawWarnBlinkerButton(actorx);
727 }
728 if (num_beacons)
729 {
730 this->DrawBeaconButton(actorx);
731 }
732 if (has_horn)
733 {
734 this->DrawHornButton(actorx);
735 }
736 }
737
738 int total_customlights = 0;
739 for (int i = 0; i < MAX_CLIGHTS; i++)
740 {
741 total_customlights += actorx->GetActor()->countCustomLights(i);
742 }
743 if (total_customlights > 0)
744 {
745 this->DrawCustomLightButtons(actorx);
746 }
747
748 const bool has_engine = actorx->GetActor()->ar_engine != nullptr;
749 const bool engine_running = has_engine && actorx->GetActor()->ar_engine->isRunning();
750 const bool has_transfercase = actorx->GetActor()->getTransferCaseMode() != nullptr;
751 const bool has_4wd = has_transfercase && actorx->GetActor()->getTransferCaseMode()->tr_ax_2 != -1;
752 const bool has_2wd = has_transfercase && actorx->GetActor()->getTransferCaseMode()->tr_2wd;
753 const size_t num_tc_gears = (has_transfercase) ? actorx->GetActor()->getTransferCaseMode()->tr_gear_ratios.size() : 0u;
754 if (has_engine)
755 {
756 ImGui::TextDisabled("Engine:");
757 this->DrawEngineButton(actorx);
758 if (!engine_running)
759 {
761 }
762 if (has_transfercase && has_4wd && has_2wd)
763 {
764 this->DrawTransferCaseModeButton(actorx);
765 }
766 if (has_transfercase && num_tc_gears > 1)
767 {
769 }
770
771 this->DrawShiftModeButton(actorx);
772
773 switch (actorx->GetActor()->ar_engine->getAutoMode())
774 {
778 break;
783 break;
789 break;
791 break;
793 break;
794 }
795
796 }
797
798 const int num_axlediffs = actorx->GetActor()->getAxleDiffMode();
799 const int num_wheeldiffs = actorx->GetActor()->getWheelDiffMode();
800 const bool tc_visible = !actorx->GetActor()->tc_nodash;
801 const bool alb_visible = !actorx->GetActor()->alb_nodash;
802 const bool has_parkingbrake = actorx->GetActor()->getTruckType() != NOT_DRIVEABLE && actorx->GetActor()->getTruckType() != BOAT;
803 if (num_axlediffs || num_wheeldiffs || tc_visible || alb_visible || has_parkingbrake || has_engine)
804 {
805 ImGui::TextDisabled("Traction:");
806 if (num_axlediffs)
807 {
808 this->DrawAxleDiffButton(actorx);
809 }
810 if (num_wheeldiffs)
811 {
812 this->DrawWheelDiffButton(actorx);
813 }
814 if (tc_visible)
815 {
816 this->DrawTractionControlButton(actorx);
817 }
818 if (alb_visible)
819 {
820 this->DrawAntiLockBrakeButton(actorx);
821 }
822 if (has_parkingbrake)
823 {
824 this->DrawParkingBrakeButton(actorx);
825 }
826 if (has_engine)
827 {
828 this->DrawCruiseControlButton(actorx);
829 }
830 }
831
832 const size_t num_locks = actorx->GetActor()->ar_hooks.size();
833 const size_t num_ties = actorx->GetActor()->ar_ties.size();
834 if (num_locks || num_ties)
835 {
836 ImGui::TextDisabled("Connections:");
837 if (num_locks)
838 {
839 this->DrawLockButton(actorx);
840 }
841 if (num_ties)
842 {
843 this->DrawSecureButton(actorx);
844 }
845 }
846
847 const size_t num_cparticles = actorx->getCParticles().size();
848 const size_t num_videocams = actorx->getVideoCameras().size();
849 ImGui::TextDisabled("View:");
850 if (num_cparticles)
851 {
852 this->DrawParticlesButton(actorx);
853 }
854 if (num_videocams)
855 {
856 this->DrawMirrorButton(actorx);
857 }
858
859 this->DrawCameraButton();
860}
861
863{
865 {
866 return;
867 }
868
869 ImDrawList* draw_list = GetImDummyFullscreenWindow("RoR_VehicleCommandHighlights");
870 for (const commandbeam_t& cmdbeam: actorx->GetActor()->ar_command_key[m_hovered_commandkey].beams)
871 {
872 const beam_t& beam = actorx->GetActor()->ar_beams[cmdbeam.cmb_beam_index];
873 ImVec2 p1_pos, p2_pos;
875 {
876 draw_list->AddLine(p1_pos, p2_pos, ImColor(m_cmdbeam_highlight_color), m_cmdbeam_highlight_thickness);
877 }
878 }
879}
880
882{
883 // In order to draw the image on top of the T-panel, the window must be focusable,
884 // so we can't simply use `GetImDummyFullscreenWindow()`
885 // ===============================================================================
886
887 int window_flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar
888 | ImGuiWindowFlags_NoSavedSettings ;
889 ImGui::SetNextWindowPos(m_helptext_fullsize_screenpos - ImGui::GetStyle().WindowPadding);
890 ImGui::SetNextWindowSize(ImVec2(HELP_TEXTURE_WIDTH, HELP_TEXTURE_HEIGHT_FULL) + ImGui::GetStyle().WindowPadding);
891 ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0)); // Fully transparent background!
892 ImGui::Begin("T-Panel help tex fullsize", NULL, window_flags);
893 ImDrawList* drawlist = ImGui::GetWindowDrawList();
894 ImTextureID im_tex = reinterpret_cast<ImTextureID>(actorx->GetHelpTex()->getHandle());
895 drawlist->AddImage(im_tex, m_helptext_fullsize_screenpos,
897 ImGui::End();
898 ImGui::PopStyleColor(1); // WindowBg
899}
900
901bool DrawSingleButtonRow(bool active, const Ogre::TexturePtr& icon, const char* name, RoR::events ev, bool* btn_active = nullptr)
902{
903 if (active)
904 {
905 ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyle().Colors[ImGuiCol_ButtonActive]);
906 }
907 else
908 {
909 ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyle().Colors[ImGuiCol_Button]);
910 }
911
912 ImGui::GetWindowDrawList()->AddRectFilled(
913 ImGui::GetCursorScreenPos() - BUTTON_OFFSET, ImGui::GetCursorScreenPos() + BUTTON_SIZE,
914 ImColor(ImGui::GetStyle().Colors[ImGuiCol_Button]), ImGui::GetStyle().FrameRounding);
915 ImGui::GetWindowDrawList()->AddImage(reinterpret_cast<ImTextureID>(icon->getHandle()),
916 ImGui::GetCursorScreenPos() - BUTTON_OFFSET, ImGui::GetCursorScreenPos() + BUTTON_SIZE);
917 ImGui::SetCursorPosX(ImGui::GetCursorPosX() + BUTTON_SIZE.x + 2*ImGui::GetStyle().ItemSpacing.x);
918 ImGui::PopStyleColor();
919
920 ImGui::Text("%s", name);
921 ImGui::SameLine();
922 const ImVec2 btn_size = ImCalcEventHighlightedSize(ev);
923 ImGui::SetCursorPosX(ImGui::GetWindowContentRegionMax().x - btn_size.x);
924 return ImDrawEventHighlightedButton(ev, nullptr, btn_active);
925}
926
934
942
950
958
960{
961 if (actorx->GetActor()->ar_is_police) // Police siren
962 {
964 {
966 }
967 }
968 else
969 {
970 // Triggering continuous command every frame is sloppy
971 // Set state and read it in GameContext via GetHornButtonState()
973 }
974}
975
990
1001
1009
1017
1025
1033
1035{
1037 {
1038 actorx->GetActor()->toggleAxleDiffMode();
1039 actorx->GetActor()->displayAxleDiffMode();
1040 }
1041}
1042
1051
1060
1069
1077
1085
1087{
1089 {
1090 actorx->GetActor()->ar_engine->toggleAutoMode();
1091 // force gui update
1093
1094 // Inform player via chatbox
1095 const char* msg = nullptr;
1096 switch (actorx->GetActor()->ar_engine->getAutoMode())
1097 {
1098 case SimGearboxMode::AUTO: msg = "Automatic shift";
1099 break;
1100 case SimGearboxMode::SEMI_AUTO: msg = "Manual shift - Auto clutch";
1101 break;
1102 case SimGearboxMode::MANUAL: msg = "Fully Manual: sequential shift";
1103 break;
1104 case SimGearboxMode::MANUAL_STICK: msg = "Fully manual: stick shift";
1105 break;
1106 case SimGearboxMode::MANUAL_RANGES: msg = "Fully Manual: stick shift with ranges";
1107 break;
1108 }
1110 }
1111}
1112
1114{
1116 {
1117 if (actorx->GetActor()->ar_engine && actorx->GetActor()->ar_engine->isRunning())
1118 {
1119 actorx->GetActor()->ar_engine->toggleContact();
1120 }
1121 else if (actorx->GetActor()->ar_engine)
1122 {
1123 actorx->GetActor()->ar_engine->startEngine();
1124 }
1125 }
1126}
1127
1129{
1130 int num_custom_flares = 0;
1131
1132 for (int i = 0; i < MAX_CLIGHTS; i++)
1133 {
1134 if (actorx->GetActor()->countCustomLights(i) > 0)
1135 {
1136 ImGui::PushID(i);
1137 num_custom_flares++;
1138
1139 if (i == 5 || i == 9) // Add new line every 4 buttons
1140 {
1141 ImGui::NewLine();
1142 }
1143
1144 std::string label = "L" + std::to_string(i + 1);
1145
1146 if (actorx->GetActor()->getCustomLightVisible(i))
1147 {
1148 ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyle().Colors[ImGuiCol_ButtonActive]);
1149 }
1150 else
1151 {
1152 ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyle().Colors[ImGuiCol_Button]);
1153 }
1154
1155 if (ImGui::Button(label.c_str(), ImVec2(32, 0)))
1156 {
1157 actorx->GetActor()->setCustomLightVisible(i, !actorx->GetActor()->getCustomLightVisible(i));
1158 }
1159 if (ImGui::IsItemHovered())
1160 {
1161 ImGui::BeginTooltip();
1162 ImGui::TextDisabled("%s %d (%s)", "Custom Light", i + 1, App::GetInputEngine()->getEventCommandTrimmed(EV_TRUCK_LIGHTTOGGLE01 + i).c_str());
1163 ImGui::EndTooltip();
1164 }
1165 ImGui::SameLine();
1166
1167 ImGui::PopStyleColor();
1168 ImGui::PopID();
1169 }
1170 }
1171 if (num_custom_flares > 0)
1172 {
1173 ImGui::NewLine();
1174 }
1175}
1176
1177
1178
1180{
1181 if (DrawSingleButtonRow(false, m_camera_icon, "Switch Camera", EV_CAMERA_CHANGE))
1182 {
1183 if (App::GetCameraManager()->EvaluateSwitchBehavior())
1184 {
1186 }
1187 }
1188}
1189
1191{
1193 {
1194 //actorx->GetActor()->hookToggle(-1, HOOK_TOGGLE, -1);
1197 hook_rq->alr_actor_instance_id = actorx->GetActor()->ar_instance_id;
1199
1200 //actorx->GetActor()->toggleSlideNodeLock();
1201 ActorLinkingRequest* slidenode_rq = new ActorLinkingRequest();
1203 slidenode_rq->alr_actor_instance_id = actorx->GetActor()->ar_instance_id;
1205 }
1206}
1207
1209{
1211 {
1212 //actorx->GetActor()->tieToggle(-1, TIE_TOGGLE, -1);
1215 tie_rq->alr_actor_instance_id = actorx->GetActor()->ar_instance_id;
1217 }
1218}
1219
1221{
1223 {
1224 actorx->GetActor()->cruisecontrolToggle();
1225 }
1226}
1227
1229{
1230 // Special element - a hint-only (non-button/highlight) hotkey + 10 inline buttons
1231 // ===============================================================================
1232
1233 ImGui::GetWindowDrawList()->AddImage(reinterpret_cast<ImTextureID>(m_beacons_icon->getHandle()),
1234 ImGui::GetCursorScreenPos() - BUTTON_OFFSET, ImGui::GetCursorScreenPos() + BUTTON_SIZE);
1235 ImGui::SetCursorPosX(ImGui::GetCursorPosX() + BUTTON_SIZE.x + 2 * ImGui::GetStyle().ItemSpacing.x);
1236
1237 ImGui::Text("Custom lights");
1238 ImGui::SameLine();
1239 const char* hotkey = "CTRL+[1...]";
1240 ImVec2 keysize = ImGui::CalcTextSize(hotkey);
1241 ImGui::SetCursorPosX((ImGui::GetWindowContentRegionMax().x) - keysize.x - ImGui::GetStyle().ItemSpacing.x);
1242 ImGui::Text(hotkey);
1243
1244 const ImVec2 BTN_PADDING = ImVec2(1, 1);
1245 const ImVec2 btn_size = ImGui::CalcTextSize("10") + (BTN_PADDING * 2);
1246 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, BTN_PADDING);
1247 for (int i = 0; i < MAX_CLIGHTS; i++)
1248 {
1249 if (actorx->GetActor()->countCustomLights(i) > 0)
1250 {
1251 ImGui::PushID(i);
1252
1253 std::string label = std::to_string(i + 1);
1254
1255 if (actorx->GetActor()->getCustomLightVisible(i))
1256 {
1257 ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyle().Colors[ImGuiCol_ButtonActive]);
1258 }
1259 else
1260 {
1261 ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyle().Colors[ImGuiCol_Button]);
1262 }
1263
1264 if (ImGui::Button(label.c_str(), btn_size))
1265 {
1266 actorx->GetActor()->setCustomLightVisible(i, !actorx->GetActor()->getCustomLightVisible(i));
1267 }
1268 if (ImGui::IsItemHovered())
1269 {
1270 ImGui::BeginTooltip();
1271 ImGui::TextDisabled("%s", App::GetInputEngine()->getEventCommandTrimmed(EV_TRUCK_LIGHTTOGGLE01 + i).c_str());
1272 ImGui::EndTooltip();
1273 }
1274 ImGui::PopStyleColor(); // Button
1275 ImGui::SameLine();
1276 ImGui::PopID();
1277 }
1278 }
1279 ImGui::PopStyleVar(); // FramePadding
1280
1281 ImGui::NewLine();
1282}
1283
1285{
1286 // Icons used https://materialdesignicons.com/
1287 // Licence https://github.com/Templarian/MaterialDesign/blob/master/LICENSE
1288
1289 m_headlight_icon = FetchIcon("car-light-high.png");
1290 m_left_blinker_icon = FetchIcon("arrow-left-bold.png");
1291 m_right_blinker_icon = FetchIcon("arrow-right-bold.png");
1292 m_warning_light_icon = FetchIcon("hazard-lights.png");
1293 m_horn_icon = FetchIcon("bugle.png");
1294 m_mirror_icon = FetchIcon("mirror-rectangle.png");
1295 m_repair_icon = FetchIcon("car-wrench.png");
1296 m_parking_brake_icon = FetchIcon("car-brake-alert.png");
1297 m_traction_control_icon = FetchIcon("car-traction-control.png");
1298 m_abs_icon = FetchIcon("car-brake-abs.png");
1299 m_physics_icon = FetchIcon("pause.png");
1300 m_actor_physics_icon = FetchIcon("pause-circle-outline.png");
1301 m_a_icon = FetchIcon("alpha-a-circle.png");
1302 m_w_icon = FetchIcon("alpha-w-circle.png");
1303 m_m_icon = FetchIcon("alpha-m-circle.png");
1304 m_g_icon = FetchIcon("alpha-g-circle.png");
1305 m_particle_icon = FetchIcon("water.png");
1306 m_shift_icon = FetchIcon("car-shift-pattern.png");
1307 m_engine_icon = FetchIcon("engine.png");
1308 m_beacons_icon = FetchIcon("alarm-light-outline.png");
1309 m_camera_icon = FetchIcon("camera-switch-outline.png");
1310 m_lock_icon = FetchIcon("alpha-l-circle.png");
1311 m_secure_icon = FetchIcon("lock-outline.png");
1312 m_cruise_control_icon = FetchIcon("car-cruise-control.png");
1313
1314 m_icons_cached = true;
1315}
Central state/object manager and communications hub.
#define RGN_CACHE
Definition Application.h:46
#define _L
const float MIN_PANEL_WIDTH
void DrawStatsLineColored(const char *name, const std::string &value, ImVec4 value_color)
const float HELP_TEXTURE_HEIGHT_FULL
const float BUTTON_Y_OFFSET
const ImVec2 BUTTONDUMMY_SIZE(18, 1)
const float HELP_TEXTURE_HEIGHT
bool DrawSingleButtonRow(bool active, const Ogre::TexturePtr &icon, const char *name, RoR::events ev, bool *btn_active=nullptr)
const ImVec2 MAX_PREVIEW_SIZE(100.f, 100.f)
const ImVec2 BUTTON_OFFSET(0, 3.f)
void DrawStatsLine(const char *name, const std::string &value)
void DrawStatsBullet(const char *name, const std::string &value)
void DrawSingleBulletRow(const char *name, RoR::events ev)
const ImVec2 BUTTON_SIZE(18, 18)
const float HELP_TEXTURE_WIDTH
Game state manager and message-queue provider.
Manager for all visuals belonging to a single actor.
#define _LC(ctx, str)
Definition Language.h:38
static const int MAX_CLIGHTS
See RoRnet::Lightmask and enum events in InputEngine.h.
Core data structures for simulation; Everything affected by by either physics, network or user intera...
#define SOUND_TOGGLE(_ACTOR_, _TRIG_)
#define SOUND_GET_STATE(_ACTOR_, _TRIG_)
bool alb_mode
Anti-lock brake state; Enabled? {1/0}.
Definition Actor.h:410
BlinkType getBlinkType()
Definition Actor.cpp:4609
EnginePtr ar_engine
Definition Actor.h:432
void toggleTransferCaseGearRatio()
Definition Actor.cpp:1522
void antilockbrakeToggle()
Definition Actor.cpp:3831
CmdKeyArray ar_command_key
BEWARE: commandkeys are indexed 1-MAX_COMMANDS!
Definition Actor.h:369
void displayTransferCaseMode()
Gets the current transfer case mode name (4WD Hi, ...)
Definition Actor.cpp:1477
int getWheelNodeCount() const
Definition Actor.cpp:902
bool getCustomParticleMode()
Definition Actor.cpp:4617
void beaconsToggle()
Definition Actor.cpp:3849
bool isTied()
Definition Actor.cpp:3924
std::vector< tie_t > ar_ties
Definition Actor.h:365
void toggleHeadlights()
Definition Actor.cpp:3062
void toggleWheelDiffMode()
Definition Actor.cpp:1407
bool getParkingBrake()
Definition Actor.h:180
bool ar_is_police
Gfx/sfx attr.
Definition Actor.h:553
bool ar_physics_paused
Actor physics individually paused by user.
Definition Actor.h:521
std::string getTruckName()
Definition Actor.h:266
void toggleBlinkType(BlinkType blink)
Definition Actor.cpp:3153
void toggleTransferCaseMode()
Definition Actor.cpp:1491
void displayAxleDiffMode()
Cycles through the available inter axle diff modes.
Definition Actor.cpp:1423
void displayWheelDiffMode()
Cycles through the available inter wheel diff modes.
Definition Actor.cpp:1451
bool tc_mode
Enabled?
Definition Actor.h:504
bool alb_nodash
Anti-lock brake attribute: Hide the dashboard indicator?
Definition Actor.h:413
int countFlaresByType(FlareType type)
Definition Actor.cpp:4598
int getWheelDiffMode()
Writes info to console/notify box.
Definition Actor.h:187
bool getCustomLightVisible(int number)
Definition Actor.cpp:4539
TransferCase * getTransferCaseMode()
Toggles between 2WD and 4WD mode.
Definition Actor.h:189
int getAxleDiffMode()
Writes info to console/notify box.
Definition Actor.h:184
int ar_num_beams
Definition Actor.h:349
int countCustomLights(int control_number)
Definition Actor.cpp:4581
std::vector< std::string > getDescription()
Definition Actor.cpp:4507
void toggleAxleDiffMode()
Definition Actor.cpp:1415
ActorInstanceID_t ar_instance_id
Static attr; session-unique ID.
Definition Actor.h:429
void setCustomLightVisible(int number, bool visible)
Definition Actor.cpp:4561
void RequestUpdateHudFeatures()
Definition Actor.h:310
Ogre::Vector3 getMaxGForces()
Definition Actor.h:131
bool getBeaconMode() const
Definition Actor.h:205
bool cc_mode
Cruise Control.
Definition Actor.h:417
void parkingbrakeToggle()
Definition Actor.cpp:3816
int ar_num_nodes
Definition Actor.h:345
float getTotalMass(bool withLocked=true)
Definition Actor.cpp:843
std::vector< hook_t > ar_hooks
Definition Actor.h:366
void tractioncontrolToggle()
Definition Actor.cpp:3840
CacheEntryPtr & getUsedActorEntry()
The actor entry itself.
Definition Actor.cpp:4873
bool tc_nodash
Hide the dashboard indicator?
Definition Actor.h:507
void toggleCustomParticles()
Definition Actor.cpp:3257
int getTruckType()
Definition Actor.h:269
beam_t * ar_beams
Definition Actor.h:348
bool isLocked()
Are hooks locked?
Definition Actor.cpp:3932
Ogre::Vector3 getGForces()
Definition Actor.h:91
void cruisecontrolToggle()
Defined in 'gameplay/CruiseControl.cpp'.
std::vector< UniqueCommandKeyPair > ar_unique_commandkey_pairs
UI helper for displaying command control keys to user (must be built at spawn).
Definition Actor.h:380
bool getHeadlightsVisible() const
Definition Actor.h:218
Ogre::String filecachename
preview image filename
Definition CacheSystem.h:87
@ CONSOLE_MSGTYPE_INFO
Generic message.
Definition Console.h:60
void putMessage(MessageArea area, MessageType type, std::string const &msg, std::string icon="")
Definition Console.cpp:103
@ CONSOLE_SYSTEM_NOTICE
Definition Console.h:51
SimGearboxMode getAutoMode()
Definition Engine.cpp:842
void startEngine()
Quick engine start. Plays sounds.
Definition Engine.cpp:995
void toggleContact()
Ignition.
Definition Engine.cpp:982
void toggleAutoMode()
Definition Engine.cpp:817
bool isRunning()
Definition Engine.h:101
void DrawVehicleStatsUI(RoR::GfxActor *actorx)
void DrawEngineButton(RoR::GfxActor *actorx)
void DrawWarnBlinkerButton(RoR::GfxActor *actorx)
void SetVisible(TPanelMode mode, TPanelFocus focus=TPANELFOCUS_NONE)
void DrawVehicleCommandsUI(RoR::GfxActor *actorx)
void UpdateStats(float dt, ActorPtr actor)
Caution: touches live data, must be synced with sim. thread.
void DrawSecureButton(RoR::GfxActor *actorx)
void DrawParkingBrakeButton(RoR::GfxActor *actorx)
void DrawVehicleDiagUI(RoR::GfxActor *actorx)
void DrawLeftBlinkerButton(RoR::GfxActor *actorx)
void DrawParticlesButton(RoR::GfxActor *actorx)
void DrawRepairButton(RoR::GfxActor *actorx)
void DrawHornButton(RoR::GfxActor *actorx)
void DrawVehicleHelpTextureFullsize(RoR::GfxActor *actorx)
void DrawMirrorButton(RoR::GfxActor *actorx)
void DrawHeadLightButton(RoR::GfxActor *actorx)
void DrawBeaconButton(RoR::GfxActor *actorx)
void DrawCruiseControlButton(RoR::GfxActor *actorx)
void DrawActorPhysicsButton(RoR::GfxActor *actorx)
void DrawAxleDiffButton(RoR::GfxActor *actorx)
void DrawVehicleCommandHighlights(RoR::GfxActor *actorx)
void DrawShiftModeButton(RoR::GfxActor *actorx)
void DrawCustomLightButton(RoR::GfxActor *actorx)
TPanelFocus m_current_focus
Updated based on currently open tab.
void DrawLockButton(RoR::GfxActor *actorx)
void Draw(RoR::GfxActor *actorx)
ImVec2 m_helptext_fullsize_screenpos
The image is drawn into separate window.
void DrawVehicleBasicsUI(RoR::GfxActor *actorx)
void DrawTransferCaseModeButton(RoR::GfxActor *actorx)
void DrawTransferCaseGearRatioButton(RoR::GfxActor *actorx)
void DrawWheelDiffButton(RoR::GfxActor *actorx)
void DrawAntiLockBrakeButton(RoR::GfxActor *actorx)
void DrawCustomLightButtons(RoR::GfxActor *actorx)
TPanelFocus m_requested_focus
Requested by SetVisible()
void DrawTractionControlButton(RoR::GfxActor *actorx)
void DrawRightBlinkerButton(RoR::GfxActor *actorx)
GuiTheme & GetTheme()
Definition GUIManager.h:168
void PushMessage(Message m)
Doesn't guarantee order! Use ChainMessage() if order matters.
std::vector< CParticle > & getCParticles()
Definition GfxActor.h:73
void SetVideoCamState(VideoCamState state)
Definition GfxActor.cpp:443
ActorSB & GetSimDataBuffer()
Definition GfxActor.h:128
bool IsDebugViewApplicable(DebugViewType dv)
std::vector< VideoCamera > & getVideoCameras()
Definition GfxActor.h:75
VideoCamState GetVideoCamState() const
Definition GfxActor.h:144
ActorPtr GetActor()
Definition GfxActor.cpp:337
NodeSB * GetSimNodeBuffer()
Definition GfxActor.h:129
void SetDebugView(DebugViewType dv)
Ogre::TexturePtr GetHelpTex()
Definition GfxActor.h:149
int countBeaconProps() const
DebugViewType GetDebugView() const
Definition GfxActor.h:145
static int resolveEventName(Ogre::String eventName)
bool tr_2wd
Does it support 2WD mode?
std::vector< float > tr_gear_ratios
Gear reduction ratios.
int tr_ax_2
This axle is only driven in 4WD mode.
@ BLINK_RIGHT
Definition SimData.h:117
@ BLINK_LEFT
Definition SimData.h:116
@ BLINK_WARN
Definition SimData.h:118
@ TRUCK
its a truck (or other land vehicle)
Definition SimData.h:85
@ NOT_DRIVEABLE
not drivable at all
Definition SimData.h:84
@ BOAT
its a boat
Definition SimData.h:87
@ AIRPLANE
its an airplane
Definition SimData.h:86
DebugViewType
Definition GfxData.h:102
@ EV_TRUCK_TOGGLE_PHYSICS
toggle physics simulation
@ EV_TRUCK_HORN
truck horn
@ EV_TRUCK_TOGGLE_VIDEOCAMERA
toggle videocamera update
@ EV_TRUCK_TOGGLE_TCASE_GEAR_RATIO
toggle the transfer case gear ratio
@ EV_COMMON_LOCK
connect hook node to a node in close proximity
@ EV_TRUCK_BLINK_RIGHT
toggle right direction indicator (blinker)
@ EV_TRUCK_TOGGLE_INTER_AXLE_DIFF
toggle the inter axle differential mode
@ EV_TRUCK_BLINK_LEFT
toggle left direction indicator (blinker)
@ EV_TRUCK_AUTOSHIFT_UP
shift automatic transmission one gear up
@ EV_TRUCK_PARKING_BRAKE
toggle parking brake
@ EV_TRUCK_MANUAL_CLUTCH
manual clutch (for manual transmission)
@ EV_TRUCK_SHIFT_UP
shift one gear up in manual transmission mode
@ EV_TRUCK_TOGGLE_CONTACT
toggle ignition
@ EV_TRUCK_TRACTION_CONTROL
toggle antilockbrake system
@ EV_COMMON_CYCLE_DEBUG_VIEWS
cycle debug view mode
@ EV_TRUCK_BLINK_WARN
toggle all direction indicators
@ EV_TRUCK_AUTOSHIFT_DOWN
shift automatic transmission one gear down
@ EV_COMMON_SECURE_LOAD
tie a load to the truck
@ EV_TRUCK_SHIFT_NEUTRAL
shift to neutral gear in manual transmission mode
@ EV_TRUCK_SWITCH_SHIFT_MODES
toggle between transmission modes
@ EV_COMMON_REPAIR_TRUCK
repair truck to original condition
@ EV_COMMON_TOGGLE_TRUCK_BEACONS
toggle truck beacons
@ EV_TRUCK_CRUISE_CONTROL
toggle cruise control
@ EV_TRUCK_TOGGLE_TCASE_4WD_MODE
toggle the transfer case 4wd mode
@ EV_COMMON_TOGGLE_TRUCK_LOW_BEAMS
toggle truck low beams (on/off); also toggles running lights.
@ EV_TRUCK_STARTER
hold to start the engine
@ EV_TRUCK_SHIFT_DOWN
shift one gear down in manual transmission mode
@ EV_COMMON_TOGGLE_CUSTOM_PARTICLES
toggle particle cannon
@ EV_TRUCK_ANTILOCK_BRAKE
toggle antilockbrake system
@ EV_CAMERA_CHANGE
change camera mode
@ EV_TRUCK_LIGHTTOGGLE01
toggle custom light 1
@ EV_TRUCK_TOGGLE_INTER_WHEEL_DIFF
toggle the inter wheel differential mode
@ EV_COMMON_TOGGLE_DEBUG_VIEW
toggle debug view mode
@ MSG_SIM_ACTOR_LINKING_REQUESTED
Payload = RoR::ActorLinkingRequest* (owner)
@ MSG_SIM_MODIFY_ACTOR_REQUESTED
Payload = RoR::ActorModifyRequest* (owner)
@ BEAM_HYDRO
Definition SimData.h:64
@ MANUAL_STICK
Fully manual: stick shift.
@ MANUAL_RANGES
Fully manual: stick shift with ranges.
@ SEMI_AUTO
Manual shift with auto clutch.
@ MANUAL
Fully manual: sequential shift.
@ AUTO
Automatic shift.
CVar * ui_show_vehicle_buttons
InputEngine * GetInputEngine()
CameraManager * GetCameraManager()
CVar * diag_hide_wheels
CVar * diag_hide_nodes
GUIManager * GetGuiManager()
GameContext * GetGameContext()
CVar * diag_hide_wheel_info
Console * GetConsole()
CVar * diag_hide_broken_beams
CVar * gfx_speedo_imperial
CVar * ui_always_show_fullsize
CVar * diag_hide_beam_stress
void ImDrawEventHighlighted(events input_event)
Definition GUIUtils.cpp:446
ImDrawList * GetImDummyFullscreenWindow(const std::string &name="RoR_TransparentFullscreenWindow")
Definition GUIUtils.cpp:394
bool ImDrawEventHighlightedButton(events input_event, bool *btn_hovered=nullptr, bool *btn_active=nullptr)
Definition GUIUtils.cpp:462
void ImTextWrappedColorMarked(std::string const &text)
Prints multiline text with '#rrggbb' color markers. Behaves like ImGui::Text* functions.
Definition GUIUtils.cpp:272
ImVec2 ImCalcEventHighlightedSize(events input_event)
Definition GUIUtils.cpp:505
bool GetScreenPosFromWorldPos(Ogre::Vector3 const &world_pos, ImVec2 &out_screen)
Definition GUIUtils.cpp:578
bool DrawGCheckbox(CVar *cvar, const char *label)
Definition GUIUtils.cpp:287
Ogre::Real Round(Ogre::Real value, unsigned short ndigits=0)
Definition Utils.cpp:101
static const CommandkeyID_t COMMANDKEYID_INVALID
Ogre::TexturePtr FetchIcon(const char *name)
Definition GUIUtils.cpp:372
Estabilishing a physics linkage between 2 actors modifies a global linkage table and triggers immedia...
Definition SimData.h:909
ActorLinkingRequestType alr_type
Definition SimData.h:911
ActorInstanceID_t alr_actor_instance_id
Definition SimData.h:910
ActorInstanceID_t amr_actor
Definition SimData.h:875
Ogre::Vector3 simbuf_node0_velo
Definition SimBuffers.h:124
float simbuf_drive_ratio
Definition SimBuffers.h:153
bool simbuf_has_engine
Definition SimBuffers.h:144
float simbuf_engine_rpm
Definition SimBuffers.h:147
int simbuf_driveable
Definition SimBuffers.h:120
std::vector< ScrewpropSB > simbuf_screwprops
Definition SimBuffers.h:135
float simbuf_wheel_speed
Definition SimBuffers.h:127
std::vector< AeroEngineSB > simbuf_aeroengines
Definition SimBuffers.h:138
float simbuf_inputshaft_rpm
Definition SimBuffers.h:152
float simbuf_engine_max_rpm
Definition SimBuffers.h:157
float simbuf_top_speed
Definition SimBuffers.h:128
float simbuf_engine_turbo_psi
Definition SimBuffers.h:149
float simbuf_engine_torque
Definition SimBuffers.h:151
Unified game event system - all requests and state changes are reported using a message.
Definition GameContext.h:52
Ogre::Vector3 AbsPosition
Definition SimBuffers.h:69
UI helper for displaying command control keys to user.
Definition SimData.h:659
Simulation: An edge in the softbody structure.
Definition SimData.h:305
node_t * p1
Definition SimData.h:309
BeamType bm_type
Definition SimData.h:322
bool bm_broken
Definition SimData.h:326
float refL
reference length
Definition SimData.h:330
float stress
Definition SimData.h:318
float L
length
Definition SimData.h:313
node_t * p2
Definition SimData.h:310
Ogre::Vector3 AbsPosition
absolute position in the world (shaky)
Definition SimData.h:267