16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-21 21:49:19 +02:00

EU7 scenery format and models streaming

This commit is contained in:
maj00r
2026-06-13 15:43:44 +02:00
parent f07c8fdcd2
commit 876a4c7c18
171 changed files with 27924 additions and 281 deletions

View File

@@ -12,6 +12,9 @@ http://mozilla.org/MPL/2.0/.
#include "application/drivermode.h"
#include "application/editormode.h"
#include "application/scenarioloadermode.h"
#include "application/scenarioloaderuilayer.h"
#include "scene/eu7/eu7_load_stats.h"
#include "scene/eu7/eu7_section_stream.h"
#include "launcher/launchermode.h"
#include "utilities/Globals.h"
@@ -707,9 +710,59 @@ void eu07_application::exit()
#endif
}
void
eu07_application::extend_loading_overlay( std::chrono::milliseconds const duration ) {
if( duration.count() <= 0 ) {
return;
}
auto const until { std::chrono::steady_clock::now() + duration };
if( until > m_loading_overlay_until ) {
m_loading_overlay_until = until;
}
if( m_loading_overlay == nullptr ) {
m_loading_overlay = std::make_shared<scenarioloader_ui>();
}
}
bool
eu07_application::loading_overlay_active() const {
if( m_modestack.empty() || m_modestack.top() != mode::driver ) {
return false;
}
if( false == simulation::is_ready ) {
return true;
}
return false;
}
void
eu07_application::sync_loading_overlay_state() {
if( m_loading_overlay == nullptr ) {
m_loading_overlay = std::make_shared<scenarioloader_ui>();
}
m_loading_overlay->set_progress( 100.f, 0.f );
}
void
eu07_application::render_loading_overlay() {
sync_loading_overlay_state();
if( m_loading_overlay == nullptr ) {
m_loading_overlay = std::make_shared<scenarioloader_ui>();
}
m_loading_overlay->render();
}
void eu07_application::render_ui()
{
if( loading_overlay_active() ) {
render_loading_overlay();
return;
}
if (m_modestack.empty())
{
return;
@@ -721,6 +774,12 @@ void eu07_application::render_ui()
void eu07_application::begin_ui_frame()
{
if( loading_overlay_active() ) {
sync_loading_overlay_state();
m_loading_overlay->begin_ui_frame();
return;
}
if (m_modestack.empty())
{
return;

View File

@@ -9,6 +9,8 @@ http://mozilla.org/MPL/2.0/.
#pragma once
#include <chrono>
#include "application/applicationmode.h"
#include "scripting/PyInt.h"
#include "network/manager.h"
@@ -55,6 +57,12 @@ public:
render_ui();
void
begin_ui_frame();
void
extend_loading_overlay( std::chrono::milliseconds const Duration );
[[nodiscard]] bool
loading_overlay_active() const;
void
render_loading_overlay();
// switches application to specified mode
bool
pop_mode();
@@ -115,9 +123,12 @@ private:
int init_modes();
bool init_network();
int run_crashgui();
void sync_loading_overlay_state();
// members
bool m_screenshot_queued = false;
std::chrono::steady_clock::time_point m_loading_overlay_until {};
std::shared_ptr<class scenarioloader_ui> m_loading_overlay;
modeptr_array m_modes { nullptr }; // collection of available application behaviour modes
mode_stack m_modestack; // current behaviour mode

View File

@@ -32,7 +32,7 @@ public:
void begin_ui_frame() {
if( m_userinterface != nullptr ) {
m_userinterface->begin_ui_frame(); } }
inline
virtual
void set_progress( float const Progress = 0.f, float const Subtaskprogress = 0.f ) {
if( m_userinterface != nullptr ) {
m_userinterface->set_progress( Progress, Subtaskprogress ); } }

View File

@@ -29,6 +29,8 @@ http://mozilla.org/MPL/2.0/.
#include "utilities/Timer.h"
#include "rendering/renderer.h"
#include "utilities/Logs.h"
#include "scene/eu7/eu7_section_stream.h"
#include "scene/eu7/eu7_pack_bench.h"
/*
namespace input {
@@ -402,6 +404,36 @@ bool driver_mode::update()
Timer::subsystem.sim_total.stop();
auto const world_presentable {
false == scene::eu7::section_stream_active()
|| scene::eu7::loading_screen_dismissed() };
auto const gameplay_stream {
scene::eu7::section_stream_active() && scene::eu7::loading_screen_dismissed() };
simulation::State.drain_deferred_eu7_trainsets( gameplay_stream ? 3.0 : 12.0 );
if( scene::eu7::section_stream_active() ) {
auto const stream_active {
simulation::is_ready || Application.loading_overlay_active() };
if( stream_active && scene::eu7::section_stream_needs_bootstrap() ) {
scene::eu7::kick_section_stream_bootstrap();
}
if( stream_active ) {
scene::eu7::update_section_stream( Global.pCamera.Pos );
scene::eu7::drain_section_stream();
}
if( scene::eu7::pack_bench_stream_phase_active() ) {
static double s_last_stream_bench_log { 0.0 };
auto const now { Timer::GetTime() };
if( now - s_last_stream_bench_log >= 30.0
&& scene::eu7::pack_bench_stream().sections_finalized > 0 ) {
scene::eu7::log_pack_stream_bench();
s_last_stream_bench_log = now;
}
}
}
simulation::Region->update_sounds();
audio::renderer.update(Global.iPause ? 0.0 : deltarealtime);
@@ -410,7 +442,9 @@ bool driver_mode::update()
GfxRenderer->Update(deltarealtime);
simulation::is_ready = simulation::is_ready || ((simulation::Train != nullptr) && (simulation::Train->is_cab_initialized)) || (Global.local_start_vehicle == "ghostview");
simulation::is_ready = simulation::is_ready
|| ( ( simulation::Train != nullptr ) && ( simulation::Train->is_cab_initialized ) )
|| ( Global.local_start_vehicle == "ghostview" && world_presentable );
return true;
}
@@ -461,7 +495,10 @@ void driver_mode::enter()
}
// maintenance method, called when the mode is deactivated
void driver_mode::exit() {}
void
driver_mode::exit() {
scene::eu7::flush_pack_stream_bench();
}
void driver_mode::on_key(int const Key, int const Scancode, int const Action, int const Mods)
{

View File

@@ -19,6 +19,15 @@ http://mozilla.org/MPL/2.0/.
#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>();
@@ -30,6 +39,13 @@ bool scenarioloader_mode::init() {
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)
@@ -48,17 +64,80 @@ bool scenarioloader_mode::update() {
}
try {
if (simulation::State.deserialize_continue(state))
return true;
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" );
// TODO: implement and use next mode cue
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 );
@@ -74,6 +153,9 @@ 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 + ")" );
@@ -85,3 +167,15 @@ 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 );
}

View File

@@ -13,8 +13,21 @@ http://mozilla.org/MPL/2.0/.
#include "simulation/simulation.h"
class scenarioloader_mode : public application_mode {
enum class load_phase {
deserialize,
eu7_load,
finished
};
std::shared_ptr<simulation::deserializer_state> state;
std::chrono::system_clock::time_point timestart;
load_phase m_phase { load_phase::deserialize };
std::chrono::steady_clock::time_point m_eu7_load_started {};
bool m_eu7_stream_primed { false };
float m_bar_progress { 0.f };
void update_bar_progress( float progress );
public:
// constructors
@@ -28,6 +41,7 @@ public:
void enter() override;
// maintenance method, called when the mode is deactivated
void exit() override;
void set_progress( float Progress = 0.f, float Subtaskprogress = 0.f ) override;
// input handlers
void on_key( int const Key, int const Scancode, int const Action, int const Mods ) override { ; }
void on_cursor_pos( double const Horizontal, double const Vertical ) override { ; }

View File

@@ -195,6 +195,10 @@ void scenarioloader_ui::render_()
ImGui::SetNextWindowSize(ImVec2(Global.window_size.x + padding * 2, Global.window_size.y + padding * 2));
ImGui::Begin("Neo Loading Screen", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoBackground);
ImDrawList* draw_list = ImGui::GetWindowDrawList();
draw_list->AddRectFilled(
ImVec2( 0.f, 0.f ),
ImVec2( screen_size.x, screen_size.y ),
IM_COL32( 0, 0, 0, 255 ) );
ImGui::PushFont(font_loading);
ImGui::SetWindowFontScale(1);
const float font_scale_mult = 48 / ImGui::GetFontSize();
@@ -228,7 +232,14 @@ void scenarioloader_ui::render_()
icon_center_y - text_size.y * 0.5f);
// Draw
//draw_list->AddImage(reinterpret_cast<ImTextureID>(loading_tex), icon_pos, ImVec2(icon_pos.x + loading_size.x, icon_pos.y + loading_size.y), ImVec2(0, 0), ImVec2(1, 1));
if( loading_tex != static_cast<GLuint>( -1 ) ) {
draw_list->AddImage(
reinterpret_cast<ImTextureID>( loading_tex ),
icon_pos,
ImVec2( icon_pos.x + loading_size.x, icon_pos.y + loading_size.y ),
ImVec2( 0, 0 ),
ImVec2( 1, 1 ) );
}
draw_list->AddText(text_pos, IM_COL32_WHITE, m_progresstext.c_str());
// Trivia