Rigs of Rods 2026.01
Soft-body Physics Simulation
Loading...
Searching...
No Matches
AppContext.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
22#include "AppContext.h"
23
24#include "AdvancedScreen.h"
25#include "Actor.h"
26#include "CameraManager.h"
27#include "ChatSystem.h"
28#include "Console.h"
29#include "ContentManager.h"
30#include "DashBoardManager.h"
31#include "Engine.h"
32#include "ErrorUtils.h"
33#include "GameContext.h"
34#include "GUIManager.h"
35#include "GUI_LoadingWindow.h"
36#include "GUI_MainSelector.h"
39#include "InputEngine.h"
40#include "Language.h"
41#include "PlatformUtils.h"
42#include "RoRVersion.h"
43#include "OverlayWrapper.h"
44
45#ifdef USE_ANGELSCRIPT
46# include "ScriptEngine.h"
47#endif
48
49#ifdef _WIN32
50# include <windows.h>
51#endif
52
53#include <iomanip>
54#include <sstream>
55#include <string>
56#include <ctime>
57
58using namespace RoR;
59
60// --------------------------
61// Input handling
62
76
77bool AppContext::mouseMoved(const OIS::MouseEvent& arg) // overrides OIS::MouseListener
78{
82
83 if (!ImGui::GetIO().WantCaptureMouse) // true if mouse is over any window
84 {
85 if (!App::GetOverlayWrapper() || !App::GetOverlayWrapper()->handleMouseMoved()) // update the old airplane / autopilot gui
86 {
87 if (!App::GetCameraManager()->handleMouseMoved())
88 {
90 }
91 }
92 }
93
94 return true;
95}
96
97bool AppContext::mousePressed(const OIS::MouseEvent& arg, OIS::MouseButtonID _id) // overrides OIS::MouseListener
98{
100 App::GetGuiManager()->GetImGui().SetMouseButtonState(_id, /*down:*/true);
102
103 if (!ImGui::GetIO().WantCaptureMouse) // true if mouse is over any window
104 {
105 if (!App::GetOverlayWrapper() || !App::GetOverlayWrapper()->handleMousePressed()) // update the old airplane / autopilot gui
106 {
107 if (App::app_state->getEnum<AppState>() == AppState::SIMULATION)
108 {
111 }
112 }
113 }
114
115 return true;
116}
117
118bool AppContext::mouseReleased(const OIS::MouseEvent& arg, OIS::MouseButtonID _id) // overrides OIS::MouseListener
119{
121 App::GetGuiManager()->GetImGui().SetMouseButtonState(_id, /*down:*/false);
123
124 if (!ImGui::GetIO().WantCaptureMouse) // true if mouse is over any window
125 {
126 if (!App::GetOverlayWrapper() || !App::GetOverlayWrapper()->handleMouseReleased()) // update the old airplane / autopilot gui
127 {
128 if (App::app_state->getEnum<AppState>() == AppState::SIMULATION)
129 {
131 }
132 }
133 }
134
135 return true;
136}
137
138bool AppContext::keyPressed(const OIS::KeyEvent& arg)
139{
141
142 if (!App::GetGuiManager()->IsGuiCaptureKeyboardRequested() &&
143 !ImGui::GetIO().WantCaptureKeyboard)
144 {
146 }
147
148 return true;
149}
150
151bool AppContext::keyReleased(const OIS::KeyEvent& arg)
152{
154
155 if (!App::GetGuiManager()->IsGuiCaptureKeyboardRequested() &&
156 !ImGui::GetIO().WantCaptureKeyboard)
157 {
159 }
160 else if (App::GetInputEngine()->isKeyDownEffective(arg.key))
161 {
162 // If capturing is requested, still pass release events for already-pressed keys.
164 }
165
166 return true;
167}
168
169bool AppContext::buttonPressed(const OIS::JoyStickEvent& arg, int) { App::GetInputEngine()->ProcessJoystickEvent(arg); return true; }
170bool AppContext::buttonReleased(const OIS::JoyStickEvent& arg, int) { App::GetInputEngine()->ProcessJoystickEvent(arg); return true; }
171bool AppContext::axisMoved(const OIS::JoyStickEvent& arg, int) { App::GetInputEngine()->ProcessJoystickEvent(arg); return true; }
172bool AppContext::sliderMoved(const OIS::JoyStickEvent& arg, int) { App::GetInputEngine()->ProcessJoystickEvent(arg); return true; }
173bool AppContext::povMoved(const OIS::JoyStickEvent& arg, int) { App::GetInputEngine()->ProcessJoystickEvent(arg); return true; }
174
175void AppContext::windowResized(Ogre::RenderWindow* rw)
176{
177 App::GetInputEngine()->windowResized(rw); // Update mouse area
179 {
181 }
182 if (App::sim_state->getEnum<AppState>() == RoR::AppState::SIMULATION)
183 {
185 {
186 actor->ar_dashboard->windowResized();
187 }
188 }
189}
190
191void AppContext::windowFocusChange(Ogre::RenderWindow* rw)
192{
193 // If you alt+TAB out of the window while any mouse button is down, OIS will not release it until you click in the window again.
194 // See https://github.com/RigsOfRods/rigs-of-rods/issues/2468
195 // To work around, we reset all internal mouse button states here and pay attention not to get them polluted by OIS again.
197 // Same applies to keyboard keys - reset them manually otherwise OIS will hold them 'down' the entire time.
199}
200
201// --------------------------
202// Rendering
203
204void AppContext::SetRenderWindowIcon(Ogre::RenderWindow* rw)
205{
206#ifdef _WIN32
207 size_t hWnd = 0;
208 rw->getCustomAttribute("WINDOW", &hWnd);
209
210 char buf[MAX_PATH];
211 ::GetModuleFileNameA(0, (LPCH)&buf, MAX_PATH);
212
213 HINSTANCE instance = ::GetModuleHandleA(buf);
214 HICON hIcon = ::LoadIconA(instance, MAKEINTRESOURCEA(101));
215 if (hIcon)
216 {
217 ::SendMessageA((HWND)hWnd, WM_SETICON, 1, (LPARAM)hIcon);
218 ::SendMessageA((HWND)hWnd, WM_SETICON, 0, (LPARAM)hIcon);
219 }
220#endif // _WIN32
221}
222
224{
225 // Create 'OGRE root' facade
226 // * leave 'plugins' param empty, we load manually below
227 // * note file 'ogre.cfg' isn't read immediatelly but only after calling 'restoreConfig()' below.
228 std::string log_filepath = PathCombine(App::sys_logs_dir->getStr(), "RoR.log");
229 std::string cfg_filepath = PathCombine(App::sys_config_dir->getStr(), "ogre.cfg");
230 LOG(fmt::format("[RoR|Startup|Rendering] Creating OGRE renderer Root object, config='{}'", cfg_filepath));
231 m_ogre_root = new Ogre::Root("", cfg_filepath, log_filepath);
232
233 // load OGRE plugins manually
234#ifdef _DEBUG
235 std::string plugins_path = PathCombine(RoR::App::sys_process_dir->getStr(), "plugins_d.cfg");
236#else
237 std::string plugins_path = PathCombine(RoR::App::sys_process_dir->getStr(), "plugins.cfg");
238#endif
239 LOG(fmt::format("[RoR|Startup|Rendering] Loading OGRE renderer plugins config '{}'.", plugins_path));
240 try
241 {
242 Ogre::ConfigFile cfg;
243 cfg.load(plugins_path);
244 std::string plugin_dir = cfg.getSetting("PluginFolder", /*section=*/"", /*default=*/App::sys_process_dir->getStr());
245 Ogre::StringVector plugins = cfg.getMultiSetting("Plugin");
246 for (Ogre::String plugin_filename: plugins)
247 {
248 try
249 {
250 m_ogre_root->loadPlugin(PathCombine(plugin_dir, plugin_filename));
251 }
252 catch (Ogre::Exception&) {} // Logged by OGRE
253 }
254 }
255 catch (Ogre::Exception& e)
256 {
258 _L("Startup error"),
259 fmt::format(_L("Could not load file '{}' - make sure the game is installed correctly.\n\nDetailed info: {}"), plugins_path, e.getDescription()));
260 return false;
261 }
262
263 // Load renderer configuration
264 bool autodetect_resolution = false;
265 try
266 {
267 if (!m_ogre_root->restoreConfig())
268 {
269 autodetect_resolution = true;
270 LOG(fmt::format("[RoR|Startup|Rendering] WARNING - invalid 'ogre.cfg', selecting render plugin manually..."));
271
272 const auto render_systems = App::GetAppContext()->GetOgreRoot()->getAvailableRenderers();
273 if (!render_systems.empty())
274 {
275 LOG(fmt::format("[RoR|Startup|Rendering] Auto-selected renderer plugin '{}'", render_systems.front()->getName()));
276 m_ogre_root->setRenderSystem(render_systems.front());
277 }
278 else
279 {
280 ErrorUtils::ShowError (_L("Startup error"), _L("No render system plugin available. Check your plugins.cfg"));
281 return false;
282 }
283 }
284 }
285 catch (Ogre::Exception& e)
286 {
287 ErrorUtils::ShowError (_L("Error restoring settings from 'ogre.cfg'"), e.getDescription());
288 return false;
289 }
290
291 const auto rs = m_ogre_root->getRenderSystemByName(App::app_rendersys_override->getStr());
292 if (rs != nullptr && rs != m_ogre_root->getRenderSystem())
293 {
294 LOG(fmt::format("[RoR|Startup|Rendering] Setting renderer '{}' on behalf of 'app_rendersys_override' (user selection via Settings UI)", rs->getName()));
295 // The user has selected a different render system during the previous session.
296 m_ogre_root->setRenderSystem(rs);
297 m_ogre_root->saveConfig();
298 }
300
301 // Start the renderer
302 LOG(fmt::format("[RoR|Startup|Rendering] Starting renderer '{}' (without auto-creating render window)", m_ogre_root->getRenderSystem()->getName()));
303 m_ogre_root->initialise(/*createWindow=*/false);
304
305 // Review configuration options
306 Ogre::ConfigOptionMap ropts = m_ogre_root->getRenderSystem()->getConfigOptions();
307 std::stringstream ropts_log;
308 for (auto& pair: ropts)
309 {
310 ropts_log << " " << pair.first << " = " << pair.second.currentValue << " (";
311 for (auto& val: pair.second.possibleValues)
312 {
313 ropts_log << val << ", ";
314 }
315 ropts_log << ")\n";
316 }
317 LOG(fmt::format("[RoR|Startup|Rendering] Renderer options as reported by OGRE:\n{}", ropts_log.str()));
318
319 // Configure the render window
320 Ogre::NameValuePairList miscParams;
321 miscParams["FSAA"] = ropts["FSAA"].currentValue;
322 miscParams["vsync"] = ropts["VSync"].currentValue;
323 miscParams["gamma"] = ropts["sRGB Gamma Conversion"].currentValue;
324 if (!App::diag_allow_window_resize->getBool())
325 {
326 miscParams["border"] = "fixed";
327 }
328#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
329 const auto rd = ropts["Rendering Device"];
330 const auto it = std::find(rd.possibleValues.begin(), rd.possibleValues.end(), rd.currentValue);
331 const int idx = std::distance(rd.possibleValues.begin(), it);
332 miscParams["monitorIndex"] = Ogre::StringConverter::toString(idx);
333 miscParams["windowProc"] = Ogre::StringConverter::toString((size_t)OgreBites::WindowEventUtilities::_WndProc);
334#endif
335
336 // Validate rendering resolution
337 Ogre::uint32 width, height;
338 std::istringstream mode (ropts["Video Mode"].currentValue);
339 Ogre::String token;
340 mode >> width;
341 mode >> token; // 'x' as seperator between width and height
342 mode >> height;
343
344 if(width < 800) width = 800;
345 if(height < 600) height = 600;
346
347 if (autodetect_resolution)
348 {
349 for (auto& p_mode_str: ropts["Video Mode"].possibleValues)
350 {
351 Ogre::uint32 p_width, p_height;
352 std::istringstream p_mode (p_mode_str);
353 p_mode >> p_width;
354 p_mode >> token; // 'x' as seperator between width and height
355 p_mode >> p_height;
356 if (p_width >= width && p_height >= height)
357 {
358 width = p_width;
359 height = p_height;
360 m_ogre_root->getRenderSystem()->setConfigOption("Video Mode", p_mode_str);
361 }
362 }
363
364 LOG(fmt::format("[RoR|Startup|Rendering] WARNING - invalid 'ogre.cfg', auto-detected resolution {}x{}", width, height));
365 m_ogre_root->saveConfig();
366 }
367
368 // Review render window settings
369 std::stringstream miscParams_log;
370 for (auto& pair: miscParams)
371 {
372 miscParams_log << " " << pair.first << " = " << pair.second << "\n";
373 }
374 LOG(fmt::format("[RoR|Startup|Rendering] Creating render window with settings:\n{}", miscParams_log.str()));
375
376 // Create render window
377 m_render_window = Ogre::Root::getSingleton().createRenderWindow (
378 "Rigs of Rods version " + Ogre::String (ROR_VERSION_STRING),
379 width, height, ropts["Full Screen"].currentValue == "Yes", &miscParams);
380 OgreBites::WindowEventUtilities::_addRenderWindow(m_render_window);
381 OgreBites::WindowEventUtilities::addWindowEventListener(m_render_window, this);
382
384 m_render_window->setActive(true);
385
386 // Create viewport (without camera)
387 m_viewport = m_render_window->addViewport(/*camera=*/nullptr);
388 m_viewport->setBackgroundColour(Ogre::ColourValue::Black);
389
390 return true;
391}
392
393Ogre::RenderWindow* AppContext::CreateCustomRenderWindow(std::string const& window_name, int width, int height)
394{
395 Ogre::NameValuePairList misc;
396 Ogre::ConfigOptionMap ropts = m_ogre_root->getRenderSystem()->getConfigOptions();
397 misc["FSAA"] = Ogre::StringConverter::parseInt(ropts["FSAA"].currentValue, 0);
398
399 Ogre::RenderWindow* rw = Ogre::Root::getSingleton().createRenderWindow(window_name, width, height, false, &misc);
400 return rw;
401}
402
404{
405 const std::time_t time = std::time(nullptr);
406 const int index = (time == m_prev_screenshot_time) ? m_prev_screenshot_index+1 : 1;
407
408 std::stringstream stamp;
409 stamp << std::put_time(std::localtime(&time), "%Y-%m-%d_%H-%M-%S") << "_" << index
411 std::string path = PathCombine(App::sys_screenshot_dir->getStr(), "screenshot_") + stamp.str();
412
413 if (App::app_screenshot_format->getStr() == "png")
414 {
416
417 png.addData("User_NickName", App::mp_player_name->getStr());
418 png.addData("User_Language", App::app_language->getStr());
419
420 if (App::app_state->getEnum<AppState>() == AppState::SIMULATION &&
421 App::GetGameContext()->GetPlayerActor())
422 {
423 png.addData("Truck_file", App::GetGameContext()->GetPlayerActor()->ar_filename);
424 png.addData("Truck_name", App::GetGameContext()->GetPlayerActor()->getTruckName());
425 }
426 if (App::GetGameContext()->GetTerrain())
427 {
428 png.addData("Terrn_file", App::sim_terrain_name->getStr());
429 png.addData("Terrn_name", App::sim_terrain_gui_name->getStr());
430 }
431 if (App::mp_state->getEnum<MpState>() == MpState::CONNECTED)
432 {
433 png.addData("MP_ServerName", App::mp_server_host->getStr());
434 }
435
436 png.write();
437 }
438 else
439 {
440 m_render_window->writeContentsToFile(path);
441 }
442
444 _L("Screenshot: ") + stamp.str());
445
448}
449
451{
452 if (!val && !m_windowed_fix)
453 {
454 // Workaround OGRE glitch - badly aligned viewport after first full->window switch
455 // Observed on Win10/OpenGL (GeForce GTX 660)
456 m_render_window->setFullscreen(false, m_render_window->getWidth()-1, m_render_window->getHeight()-1);
457 m_render_window->setFullscreen(false, m_render_window->getWidth()+1, m_render_window->getHeight()+1);
458 }
459 else
460 {
461 m_render_window->setFullscreen(val, m_render_window->getWidth(), m_render_window->getHeight());
462 }
463}
464
465// --------------------------
466// Profiling
467
469{
470#if OGRE_PROFILING == 1 // Singleton is null otherwise
471
472 // WORKAROUND for OGRE v14.5.2 bug - repeated `setEnabled()` true causes shutdown-reinit cycle.
473 // See https://github.com/OGRECave/ogre/commit/05dd52dc7c9abfc3a15734dab59deede7288404a
475 {
477 Ogre::Profiler::getSingleton().setEnabled(m_profiler_enabled);
478 }
479
480 if (App::diag_profiler_rate->getInt() < 1) // Check valid uint & Avoid division by zero in OGRE
481 {
483 fmt::format(_L("Invalid profiler update rate ({}), resetting to default"), App::diag_profiler_rate->getInt()));
484 App::diag_profiler_rate->setVal(10); // Default in OGRE
485 }
486 Ogre::Profiler::getSingleton().setUpdateDisplayFrequency((Ogre::uint)App::diag_profiler_rate->getInt());
487#endif
488}
489
490// --------------------------
491// Program paths and logging
492
494{
495 // Process directory
496 std::string exe_path = RoR::GetExecutablePath();
497 if (exe_path.empty())
498 {
499 ErrorUtils::ShowError(_L("Startup error"), _L("Error while retrieving program directory path"));
500 return false;
501 }
502 App::sys_process_dir->setStr(RoR::GetParentDirectory(exe_path.c_str()).c_str());
503
504 // RoR's home directory
505 std::string local_userdir = PathCombine(App::sys_process_dir->getStr(), "config"); // TODO: Think of a better name, this is ambiguious with ~/.rigsofrods/config which stores configfiles! ~ only_a_ptr, 02/2018
506 if (FolderExists(local_userdir))
507 {
508 // It's a portable installation
509 App::sys_user_dir->setStr(local_userdir.c_str());
510 }
511 else
512 {
513 // Default location - user's home directory
514 std::string user_home = RoR::GetUserHomeDirectory();
515 if (user_home.empty())
516 {
517 ErrorUtils::ShowError(_L("Startup error"), _L("Error while retrieving user directory path"));
518 return false;
519 }
520 RoR::Str<500> ror_homedir;
521#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
522 ror_homedir << user_home << PATH_SLASH << "My Games";
523 CreateFolder(ror_homedir.ToCStr());
524 ror_homedir << PATH_SLASH << "Rigs of Rods";
525#elif OGRE_PLATFORM == OGRE_PLATFORM_LINUX
526 char* env_SNAP = getenv("SNAP_USER_COMMON");
527 if(env_SNAP)
528 ror_homedir = env_SNAP;
529 else
530 ror_homedir << user_home << PATH_SLASH << ".rigsofrods";
531#elif OGRE_PLATFORM == OGRE_PLATFORM_APPLE
532 ror_homedir << user_home << PATH_SLASH << "RigsOfRods";
533#endif
534 CreateFolder(ror_homedir.ToCStr ());
535 App::sys_user_dir->setStr(ror_homedir.ToCStr ());
536 }
537
538 return true;
539}
540
542{
543 std::string logs_dir = PathCombine(App::sys_user_dir->getStr(), "logs");
544 CreateFolder(logs_dir);
545 App::sys_logs_dir->setStr(logs_dir.c_str());
546
547 auto ogre_log_manager = OGRE_NEW Ogre::LogManager();
548 std::string rorlog_path = PathCombine(logs_dir, "RoR.log");
549 Ogre::Log* rorlog = ogre_log_manager->createLog(rorlog_path, true, true);
550 rorlog->stream() << "[RoR] Rigs of Rods (www.rigsofrods.org) version " << ROR_VERSION_STRING;
551 std::time_t t = std::time(nullptr);
552 rorlog->stream() << "[RoR] Current date: " << std::put_time(std::localtime(&t), "%Y-%m-%d");
553
554 rorlog->addListener(App::GetConsole()); // Allow console to intercept log messages
555}
556
558{
559 std::string process_dir = PathCombine(App::sys_process_dir->getStr(), "resources");
560#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
561 if (!FolderExists(process_dir))
562 {
563 process_dir = "/usr/share/rigsofrods/resources/";
564 }
565#endif
566 if (!FolderExists(process_dir))
567 {
568 ErrorUtils::ShowError(_L("Startup error"), _L("Resources folder not found. Check if correctly installed."));
569 return false;
570 }
571 App::sys_resources_dir->setStr(process_dir);
572 return true;
573}
574
576{
577 Ogre::String src_path = PathCombine(App::sys_resources_dir->getStr(), "skeleton.zip");
578 Ogre::ResourceGroupManager::getSingleton().addResourceLocation(src_path, "Zip", "SrcRG");
579 Ogre::FileInfoListPtr fl = Ogre::ResourceGroupManager::getSingleton().findResourceFileInfo("SrcRG", "*", true);
580 if (fl->empty())
581 {
582 ErrorUtils::ShowError(_L("Startup error"), _L("Faulty resource folder. Check if correctly installed."));
583 return false;
584 }
585 Ogre::String dst_path = PathCombine(App::sys_user_dir->getStr(), "");
586 for (auto file : *fl)
587 {
588 CreateFolder(dst_path + file.basename);
589 }
590 fl = Ogre::ResourceGroupManager::getSingleton().findResourceFileInfo("SrcRG", "*");
591 if (fl->empty())
592 {
593 ErrorUtils::ShowError(_L("Startup error"), _L("Faulty resource folder. Check if correctly installed."));
594 return false;
595 }
596 Ogre::ResourceGroupManager::getSingleton().addResourceLocation(dst_path, "FileSystem", "DstRG", false, false);
597 for (auto file : *fl)
598 {
599 if (file.uncompressedSize == 0)
600 continue;
601 Ogre::String path = file.path + file.basename;
602 if (!Ogre::ResourceGroupManager::getSingleton().findResourceFileInfo("DstRG", path)->empty())
603 continue;
604 Ogre::DataStreamPtr src_ds = Ogre::ResourceGroupManager::getSingleton().openResource(path, "SrcRG");
605 Ogre::DataStreamPtr dst_ds = Ogre::ResourceGroupManager::getSingleton().createResource(path, "DstRG");
606 std::vector<char> buf(src_ds->size());
607 size_t read = src_ds->read(buf.data(), src_ds->size());
608 if (read > 0)
609 {
610 dst_ds->write(buf.data(), read);
611 }
612 }
613 Ogre::ResourceGroupManager::getSingleton().destroyResourceGroup("SrcRG");
614 Ogre::ResourceGroupManager::getSingleton().destroyResourceGroup("DstRG");
615
616 return true;
617}
618
620{
621#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
622 Ogre::String old_ror_homedir = Ogre::StringUtil::format("%s\\Rigs of Rods 0.4", RoR::GetUserHomeDirectory().c_str());
623 if(FolderExists(old_ror_homedir))
624 {
625 if (!FileExists(Ogre::StringUtil::format("%s\\OBSOLETE_FOLDER.txt", old_ror_homedir.c_str())))
626 {
627 Ogre::String obsoleteMessage = Ogre::StringUtil::format("This folder is obsolete, please move your mods to %s", App::sys_user_dir->getStr());
628 try
629 {
630 Ogre::ResourceGroupManager::getSingleton().addResourceLocation(old_ror_homedir, "FileSystem", "homedir", false, false);
631 Ogre::DataStreamPtr stream = Ogre::ResourceGroupManager::getSingleton().createResource("OBSOLETE_FOLDER.txt", "homedir");
632 stream->write(obsoleteMessage.c_str(), obsoleteMessage.length());
633 Ogre::ResourceGroupManager::getSingleton().destroyResourceGroup("homedir");
634 }
635 catch (std::exception & e)
636 {
637 RoR::LogFormat("Error writing to %s, message: '%s'", old_ror_homedir.c_str(), e.what());
638 }
639 Ogre::String message = Ogre::StringUtil::format(
640 "Welcome to Rigs of Rods %s\nPlease note that the mods folder has moved to:\n\"%s\"\nPlease move your mods to the new folder to continue using them",
642 App::sys_user_dir->getStr()
643 );
644
645 RoR::App::GetGuiManager()->ShowMessageBox("Obsolete folder detected", message.c_str());
646 }
647 }
648#endif // OGRE_PLATFORM_WIN32
649}
650
652{
653 m_mainthread_id = std::this_thread::get_id();
654
655 // This cannot be done earlier as it uses the above thread ID to assert() against invalid access.
657}
System integration layer; inspired by OgreBites::ApplicationContext.
void LOG(const char *msg)
Legacy alias - formerly a macro.
#define _L
Game state manager and message-queue provider.
Handles controller inputs from player.
Platform-specific utilities. We use narrow UTF-8 encoded strings as paths. Inspired by http://utf8eve...
const char *const ROR_VERSION_STRING_SHORT
const char *const ROR_VERSION_STRING
void addData(Ogre::String name, Ogre::String value)
void InjectKeyReleased(const OIS::KeyEvent &arg)
void InjectMouseMoved(const OIS::MouseEvent &arg)
void ResetAllMouseButtons()
void SetMouseButtonState(OIS::MouseButtonID id, bool down)
void InjectKeyPressed(const OIS::KeyEvent &arg)
ActorPtrVec & GetActors()
Ogre::Root * GetOgreRoot()
Definition AppContext.h:68
RoR::ForceFeedback m_force_feedback
Definition AppContext.h:109
bool SetUpConfigSkeleton()
virtual bool buttonPressed(const OIS::JoyStickEvent &arg, int button) override
void SetUpObsoleteConfMarker()
virtual bool mouseMoved(const OIS::MouseEvent &arg) override
Ogre::RenderWindow * CreateCustomRenderWindow(std::string const &name, int width, int height)
bool SetUpProgramPaths()
bool m_windowed_fix
Workaround OGRE glitch when switching from fullscreen.
Definition AppContext.h:103
virtual bool mousePressed(const OIS::MouseEvent &arg, OIS::MouseButtonID id) override
bool SetUpResourcesDir()
virtual bool sliderMoved(const OIS::JoyStickEvent &arg, int) override
Ogre::Viewport * m_viewport
Definition AppContext.h:102
virtual bool povMoved(const OIS::JoyStickEvent &arg, int) override
virtual bool buttonReleased(const OIS::JoyStickEvent &arg, int button) override
virtual bool axisMoved(const OIS::JoyStickEvent &arg, int axis) override
virtual bool mouseReleased(const OIS::MouseEvent &arg, OIS::MouseButtonID id) override
int m_prev_screenshot_index
Definition AppContext.h:107
void SetRenderWindowIcon(Ogre::RenderWindow *rw)
virtual void windowFocusChange(Ogre::RenderWindow *rw) override
void CaptureScreenshot()
virtual bool keyPressed(const OIS::KeyEvent &arg) override
bool m_profiler_enabled
Last known state, to workaround OGRE v14.5.2 bug.
Definition AppContext.h:104
Ogre::RenderWindow * m_render_window
Definition AppContext.h:101
virtual bool keyReleased(const OIS::KeyEvent &arg) override
std::thread::id m_mainthread_id
Definition AppContext.h:111
Ogre::Root * m_ogre_root
Definition AppContext.h:100
std::time_t m_prev_screenshot_time
Definition AppContext.h:106
void ActivateFullscreen(bool val)
virtual void windowResized(Ogre::RenderWindow *rw) override
std::string const & getStr() const
Definition CVar.h:95
bool getBool() const
Definition CVar.h:98
void setStr(std::string const &str)
Definition CVar.h:83
void setVal(T val)
Definition CVar.h:72
Definition CacheSystem.h:56
@ 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
@ CONSOLE_SYSTEM_WARNING
Definition Console.h:53
OgreImGui & GetImGui()
Definition GUIManager.h:170
void ShowMessageBox(const char *title, const char *text, bool allow_close=true, const char *btn1_text="OK", const char *btn2_text=nullptr)
SceneMouse & GetSceneMouse()
CacheEntryPtr m_dummy_cache_selection
ActorManager * GetActorManager()
void SetKeyboardListener(OIS::KeyListener *obj)
void ProcessKeyRelease(const OIS::KeyEvent &arg)
void processMouseMotionEvent(const OIS::MouseEvent &arg)
void SetJoystickListener(OIS::JoyStickListener *obj)
void ProcessJoystickEvent(const OIS::JoyStickEvent &arg)
void windowResized(Ogre::RenderWindow *rw)
void processMouseReleaseEvent(const OIS::MouseEvent &arg, OIS::MouseButtonID _id)
void resetKeysAndMouseButtons()
void ProcessKeyPress(const OIS::KeyEvent &arg)
void SetMouseListener(OIS::MouseListener *obj)
void processMousePressEvent(const OIS::MouseEvent &arg, OIS::MouseButtonID _id)
bool handleMousePressed()
bool handleMouseMoved()
bool handleMouseReleased()
Wrapper for classic c-string (local buffer) Refresher: strlen() excludes '\0' terminator; strncat() A...
Definition Str.h:36
const char * ToCStr() const
Definition Str.h:46
void CreateFolder(const char *path)
Path must be UTF-8 encoded.
std::string GetExecutablePath()
Returns UTF-8 path or empty string on error.
std::string GetUserHomeDirectory()
Returns UTF-8 path or empty string on error.
bool FolderExists(const char *path)
Path must be UTF-8 encoded.
char PATH_SLASH
std::string GetParentDirectory(const char *src_buff)
Returns UTF-8 path without trailing slash.
std::string PathCombine(std::string a, std::string b)
bool FileExists(const char *path)
Path must be UTF-8 encoded.
CVar * mp_player_name
CVar * diag_profiler_rate
CVar * io_ffb_enabled
AppContext * GetAppContext()
CVar * app_screenshot_format
CVar * sim_state
OverlayWrapper * GetOverlayWrapper()
InputEngine * GetInputEngine()
CVar * diag_allow_window_resize
CVar * app_language
CVar * sys_logs_dir
CVar * sim_terrain_name
CVar * app_rendersys_override
CVar * sim_terrain_gui_name
CameraManager * GetCameraManager()
CVar * diag_profiler_enabled
GUIManager * GetGuiManager()
GameContext * GetGameContext()
CVar * sys_config_dir
CVar * app_state
CVar * mp_state
CVar * sys_user_dir
Console * GetConsole()
CVar * sys_screenshot_dir
void CreateInputEngine()
CVar * sys_resources_dir
CVar * mp_server_host
CVar * sys_process_dir
void LogFormat(const char *format,...)
Improved logging utility. Uses fixed 2Kb buffer.
static int ShowError(const std::string &title, const std::string &message)
shows a simple error message box