use crate::canonical::{project_resolved_profile, project_resolved_profile_v2};
use crate::{ResolvedProfile, ResolvedProfileV2};
use animsmith_core::engine_contract::EngineContractError;
use animsmith_core::prediction::{
PredictionContractError, PredictionProvenanceV1, PredictionProvenanceV2,
PredictionProvenanceV3, PredictionProvenanceV4, PredictionRuleInputsV1,
RawSceneAttachmentBindingV1, RawSceneAttachmentUnavailableReasonV1, RawSourceBindingV1,
RawSourceBindingV2,
};
use animsmith_core::{
EngineRootMotionProjectIntentV1, LoadedSource, PredictionProvenanceV5, PredictionProvenanceV6,
RawAnimationChannelInventoryV1, RawTransformPathInventoryV1, SourceFormatV1,
};
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum PredictionProvenanceProjectionError {
#[error("resolved engine evidence is invalid: {0}")]
EngineContract(#[from] EngineContractError),
#[error("prediction provenance is invalid: {0}")]
PredictionContract(#[from] PredictionContractError),
}
pub fn project_prediction_provenance_v1(
profile: &ResolvedProfile,
source: &LoadedSource,
) -> Result<PredictionProvenanceV1, PredictionProvenanceProjectionError> {
let (profile_contract, settings_contract) = project_resolved_profile(profile)?;
let raw_source = RawSourceBindingV1::from_source(source.source_facts());
Ok(PredictionProvenanceV1::new(
profile_contract,
profile.source_format(),
settings_contract,
raw_source,
source.dependency_closure().clone(),
)?)
}
pub fn project_prediction_provenance_v2(
profile: &ResolvedProfileV2,
source: &LoadedSource,
) -> Result<PredictionProvenanceV2, PredictionProvenanceProjectionError> {
let (profile_contract, settings_contract) = project_resolved_profile_v2(profile)?;
let raw_source = RawSourceBindingV1::from_source(source.source_facts());
Ok(PredictionProvenanceV2::new(
profile_contract,
profile.source_format(),
settings_contract,
raw_source,
source.dependency_closure().clone(),
)?)
}
pub fn project_prediction_provenance_v3(
profile: &ResolvedProfileV2,
source: &LoadedSource,
) -> Result<PredictionProvenanceV3, PredictionProvenanceProjectionError> {
let (profile_contract, settings_contract) = project_resolved_profile_v2(profile)?;
let raw_source =
RawSourceBindingV2::from_source(source.source_facts(), source.exact_source_timing())?;
Ok(PredictionProvenanceV3::new(
profile_contract,
profile.source_format(),
settings_contract,
raw_source,
source.dependency_closure().clone(),
)?)
}
pub fn project_prediction_provenance_v4(
profile: &crate::ResolvedProfileSettingsV2,
source: &LoadedSource,
runtime_node_selectors: Vec<String>,
) -> Result<PredictionProvenanceV4, PredictionProvenanceProjectionError> {
let (profile_contract, settings_contract) =
crate::canonical::project_resolved_engine_settings_v3(profile)?;
let raw_source =
RawSourceBindingV2::from_source(source.source_facts(), source.exact_source_timing())?;
let raw_scene_attachment = source
.raw_scene_attachment_inventory()
.cloned()
.map_or_else(
|| {
RawSceneAttachmentBindingV1::unavailable(match source.source_facts().format() {
SourceFormatV1::Glb | SourceFormatV1::GltfJson => {
RawSceneAttachmentUnavailableReasonV1::LoaderEvidenceUnavailable
}
SourceFormatV1::Fbx => {
RawSceneAttachmentUnavailableReasonV1::UnsupportedSourceFormat
}
})
},
RawSceneAttachmentBindingV1::available,
);
Ok(PredictionProvenanceV4::new(
profile_contract,
profile.source_format(),
settings_contract,
raw_source,
raw_scene_attachment,
source.dependency_closure().clone(),
PredictionRuleInputsV1::new(runtime_node_selectors)?,
)?)
}
pub fn project_prediction_provenance_v5(
profile: &crate::ResolvedProfileSettingsV2,
source: &LoadedSource,
runtime_node_selectors: Vec<String>,
) -> Result<PredictionProvenanceV5, PredictionProvenanceProjectionError> {
let base = project_prediction_provenance_v4(profile, source, runtime_node_selectors)?;
Ok(PredictionProvenanceV5::new(
base,
RawAnimationChannelInventoryV1::from_source(source.source_facts()),
)?)
}
pub fn project_prediction_provenance_v6(
profile: &crate::ResolvedProfileSettingsV2,
source: &LoadedSource,
runtime_node_selectors: Vec<String>,
root_motion_project_intent: EngineRootMotionProjectIntentV1,
) -> Result<PredictionProvenanceV6, PredictionProvenanceProjectionError> {
let base = project_prediction_provenance_v5(profile, source, runtime_node_selectors)?;
let raw_transform_paths = source
.raw_transform_path_inventory()
.cloned()
.unwrap_or_else(|| {
RawTransformPathInventoryV1::unavailable(
source.source_facts().primary_identity().clone(),
source.source_facts().format(),
source.document().skeleton.bones.len() as u64,
)
});
Ok(PredictionProvenanceV6::new(
base,
raw_transform_paths,
root_motion_project_intent,
)?)
}