mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-23 00:29:19 +02:00
fix
This commit is contained in:
@@ -12,9 +12,6 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "application/drivermode.h"
|
#include "application/drivermode.h"
|
||||||
#include "application/editormode.h"
|
#include "application/editormode.h"
|
||||||
#include "application/scenarioloadermode.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 "launcher/launchermode.h"
|
||||||
|
|
||||||
#include "utilities/Globals.h"
|
#include "utilities/Globals.h"
|
||||||
@@ -710,59 +707,9 @@ void eu07_application::exit()
|
|||||||
#endif
|
#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()
|
void eu07_application::render_ui()
|
||||||
{
|
{
|
||||||
|
|
||||||
if( loading_overlay_active() ) {
|
|
||||||
render_loading_overlay();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_modestack.empty())
|
if (m_modestack.empty())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -774,12 +721,6 @@ void eu07_application::render_ui()
|
|||||||
void eu07_application::begin_ui_frame()
|
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())
|
if (m_modestack.empty())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
|
|
||||||
#include "application/applicationmode.h"
|
#include "application/applicationmode.h"
|
||||||
#include "scripting/PyInt.h"
|
#include "scripting/PyInt.h"
|
||||||
#include "network/manager.h"
|
#include "network/manager.h"
|
||||||
@@ -57,12 +55,6 @@ public:
|
|||||||
render_ui();
|
render_ui();
|
||||||
void
|
void
|
||||||
begin_ui_frame();
|
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
|
// switches application to specified mode
|
||||||
bool
|
bool
|
||||||
pop_mode();
|
pop_mode();
|
||||||
@@ -123,12 +115,9 @@ private:
|
|||||||
int init_modes();
|
int init_modes();
|
||||||
bool init_network();
|
bool init_network();
|
||||||
int run_crashgui();
|
int run_crashgui();
|
||||||
void sync_loading_overlay_state();
|
|
||||||
// members
|
// members
|
||||||
|
|
||||||
bool m_screenshot_queued = false;
|
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
|
modeptr_array m_modes { nullptr }; // collection of available application behaviour modes
|
||||||
mode_stack m_modestack; // current behaviour mode
|
mode_stack m_modestack; // current behaviour mode
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ public:
|
|||||||
void begin_ui_frame() {
|
void begin_ui_frame() {
|
||||||
if( m_userinterface != nullptr ) {
|
if( m_userinterface != nullptr ) {
|
||||||
m_userinterface->begin_ui_frame(); } }
|
m_userinterface->begin_ui_frame(); } }
|
||||||
virtual
|
inline
|
||||||
void set_progress( float const Progress = 0.f, float const Subtaskprogress = 0.f ) {
|
void set_progress( float const Progress = 0.f, float const Subtaskprogress = 0.f ) {
|
||||||
if( m_userinterface != nullptr ) {
|
if( m_userinterface != nullptr ) {
|
||||||
m_userinterface->set_progress( Progress, Subtaskprogress ); } }
|
m_userinterface->set_progress( Progress, Subtaskprogress ); } }
|
||||||
|
|||||||
@@ -404,24 +404,14 @@ bool driver_mode::update()
|
|||||||
|
|
||||||
Timer::subsystem.sim_total.stop();
|
Timer::subsystem.sim_total.stop();
|
||||||
|
|
||||||
auto const world_presentable {
|
simulation::State.drain_deferred_eu7_trainsets( 12.0 );
|
||||||
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() ) {
|
if( scene::eu7::section_stream_active() ) {
|
||||||
auto const stream_active {
|
if( scene::eu7::section_stream_needs_bootstrap() ) {
|
||||||
simulation::is_ready || Application.loading_overlay_active() };
|
|
||||||
if( stream_active && scene::eu7::section_stream_needs_bootstrap() ) {
|
|
||||||
scene::eu7::kick_section_stream_bootstrap();
|
scene::eu7::kick_section_stream_bootstrap();
|
||||||
}
|
}
|
||||||
if( stream_active ) {
|
|
||||||
scene::eu7::update_section_stream( Global.pCamera.Pos );
|
scene::eu7::update_section_stream( Global.pCamera.Pos );
|
||||||
scene::eu7::drain_section_stream();
|
scene::eu7::drain_section_stream();
|
||||||
}
|
|
||||||
|
|
||||||
if( scene::eu7::pack_bench_stream_phase_active() ) {
|
if( scene::eu7::pack_bench_stream_phase_active() ) {
|
||||||
static double s_last_stream_bench_log { 0.0 };
|
static double s_last_stream_bench_log { 0.0 };
|
||||||
@@ -442,9 +432,7 @@ bool driver_mode::update()
|
|||||||
|
|
||||||
GfxRenderer->Update(deltarealtime);
|
GfxRenderer->Update(deltarealtime);
|
||||||
|
|
||||||
simulation::is_ready = simulation::is_ready
|
simulation::is_ready = simulation::is_ready || ((simulation::Train != nullptr) && (simulation::Train->is_cab_initialized)) || (Global.local_start_vehicle == "ghostview");
|
||||||
|| ( ( simulation::Train != nullptr ) && ( simulation::Train->is_cab_initialized ) )
|
|
||||||
|| ( Global.local_start_vehicle == "ghostview" && world_presentable );
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -455,6 +443,10 @@ void driver_mode::enter()
|
|||||||
|
|
||||||
TDynamicObject *nPlayerTrain{((Global.local_start_vehicle != "ghostview") ? simulation::Vehicles.find(Global.local_start_vehicle) : nullptr)};
|
TDynamicObject *nPlayerTrain{((Global.local_start_vehicle != "ghostview") ? simulation::Vehicles.find(Global.local_start_vehicle) : nullptr)};
|
||||||
|
|
||||||
|
if( scene::eu7::section_stream_active() ) {
|
||||||
|
scene::eu7::dismiss_loading_screen();
|
||||||
|
}
|
||||||
|
|
||||||
Camera.Init(Global.FreeCameraInit[0], Global.FreeCameraInitAngle[0], nullptr);
|
Camera.Init(Global.FreeCameraInit[0], Global.FreeCameraInitAngle[0], nullptr);
|
||||||
Global.pCamera = Camera;
|
Global.pCamera = Camera;
|
||||||
Global.pDebugCamera = DebugCamera;
|
Global.pDebugCamera = DebugCamera;
|
||||||
@@ -462,6 +454,26 @@ void driver_mode::enter()
|
|||||||
FreeFlyModeFlag = true;
|
FreeFlyModeFlag = true;
|
||||||
DebugCamera = Camera;
|
DebugCamera = Camera;
|
||||||
|
|
||||||
|
if( scene::eu7::section_stream_active() ) {
|
||||||
|
if( scene::eu7::section_stream_needs_bootstrap() ) {
|
||||||
|
scene::eu7::kick_section_stream_bootstrap();
|
||||||
|
}
|
||||||
|
auto stream_pos { scene::eu7::resolve_section_stream_position( Global.pCamera.Pos ) };
|
||||||
|
if( stream_pos.x != 0.0 || stream_pos.y != 0.0 || stream_pos.z != 0.0 ) {
|
||||||
|
Global.pCamera.Pos = stream_pos;
|
||||||
|
Camera = Global.pCamera;
|
||||||
|
}
|
||||||
|
scene::eu7::update_section_stream( Global.pCamera.Pos );
|
||||||
|
for( int i { 0 }; i < 64; ++i ) {
|
||||||
|
scene::eu7::drain_section_stream();
|
||||||
|
if( scene::eu7::section_stream_ready_around(
|
||||||
|
stream_pos,
|
||||||
|
scene::eu7::kSectionStreamBootstrapRadiusKm ) ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (nPlayerTrain)
|
if (nPlayerTrain)
|
||||||
{
|
{
|
||||||
WriteLog("Trying to enter player train, \"" + Global.local_start_vehicle + "\"");
|
WriteLog("Trying to enter player train, \"" + Global.local_start_vehicle + "\"");
|
||||||
|
|||||||
@@ -19,16 +19,8 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "rendering/renderer.h"
|
#include "rendering/renderer.h"
|
||||||
#include "utilities/Logs.h"
|
#include "utilities/Logs.h"
|
||||||
#include "utilities/translation.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"
|
#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() {
|
scenarioloader_mode::scenarioloader_mode() {
|
||||||
m_userinterface = std::make_shared<scenarioloader_ui>();
|
m_userinterface = std::make_shared<scenarioloader_ui>();
|
||||||
}
|
}
|
||||||
@@ -39,13 +31,6 @@ bool scenarioloader_mode::init() {
|
|||||||
return true;
|
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
|
// mode-specific update of simulation data. returns: false on error, true otherwise
|
||||||
bool scenarioloader_mode::update() {
|
bool scenarioloader_mode::update() {
|
||||||
if (!Global.ready_to_load)
|
if (!Global.ready_to_load)
|
||||||
@@ -64,80 +49,22 @@ bool scenarioloader_mode::update() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if( m_phase == load_phase::deserialize ) {
|
if (simulation::State.deserialize_continue(state))
|
||||||
if( simulation::State.deserialize_continue( state ) ) {
|
|
||||||
return true;
|
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) {
|
catch (invalid_scenery_exception &e) {
|
||||||
ErrorLog( "Bad init: scenario loading failed" );
|
ErrorLog( "Bad init: scenario loading failed" );
|
||||||
Application.pop_mode();
|
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" );
|
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 );
|
if( scene::eu7::section_stream_active() ) {
|
||||||
|
scene::eu7::preload_section_stream( 3000.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: implement and use next mode cue
|
||||||
|
|
||||||
Application.pop_mode();
|
Application.pop_mode();
|
||||||
Application.push_mode( eu07_application::mode::driver );
|
Application.push_mode( eu07_application::mode::driver );
|
||||||
|
|
||||||
@@ -153,9 +80,6 @@ void scenarioloader_mode::enter() {
|
|||||||
// TBD: hide cursor in fullscreen mode?
|
// TBD: hide cursor in fullscreen mode?
|
||||||
Application.set_cursor( GLFW_CURSOR_NORMAL );
|
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;
|
simulation::is_ready = false;
|
||||||
|
|
||||||
Application.set_title( Global.AppName + " (" + Global.SceneryFile + ")" );
|
Application.set_title( Global.AppName + " (" + Global.SceneryFile + ")" );
|
||||||
@@ -167,15 +91,3 @@ void scenarioloader_mode::exit() {
|
|||||||
simulation::Time.init( Global.starting_timestamp );
|
simulation::Time.init( Global.starting_timestamp );
|
||||||
simulation::Environment.init();
|
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 );
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -13,21 +13,8 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "simulation/simulation.h"
|
#include "simulation/simulation.h"
|
||||||
|
|
||||||
class scenarioloader_mode : public application_mode {
|
class scenarioloader_mode : public application_mode {
|
||||||
|
|
||||||
enum class load_phase {
|
|
||||||
deserialize,
|
|
||||||
eu7_load,
|
|
||||||
finished
|
|
||||||
};
|
|
||||||
|
|
||||||
std::shared_ptr<simulation::deserializer_state> state;
|
std::shared_ptr<simulation::deserializer_state> state;
|
||||||
std::chrono::system_clock::time_point timestart;
|
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:
|
public:
|
||||||
// constructors
|
// constructors
|
||||||
@@ -41,7 +28,6 @@ public:
|
|||||||
void enter() override;
|
void enter() override;
|
||||||
// maintenance method, called when the mode is deactivated
|
// maintenance method, called when the mode is deactivated
|
||||||
void exit() override;
|
void exit() override;
|
||||||
void set_progress( float Progress = 0.f, float Subtaskprogress = 0.f ) override;
|
|
||||||
// input handlers
|
// input handlers
|
||||||
void on_key( int const Key, int const Scancode, int const Action, int const Mods ) override { ; }
|
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 { ; }
|
void on_cursor_pos( double const Horizontal, double const Vertical ) override { ; }
|
||||||
|
|||||||
@@ -195,10 +195,6 @@ void scenarioloader_ui::render_()
|
|||||||
ImGui::SetNextWindowSize(ImVec2(Global.window_size.x + padding * 2, Global.window_size.y + padding * 2));
|
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);
|
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();
|
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::PushFont(font_loading);
|
||||||
ImGui::SetWindowFontScale(1);
|
ImGui::SetWindowFontScale(1);
|
||||||
const float font_scale_mult = 48 / ImGui::GetFontSize();
|
const float font_scale_mult = 48 / ImGui::GetFontSize();
|
||||||
@@ -232,14 +228,7 @@ void scenarioloader_ui::render_()
|
|||||||
icon_center_y - text_size.y * 0.5f);
|
icon_center_y - text_size.y * 0.5f);
|
||||||
|
|
||||||
// Draw
|
// Draw
|
||||||
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->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());
|
draw_list->AddText(text_pos, IM_COL32_WHITE, m_progresstext.c_str());
|
||||||
|
|
||||||
// Trivia
|
// Trivia
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "utilities/Timer.h"
|
#include "utilities/Timer.h"
|
||||||
#include "vehicle/Train.h"
|
#include "vehicle/Train.h"
|
||||||
#include "vehicle/Camera.h"
|
#include "vehicle/Camera.h"
|
||||||
#include "scene/eu7/eu7_section_stream.h"
|
|
||||||
#include "simulation/simulation.h"
|
#include "simulation/simulation.h"
|
||||||
#include "utilities/Logs.h"
|
#include "utilities/Logs.h"
|
||||||
#include "simulation/simulationtime.h"
|
#include "simulation/simulationtime.h"
|
||||||
@@ -734,9 +733,7 @@ void opengl33_renderer::Render_pass(viewport_config &vp, rendermode const Mode)
|
|||||||
m_current_viewport = &vp;
|
m_current_viewport = &vp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ( false == simulation::is_ready )
|
if ((!simulation::is_ready) || (Global.gfx_skiprendering))
|
||||||
|| scene::eu7::loading_screen_blocks_world( scene::eu7::stream_loading_position() )
|
|
||||||
|| Global.gfx_skiprendering )
|
|
||||||
{
|
{
|
||||||
gl::framebuffer::unbind();
|
gl::framebuffer::unbind();
|
||||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "utilities/color.h"
|
#include "utilities/color.h"
|
||||||
#include "utilities/Globals.h"
|
#include "utilities/Globals.h"
|
||||||
#include "vehicle/Camera.h"
|
#include "vehicle/Camera.h"
|
||||||
#include "scene/eu7/eu7_section_stream.h"
|
|
||||||
#include "utilities/Timer.h"
|
#include "utilities/Timer.h"
|
||||||
#include "simulation/simulation.h"
|
#include "simulation/simulation.h"
|
||||||
#include "simulation/simulationtime.h"
|
#include "simulation/simulationtime.h"
|
||||||
@@ -415,12 +414,9 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
|
|||||||
|
|
||||||
m_colorpass = m_renderpass;
|
m_colorpass = m_renderpass;
|
||||||
|
|
||||||
if( ( false == simulation::is_ready )
|
if( ( !simulation::is_ready ) || ( Global.gfx_skiprendering ) ) {
|
||||||
|| scene::eu7::loading_screen_blocks_world( scene::eu7::stream_loading_position() )
|
::glClearColor( 51.0f / 255.f, 102.0f / 255.f, 85.0f / 255.f, 1.f ); // initial background Color
|
||||||
|| Global.gfx_skiprendering ) {
|
|
||||||
::glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
|
|
||||||
::glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
::glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||||
Application.render_ui();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ scenario_needs_eu7_regen( std::string const &scenario_file ) {
|
|||||||
|
|
||||||
if( probe_file( resolved ) ) {
|
if( probe_file( resolved ) ) {
|
||||||
|
|
||||||
return text_module_is_newer_than_binary( scenario_file );
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,7 +176,7 @@ scenario_needs_eu7_regen( std::string const &scenario_file ) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false == should_use_binary_module( scenario_file );
|
return false == probe_baked_scenario( scenario_file );
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@@ -204,28 +204,6 @@ ensure_scenario_eu7( std::string const &scenario_file ) {
|
|||||||
|
|
||||||
if( probe_file( resolved ) ) {
|
if( probe_file( resolved ) ) {
|
||||||
|
|
||||||
#ifdef WITH_EU7_PARSER
|
|
||||||
|
|
||||||
if( Global.eu7_auto_bake && text_module_is_newer_than_binary( scenario_file ) ) {
|
|
||||||
|
|
||||||
auto const text_root { text_source_path( scenario_file ) };
|
|
||||||
|
|
||||||
if( false == text_root.empty() ) {
|
|
||||||
|
|
||||||
WriteLog(
|
|
||||||
|
|
||||||
"EU7: .eu7 nieaktualny wzgledem " + text_root + ", rebake..." );
|
|
||||||
|
|
||||||
run_scenario_tree_bake( text_root, eu7_path, outcome );
|
|
||||||
|
|
||||||
return outcome;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
outcome.ok = true;
|
outcome.ok = true;
|
||||||
|
|
||||||
outcome.message = "uzywam .eu7: " + resolved;
|
outcome.message = "uzywam .eu7: " + resolved;
|
||||||
@@ -242,7 +220,7 @@ ensure_scenario_eu7( std::string const &scenario_file ) {
|
|||||||
|
|
||||||
if( false == Global.eu7_auto_bake ) {
|
if( false == Global.eu7_auto_bake ) {
|
||||||
|
|
||||||
if( should_use_binary_module( scenario_file ) ) {
|
if( probe_baked_scenario( scenario_file ) ) {
|
||||||
|
|
||||||
outcome.ok = true;
|
outcome.ok = true;
|
||||||
|
|
||||||
@@ -282,7 +260,7 @@ ensure_scenario_eu7( std::string const &scenario_file ) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
if( should_use_binary_module( scenario_file ) ) {
|
if( probe_baked_scenario( scenario_file ) ) {
|
||||||
|
|
||||||
outcome.ok = true;
|
outcome.ok = true;
|
||||||
|
|
||||||
@@ -296,23 +274,13 @@ ensure_scenario_eu7( std::string const &scenario_file ) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
if( probe_file( eu7_path ) ) {
|
|
||||||
|
|
||||||
WriteLog(
|
|
||||||
|
|
||||||
"EU7: .eu7 nieaktualny wzgledem " + resolved + ", rebake..." );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
run_scenario_tree_bake( resolved, eu7_path, outcome );
|
run_scenario_tree_bake( resolved, eu7_path, outcome );
|
||||||
|
|
||||||
return outcome;
|
return outcome;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
if( should_use_binary_module( scenario_file ) ) {
|
if( probe_baked_scenario( scenario_file ) ) {
|
||||||
|
|
||||||
outcome.ok = true;
|
outcome.ok = true;
|
||||||
|
|
||||||
|
|||||||
@@ -257,11 +257,7 @@ load_module_recursive(
|
|||||||
if( child_loaded ) {
|
if( child_loaded ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if( !child.empty() && probe_file( child ) && false == should_use_binary_module( ref ) ) {
|
if( !child.empty() ) {
|
||||||
WriteLog(
|
|
||||||
"EU7: przestarzaly .eu7, fallback SCM: " + include_text_path( include ) );
|
|
||||||
}
|
|
||||||
else if( !child.empty() ) {
|
|
||||||
WriteLog(
|
WriteLog(
|
||||||
"EU7 include niedostepny, fallback SCM: " + include_text_path( include ) );
|
"EU7 include niedostepny, fallback SCM: " + include_text_path( include ) );
|
||||||
}
|
}
|
||||||
@@ -458,23 +454,9 @@ text_source_path( std::string const &reference ) {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
text_module_is_newer_than_binary( std::string const &reference ) {
|
|
||||||
auto const text { text_source_path( reference ) };
|
|
||||||
if( text.empty() || false == FileExists( text ) ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
auto const eu7 { binary_path( reference ) };
|
|
||||||
if( false == FileExists( eu7 ) ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return last_modified( text ) > last_modified( eu7 );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
should_use_binary_module( std::string const &reference ) {
|
should_use_binary_module( std::string const &reference ) {
|
||||||
auto const eu7 { binary_path( reference ) };
|
return probe_file( binary_path( reference ) );
|
||||||
return probe_file( eu7 ) && false == text_module_is_newer_than_binary( reference );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|||||||
@@ -75,13 +75,9 @@ namespace eu7 {
|
|||||||
[[nodiscard]] std::string
|
[[nodiscard]] std::string
|
||||||
text_source_path( std::string const &Reference );
|
text_source_path( std::string const &Reference );
|
||||||
|
|
||||||
// Tekst istnieje i jest nowszy niz .eu7 (lub brak .eu7).
|
// Istniejacy, poprawny plik .eu7 obok referencji tekstowej.
|
||||||
[[nodiscard]] bool
|
[[nodiscard]] bool
|
||||||
text_module_is_newer_than_binary( std::string const &Reference );
|
should_use_binary_module( std::string const &Reference );
|
||||||
|
|
||||||
// Istniejacy, poprawny .eu7 nie starszy niz odpowiednik tekstowy.
|
|
||||||
[[nodiscard]] bool
|
|
||||||
should_use_binary_module( std::string const &Reference );
|
|
||||||
|
|
||||||
// Czy plik zawiera chunk TERR.
|
// Czy plik zawiera chunk TERR.
|
||||||
[[nodiscard]] bool
|
[[nodiscard]] bool
|
||||||
|
|||||||
@@ -497,26 +497,39 @@ parse_pack_section_header(
|
|||||||
Eu7PackIndexEntry const &entry,
|
Eu7PackIndexEntry const &entry,
|
||||||
Eu7PackSectionCursor &cursor ) {
|
Eu7PackSectionCursor &cursor ) {
|
||||||
cursor = {};
|
cursor = {};
|
||||||
input.seekg(
|
auto const section_start {
|
||||||
static_cast<std::streamoff>( module.pack_payload_offset + entry.pack_offset ) );
|
static_cast<std::streamoff>( module.pack_payload_offset + entry.pack_offset ) };
|
||||||
|
input.seekg( section_start );
|
||||||
|
|
||||||
const auto peek { input.peek() };
|
const auto peek { input.peek() };
|
||||||
const std::uint8_t first_byte {
|
const std::uint8_t first_byte {
|
||||||
peek == EOF ? std::uint8_t { 0 } : static_cast<std::uint8_t>( peek ) };
|
peek == EOF ? std::uint8_t { 0 } : static_cast<std::uint8_t>( peek ) };
|
||||||
|
|
||||||
if( first_byte == kPackSectionFormatV8 ) {
|
if( first_byte == 2 ) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
"EU7 PACK: format v9 nieobslugiwany — przebake plik .eu7" );
|
||||||
|
}
|
||||||
|
|
||||||
|
// v8 header starts with byte 1 — same as kNodeFlagHasName on flat v7 models.
|
||||||
|
// Accept v8 only when PROT exists and solo+inst counts match PIDX model_count.
|
||||||
|
bool use_v8_header { false };
|
||||||
|
if(
|
||||||
|
first_byte == kPackSectionFormatV8 &&
|
||||||
|
false == module.model_prototypes.empty() ) {
|
||||||
cursor.section_format = sn_utils::d_uint8( input );
|
cursor.section_format = sn_utils::d_uint8( input );
|
||||||
const std::uint32_t solo_total { sn_utils::ld_uint32( input ) };
|
const std::uint32_t solo_total { sn_utils::ld_uint32( input ) };
|
||||||
const std::uint32_t inst_total { sn_utils::ld_uint32( input ) };
|
const std::uint32_t inst_total { sn_utils::ld_uint32( input ) };
|
||||||
|
if( solo_total + inst_total == entry.model_count ) {
|
||||||
|
use_v8_header = true;
|
||||||
cursor.model_total = solo_total + inst_total;
|
cursor.model_total = solo_total + inst_total;
|
||||||
cursor.solo_remaining = solo_total;
|
cursor.solo_remaining = solo_total;
|
||||||
cursor.inst_remaining = inst_total;
|
cursor.inst_remaining = inst_total;
|
||||||
}
|
}
|
||||||
else if( first_byte == 2 ) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
"EU7 PACK: format v9 nieobslugiwany — przebake plik .eu7" );
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
|
if( false == use_v8_header ) {
|
||||||
|
input.seekg( section_start );
|
||||||
|
cursor.section_format = 0;
|
||||||
cursor.model_total = entry.model_count;
|
cursor.model_total = entry.model_count;
|
||||||
cursor.solo_remaining = entry.model_count;
|
cursor.solo_remaining = entry.model_count;
|
||||||
cursor.inst_remaining = 0;
|
cursor.inst_remaining = 0;
|
||||||
@@ -539,8 +552,10 @@ read_pack_models_chunk_impl(
|
|||||||
|
|
||||||
std::vector<Eu7Model> models;
|
std::vector<Eu7Model> models;
|
||||||
auto const remaining {
|
auto const remaining {
|
||||||
|
std::min(
|
||||||
static_cast<std::size_t>( cursor.solo_remaining ) +
|
static_cast<std::size_t>( cursor.solo_remaining ) +
|
||||||
static_cast<std::size_t>( cursor.inst_remaining ) };
|
static_cast<std::size_t>( cursor.inst_remaining ),
|
||||||
|
static_cast<std::size_t>( cursor.model_total ) ) };
|
||||||
models.reserve( std::min( max_count, remaining ) );
|
models.reserve( std::min( max_count, remaining ) );
|
||||||
|
|
||||||
while(
|
while(
|
||||||
@@ -1104,46 +1119,4 @@ read_pack_section( Eu7Module const &module, int const row, int const column ) {
|
|||||||
return read_pack_section_impl( module, row, column );
|
return read_pack_section_impl( module, row, column );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
seek_pack_section(
|
|
||||||
Eu7Module const &module,
|
|
||||||
std::istream &input,
|
|
||||||
Eu7PackIndexEntry const &entry,
|
|
||||||
Eu7PackSectionCursor &cursor ) {
|
|
||||||
if( false == module.has_pack_chunk ) {
|
|
||||||
cursor = {};
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
parse_pack_section_header( module, input, entry, cursor );
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Eu7Model>
|
|
||||||
read_pack_models_chunk(
|
|
||||||
Eu7Module const &module,
|
|
||||||
std::istream &input,
|
|
||||||
Eu7PackSectionCursor &cursor,
|
|
||||||
std::size_t const max_count ) {
|
|
||||||
StringTable const strings { module.strings };
|
|
||||||
return read_pack_models_chunk_impl( module, input, cursor, max_count, strings );
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
resume_pack_section(
|
|
||||||
Eu7Module const &module,
|
|
||||||
std::istream &input,
|
|
||||||
Eu7PackIndexEntry const &entry,
|
|
||||||
std::uint64_t const resume_byte_offset,
|
|
||||||
Eu7PackSectionCursor const resume_cursor,
|
|
||||||
Eu7PackSectionCursor &cursor ) {
|
|
||||||
if( false == module.has_pack_chunk ) {
|
|
||||||
cursor = {};
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
input.seekg(
|
|
||||||
static_cast<std::streamoff>(
|
|
||||||
module.pack_payload_offset + entry.pack_offset + resume_byte_offset ) );
|
|
||||||
cursor = resume_cursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace scene::eu7
|
} // namespace scene::eu7
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
|
|
||||||
#include "scene/eu7/eu7_types.h"
|
#include "scene/eu7/eu7_types.h"
|
||||||
|
|
||||||
#include <istream>
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -32,30 +31,4 @@ find_pack_entry( Eu7Module const &Module, int Row, int Column );
|
|||||||
[[nodiscard]] std::vector<Eu7Model>
|
[[nodiscard]] std::vector<Eu7Model>
|
||||||
read_pack_section( Eu7Module const &Module, int Row, int Column );
|
read_pack_section( Eu7Module const &Module, int Row, int Column );
|
||||||
|
|
||||||
// Seek do pack_offset z PIDX i parsuj naglowek sekcji (v7/v8).
|
|
||||||
void
|
|
||||||
seek_pack_section(
|
|
||||||
Eu7Module const &Module,
|
|
||||||
std::istream &Input,
|
|
||||||
Eu7PackIndexEntry const &Entry,
|
|
||||||
Eu7PackSectionCursor &Cursor );
|
|
||||||
|
|
||||||
// Odczyt do max_count modeli z biezacej pozycji strumienia (po seek_pack_section).
|
|
||||||
[[nodiscard]] std::vector<Eu7Model>
|
|
||||||
read_pack_models_chunk(
|
|
||||||
Eu7Module const &Module,
|
|
||||||
std::istream &Input,
|
|
||||||
Eu7PackSectionCursor &Cursor,
|
|
||||||
std::size_t MaxCount );
|
|
||||||
|
|
||||||
// Wznowienie odczytu sub-chunka (offset wzgledem pack_offset sekcji z PIDX).
|
|
||||||
void
|
|
||||||
resume_pack_section(
|
|
||||||
Eu7Module const &Module,
|
|
||||||
std::istream &Input,
|
|
||||||
Eu7PackIndexEntry const &Entry,
|
|
||||||
std::uint64_t ResumeByteOffset,
|
|
||||||
Eu7PackSectionCursor ResumeCursor,
|
|
||||||
Eu7PackSectionCursor &Cursor );
|
|
||||||
|
|
||||||
} // namespace scene::eu7
|
} // namespace scene::eu7
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ namespace scene::eu7 {
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr double kDrainBudgetMs { 12.0 };
|
constexpr double kDrainBudgetMs { 12.0 };
|
||||||
constexpr double kLoaderDrainBudgetMs { 48.0 };
|
constexpr double kLoaderDrainBudgetMs { 96.0 };
|
||||||
constexpr std::size_t kLoaderSectionsPerDrain { 8 };
|
constexpr std::size_t kLoaderSectionsPerDrain { 8 };
|
||||||
|
|
||||||
constexpr double kGameplayApplyBudgetMs { 4.0 };
|
constexpr double kGameplayApplyBudgetMs { 4.0 };
|
||||||
@@ -72,7 +72,6 @@ constexpr float kStationaryCatchupRingThreshold { 0.70f };
|
|||||||
constexpr double kStationaryCatchupSpeedMps { 5.0 };
|
constexpr double kStationaryCatchupSpeedMps { 5.0 };
|
||||||
constexpr std::size_t kCatchupMaxInFlightSections { 20 };
|
constexpr std::size_t kCatchupMaxInFlightSections { 20 };
|
||||||
constexpr std::size_t kCatchupMaxReadySections { 8 };
|
constexpr std::size_t kCatchupMaxReadySections { 8 };
|
||||||
constexpr std::size_t kPackWorkerSubChunkModels { 512 };
|
|
||||||
constexpr std::size_t kBootstrapDrainMs { 32 };
|
constexpr std::size_t kBootstrapDrainMs { 32 };
|
||||||
constexpr std::size_t kBootstrapTimeoutMs { 120000 };
|
constexpr std::size_t kBootstrapTimeoutMs { 120000 };
|
||||||
constexpr std::chrono::milliseconds kPresentableHoldMs { 200 };
|
constexpr std::chrono::milliseconds kPresentableHoldMs { 200 };
|
||||||
@@ -90,10 +89,6 @@ struct PackSectionJob {
|
|||||||
int column { 0 };
|
int column { 0 };
|
||||||
std::size_t section_idx { 0 };
|
std::size_t section_idx { 0 };
|
||||||
int priority { 0 };
|
int priority { 0 };
|
||||||
std::uint64_t resume_byte_offset { 0 };
|
|
||||||
std::uint32_t subchunk_index { 0 };
|
|
||||||
Eu7PackSectionCursor header_cursor {};
|
|
||||||
Eu7PackSectionCursor resume_cursor {};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PackSectionReady {
|
struct PackSectionReady {
|
||||||
@@ -102,8 +97,7 @@ struct PackSectionReady {
|
|||||||
std::size_t section_idx { 0 };
|
std::size_t section_idx { 0 };
|
||||||
std::unique_ptr<std::vector<Eu7Model>> models;
|
std::unique_ptr<std::vector<Eu7Model>> models;
|
||||||
bool failed { false };
|
bool failed { false };
|
||||||
bool section_final { true };
|
std::size_t apply_offset { 0 };
|
||||||
std::uint32_t subchunk_index { 0 };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SectionStreamState {
|
struct SectionStreamState {
|
||||||
@@ -123,6 +117,8 @@ struct SectionStreamState {
|
|||||||
std::size_t pending_apply_offset { 0 };
|
std::size_t pending_apply_offset { 0 };
|
||||||
glm::dvec3 last_enqueue_position {};
|
glm::dvec3 last_enqueue_position {};
|
||||||
bool has_last_enqueue_position { false };
|
bool has_last_enqueue_position { false };
|
||||||
|
glm::dvec3 anchor_position {};
|
||||||
|
bool has_anchor_position { false };
|
||||||
|
|
||||||
std::unordered_map<std::string, TModel3d *> mesh_cache;
|
std::unordered_map<std::string, TModel3d *> mesh_cache;
|
||||||
std::unordered_map<std::string, scene::node_data> nodedata_cache;
|
std::unordered_map<std::string, scene::node_data> nodedata_cache;
|
||||||
@@ -165,7 +161,10 @@ void
|
|||||||
finalize_section( PackSectionReady const &batch );
|
finalize_section( PackSectionReady const &batch );
|
||||||
|
|
||||||
void
|
void
|
||||||
fail_section( std::size_t const section_idx );
|
fail_section( std::size_t const section_idx, int const row = -1, int const column = -1 );
|
||||||
|
|
||||||
|
void
|
||||||
|
enqueue_failed_section( PackSectionJob const &job );
|
||||||
|
|
||||||
void
|
void
|
||||||
release_pending_buffer();
|
release_pending_buffer();
|
||||||
@@ -194,6 +193,12 @@ stream_worker_count() {
|
|||||||
return std::min( requested, kMaxPackStreamWorkers );
|
return std::min( requested, kMaxPackStreamWorkers );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
reset_stream_fields();
|
||||||
|
|
||||||
|
void
|
||||||
|
note_apply_progress();
|
||||||
|
|
||||||
void
|
void
|
||||||
reset_stream_fields() {
|
reset_stream_fields() {
|
||||||
g_stream.module = nullptr;
|
g_stream.module = nullptr;
|
||||||
@@ -210,9 +215,12 @@ reset_stream_fields() {
|
|||||||
g_stream.pending_apply.reset();
|
g_stream.pending_apply.reset();
|
||||||
g_stream.pending_apply_offset = 0;
|
g_stream.pending_apply_offset = 0;
|
||||||
g_stream.has_last_enqueue_position = false;
|
g_stream.has_last_enqueue_position = false;
|
||||||
|
g_stream.anchor_position = {};
|
||||||
|
g_stream.has_anchor_position = false;
|
||||||
g_stream.mesh_cache.clear();
|
g_stream.mesh_cache.clear();
|
||||||
g_stream.nodedata_cache.clear();
|
g_stream.nodedata_cache.clear();
|
||||||
reset_pack_texture_warm_cache();
|
reset_pack_texture_warm_cache();
|
||||||
|
note_apply_progress();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] Eu7Module const &
|
[[nodiscard]] Eu7Module const &
|
||||||
@@ -223,14 +231,6 @@ stream_module() {
|
|||||||
return *g_stream.module;
|
return *g_stream.module;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] std::string const &
|
|
||||||
pack_stream_file_path() {
|
|
||||||
if( false == g_stream.path.empty() ) {
|
|
||||||
return g_stream.path;
|
|
||||||
}
|
|
||||||
return stream_module().source_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
release_pending_buffer() {
|
release_pending_buffer() {
|
||||||
if( false == g_stream.pending_apply.has_value() ) {
|
if( false == g_stream.pending_apply.has_value() ) {
|
||||||
@@ -315,10 +315,7 @@ adaptive_slice_instances( std::size_t const section_total ) {
|
|||||||
limit = std::min( limit, kCatchupSliceInstances );
|
limit = std::min( limit, kCatchupSliceInstances );
|
||||||
}
|
}
|
||||||
else if( speed > 600.0 ) {
|
else if( speed > 600.0 ) {
|
||||||
limit = std::min( limit, std::size_t { 96 } );
|
limit = std::min( limit, std::size_t { 128 } );
|
||||||
}
|
|
||||||
else if( speed > 300.0 ) {
|
|
||||||
limit = std::min( limit, std::size_t { 80 } );
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
limit = std::min( limit, std::size_t { 96 } );
|
limit = std::min( limit, std::size_t { 96 } );
|
||||||
@@ -334,19 +331,13 @@ adaptive_slice_instances( std::size_t const section_total ) {
|
|||||||
else if( section_total > 800 ) {
|
else if( section_total > 800 ) {
|
||||||
limit = std::min( limit, std::size_t { 80 } );
|
limit = std::min( limit, std::size_t { 80 } );
|
||||||
}
|
}
|
||||||
else if( section_total <= kPackWorkerSubChunkModels ) {
|
|
||||||
limit = std::min( limit, std::size_t { 64 } );
|
|
||||||
if( g_stream_catchup && camera_stream_speed_mps() > 300.0 ) {
|
|
||||||
limit = std::min( limit, std::size_t { 48 } );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto const last_ms { pack_bench_stream().last_chunk_ms };
|
auto const last_ms { pack_bench_stream().last_chunk_ms };
|
||||||
if( last_ms >= 24.0 ) {
|
if( last_ms >= 24.0 ) {
|
||||||
limit = std::min( limit, std::size_t { 32 } );
|
limit = std::min( limit, std::size_t { 32 } );
|
||||||
}
|
}
|
||||||
else if( last_ms >= 12.0 ) {
|
else if( last_ms >= 12.0 ) {
|
||||||
limit = std::min( limit, std::size_t { 48 } );
|
limit = std::min( limit, std::size_t { 64 } );
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::max( limit, std::size_t { 16 } );
|
return std::max( limit, std::size_t { 16 } );
|
||||||
@@ -354,12 +345,8 @@ adaptive_slice_instances( std::size_t const section_total ) {
|
|||||||
|
|
||||||
[[nodiscard]] std::size_t
|
[[nodiscard]] std::size_t
|
||||||
adaptive_cold_meshes() {
|
adaptive_cold_meshes() {
|
||||||
auto const &stream { pack_bench_stream() };
|
|
||||||
if( stream.last_chunk_ms >= 40.0 || stream.peak_chunk_ms >= 80.0 ) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
auto limit { gameplay_slice_cold_meshes() };
|
auto limit { gameplay_slice_cold_meshes() };
|
||||||
if( stream.last_chunk_ms >= 12.0 ) {
|
if( pack_bench_stream().last_chunk_ms >= 12.0 ) {
|
||||||
limit = 1;
|
limit = 1;
|
||||||
}
|
}
|
||||||
return limit;
|
return limit;
|
||||||
@@ -432,13 +419,7 @@ preload_slice_cold_meshes(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
replace_slashes( model_file );
|
replace_slashes( model_file );
|
||||||
if( g_stream.mesh_cache.contains( model_file ) ) {
|
if( false == g_stream.mesh_cache.contains( model_file ) ) {
|
||||||
slice_count = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if( max_cold_meshes == 0 ) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
TModel3d *mesh { nullptr };
|
TModel3d *mesh { nullptr };
|
||||||
{
|
{
|
||||||
PackBenchTimer const load_timer { &Eu7PackBench::main_cold_getmodel_ms };
|
PackBenchTimer const load_timer { &Eu7PackBench::main_cold_getmodel_ms };
|
||||||
@@ -449,12 +430,71 @@ preload_slice_cold_meshes(
|
|||||||
TAnimModel::warm_instanceable_cache( mesh );
|
TAnimModel::warm_instanceable_cache( mesh );
|
||||||
}
|
}
|
||||||
g_stream.mesh_cache.emplace( model_file, mesh );
|
g_stream.mesh_cache.emplace( model_file, mesh );
|
||||||
slice_count = 1;
|
|
||||||
cold_loaded = 1;
|
cold_loaded = 1;
|
||||||
}
|
}
|
||||||
|
slice_count = 1;
|
||||||
|
}
|
||||||
return cold_loaded;
|
return cold_loaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr int kApplyStuckSkipFrames { 20 };
|
||||||
|
|
||||||
|
std::size_t g_apply_stuck_offset { std::numeric_limits<std::size_t>::max() };
|
||||||
|
int g_apply_stuck_frames { 0 };
|
||||||
|
|
||||||
|
void
|
||||||
|
note_apply_progress() {
|
||||||
|
g_apply_stuck_offset = std::numeric_limits<std::size_t>::max();
|
||||||
|
g_apply_stuck_frames = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool
|
||||||
|
maybe_skip_stuck_apply_offset() {
|
||||||
|
if( false == g_stream.pending_apply.has_value() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const offset { g_stream.pending_apply_offset };
|
||||||
|
if( offset == g_apply_stuck_offset ) {
|
||||||
|
++g_apply_stuck_frames;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
g_apply_stuck_offset = offset;
|
||||||
|
g_apply_stuck_frames = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( g_apply_stuck_frames < kApplyStuckSkipFrames ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const total {
|
||||||
|
g_stream.pending_apply->models != nullptr ?
|
||||||
|
g_stream.pending_apply->models->size() :
|
||||||
|
0 };
|
||||||
|
if( offset >= total ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto model_file { ( *g_stream.pending_apply->models )[ offset ].model_file };
|
||||||
|
WriteLog(
|
||||||
|
"EU7 PACK: skip stuck model offset=" + std::to_string( offset ) + "/" +
|
||||||
|
std::to_string( total ) + " sec=" + std::to_string( g_stream.pending_apply->row ) + "," +
|
||||||
|
std::to_string( g_stream.pending_apply->column ) +
|
||||||
|
( model_file.empty() ? "" : " file=\"" + model_file + "\"" ) );
|
||||||
|
if( false == model_file.empty() && model_file != "notload" ) {
|
||||||
|
replace_slashes( model_file );
|
||||||
|
g_stream.mesh_cache.emplace( std::move( model_file ), nullptr );
|
||||||
|
}
|
||||||
|
g_stream.pending_apply_offset = offset + 1;
|
||||||
|
note_apply_progress();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
maybe_preempt_distant_pending() {
|
||||||
|
// Wyłączone — najpierw stabilność: dokończ bieżącą sekcję zamiast preemptować.
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool
|
[[nodiscard]] bool
|
||||||
apply_pending_chunk(
|
apply_pending_chunk(
|
||||||
double const budget_ms,
|
double const budget_ms,
|
||||||
@@ -462,9 +502,16 @@ apply_pending_chunk(
|
|||||||
std::size_t const max_cold_meshes,
|
std::size_t const max_cold_meshes,
|
||||||
double const cold_budget_ms,
|
double const cold_budget_ms,
|
||||||
std::size_t const max_chunks ) {
|
std::size_t const max_chunks ) {
|
||||||
|
(void)max_instances;
|
||||||
|
(void)max_cold_meshes;
|
||||||
|
(void)cold_budget_ms;
|
||||||
if( g_stream.serializer == nullptr ) {
|
if( g_stream.serializer == nullptr ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if( maybe_skip_stuck_apply_offset() ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
maybe_preempt_distant_pending();
|
||||||
if( false == g_stream.pending_apply.has_value() && false == try_dequeue_ready_batch() ) {
|
if( false == g_stream.pending_apply.has_value() && false == try_dequeue_ready_batch() ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -483,7 +530,7 @@ apply_pending_chunk(
|
|||||||
auto &batch { *g_stream.pending_apply };
|
auto &batch { *g_stream.pending_apply };
|
||||||
if( batch.failed || batch.models == nullptr || batch.models->empty() ) {
|
if( batch.failed || batch.models == nullptr || batch.models->empty() ) {
|
||||||
if( batch.failed ) {
|
if( batch.failed ) {
|
||||||
fail_section( batch.section_idx );
|
fail_section( batch.section_idx, batch.row, batch.column );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
finalize_section( batch );
|
finalize_section( batch );
|
||||||
@@ -497,21 +544,15 @@ apply_pending_chunk(
|
|||||||
auto const total { batch.models->size() };
|
auto const total { batch.models->size() };
|
||||||
auto const offset { g_stream.pending_apply_offset };
|
auto const offset { g_stream.pending_apply_offset };
|
||||||
if( offset >= total ) {
|
if( offset >= total ) {
|
||||||
if( batch.section_final ) {
|
|
||||||
finalize_section( batch );
|
finalize_section( batch );
|
||||||
}
|
|
||||||
release_pending_buffer();
|
release_pending_buffer();
|
||||||
applied_work = true;
|
applied_work = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const effective_instances {
|
// Sekcja 1 km (komorka TCP) — apply w calosci, bez dzielenia na plasterki.
|
||||||
std::min( max_instances, adaptive_slice_instances( total ) ) };
|
|
||||||
auto const effective_cold {
|
|
||||||
std::min( max_cold_meshes, adaptive_cold_meshes() ) };
|
|
||||||
auto const remaining { total - offset };
|
auto const remaining { total - offset };
|
||||||
auto const chunk_cap { std::min( effective_instances, remaining ) };
|
std::size_t chunk_count { remaining };
|
||||||
std::size_t chunk_count { chunk_cap };
|
|
||||||
|
|
||||||
auto const chunk_started { std::chrono::steady_clock::now() };
|
auto const chunk_started { std::chrono::steady_clock::now() };
|
||||||
double cold_ms { 0.0 };
|
double cold_ms { 0.0 };
|
||||||
@@ -524,15 +565,18 @@ apply_pending_chunk(
|
|||||||
auto const phase_started { std::chrono::steady_clock::now() };
|
auto const phase_started { std::chrono::steady_clock::now() };
|
||||||
cold_loads = preload_slice_cold_meshes(
|
cold_loads = preload_slice_cold_meshes(
|
||||||
models_ptr + offset,
|
models_ptr + offset,
|
||||||
chunk_cap,
|
remaining,
|
||||||
effective_cold,
|
remaining,
|
||||||
cold_budget_ms,
|
0.0,
|
||||||
chunk_count );
|
chunk_count );
|
||||||
cold_ms = std::chrono::duration<double, std::milli>(
|
cold_ms = std::chrono::duration<double, std::milli>(
|
||||||
std::chrono::steady_clock::now() - phase_started ).count();
|
std::chrono::steady_clock::now() - phase_started ).count();
|
||||||
}
|
}
|
||||||
if( chunk_count == 0 ) {
|
if( chunk_count == 0 ) {
|
||||||
return applied_work;
|
g_stream.pending_apply_offset = offset + 1;
|
||||||
|
note_apply_progress();
|
||||||
|
applied_work = true;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -582,13 +626,12 @@ apply_pending_chunk(
|
|||||||
}
|
}
|
||||||
load_stats().pack_models += chunk_count;
|
load_stats().pack_models += chunk_count;
|
||||||
g_stream.pending_apply_offset = offset + chunk_count;
|
g_stream.pending_apply_offset = offset + chunk_count;
|
||||||
|
note_apply_progress();
|
||||||
applied_work = true;
|
applied_work = true;
|
||||||
++chunks_done;
|
++chunks_done;
|
||||||
|
|
||||||
if( g_stream.pending_apply_offset >= total ) {
|
if( g_stream.pending_apply_offset >= total ) {
|
||||||
if( batch.section_final ) {
|
|
||||||
finalize_section( batch );
|
finalize_section( batch );
|
||||||
}
|
|
||||||
release_pending_buffer();
|
release_pending_buffer();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -712,134 +755,46 @@ worker_loop( std::stop_token const stop_token ) {
|
|||||||
auto const &module { stream_module() };
|
auto const &module { stream_module() };
|
||||||
auto const entry { find_pack_entry( module, job.row, job.column ) };
|
auto const entry { find_pack_entry( module, job.row, job.column ) };
|
||||||
if( false == entry.has_value() || entry->model_count == 0 ) {
|
if( false == entry.has_value() || entry->model_count == 0 ) {
|
||||||
PackSectionReady result;
|
enqueue_failed_section( job );
|
||||||
result.row = job.row;
|
|
||||||
result.column = job.column;
|
|
||||||
result.section_idx = job.section_idx;
|
|
||||||
result.failed = true;
|
|
||||||
result.section_final = true;
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock { g_stream.ready.mutex };
|
|
||||||
g_stream.ready.data.push_back( std::move( result ) );
|
|
||||||
}
|
|
||||||
pack_bench_inc( &Eu7PackBench::worker_failures );
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const &pack_path { pack_stream_file_path() };
|
|
||||||
if( pack_path.empty() ) {
|
|
||||||
throw std::runtime_error( "EU7 PACK: brak sciezki pliku PACK" );
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ifstream input { pack_path, std::ios::binary };
|
|
||||||
if( !input ) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
"EU7 PACK: nie mozna otworzyc \"" + pack_path + "\"" );
|
|
||||||
}
|
|
||||||
|
|
||||||
Eu7PackSectionCursor header_cursor {};
|
|
||||||
Eu7PackSectionCursor cursor {};
|
|
||||||
if( job.resume_byte_offset == 0 ) {
|
|
||||||
seek_pack_section( module, input, *entry, header_cursor );
|
|
||||||
cursor = header_cursor;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
header_cursor = job.header_cursor;
|
|
||||||
resume_pack_section(
|
|
||||||
module,
|
|
||||||
input,
|
|
||||||
*entry,
|
|
||||||
job.resume_byte_offset,
|
|
||||||
job.resume_cursor,
|
|
||||||
cursor );
|
|
||||||
}
|
|
||||||
|
|
||||||
auto batch_index { job.subchunk_index };
|
|
||||||
bool section_completed { false };
|
|
||||||
for( ;; ) {
|
|
||||||
if( cursor.solo_remaining == 0 && cursor.inst_remaining == 0 ) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ready_queue_size() >= g_stream_max_ready ) {
|
|
||||||
PackSectionJob resume_job { job };
|
|
||||||
resume_job.header_cursor = header_cursor;
|
|
||||||
resume_job.resume_byte_offset = static_cast<std::uint64_t>(
|
|
||||||
input.tellg() - static_cast<std::streamoff>(
|
|
||||||
module.pack_payload_offset + entry->pack_offset ) );
|
|
||||||
resume_job.subchunk_index = batch_index;
|
|
||||||
resume_job.resume_cursor = cursor;
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock { g_stream.jobs.mutex };
|
|
||||||
g_stream.jobs.data.push_front( std::move( resume_job ) );
|
|
||||||
}
|
|
||||||
g_stream.work_cv.notify_all();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<std::vector<Eu7Model>> models;
|
std::unique_ptr<std::vector<Eu7Model>> models;
|
||||||
{
|
{
|
||||||
PackBenchTimer const read_timer { &Eu7PackBench::worker_read_pack_ms };
|
PackBenchTimer const read_timer { &Eu7PackBench::worker_read_pack_ms };
|
||||||
auto chunk {
|
auto section { read_pack_section( module, job.row, job.column ) };
|
||||||
read_pack_models_chunk(
|
if( false == section.empty() ) {
|
||||||
module,
|
models = std::make_unique<std::vector<Eu7Model>>( std::move( section ) );
|
||||||
input,
|
|
||||||
cursor,
|
|
||||||
kPackWorkerSubChunkModels ) };
|
|
||||||
if( chunk.empty() ) {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
models = std::make_unique<std::vector<Eu7Model>>( std::move( chunk ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
section_completed =
|
|
||||||
cursor.solo_remaining == 0 && cursor.inst_remaining == 0;
|
|
||||||
|
|
||||||
PackSectionReady result;
|
PackSectionReady result;
|
||||||
result.row = job.row;
|
result.row = job.row;
|
||||||
result.column = job.column;
|
result.column = job.column;
|
||||||
result.section_idx = job.section_idx;
|
result.section_idx = job.section_idx;
|
||||||
result.models = std::move( models );
|
result.models = std::move( models );
|
||||||
result.subchunk_index = batch_index;
|
result.failed = result.models == nullptr;
|
||||||
result.section_final = section_completed;
|
|
||||||
|
if( result.failed ) {
|
||||||
|
enqueue_failed_section( job );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if( result.models != nullptr ) {
|
|
||||||
pack_bench_inc(
|
pack_bench_inc(
|
||||||
&Eu7PackBench::worker_models_decoded, result.models->size() );
|
&Eu7PackBench::worker_models_decoded, result.models->size() );
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock { g_stream.ready.mutex };
|
std::lock_guard<std::mutex> lock { g_stream.ready.mutex };
|
||||||
g_stream.ready.data.push_back( std::move( result ) );
|
g_stream.ready.data.push_back( std::move( result ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
++batch_index;
|
|
||||||
|
|
||||||
if( section_completed ) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( section_completed ) {
|
|
||||||
pack_bench_inc( &Eu7PackBench::worker_sections_done );
|
pack_bench_inc( &Eu7PackBench::worker_sections_done );
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch( std::exception const &ex ) {
|
catch( std::exception const &ex ) {
|
||||||
ErrorLog(
|
ErrorLog(
|
||||||
std::string{ "EU7 PACK: sekcja " + std::to_string( job.row ) + "," +
|
std::string{ "EU7 PACK: sekcja " + std::to_string( job.row ) + "," +
|
||||||
std::to_string( job.column ) + ": " } + ex.what() );
|
std::to_string( job.column ) + ": " } + ex.what() );
|
||||||
fail_section( job.section_idx );
|
enqueue_failed_section( job );
|
||||||
PackSectionReady result;
|
|
||||||
result.row = job.row;
|
|
||||||
result.column = job.column;
|
|
||||||
result.section_idx = job.section_idx;
|
|
||||||
result.failed = true;
|
|
||||||
result.section_final = true;
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock { g_stream.ready.mutex };
|
|
||||||
g_stream.ready.data.push_back( std::move( result ) );
|
|
||||||
}
|
|
||||||
pack_bench_inc( &Eu7PackBench::worker_failures );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -894,9 +849,6 @@ start_workers() {
|
|||||||
|
|
||||||
void
|
void
|
||||||
finalize_section( PackSectionReady const &batch ) {
|
finalize_section( PackSectionReady const &batch ) {
|
||||||
if( false == batch.section_final ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
g_stream.loaded_sections.insert( batch.section_idx );
|
g_stream.loaded_sections.insert( batch.section_idx );
|
||||||
g_stream.in_flight_sections.erase( batch.section_idx );
|
g_stream.in_flight_sections.erase( batch.section_idx );
|
||||||
++load_stats().pack_sections_loaded;
|
++load_stats().pack_sections_loaded;
|
||||||
@@ -904,11 +856,43 @@ finalize_section( PackSectionReady const &batch ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fail_section( std::size_t const section_idx ) {
|
fail_section(
|
||||||
|
std::size_t const section_idx,
|
||||||
|
int const row,
|
||||||
|
int const column ) {
|
||||||
|
if( g_stream.loaded_sections.contains( section_idx ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( row >= 0 && column >= 0 ) {
|
||||||
|
WriteLog(
|
||||||
|
"EU7 PACK: failed section " + std::to_string( row ) + "," +
|
||||||
|
std::to_string( column ) );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
WriteLog( "EU7 PACK: failed section idx=" + std::to_string( section_idx ) );
|
||||||
|
}
|
||||||
|
|
||||||
g_stream.loaded_sections.insert( section_idx );
|
g_stream.loaded_sections.insert( section_idx );
|
||||||
g_stream.in_flight_sections.erase( section_idx );
|
g_stream.in_flight_sections.erase( section_idx );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
enqueue_failed_section( PackSectionJob const &job ) {
|
||||||
|
PackSectionReady result;
|
||||||
|
result.row = job.row;
|
||||||
|
result.column = job.column;
|
||||||
|
result.section_idx = job.section_idx;
|
||||||
|
result.failed = true;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock { g_stream.ready.mutex };
|
||||||
|
g_stream.ready.data.push_back( std::move( result ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
pack_bench_inc( &Eu7PackBench::worker_failures );
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] int
|
[[nodiscard]] int
|
||||||
section_manhattan_sections(
|
section_manhattan_sections(
|
||||||
int const row,
|
int const row,
|
||||||
@@ -1212,37 +1196,68 @@ try_dequeue_ready_batch() {
|
|||||||
bool has_batch { false };
|
bool has_batch { false };
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock { g_stream.ready.mutex };
|
std::lock_guard<std::mutex> lock { g_stream.ready.mutex };
|
||||||
|
for( auto it { g_stream.ready.data.begin() }; it != g_stream.ready.data.end(); ) {
|
||||||
|
if( it->failed || it->models == nullptr || it->models->empty() ) {
|
||||||
|
if( it->failed ) {
|
||||||
|
fail_section( it->section_idx, it->row, it->column );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
finalize_section( *it );
|
||||||
|
}
|
||||||
|
it = g_stream.ready.data.erase( it );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
if( false == g_stream.ready.data.empty() ) {
|
if( false == g_stream.ready.data.empty() ) {
|
||||||
auto const best_it {
|
auto const pick_best {
|
||||||
std::min_element(
|
[&]( int const max_distance ) -> std::deque<PackSectionReady>::iterator {
|
||||||
g_stream.ready.data.begin(),
|
auto best_it { g_stream.ready.data.end() };
|
||||||
g_stream.ready.data.end(),
|
auto best_dist { std::numeric_limits<int>::max() };
|
||||||
[]( PackSectionReady const &lhs, PackSectionReady const &rhs ) {
|
for( auto it { g_stream.ready.data.begin() }; it != g_stream.ready.data.end(); ++it ) {
|
||||||
auto const lhs_dist {
|
if( it->failed || it->models == nullptr || it->models->empty() ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto const dist {
|
||||||
section_manhattan_sections(
|
section_manhattan_sections(
|
||||||
lhs.row,
|
it->row,
|
||||||
lhs.column,
|
it->column,
|
||||||
g_stream.center_row,
|
g_stream.center_row,
|
||||||
g_stream.center_column ) };
|
g_stream.center_column ) };
|
||||||
auto const rhs_dist {
|
if( max_distance >= 0 && dist > max_distance ) {
|
||||||
section_manhattan_sections(
|
continue;
|
||||||
rhs.row,
|
|
||||||
rhs.column,
|
|
||||||
g_stream.center_row,
|
|
||||||
g_stream.center_column ) };
|
|
||||||
if( lhs_dist != rhs_dist ) {
|
|
||||||
return lhs_dist < rhs_dist;
|
|
||||||
}
|
}
|
||||||
if( lhs.section_idx != rhs.section_idx ) {
|
if( dist < best_dist || ( dist == best_dist && best_it == g_stream.ready.data.end() ) ) {
|
||||||
return lhs.section_idx < rhs.section_idx;
|
best_dist = dist;
|
||||||
|
best_it = it;
|
||||||
}
|
}
|
||||||
return lhs.subchunk_index < rhs.subchunk_index;
|
else if(
|
||||||
} ) };
|
dist == best_dist && best_it != g_stream.ready.data.end() &&
|
||||||
|
it->section_idx < best_it->section_idx ) {
|
||||||
|
best_it = it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return best_it;
|
||||||
|
} };
|
||||||
|
|
||||||
|
auto best_it {
|
||||||
|
pick_best( kSectionStreamGameplayRadiusKm ) };
|
||||||
|
if( best_it == g_stream.ready.data.end() ) {
|
||||||
|
best_it = pick_best( -1 );
|
||||||
|
}
|
||||||
|
if(
|
||||||
|
best_it == g_stream.ready.data.end()
|
||||||
|
&& false == g_stream.ready.data.empty() ) {
|
||||||
|
best_it = g_stream.ready.data.begin();
|
||||||
|
}
|
||||||
|
if( best_it != g_stream.ready.data.end() ) {
|
||||||
batch = std::move( *best_it );
|
batch = std::move( *best_it );
|
||||||
g_stream.ready.data.erase( best_it );
|
g_stream.ready.data.erase( best_it );
|
||||||
has_batch = true;
|
has_batch = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if( false == has_batch ) {
|
if( false == has_batch ) {
|
||||||
return false;
|
return false;
|
||||||
@@ -1250,7 +1265,7 @@ try_dequeue_ready_batch() {
|
|||||||
|
|
||||||
if( batch.failed || batch.models == nullptr || batch.models->empty() ) {
|
if( batch.failed || batch.models == nullptr || batch.models->empty() ) {
|
||||||
if( batch.failed ) {
|
if( batch.failed ) {
|
||||||
fail_section( batch.section_idx );
|
fail_section( batch.section_idx, batch.row, batch.column );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
finalize_section( batch );
|
finalize_section( batch );
|
||||||
@@ -1259,7 +1274,8 @@ try_dequeue_ready_batch() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
g_stream.pending_apply = std::move( batch );
|
g_stream.pending_apply = std::move( batch );
|
||||||
g_stream.pending_apply_offset = 0;
|
g_stream.pending_apply_offset = g_stream.pending_apply->apply_offset;
|
||||||
|
g_stream.pending_apply->apply_offset = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1371,30 +1387,29 @@ drain_until_budget( double const budget_ms ) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
sync_stream_limits( glm::dvec3 const &world_position ) {
|
sync_stream_limits( glm::dvec3 const &world_position ) {
|
||||||
if( false == g_loading_screen_dismissed ) {
|
(void)world_position;
|
||||||
g_stream_catchup = false;
|
g_stream_catchup = false;
|
||||||
|
if( false == g_loading_screen_dismissed ) {
|
||||||
g_stream_max_in_flight = 6;
|
g_stream_max_in_flight = 6;
|
||||||
g_stream_max_ready = 2;
|
g_stream_max_ready = 2;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const inner_progress {
|
g_stream_max_in_flight = kMaxInFlightSections;
|
||||||
section_stream_ring_progress( world_position, kSectionStreamGameplayRadiusKm ) };
|
g_stream_max_ready = kMaxReadySections;
|
||||||
g_stream_catchup =
|
|
||||||
inner_progress < 0.99f
|
|
||||||
|| false == section_stream_ready_around(
|
|
||||||
world_position,
|
|
||||||
kSectionStreamGameplayRadiusKm );
|
|
||||||
g_stream_max_in_flight = g_stream_catchup ?
|
|
||||||
kCatchupMaxInFlightSections :
|
|
||||||
kMaxInFlightSections;
|
|
||||||
g_stream_max_ready = g_stream_catchup ?
|
|
||||||
kCatchupMaxReadySections :
|
|
||||||
kMaxReadySections;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
void
|
||||||
|
remember_stream_anchor( glm::dvec3 const &position );
|
||||||
|
|
||||||
|
[[nodiscard]] bool
|
||||||
|
camera_far_from_stream_anchor( glm::dvec3 const &camera_position );
|
||||||
|
|
||||||
|
[[nodiscard]] glm::dvec3
|
||||||
|
resolve_section_stream_position( glm::dvec3 const &hint );
|
||||||
|
|
||||||
void
|
void
|
||||||
init_section_stream(
|
init_section_stream(
|
||||||
Eu7Module const &root_module,
|
Eu7Module const &root_module,
|
||||||
@@ -1434,6 +1449,8 @@ prime_section_stream( Eu7Module const &root_module ) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remember_stream_anchor( initial );
|
||||||
|
|
||||||
auto const [row, column] { section_row_column( initial ) };
|
auto const [row, column] { section_row_column( initial ) };
|
||||||
g_stream.center_row = row;
|
g_stream.center_row = row;
|
||||||
g_stream.center_column = column;
|
g_stream.center_column = column;
|
||||||
@@ -1534,12 +1551,14 @@ update_section_stream( glm::dvec3 const &world_position ) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const [center_row, center_column] { section_row_column( world_position ) };
|
auto const stream_position { resolve_section_stream_position( world_position ) };
|
||||||
|
|
||||||
|
auto const [center_row, center_column] { section_row_column( stream_position ) };
|
||||||
auto const center_moved {
|
auto const center_moved {
|
||||||
center_row != g_stream.center_row || center_column != g_stream.center_column };
|
center_row != g_stream.center_row || center_column != g_stream.center_column };
|
||||||
auto const moved_since_enqueue {
|
auto const moved_since_enqueue {
|
||||||
g_stream.has_last_enqueue_position ?
|
g_stream.has_last_enqueue_position ?
|
||||||
glm::length( world_position - g_stream.last_enqueue_position ) :
|
glm::length( stream_position - g_stream.last_enqueue_position ) :
|
||||||
std::numeric_limits<double>::infinity() };
|
std::numeric_limits<double>::infinity() };
|
||||||
|
|
||||||
if( moved_since_enqueue > kTeleportReenqueueDistanceM ) {
|
if( moved_since_enqueue > kTeleportReenqueueDistanceM ) {
|
||||||
@@ -1553,41 +1572,33 @@ update_section_stream( glm::dvec3 const &world_position ) {
|
|||||||
reprioritize_job_queue();
|
reprioritize_job_queue();
|
||||||
}
|
}
|
||||||
|
|
||||||
sync_stream_limits( world_position );
|
sync_stream_limits( stream_position );
|
||||||
|
|
||||||
auto const ring_radius { g_stream.radius };
|
auto const inner_ring_ready {
|
||||||
auto const reenqueue_distance {
|
section_stream_ready_around( stream_position, kSectionStreamGameplayRadiusKm ) };
|
||||||
g_stream_catchup ? kCatchupReenqueueDistanceM : kReenqueueDistanceM };
|
auto const ring_radius {
|
||||||
auto max_lookahead { g_stream_catchup ? 15 : 5 };
|
inner_ring_ready ? g_stream.radius : kSectionStreamGameplayRadiusKm };
|
||||||
if( g_stream_catchup ) {
|
auto const reenqueue_distance { kReenqueueDistanceM };
|
||||||
auto const speed { camera_stream_speed_mps() };
|
auto max_lookahead { inner_ring_ready ? 5 : 0 };
|
||||||
if( speed > 1200.0 ) {
|
|
||||||
max_lookahead = 25;
|
|
||||||
}
|
|
||||||
else if( speed > 600.0 ) {
|
|
||||||
max_lookahead = 20;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
auto const travel_forward { guess_travel_forward() };
|
auto const travel_forward { guess_travel_forward() };
|
||||||
|
|
||||||
auto const current_section_unloaded {
|
auto const current_section_unloaded {
|
||||||
section_has_pack_models( center_row, center_column )
|
section_has_pack_models( center_row, center_column )
|
||||||
&& false == g_stream.loaded_sections.contains( section_index( center_row, center_column ) ) };
|
&& false == g_stream.loaded_sections.contains( section_index( center_row, center_column ) ) };
|
||||||
auto const inner_ring_incomplete {
|
auto const inner_ring_incomplete { current_section_unloaded || false == inner_ring_ready };
|
||||||
current_section_unloaded
|
|
||||||
|| false == section_stream_ready_around( world_position, kSectionStreamGameplayRadiusKm ) };
|
|
||||||
auto const should_reenqueue {
|
auto const should_reenqueue {
|
||||||
center_moved
|
center_moved
|
||||||
|| false == g_stream.has_last_enqueue_position
|
|| false == g_stream.has_last_enqueue_position
|
||||||
|| moved_since_enqueue >= reenqueue_distance };
|
|| moved_since_enqueue >= reenqueue_distance };
|
||||||
|
|
||||||
if( should_reenqueue || inner_ring_incomplete || g_stream_catchup ) {
|
if( should_reenqueue || inner_ring_incomplete ) {
|
||||||
enqueue_sections_around( center_row, center_column, ring_radius, world_position );
|
enqueue_sections_around( center_row, center_column, ring_radius, stream_position );
|
||||||
g_stream.last_enqueue_position = world_position;
|
g_stream.last_enqueue_position = stream_position;
|
||||||
g_stream.has_last_enqueue_position = true;
|
g_stream.has_last_enqueue_position = true;
|
||||||
if( should_reenqueue || inner_ring_incomplete ) {
|
if( should_reenqueue || inner_ring_incomplete ) {
|
||||||
pack_bench_inc( &Eu7PackBench::stream_reenqueue );
|
pack_bench_inc( &Eu7PackBench::stream_reenqueue );
|
||||||
}
|
}
|
||||||
|
if( max_lookahead > 0 ) {
|
||||||
enqueue_movement_lookahead(
|
enqueue_movement_lookahead(
|
||||||
center_row,
|
center_row,
|
||||||
center_column,
|
center_column,
|
||||||
@@ -1595,23 +1606,13 @@ update_section_stream( glm::dvec3 const &world_position ) {
|
|||||||
travel_forward,
|
travel_forward,
|
||||||
max_lookahead );
|
max_lookahead );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool
|
[[nodiscard]] bool
|
||||||
section_stream_drain_idle( glm::dvec3 const &world_position ) {
|
section_stream_drain_idle( glm::dvec3 const &world_position ) {
|
||||||
if( g_stream.bootstrap_pending || g_stream.bootstrap_active ) {
|
(void)world_position;
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
if( g_stream.pending_apply.has_value() || ready_queue_size() > 0 ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if( false == g_stream.in_flight_sections.empty() || g_stream_catchup ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if( false == section_stream_ready_around( world_position, kSectionStreamGameplayRadiusKm ) ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return load_stats().pack_models >= 500;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1624,33 +1625,27 @@ drain_section_stream(
|
|||||||
if( false == g_stream.active ) {
|
if( false == g_stream.active ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if( section_stream_drain_idle( Global.pCamera.Pos ) ) {
|
auto const stream_position {
|
||||||
|
resolve_section_stream_position(
|
||||||
|
g_loading_screen_dismissed ?
|
||||||
|
Global.pCamera.Pos :
|
||||||
|
stream_loading_position() ) };
|
||||||
|
if( gameplay_stream_mode() && section_stream_drain_idle( stream_position ) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( gameplay_stream_mode() ) {
|
auto const inner_ring_ready {
|
||||||
auto apply_budget { gameplay_apply_budget_ms() };
|
section_stream_ready_around(
|
||||||
std::size_t max_chunks { 1 };
|
stream_position,
|
||||||
if( g_stream_catchup ) {
|
|
||||||
auto const inner_ring {
|
|
||||||
section_stream_ring_progress(
|
|
||||||
Global.pCamera.Pos,
|
|
||||||
kSectionStreamGameplayRadiusKm ) };
|
kSectionStreamGameplayRadiusKm ) };
|
||||||
auto const speed { camera_stream_speed_mps() };
|
|
||||||
if(
|
if( gameplay_stream_mode() && inner_ring_ready ) {
|
||||||
inner_ring < kStationaryCatchupRingThreshold
|
drain_until_budget( kDrainBudgetMs );
|
||||||
&& speed < kStationaryCatchupSpeedMps ) {
|
maybe_log_stream_status( stream_position );
|
||||||
max_chunks = 2;
|
|
||||||
apply_budget = std::max( apply_budget, kCatchupApplyBudgetMs * 1.25 );
|
|
||||||
}
|
}
|
||||||
}
|
else if( gameplay_stream_mode() ) {
|
||||||
drain_apply_budget(
|
drain_until_budget( kLoaderDrainBudgetMs );
|
||||||
apply_budget,
|
maybe_log_stream_status( stream_position );
|
||||||
gameplay_slice_instances(),
|
|
||||||
gameplay_slice_cold_meshes(),
|
|
||||||
gameplay_cold_budget_ms(),
|
|
||||||
max_chunks );
|
|
||||||
maybe_log_stream_status( Global.pCamera.Pos );
|
|
||||||
}
|
}
|
||||||
else if( false == g_loading_screen_dismissed ) {
|
else if( false == g_loading_screen_dismissed ) {
|
||||||
auto position { stream_loading_position() };
|
auto position { stream_loading_position() };
|
||||||
@@ -1693,6 +1688,8 @@ kick_section_stream_bootstrap() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remember_stream_anchor( position );
|
||||||
|
|
||||||
auto const [row, column] { section_row_column( position ) };
|
auto const [row, column] { section_row_column( position ) };
|
||||||
g_stream.center_row = row;
|
g_stream.center_row = row;
|
||||||
g_stream.center_column = column;
|
g_stream.center_column = column;
|
||||||
@@ -1734,6 +1731,7 @@ preload_section_stream( double const max_drain_ms ) {
|
|||||||
if( position.x == 0.0 && position.y == 0.0 && position.z == 0.0 ) {
|
if( position.x == 0.0 && position.y == 0.0 && position.z == 0.0 ) {
|
||||||
position = guess_initial_stream_position( stream_module() );
|
position = guess_initial_stream_position( stream_module() );
|
||||||
}
|
}
|
||||||
|
position = resolve_section_stream_position( position );
|
||||||
|
|
||||||
if( section_stream_needs_bootstrap() ) {
|
if( section_stream_needs_bootstrap() ) {
|
||||||
if( position.x != 0.0 || position.y != 0.0 || position.z != 0.0 ) {
|
if( position.x != 0.0 || position.y != 0.0 || position.z != 0.0 ) {
|
||||||
@@ -1932,6 +1930,23 @@ dismiss_loading_screen() {
|
|||||||
pack_bench_begin_stream_phase();
|
pack_bench_begin_stream_phase();
|
||||||
g_loading_screen_dismissed = true;
|
g_loading_screen_dismissed = true;
|
||||||
g_ring_ready_since.reset();
|
g_ring_ready_since.reset();
|
||||||
|
|
||||||
|
if( g_stream.has_anchor_position ) {
|
||||||
|
auto const &saved_camera { Global.FreeCameraInit[ 0 ] };
|
||||||
|
auto const camera_unset {
|
||||||
|
saved_camera.x == 0.0 && saved_camera.y == 0.0 && saved_camera.z == 0.0 };
|
||||||
|
auto const camera_off_scenery {
|
||||||
|
false == camera_unset && camera_far_from_stream_anchor( saved_camera ) };
|
||||||
|
if( camera_unset || camera_off_scenery ) {
|
||||||
|
Global.FreeCameraInit[ 0 ] = g_stream.anchor_position;
|
||||||
|
Global.pCamera.Pos = g_stream.anchor_position;
|
||||||
|
WriteLog(
|
||||||
|
"EU7 PACK: ustawiam kamere startowa na " +
|
||||||
|
std::to_string( g_stream.anchor_position.x ) + "," +
|
||||||
|
std::to_string( g_stream.anchor_position.y ) + "," +
|
||||||
|
std::to_string( g_stream.anchor_position.z ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@@ -1978,15 +1993,24 @@ loading_screen_blocks_world(
|
|||||||
|
|
||||||
glm::dvec3
|
glm::dvec3
|
||||||
stream_loading_position() {
|
stream_loading_position() {
|
||||||
if( Global.pCamera.Pos.x != 0.0 || Global.pCamera.Pos.y != 0.0 || Global.pCamera.Pos.z != 0.0 ) {
|
if( g_loading_screen_dismissed ) {
|
||||||
return Global.pCamera.Pos;
|
return Global.pCamera.Pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto const &camera { Global.pCamera.Pos };
|
||||||
|
if( camera.x != 0.0 || camera.y != 0.0 || camera.z != 0.0 ) {
|
||||||
|
return camera;
|
||||||
|
}
|
||||||
|
|
||||||
auto position { resolve_stream_position() };
|
auto position { resolve_stream_position() };
|
||||||
if( position.x != 0.0 || position.y != 0.0 || position.z != 0.0 ) {
|
if( position.x != 0.0 || position.y != 0.0 || position.z != 0.0 ) {
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( g_stream.has_anchor_position ) {
|
||||||
|
return g_stream.anchor_position;
|
||||||
|
}
|
||||||
|
|
||||||
return Global.FreeCameraInit[ 0 ];
|
return Global.FreeCameraInit[ 0 ];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2025,6 +2049,48 @@ section_stream_ring_progress(
|
|||||||
return std::clamp( accumulated / static_cast<float>( pack_sections ), 0.f, 1.f );
|
return std::clamp( accumulated / static_cast<float>( pack_sections ), 0.f, 1.f );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
remember_stream_anchor( glm::dvec3 const &position ) {
|
||||||
|
if( position.x == 0.0 && position.y == 0.0 && position.z == 0.0 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_stream.anchor_position = position;
|
||||||
|
g_stream.has_anchor_position = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] glm::dvec3
|
||||||
|
resolve_section_stream_position( glm::dvec3 const &hint ) {
|
||||||
|
if(
|
||||||
|
hint.x == 0.0 && hint.y == 0.0 && hint.z == 0.0
|
||||||
|
&& g_stream.has_anchor_position ) {
|
||||||
|
return g_stream.anchor_position;
|
||||||
|
}
|
||||||
|
if( camera_far_from_stream_anchor( hint ) && g_stream.has_anchor_position ) {
|
||||||
|
return g_stream.anchor_position;
|
||||||
|
}
|
||||||
|
return hint;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool
|
||||||
|
camera_far_from_stream_anchor( glm::dvec3 const &camera_position ) {
|
||||||
|
if( false == g_stream.has_anchor_position ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto const anchor_dist {
|
||||||
|
glm::length(
|
||||||
|
glm::dvec2 {
|
||||||
|
camera_position.x - g_stream.anchor_position.x,
|
||||||
|
camera_position.z - g_stream.anchor_position.z } ) };
|
||||||
|
auto const anchor_magnitude {
|
||||||
|
glm::length(
|
||||||
|
glm::dvec2 { g_stream.anchor_position.x, g_stream.anchor_position.z } ) };
|
||||||
|
auto const camera_magnitude {
|
||||||
|
glm::length( glm::dvec2 { camera_position.x, camera_position.z } ) };
|
||||||
|
return anchor_dist > 30000.0
|
||||||
|
&& camera_magnitude < 30000.0
|
||||||
|
&& anchor_magnitude > 50000.0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
reset_section_stream() {
|
reset_section_stream() {
|
||||||
flush_pack_stream_bench();
|
flush_pack_stream_bench();
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class state_serializer;
|
|||||||
|
|
||||||
namespace scene::eu7 {
|
namespace scene::eu7 {
|
||||||
|
|
||||||
constexpr int kSectionStreamBootstrapRadiusKm { 3 };
|
constexpr int kSectionStreamBootstrapRadiusKm { 4 };
|
||||||
constexpr int kSectionStreamGameplayRadiusKm { 4 };
|
constexpr int kSectionStreamGameplayRadiusKm { 4 };
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -34,6 +34,10 @@ prime_section_stream( Eu7Module const &RootModule );
|
|||||||
[[nodiscard]] glm::dvec3
|
[[nodiscard]] glm::dvec3
|
||||||
resolve_stream_position();
|
resolve_stream_position();
|
||||||
|
|
||||||
|
// Kamera / pojazd moga byc w innej przestrzeni wspolrzednych niz PACK — uzyj kotwicy scenerii.
|
||||||
|
[[nodiscard]] glm::dvec3
|
||||||
|
resolve_section_stream_position( glm::dvec3 const &Hint );
|
||||||
|
|
||||||
// Opcjonalnie blokuje do zaladowania pierścienia bootstrap wokol pozycji (debug/narzedzia).
|
// Opcjonalnie blokuje do zaladowania pierścienia bootstrap wokol pozycji (debug/narzedzia).
|
||||||
void
|
void
|
||||||
bootstrap_section_stream( glm::dvec3 const &WorldPosition );
|
bootstrap_section_stream( glm::dvec3 const &WorldPosition );
|
||||||
|
|||||||
@@ -360,7 +360,7 @@ struct Eu7PackIndexEntry {
|
|||||||
std::uint64_t pack_offset = 0;
|
std::uint64_t pack_offset = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Stan inkrementalnego odczytu sekcji PACK z istream (po seek_pack_section).
|
// Stan odczytu sekcji PACK z istream (uzywany wewnetrznie przez reader).
|
||||||
struct Eu7PackSectionCursor {
|
struct Eu7PackSectionCursor {
|
||||||
std::uint32_t solo_remaining { 0 };
|
std::uint32_t solo_remaining { 0 };
|
||||||
std::uint32_t inst_remaining { 0 };
|
std::uint32_t inst_remaining { 0 };
|
||||||
|
|||||||
@@ -617,15 +617,16 @@ state_serializer::deserialize_begin( std::string const &Scenariofile ) {
|
|||||||
is_pure_eu7_scenario = scene::eu7::probe_file( resolved_scenario );
|
is_pure_eu7_scenario = scene::eu7::probe_file( resolved_scenario );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool const has_baked_eu7_root {
|
bool const use_eu7_scenario {
|
||||||
false == is_pure_eu7_scenario &&
|
is_pure_eu7_scenario || scene::eu7::probe_baked_scenario( Scenariofile ) };
|
||||||
scene::eu7::should_use_binary_module( Scenariofile ) };
|
auto const eu7_load_path {
|
||||||
auto const baked_root_path {
|
is_pure_eu7_scenario ?
|
||||||
|
resolved_scenario :
|
||||||
scene::eu7::resolve_scenery_path( scene::eu7::binary_path( Scenariofile ) ) };
|
scene::eu7::resolve_scenery_path( scene::eu7::binary_path( Scenariofile ) ) };
|
||||||
|
|
||||||
// Scenariusz EU7B: nie parsujemy binarki jako tekstu SCM.
|
// Scenariusz EU7B: nie parsujemy binarki jako tekstu SCM.
|
||||||
std::shared_ptr<deserializer_state> state;
|
std::shared_ptr<deserializer_state> state;
|
||||||
if( is_pure_eu7_scenario ) {
|
if( use_eu7_scenario ) {
|
||||||
state = std::make_shared<deserializer_state>(
|
state = std::make_shared<deserializer_state>(
|
||||||
std::string{}, cParser::buffer_TEXT, Global.asCurrentSceneryPath, Global.bLoadTraction );
|
std::string{}, cParser::buffer_TEXT, Global.asCurrentSceneryPath, Global.bLoadTraction );
|
||||||
state->scenariofile = Scenariofile;
|
state->scenariofile = Scenariofile;
|
||||||
@@ -637,25 +638,12 @@ state_serializer::deserialize_begin( std::string const &Scenariofile ) {
|
|||||||
|
|
||||||
state->scratchpad.name = Scenariofile;
|
state->scratchpad.name = Scenariofile;
|
||||||
|
|
||||||
if( is_pure_eu7_scenario ) {
|
if( use_eu7_scenario ) {
|
||||||
Global.file_binary_terrain_state = true;
|
Global.file_binary_terrain_state = true;
|
||||||
state->scratchpad.binary.terrain = true;
|
state->scratchpad.binary.terrain = true;
|
||||||
state->scratchpad.binary.terrain_included = true;
|
state->scratchpad.binary.terrain_included = true;
|
||||||
WriteLog( "EU7 scenario: " + resolved_scenario );
|
WriteLog( "EU7 scenario: " + eu7_load_path );
|
||||||
if( false == scene::eu7::load_module( resolved_scenario, *this ) ) {
|
if( false == scene::eu7::load_module( eu7_load_path, *this ) ) {
|
||||||
throw invalid_scenery_exception();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if( has_baked_eu7_root ) {
|
|
||||||
Global.file_binary_terrain_state = true;
|
|
||||||
state->scratchpad.binary.terrain = true;
|
|
||||||
if( scene::eu7::is_scenario_terrain( Scenariofile ) ) {
|
|
||||||
state->scratchpad.binary.terrain_included = true;
|
|
||||||
}
|
|
||||||
WriteLog(
|
|
||||||
"EU7 hybrid: metadata z \"" + Scenariofile + "\", sceneria z \"" +
|
|
||||||
baked_root_path + "\"" );
|
|
||||||
if( false == scene::eu7::load_module( baked_root_path, *this ) ) {
|
|
||||||
throw invalid_scenery_exception();
|
throw invalid_scenery_exception();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ def read_cstring(f, rva: int) -> str:
|
|||||||
def parse(path: Path) -> None:
|
def parse(path: Path) -> None:
|
||||||
with path.open("rb") as f:
|
with path.open("rb") as f:
|
||||||
sig, ver, num_streams, dir_rva, checksum, ts, flags = struct.unpack(
|
sig, ver, num_streams, dir_rva, checksum, ts, flags = struct.unpack(
|
||||||
"<IIIIIQ", f.read(32)
|
"<IIIIIIQ", f.read(32)
|
||||||
)
|
)
|
||||||
print(f"File: {path}")
|
print(f"File: {path}")
|
||||||
print(f"Size: {path.stat().st_size:,} bytes")
|
print(f"Size: {path.stat().st_size:,} bytes")
|
||||||
|
|||||||
@@ -366,9 +366,7 @@ void cParser::startIncludeFromParser(cParser& srcParser, bool ToLower, std::stri
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( scene::eu7::probe_file( eu7path ) ) {
|
|
||||||
WriteLog( "EU7: przestarzaly .eu7, fallback SCM: " + includefile );
|
|
||||||
}
|
|
||||||
if (isTerrain && true == Global.file_binary_terrain_state) {
|
if (isTerrain && true == Global.file_binary_terrain_state) {
|
||||||
WriteLog("Binary terrain present, ignoring: " + includefile);
|
WriteLog("Binary terrain present, ignoring: " + includefile);
|
||||||
readParameters(srcParser); // preserve original side-effect: still consume parameters
|
readParameters(srcParser); // preserve original side-effect: still consume parameters
|
||||||
|
|||||||
@@ -75,6 +75,17 @@ ui::map_panel::map_panel() : ui_panel(STR_C("Map"), false)
|
|||||||
|
|
||||||
scene_ubo = std::make_unique<gl::ubo>(sizeof(gl::scene_ubs), 0);
|
scene_ubo = std::make_unique<gl::ubo>(sizeof(gl::scene_ubs), 0);
|
||||||
|
|
||||||
|
if( simulation::Train != nullptr && simulation::Train->Dynamic() != nullptr ) {
|
||||||
|
mode = MODE_VEHICLE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto const &start { Global.FreeCameraInit[ 0 ] };
|
||||||
|
if( start.x != 0.0 || start.z != 0.0 ) {
|
||||||
|
mode = MODE_CAMERA;
|
||||||
|
translate = glm::vec2( static_cast<float>( start.x ), static_cast<float>( start.z ) ) * -zoom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
init_done = true;
|
init_done = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,9 +99,6 @@ float ui::map_panel::get_vehicle_rotation()
|
|||||||
|
|
||||||
void ui::map_panel::render_map_texture(glm::mat4 transform, glm::vec2 surface_size)
|
void ui::map_panel::render_map_texture(glm::mat4 transform, glm::vec2 surface_size)
|
||||||
{
|
{
|
||||||
cFrustum frustum;
|
|
||||||
frustum.calculate(transform, glm::mat4());
|
|
||||||
|
|
||||||
m_colored_paths.switches.clear();
|
m_colored_paths.switches.clear();
|
||||||
m_colored_paths.occupied.clear();
|
m_colored_paths.occupied.clear();
|
||||||
m_colored_paths.future.clear();
|
m_colored_paths.future.clear();
|
||||||
@@ -102,17 +110,17 @@ void ui::map_panel::render_map_texture(glm::mat4 transform, glm::vec2 surface_si
|
|||||||
for (int column = 0; column < scene::EU07_REGIONSIDESECTIONCOUNT; column++)
|
for (int column = 0; column < scene::EU07_REGIONSIDESECTIONCOUNT; column++)
|
||||||
{
|
{
|
||||||
scene::basic_section *section = simulation::Region->get_section(row * scene::EU07_REGIONSIDESECTIONCOUNT + column);
|
scene::basic_section *section = simulation::Region->get_section(row * scene::EU07_REGIONSIDESECTIONCOUNT + column);
|
||||||
if (section && frustum.sphere_inside(section->area().center, section->area().radius) > 0.f)
|
if( section == nullptr ) {
|
||||||
{
|
continue;
|
||||||
|
}
|
||||||
const gfx::geometrybank_handle handle = section->get_map_geometry();
|
const gfx::geometrybank_handle handle = section->get_map_geometry();
|
||||||
if (handle != null_handle)
|
if( handle != null_handle )
|
||||||
{
|
{
|
||||||
m_section_handles.push_back(handle);
|
m_section_handles.push_back(handle);
|
||||||
section->get_map_active_paths(m_colored_paths);
|
section->get_map_active_paths(m_colored_paths);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (TTrack *track : simulation::Paths.sequence()) {
|
for (TTrack *track : simulation::Paths.sequence()) {
|
||||||
track->get_map_future_paths(m_colored_paths);
|
track->get_map_future_paths(m_colored_paths);
|
||||||
@@ -230,6 +238,17 @@ void ui::map_panel::render_contents()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( simulation::Train != nullptr && simulation::Train->Dynamic() != nullptr ) {
|
||||||
|
if( mode == MODE_MANUAL ) {
|
||||||
|
mode = MODE_VEHICLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(
|
||||||
|
mode == MODE_MANUAL
|
||||||
|
&& ( Global.pCamera.Pos.x != 0.0 || Global.pCamera.Pos.z != 0.0 ) ) {
|
||||||
|
mode = MODE_CAMERA;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
float prev_zoom = zoom;
|
float prev_zoom = zoom;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user