1use std::sync::Arc;
2
3pub use hydrate_schema::*;
4
5pub use hydrate_data::*;
6
7mod pipeline_error;
8
9mod build;
10mod import;
11mod project;
12mod thumbnails;
13pub use thumbnails::*;
14
15pub use import::{
16 import_util::create_asset_name,
17 import_util::recursively_gather_import_operations_and_create_assets, ImportContext,
18 ImportJobSourceFile, ImportJobToQueue, ImportJobs, ImportStatus, ImportStatusImporting,
19 ImportType, Importer, ImporterRegistry, ImporterRegistryBuilder, RequestedImportable,
20 ScanContext, ScannedImportable,
21};
22
23pub use project::{HydrateProjectConfiguration, NamePathPair};
24
25pub use crate::build::{
26 AssetArtifactIdPair, BuildJobs, BuildStatus, BuildStatusBuilding, Builder, BuilderContext,
27 BuilderRegistry, BuilderRegistryBuilder, EnumerateDependenciesContext, HandleFactory,
28 JobEnumeratedDependencies, JobId, JobInput, JobOutput, JobProcessor, JobProcessorRegistry,
29 JobProcessorRegistryBuilder, RunContext,
30};
31pub use pipeline_error::*;
32
33mod log_events;
34mod uuid_newtype;
35pub use log_events::*;
36
37pub struct AssetPluginRegistries {
38 pub importer_registry: ImporterRegistry,
39 pub builder_registry: BuilderRegistry,
40 pub job_processor_registry: JobProcessorRegistry,
41 pub thumbnail_provider_registry: ThumbnailProviderRegistry,
42}
43
44pub struct AssetPluginSetupContext<'a> {
45 pub importer_registry: &'a mut ImporterRegistryBuilder,
46 pub builder_registry: &'a mut BuilderRegistryBuilder,
47 pub job_processor_registry: &'a mut JobProcessorRegistryBuilder,
48 pub thumbnail_provider_registry: &'a mut ThumbnailProviderRegistryBuilder,
49}
50
51pub trait AssetPlugin {
52 fn setup(context: AssetPluginSetupContext);
53}
54
55pub struct AssetPluginRegistryBuilders {
56 importer_registry: ImporterRegistryBuilder,
57 builder_registry: BuilderRegistryBuilder,
58 job_processor_registry: JobProcessorRegistryBuilder,
59 thumbnail_provider_registry: ThumbnailProviderRegistryBuilder,
60}
61
62impl AssetPluginRegistryBuilders {
63 pub fn new() -> Self {
64 AssetPluginRegistryBuilders {
65 importer_registry: Default::default(),
66 builder_registry: Default::default(),
67 job_processor_registry: Default::default(),
68 thumbnail_provider_registry: Default::default(),
69 }
70 }
71
72 pub fn register_plugin<T: AssetPlugin>(mut self) -> Self {
73 T::setup(AssetPluginSetupContext {
74 importer_registry: &mut self.importer_registry,
75 builder_registry: &mut self.builder_registry,
76 job_processor_registry: &mut self.job_processor_registry,
77 thumbnail_provider_registry: &mut self.thumbnail_provider_registry,
78 });
79 self
80 }
81
82 pub fn finish(
83 self,
84 schema_set: &SchemaSet,
85 ) -> AssetPluginRegistries {
86 let importer_registry = self.importer_registry.build();
87 let builder_registry = self.builder_registry.build(schema_set);
88 let job_processor_registry = self.job_processor_registry.build();
89 let thumbnail_provider_registry = self.thumbnail_provider_registry.build(schema_set);
90
91 AssetPluginRegistries {
92 importer_registry,
93 builder_registry,
94 job_processor_registry,
95 thumbnail_provider_registry,
96 }
97 }
98}
99
100pub trait DynEditorModel {
101 fn schema_set(&self) -> &SchemaSet;
102
103 fn handle_import_complete(
104 &mut self,
105 asset_id: AssetId,
106 asset_name: AssetName,
107 asset_location: AssetLocation,
108 default_asset: &SingleObject,
109 replace_with_default_asset: bool,
110 import_info: ImportInfo,
111 canonical_path_references: &HashMap<CanonicalPathReference, AssetId>,
112 path_references: &HashMap<PathReferenceHash, CanonicalPathReference>,
113 ) -> DataSetResult<()>;
114
115 fn data_set(&self) -> &DataSet;
116
117 fn is_path_node_or_root(
118 &self,
119 schema_record: &SchemaRecord,
120 ) -> bool;
121
122 fn asset_display_name_long(
123 &self,
124 asset_id: AssetId,
125 ) -> String;
126}
127
128pub trait DynEditContext {
129 fn data_set(&self) -> &DataSet;
130
131 fn schema_set(&self) -> &SchemaSet;
132}
133
134pub enum AssetEngineState {
135 Idle,
136 Importing(ImportStatusImporting),
137 Building(BuildStatusBuilding),
138 ImportCompleted(Arc<ImportLogData>),
139 BuildCompleted(Arc<BuildLogData>),
140}
141
142pub struct AssetEngine {
143 importer_registry: ImporterRegistry,
144 import_jobs: ImportJobs,
145 builder_registry: BuilderRegistry,
146 build_jobs: BuildJobs,
147 thumbnail_system: ThumbnailSystem,
148}
149
150impl AssetEngine {
151 pub fn new(
152 schema_set: &SchemaSet,
153 registries: AssetPluginRegistries,
154 editor_model: &dyn DynEditorModel,
155 project_configuration: &HydrateProjectConfiguration,
156 ) -> Self {
157 let import_jobs = ImportJobs::new(
158 project_configuration,
159 ®istries.importer_registry,
160 editor_model,
161 &project_configuration.import_data_path,
162 );
163
164 let build_jobs = BuildJobs::new(
165 schema_set,
166 ®istries.job_processor_registry,
167 project_configuration.import_data_path.clone(),
168 project_configuration.job_data_path.clone(),
169 project_configuration.build_data_path.clone(),
170 );
171
172 let thumbnail_system = ThumbnailSystem::new(
173 project_configuration,
174 registries.thumbnail_provider_registry,
175 schema_set,
176 );
177
178 AssetEngine {
181 importer_registry: registries.importer_registry,
182 import_jobs,
183 builder_registry: registries.builder_registry,
184 build_jobs,
185 thumbnail_system,
186 }
187 }
188
189 pub fn current_task_log_data(&self) -> LogDataRef {
190 if let Some(build_log) = self.build_jobs.current_build_log() {
191 LogDataRef::Build(build_log)
192 } else if let Some(import_log) = self.import_jobs.current_import_log() {
193 LogDataRef::Import(import_log)
194 } else {
195 LogDataRef::None
196 }
197 }
198
199 pub fn thumbnail_provider_registry(&self) -> &ThumbnailProviderRegistry {
200 self.thumbnail_system.thumbnail_provider_registry()
201 }
202
203 pub fn importer_registry(&self) -> &ImporterRegistry {
204 &self.importer_registry
205 }
206
207 #[profiling::function]
208 pub fn update(
209 &mut self,
210 editor_model: &mut dyn DynEditorModel,
211 ) -> PipelineResult<AssetEngineState> {
212 if !self.build_jobs.is_building() {
222 let import_state = self
223 .import_jobs
224 .update(&self.importer_registry, editor_model)?;
225
226 match import_state {
227 ImportStatus::Idle => {
228 }
230 ImportStatus::Importing(importing_state) => {
231 return Ok(AssetEngineState::Importing(importing_state))
232 }
233 ImportStatus::Completed(import_log_data) => {
234 return Ok(AssetEngineState::ImportCompleted(import_log_data))
235 }
236 }
237 }
238
239 if !self.build_jobs.is_building() {
240 assert!(!self.import_jobs.is_importing());
241 self.thumbnail_system
242 .update(editor_model.data_set(), editor_model.schema_set());
243 }
244
245 let build_state =
252 self.build_jobs
253 .update(&self.builder_registry, editor_model, &self.import_jobs)?;
254
255 match build_state {
256 BuildStatus::Idle => Ok(AssetEngineState::Idle),
257 BuildStatus::Building(building_state) => {
258 return Ok(AssetEngineState::Building(building_state))
259 }
260 BuildStatus::Completed(build_log_data) => {
261 return Ok(AssetEngineState::BuildCompleted(build_log_data))
262 }
263 }
264 }
265
266 pub fn thumbnail_system_state(&self) -> &ThumbnailSystemState {
267 self.thumbnail_system.system_state()
268 }
269
270 pub fn importers_for_file_extension(
271 &self,
272 extension: &str,
273 ) -> &[ImporterId] {
274 self.importer_registry
275 .importers_for_file_extension(extension)
276 }
277
278 pub fn importer(
279 &self,
280 importer_id: ImporterId,
281 ) -> Option<&Arc<dyn Importer>> {
282 self.importer_registry.importer(importer_id)
283 }
284
285 pub fn builder_for_asset(
286 &self,
287 fingerprint: SchemaFingerprint,
288 ) -> Option<&Box<dyn Builder>> {
289 self.builder_registry.builder_for_asset(fingerprint)
290 }
291
292 pub fn queue_import_operation(
293 &mut self,
294 import_job_to_queue: ImportJobToQueue,
295 ) {
296 self.import_jobs.queue_import_operation(import_job_to_queue);
297 }
298
299 pub fn queue_build_asset(
300 &mut self,
301 asset_id: AssetId,
302 ) {
303 self.build_jobs.queue_build_operation(asset_id);
304 }
305
306 pub fn needs_build(&self) -> bool {
307 self.build_jobs.needs_build()
308 }
309
310 pub fn queue_build_all(&mut self) {
311 self.build_jobs.build();
312 }
313
314 pub fn duplicate_import_data(
315 &self,
316 old_asset_id: AssetId,
317 new_asset_id: AssetId,
318 ) -> PipelineResult<()> {
319 self.import_jobs
320 .duplicate_import_data(old_asset_id, new_asset_id)
321 }
322}