diff options
| author | Valentin Popov <valentin@popov.link> | 2026-07-18 08:36:29 +0300 |
|---|---|---|
| committer | Valentin Popov <valentin@popov.link> | 2026-07-18 08:36:29 +0300 |
| commit | 697cbbfd36bb8d82dd2b419bc181889cc3c46f6a (patch) | |
| tree | 0af8dc6b98b634bc804e700746d0c1582e9eea45 /crates/fparkan-runtime/src | |
| parent | f75601a86a9202f8f226ac04a1238b3660071915 (diff) | |
| download | fparkan-697cbbfd36bb8d82dd2b419bc181889cc3c46f6a.tar.xz fparkan-697cbbfd36bb8d82dd2b419bc181889cc3c46f6a.zip | |
feat(runtime): bound static preview asset loading
Diffstat (limited to 'crates/fparkan-runtime/src')
| -rw-r--r-- | crates/fparkan-runtime/src/lib.rs | 77 |
1 files changed, 69 insertions, 8 deletions
diff --git a/crates/fparkan-runtime/src/lib.rs b/crates/fparkan-runtime/src/lib.rs index 6a4e478..a7c9932 100644 --- a/crates/fparkan-runtime/src/lib.rs +++ b/crates/fparkan-runtime/src/lib.rs @@ -31,7 +31,7 @@ use fparkan_path::{normalize_relative, NormalizedPath, PathError, PathPolicy}; use fparkan_prototype::{ build_prototype_graph_report, PrototypeGraph, PrototypeGraphFailure, PrototypeGraphReport, }; -use fparkan_resource::{resource_name, CachedResourceRepository}; +use fparkan_resource::{resource_name, CachedResourceRepository, ResourceRepository}; use fparkan_vfs::{Vfs, VfsError}; use fparkan_world::{ construct_object, new as new_world, register_object, step, InputSnapshot, ObjectDraft, @@ -182,6 +182,17 @@ pub struct MissionObjectDraft { #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] struct MissionLoadOptions { fail_after_registered_objects: Option<usize>, + asset_scope: MissionAssetScope, +} + +/// Selects how much of the resolved mission asset graph to prepare. +#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] +enum MissionAssetScope { + /// Prepare every reachable asset; required by normal runtime loading. + #[default] + Full, + /// Prepare one root at a time until a mesh-backed preview model is found. + FirstMeshPreview, } /// Loaded mission. @@ -462,6 +473,33 @@ pub fn load_mission( load_mission_with_trace(engine, request).map(|(loaded, _trace)| loaded) } +/// Loads a mission using the bounded static-preview asset scope. +/// +/// This mode preserves map, TMA, graph, construction and registration work, +/// but prepares only the first root that supplies a mesh-backed model. It is +/// intended solely for the opt-in static Vulkan preview and must not be used +/// for normal gameplay, where all reachable assets remain required. +/// +/// # Errors +/// +/// Returns [`EngineError`] under the same decoding, graph, terrain and world +/// conditions as [`load_mission`], plus asset errors for the roots examined by +/// the preview scope. +pub fn load_mission_static_preview( + engine: &mut Engine, + request: MissionRequest, +) -> Result<LoadedMission, EngineError> { + load_mission_with_options( + engine, + request, + MissionLoadOptions { + asset_scope: MissionAssetScope::FirstMeshPreview, + ..MissionLoadOptions::default() + }, + ) + .map(|(loaded, _trace)| loaded) +} + /// Loads mission transactionally and returns a diagnostic trace. /// /// # Errors @@ -564,15 +602,22 @@ fn load_mission_with_options( failures: prototype_report.failures.clone(), }); } - let mission_assets = AssetManager::new(repository) - .prepare_mission_assets( + let asset_manager = AssetManager::new(repository); + let mission_assets = match options.asset_scope { + MissionAssetScope::Full => asset_manager.prepare_mission_assets( &prototype_graph.root_prototype_request_spans, &resolved_prototypes, - ) - .map_err(|source| EngineError::AssetPreparation { - mission: request.key.clone(), - source, - })?; + ), + MissionAssetScope::FirstMeshPreview => prepare_first_mesh_preview_assets( + &asset_manager, + &prototype_graph.root_prototype_request_spans, + &resolved_prototypes, + ), + } + .map_err(|source| EngineError::AssetPreparation { + mission: request.key.clone(), + source, + })?; let mission_asset_plan = mission_assets.to_plan(); let object_drafts: Vec<_> = mission .objects @@ -672,6 +717,21 @@ fn load_mission_with_options( Ok((summary, trace)) } +fn prepare_first_mesh_preview_assets<R: ResourceRepository>( + asset_manager: &AssetManager<R>, + root_spans: &[std::ops::Range<usize>], + prototypes: &[fparkan_prototype::EffectivePrototype], +) -> Result<MissionAssets, AssetPreparationError> { + for span in root_spans { + let assets = + asset_manager.prepare_mission_assets(std::slice::from_ref(span), prototypes)?; + if !assets.models.is_empty() { + return Ok(assets); + } + } + Ok(MissionAssets::default()) +} + /// Steps headless mode. /// /// # Errors @@ -1063,6 +1123,7 @@ mod tests { }, MissionLoadOptions { fail_after_registered_objects: Some(1), + ..MissionLoadOptions::default() }, ) .expect_err("forced registration failure"); |
