16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-18 10:09:17 +02:00
Files
maszyna/application/scenarioloadermode.cpp
2026-06-13 15:43:44 +02:00

182 lines
5.5 KiB
C++

/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#include "stdafx.h"
#include "application/scenarioloadermode.h"
#include "utilities/Globals.h"
#include "simulation/simulation.h"
#include "simulation/simulationtime.h"
#include "simulation/simulationenvironment.h"
#include "application/application.h"
#include "application/scenarioloaderuilayer.h"
#include "rendering/renderer.h"
#include "utilities/Logs.h"
#include "utilities/translation.h"
#include "scene/eu7/eu7_load_stats.h"
#include "scene/eu7/eu7_pack_bench.h"
#include "scene/eu7/eu7_section_stream.h"
namespace {
constexpr std::chrono::seconds kEu7LoadTimeout { 90 };
constexpr float kDeserializeBarShare { 70.f };
constexpr float kPackBarShare { 30.f };
} // namespace
scenarioloader_mode::scenarioloader_mode() {
m_userinterface = std::make_shared<scenarioloader_ui>();
}
// initializes internal data structures of the mode. returns: true on success, false otherwise
bool scenarioloader_mode::init() {
// nothing to do here
return true;
}
void scenarioloader_mode::update_bar_progress( float const progress ) {
m_bar_progress = std::max( m_bar_progress, std::clamp( progress, 0.f, 100.f ) );
if( m_userinterface != nullptr ) {
m_userinterface->set_progress( m_bar_progress, 0.f );
}
}
// mode-specific update of simulation data. returns: false on error, true otherwise
bool scenarioloader_mode::update() {
if (!Global.ready_to_load)
// waiting for network connection
return true;
if (!state) {
WriteLog("using simulation seed: " + std::to_string(Global.random_seed), logtype::generic);
WriteLog("using simulation starting timestamp: " + std::to_string(Global.starting_timestamp), logtype::generic);
Application.set_title( Global.AppName + " (" + Global.SceneryFile + ")" );
WriteLog( "\nLoading scenario \"" + Global.SceneryFile + "\"..." );
timestart = std::chrono::system_clock::now();
state = simulation::State.deserialize_begin(Global.SceneryFile);
}
try {
if( m_phase == load_phase::deserialize ) {
if( simulation::State.deserialize_continue( state ) ) {
return true;
}
m_phase = load_phase::eu7_load;
m_eu7_load_started = std::chrono::steady_clock::now();
m_eu7_stream_primed = false;
}
}
catch (invalid_scenery_exception &e) {
ErrorLog( "Bad init: scenario loading failed" );
Application.pop_mode();
return true;
}
if( m_phase == load_phase::eu7_load ) {
if( scene::eu7::section_stream_active() ) {
simulation::State.drain_deferred_eu7_trainsets( 16.0 );
auto const position { scene::eu7::stream_loading_position() };
if( false == m_eu7_stream_primed ) {
if( scene::eu7::section_stream_needs_bootstrap() ) {
scene::eu7::kick_section_stream_bootstrap();
}
m_eu7_stream_primed = true;
}
scene::eu7::drain_section_stream();
auto const ring_progress {
scene::eu7::section_stream_ring_progress(
position,
scene::eu7::kSectionStreamBootstrapRadiusKm ) };
update_bar_progress(
kDeserializeBarShare + ring_progress * kPackBarShare );
auto const timed_out {
std::chrono::steady_clock::now() - m_eu7_load_started >= kEu7LoadTimeout };
auto const bootstrap_ready {
scene::eu7::section_stream_ready_around(
position,
scene::eu7::kSectionStreamBootstrapRadiusKm ) };
if(
bootstrap_ready
|| scene::eu7::section_stream_presentable_around(
position,
scene::eu7::kSectionStreamBootstrapRadiusKm ) ) {
WriteLog( "EU7 PACK: pierścień wokół pozycji startowej gotowy do pokazania" );
scene::eu7::dismiss_loading_screen();
m_phase = load_phase::finished;
}
else if( timed_out ) {
ErrorLog(
"EU7 PACK: timeout ładowania pierścienia wokół kamery — wchodzę w jazdę (ring=" +
std::to_string( static_cast<int>( ring_progress * 100.f ) ) + "%)" );
scene::eu7::dismiss_loading_screen();
m_phase = load_phase::finished;
}
else {
return true;
}
}
else {
scene::eu7::dismiss_loading_screen();
m_phase = load_phase::finished;
}
}
WriteLog( "Scenario loading time: " + std::to_string( std::chrono::duration_cast<std::chrono::seconds>( ( std::chrono::system_clock::now() - timestart ) ).count() ) + " seconds" );
scene::eu7::log_load_stats();
scene::eu7::log_pack_bench();
update_bar_progress( 100.f );
Application.pop_mode();
Application.push_mode( eu07_application::mode::driver );
return true;
}
bool scenarioloader_mode::is_command_processor() const {
return false;
}
// maintenance method, called when the mode is activated
void scenarioloader_mode::enter() {
// TBD: hide cursor in fullscreen mode?
Application.set_cursor( GLFW_CURSOR_NORMAL );
m_phase = load_phase::deserialize;
m_eu7_stream_primed = false;
m_bar_progress = 0.f;
simulation::is_ready = false;
Application.set_title( Global.AppName + " (" + Global.SceneryFile + ")" );
m_userinterface->set_progress(STR("Loading scenery"));
}
// maintenance method, called when the mode is deactivated
void scenarioloader_mode::exit() {
simulation::Time.init( Global.starting_timestamp );
simulation::Environment.init();
}
void scenarioloader_mode::set_progress(
float const Progress,
float const Subtaskprogress ) {
if( m_phase != load_phase::deserialize ) {
return;
}
auto const parser_progress {
std::max( Progress, Subtaskprogress ) };
update_bar_progress( parser_progress * kDeserializeBarShare / 100.f );
}