1use crate::canonical::{project_resolved_profile, project_resolved_profile_v2};
2use crate::{ResolvedProfile, ResolvedProfileV2};
3use animsmith_core::engine_contract::EngineContractError;
4use animsmith_core::prediction::{
5 PredictionContractError, PredictionProvenanceV1, PredictionProvenanceV2,
6 PredictionProvenanceV3, PredictionProvenanceV4, PredictionRuleInputsV1,
7 RawSceneAttachmentBindingV1, RawSceneAttachmentUnavailableReasonV1, RawSourceBindingV1,
8 RawSourceBindingV2,
9};
10use animsmith_core::{
11 EngineRootMotionProjectIntentV1, LoadedSource, PredictionProvenanceV5, PredictionProvenanceV6,
12 RawAnimationChannelInventoryV1, RawTransformPathInventoryV1, SourceFormatV1,
13};
14
15#[derive(Debug, thiserror::Error)]
17#[non_exhaustive]
18pub enum PredictionProvenanceProjectionError {
19 #[error("resolved engine evidence is invalid: {0}")]
22 EngineContract(#[from] EngineContractError),
23 #[error("prediction provenance is invalid: {0}")]
26 PredictionContract(#[from] PredictionContractError),
27}
28
29pub fn project_prediction_provenance_v1(
44 profile: &ResolvedProfile,
45 source: &LoadedSource,
46) -> Result<PredictionProvenanceV1, PredictionProvenanceProjectionError> {
47 let (profile_contract, settings_contract) = project_resolved_profile(profile)?;
48 let raw_source = RawSourceBindingV1::from_source(source.source_facts());
49 Ok(PredictionProvenanceV1::new(
50 profile_contract,
51 profile.source_format(),
52 settings_contract,
53 raw_source,
54 source.dependency_closure().clone(),
55 )?)
56}
57
58pub fn project_prediction_provenance_v2(
63 profile: &ResolvedProfileV2,
64 source: &LoadedSource,
65) -> Result<PredictionProvenanceV2, PredictionProvenanceProjectionError> {
66 let (profile_contract, settings_contract) = project_resolved_profile_v2(profile)?;
67 let raw_source = RawSourceBindingV1::from_source(source.source_facts());
68 Ok(PredictionProvenanceV2::new(
69 profile_contract,
70 profile.source_format(),
71 settings_contract,
72 raw_source,
73 source.dependency_closure().clone(),
74 )?)
75}
76
77pub fn project_prediction_provenance_v3(
84 profile: &ResolvedProfileV2,
85 source: &LoadedSource,
86) -> Result<PredictionProvenanceV3, PredictionProvenanceProjectionError> {
87 let (profile_contract, settings_contract) = project_resolved_profile_v2(profile)?;
88 let raw_source =
89 RawSourceBindingV2::from_source(source.source_facts(), source.exact_source_timing())?;
90 Ok(PredictionProvenanceV3::new(
91 profile_contract,
92 profile.source_format(),
93 settings_contract,
94 raw_source,
95 source.dependency_closure().clone(),
96 )?)
97}
98
99pub fn project_prediction_provenance_v4(
114 profile: &crate::ResolvedProfileSettingsV2,
115 source: &LoadedSource,
116 runtime_node_selectors: Vec<String>,
117) -> Result<PredictionProvenanceV4, PredictionProvenanceProjectionError> {
118 let (profile_contract, settings_contract) =
119 crate::canonical::project_resolved_engine_settings_v3(profile)?;
120 let raw_source =
121 RawSourceBindingV2::from_source(source.source_facts(), source.exact_source_timing())?;
122 let raw_scene_attachment = source
123 .raw_scene_attachment_inventory()
124 .cloned()
125 .map_or_else(
126 || {
127 RawSceneAttachmentBindingV1::unavailable(match source.source_facts().format() {
128 SourceFormatV1::Glb | SourceFormatV1::GltfJson => {
129 RawSceneAttachmentUnavailableReasonV1::LoaderEvidenceUnavailable
130 }
131 SourceFormatV1::Fbx => {
132 RawSceneAttachmentUnavailableReasonV1::UnsupportedSourceFormat
133 }
134 })
135 },
136 RawSceneAttachmentBindingV1::available,
137 );
138 Ok(PredictionProvenanceV4::new(
139 profile_contract,
140 profile.source_format(),
141 settings_contract,
142 raw_source,
143 raw_scene_attachment,
144 source.dependency_closure().clone(),
145 PredictionRuleInputsV1::new(runtime_node_selectors)?,
146 )?)
147}
148
149pub fn project_prediction_provenance_v5(
152 profile: &crate::ResolvedProfileSettingsV2,
153 source: &LoadedSource,
154 runtime_node_selectors: Vec<String>,
155) -> Result<PredictionProvenanceV5, PredictionProvenanceProjectionError> {
156 let base = project_prediction_provenance_v4(profile, source, runtime_node_selectors)?;
157 Ok(PredictionProvenanceV5::new(
158 base,
159 RawAnimationChannelInventoryV1::from_source(source.source_facts()),
160 )?)
161}
162
163pub fn project_prediction_provenance_v6(
169 profile: &crate::ResolvedProfileSettingsV2,
170 source: &LoadedSource,
171 runtime_node_selectors: Vec<String>,
172 root_motion_project_intent: EngineRootMotionProjectIntentV1,
173) -> Result<PredictionProvenanceV6, PredictionProvenanceProjectionError> {
174 let base = project_prediction_provenance_v5(profile, source, runtime_node_selectors)?;
175 let raw_transform_paths = source
176 .raw_transform_path_inventory()
177 .cloned()
178 .unwrap_or_else(|| {
179 RawTransformPathInventoryV1::unavailable(
180 source.source_facts().primary_identity().clone(),
181 source.source_facts().format(),
182 source.document().skeleton.bones.len() as u64,
183 )
184 });
185 Ok(PredictionProvenanceV6::new(
186 base,
187 raw_transform_paths,
188 root_motion_project_intent,
189 )?)
190}