1use crate::app::UiState;
2use crate::modal_action::ModalAction;
3use crate::ui::modals::ConfirmQuitWithoutSaving;
4use crate::ui::modals::ConfirmRevertChanges;
5use crossbeam_channel::{Receiver, Sender};
6use egui::KeyboardShortcut;
7use hydrate_base::hashing::HashMap;
8use hydrate_model::edit_context::EditContext;
9use hydrate_model::pipeline::{AssetEngine, HydrateProjectConfiguration, ImportJobToQueue};
10use hydrate_model::{
11 AssetId, AssetLocation, AssetName, DataSetError, DataSetErrorWithBacktrace, DataSetResult,
12 EditorModel, EndContextBehavior, NullOverride, OverrideBehavior, PropertyPath, Schema,
13 SchemaFingerprint, SchemaRecord, Value,
14};
15use std::path::PathBuf;
16use std::sync::Arc;
17use uuid::Uuid;
18
19pub enum UIAction {
20 TryBeginModalAction(Box<dyn ModalAction>),
21 EditContext(
22 &'static str,
23 Box<dyn FnOnce(&mut EditContext) -> DataSetResult<EndContextBehavior>>,
24 ),
25 Undo,
26 Redo,
27 SaveAll,
28 RevertAll,
29 RevertAllNoConfirm,
30 Quit,
31 QuitNoConfirm,
32 PersistAssets(Vec<AssetId>),
33 BuildAll,
34 ReimportAndRebuild(Vec<AssetId>),
35 ForceRebuild(Vec<AssetId>),
36 ShowAssetInAssetGallery(AssetId),
37 MoveAssets(Vec<AssetId>, AssetLocation),
38 MoveOrRename(Vec<AssetId>, Option<AssetName>, AssetLocation),
39 NewAsset(AssetName, AssetLocation, SchemaRecord, Option<AssetId>),
40 DuplicateAssets(Vec<AssetId>),
41 DeleteAssets(Vec<AssetId>),
42 SetProperty(
43 Vec<AssetId>,
44 PropertyPath,
45 Option<Value>,
46 EndContextBehavior,
47 ),
48 ClearPropertiesForRecord(Vec<AssetId>, PropertyPath, SchemaFingerprint),
49 CommitPendingUndoContext,
50 ApplyPropertyOverrideToPrototype(Vec<AssetId>, PropertyPath),
51 ApplyPropertyOverrideToPrototypeForRecord(Vec<AssetId>, PropertyPath, SchemaFingerprint),
52 ApplyResolvedPropertyToAllSelected(AssetId, Vec<AssetId>, PropertyPath),
53 ApplyResolvedPropertyToAllSelectedForRecord(
54 AssetId,
55 Vec<AssetId>,
56 PropertyPath,
57 SchemaFingerprint,
58 ),
59 SetNullOverride(Vec<AssetId>, PropertyPath, NullOverride),
60 AddDynamicArrayEntry(AssetId, PropertyPath),
61 AddMapEntry(AssetId, PropertyPath),
62 RemoveDynamicArrayEntry(AssetId, PropertyPath, Uuid),
63 RemoveMapEntry(AssetId, PropertyPath, Uuid),
64 MoveDynamicArrayEntryUp(AssetId, PropertyPath, Uuid),
65 MoveDynamicArrayEntryDown(AssetId, PropertyPath, Uuid),
66 MoveStaticArrayOverrideUp(Vec<AssetId>, PropertyPath, usize),
68 MoveStaticArrayOverrideDown(Vec<AssetId>, PropertyPath, usize),
69 OverrideWithDefault(Vec<AssetId>, PropertyPath),
70 SetOverrideBehavior(Vec<AssetId>, PropertyPath, OverrideBehavior),
71 ToggleSelectAllAssetGallery,
72}
73
74impl UIAction {
75 }
81
82pub struct UIActionQueueSenderInner {
83 action_queue_tx: Sender<UIAction>,
84}
85
86#[derive(Clone)]
87pub struct UIActionQueueSender {
88 inner: Arc<UIActionQueueSenderInner>,
89}
90
91impl UIActionQueueSender {
92 pub fn queue_action(
93 &self,
94 action: UIAction,
95 ) {
96 self.inner.action_queue_tx.send(action).unwrap();
97 }
98
99 pub fn try_set_modal_action<T: ModalAction + 'static>(
101 &self,
102 action: T,
103 ) {
104 self.queue_action(UIAction::TryBeginModalAction(Box::new(action)))
105 }
106
107 }
122
123pub struct UIActionQueueReceiver {
124 sender: UIActionQueueSender,
125 action_queue_tx: Sender<UIAction>,
126 action_queue_rx: Receiver<UIAction>,
127 anything_has_focus_last_frame: bool,
128}
129
130impl Default for UIActionQueueReceiver {
131 fn default() -> Self {
132 let (action_queue_tx, action_queue_rx) = crossbeam_channel::unbounded();
133
134 let sender_inner = UIActionQueueSenderInner {
135 action_queue_tx: action_queue_tx.clone(),
136 };
137
138 let sender = UIActionQueueSender {
139 inner: Arc::new(sender_inner),
140 };
141
142 UIActionQueueReceiver {
143 sender,
144 action_queue_tx,
145 action_queue_rx,
146 anything_has_focus_last_frame: false,
147 }
148 }
149}
150
151impl UIActionQueueReceiver {
152 pub fn sender(&self) -> UIActionQueueSender {
153 self.sender.clone()
154 }
155
156 pub fn queue_action(
157 &self,
158 action: UIAction,
159 ) {
160 self.action_queue_tx.send(action).unwrap();
161 }
162
163 pub fn process(
164 &mut self,
165 project_config: &HydrateProjectConfiguration,
166 editor_model: &mut EditorModel,
167 asset_engine: &mut AssetEngine,
168 ui_state: &mut UiState,
169 modal_action: &mut Option<Box<dyn ModalAction>>,
170 ctx: &egui::Context,
171 ) {
172 {
173 let anything_has_focus = ctx.memory(|mem| mem.focus().is_some());
175 if !anything_has_focus && !self.anything_has_focus_last_frame {
176 ctx.input_mut(|input| {
177 if input.consume_shortcut(&KeyboardShortcut {
187 key: egui::Key::A,
188 modifiers: egui::Modifiers::COMMAND,
189 }) {
190 self.action_queue_tx
192 .send(UIAction::ToggleSelectAllAssetGallery)
193 .unwrap();
194 }
195
196 if input.consume_shortcut(&KeyboardShortcut {
197 key: egui::Key::B,
198 modifiers: egui::Modifiers::COMMAND | egui::Modifiers::SHIFT,
199 }) {
200 self.action_queue_tx.send(UIAction::BuildAll).unwrap();
201 }
202
203 if input.consume_shortcut(&KeyboardShortcut {
204 key: egui::Key::S,
205 modifiers: egui::Modifiers::COMMAND,
206 }) {
207 self.action_queue_tx.send(UIAction::SaveAll).unwrap();
208 }
209
210 if input.consume_shortcut(&KeyboardShortcut {
211 key: egui::Key::Z,
212 modifiers: egui::Modifiers::COMMAND,
213 }) {
214 self.action_queue_tx.send(UIAction::Undo).unwrap();
215 }
216
217 if input.consume_shortcut(&KeyboardShortcut {
218 key: egui::Key::Z,
219 modifiers: egui::Modifiers::COMMAND | egui::Modifiers::SHIFT,
220 }) {
221 self.action_queue_tx.send(UIAction::Redo).unwrap();
222 }
223 });
224 }
225
226 self.anything_has_focus_last_frame = anything_has_focus;
227 }
228
229 let mut import_job_to_queue = ImportJobToQueue::default();
230 while let Ok(action) = self.action_queue_rx.try_recv() {
231 match action {
232 UIAction::ToggleSelectAllAssetGallery => {
233 ui_state.asset_gallery_ui_state.toggle_select_all();
234 }
235 UIAction::SaveAll => editor_model.save_root_edit_context(),
236 UIAction::RevertAll => {
237 if editor_model.any_edit_context_has_unsaved_changes() {
238 *modal_action = Some(Box::new(ConfirmRevertChanges {}))
239 }
240 }
241 UIAction::RevertAllNoConfirm => {
242 editor_model.revert_root_edit_context(project_config, &mut import_job_to_queue)
243 }
244 UIAction::Undo => editor_model.undo().unwrap(),
245 UIAction::Redo => editor_model.redo().unwrap(),
246 UIAction::Quit => {
247 if editor_model.any_edit_context_has_unsaved_changes() {
249 *modal_action = Some(Box::new(ConfirmQuitWithoutSaving {}))
250 } else {
251 self.action_queue_tx.send(UIAction::QuitNoConfirm).unwrap();
252 }
253 }
254 UIAction::QuitNoConfirm => {
255 ui_state.user_confirmed_should_quit = true;
256 ctx.send_viewport_cmd(egui::ViewportCommand::Close)
257 }
258 UIAction::TryBeginModalAction(modal) => {
259 if modal_action.is_none() {
260 *modal_action = Some(modal);
261 }
262 }
263 UIAction::EditContext(undo_context_name, f) => editor_model
264 .root_edit_context_mut()
265 .with_undo_context(&undo_context_name, |x| f(x).unwrap()),
266
267 UIAction::PersistAssets(asset_ids) => {
268 for asset_id in asset_ids {
269 editor_model.persist_generated_asset(asset_id);
270 }
271 }
272 UIAction::BuildAll => {
273 asset_engine.queue_build_all();
274 }
275 UIAction::MoveOrRename(asset_ids, new_name, new_location) => {
276 editor_model.root_edit_context_mut().with_undo_context(
277 "MoveOrRename",
278 |edit_context| {
279 for &asset_id in &asset_ids {
280 if let Some(new_name) = &new_name {
281 edit_context
282 .set_asset_name(asset_id, new_name.clone())
283 .unwrap();
284 }
285
286 edit_context
287 .set_asset_location(asset_id, new_location)
288 .unwrap();
289 }
290
291 EndContextBehavior::Finish
292 },
293 );
294 }
295 UIAction::ReimportAndRebuild(asset_ids) => {
296 let mut import_job_to_queue = ImportJobToQueue::default();
302 for &asset_id in &asset_ids {
303 let root_edit_context = editor_model.root_edit_context();
304 let import_info = root_edit_context.import_info(asset_id);
305 if let Some(import_info) = import_info {
306 let source_file_path: PathBuf = import_info
309 .source_file()
310 .canonicalized_absolute_path(root_edit_context, &PathBuf::default())
311 .unwrap()
312 .path()
313 .into();
314
315 let mut asset_id_assignments = HashMap::default();
324 asset_id_assignments
325 .insert(import_info.importable_name().clone(), asset_id);
326
327 println!("reimport {:?}", source_file_path);
328 hydrate_model::pipeline::recursively_gather_import_operations_and_create_assets(
329 project_config,
330 &source_file_path,
331 asset_engine.importer_registry().importer(import_info.importer_id()).unwrap(),
332 root_edit_context,
333 asset_engine.importer_registry(),
334 &root_edit_context.asset_location(asset_id).unwrap(),
335 Some(&asset_id_assignments),
336 &mut import_job_to_queue,
337 ).unwrap();
338
339 }
341 }
342
343 if !import_job_to_queue.is_empty() {
344 asset_engine.queue_import_operation(import_job_to_queue);
345
346 }
351
352 asset_engine.queue_build_all();
353 }
354 UIAction::ForceRebuild(_asset_ids) => {
355 asset_engine.queue_build_all();
361 }
362 UIAction::ShowAssetInAssetGallery(asset_id) => {
363 ui_state
364 .asset_gallery_ui_state
365 .set_selection(Some(asset_id));
366
367 if let Some(location) =
368 editor_model.root_edit_context().asset_location(asset_id)
369 {
370 ui_state.asset_tree_ui_state.selected_tree_node = Some(location);
371 }
372 }
373 UIAction::MoveAssets(moving_assets, new_location) => {
374 editor_model.root_edit_context_mut().with_undo_context(
375 "move asset",
376 |edit_context| {
377 for &moving_asset in &moving_assets {
378 let result =
379 edit_context.set_asset_location(moving_asset, new_location);
380 match result {
381 Ok(_) => {
382 }
384 Err(DataSetErrorWithBacktrace {
385 error: DataSetError::NewLocationIsChildOfCurrentAsset,
386 ..
387 }) => {
388 }
390 _ => {
391 unimplemented!()
392 }
393 }
394 }
395
396 EndContextBehavior::Finish
397 },
398 );
399 }
400 UIAction::NewAsset(asset_name, asset_location, schema_record, prototype) => {
401 editor_model.root_edit_context_mut().with_undo_context(
402 "new asset",
403 |edit_context| {
404 let new_asset_id = if let Some(prototype) = prototype {
405 edit_context
406 .new_asset_from_prototype(
407 &asset_name,
408 &asset_location,
409 prototype,
410 )
411 .unwrap()
412 } else {
413 edit_context.new_asset(&asset_name, &asset_location, &schema_record)
414 };
415
416 self.sender
417 .queue_action(UIAction::ShowAssetInAssetGallery(new_asset_id));
418 EndContextBehavior::Finish
419 },
420 );
421 }
422 UIAction::DuplicateAssets(asset_ids) => {
423 editor_model.root_edit_context_mut().with_undo_context(
424 "delete asset",
425 |edit_context| {
426 for asset_id in asset_ids {
427 let new_asset_id = edit_context.duplicate_asset(asset_id).unwrap();
428 if edit_context.import_info(asset_id).is_some() {
429 asset_engine
430 .duplicate_import_data(asset_id, new_asset_id)
431 .unwrap();
432 }
433 }
434 EndContextBehavior::Finish
435 },
436 );
437 }
438 UIAction::DeleteAssets(asset_ids) => {
439 editor_model.root_edit_context_mut().with_undo_context(
440 "delete asset",
441 |edit_context| {
442 for asset_id in asset_ids {
443 edit_context.delete_asset(asset_id).unwrap();
444 }
445 EndContextBehavior::Finish
446 },
447 );
448 }
449 UIAction::SetProperty(asset_ids, property_path, value, end_context_behavior) => {
450 editor_model.root_edit_context_mut().with_undo_context(
451 "set property",
452 |edit_context| {
453 for asset_id in asset_ids {
454 edit_context
455 .set_property_override(
456 asset_id,
457 property_path.path(),
458 value.clone(),
459 )
460 .unwrap();
461 }
462 end_context_behavior
463 },
464 );
465 }
466 UIAction::ClearPropertiesForRecord(
467 asset_ids,
468 property_path,
469 record_schema_fingerprint,
470 ) => {
471 editor_model.root_edit_context_mut().with_undo_context(
472 "ClearPropertiesForRecord",
473 |edit_context| {
474 let record_schema = edit_context
475 .schema_set()
476 .find_named_type_by_fingerprint(record_schema_fingerprint)
477 .unwrap()
478 .as_record()
479 .unwrap()
480 .clone();
481
482 for field in record_schema.fields() {
483 let field_path = property_path.push(field.name());
484 for &asset_id in &asset_ids {
485 edit_context
486 .set_property_override(asset_id, field_path.path(), None)
487 .unwrap();
488 }
489 }
490
491 EndContextBehavior::Finish
492 },
493 );
494 }
495 UIAction::CommitPendingUndoContext => {
496 editor_model
497 .root_edit_context_mut()
498 .commit_pending_undo_context();
499 }
500 UIAction::ApplyPropertyOverrideToPrototype(asset_ids, property_path) => {
501 editor_model.root_edit_context_mut().with_undo_context(
502 "apply override",
503 |edit_context| {
504 for asset_id in asset_ids {
505 edit_context
506 .apply_property_override_to_prototype(
507 asset_id,
508 property_path.path(),
509 )
510 .unwrap();
511 }
512 EndContextBehavior::Finish
513 },
514 );
515 }
516
517 UIAction::ApplyPropertyOverrideToPrototypeForRecord(
518 asset_ids,
519 property_path,
520 record_schema_fingerprint,
521 ) => {
522 editor_model.root_edit_context_mut().with_undo_context(
523 "ApplyPropertyOverrideToPrototypeForRecord",
524 |edit_context| {
525 let record_schema = edit_context
526 .schema_set()
527 .find_named_type_by_fingerprint(record_schema_fingerprint)
528 .unwrap()
529 .as_record()
530 .unwrap()
531 .clone();
532
533 for field in record_schema.fields() {
534 let field_path = property_path.push(field.name());
535 for &asset_id in &asset_ids {
536 edit_context
537 .apply_property_override_to_prototype(
538 asset_id,
539 field_path.path(),
540 )
541 .unwrap();
542 }
543 }
544
545 EndContextBehavior::Finish
546 },
547 );
548 }
549
550 UIAction::ApplyResolvedPropertyToAllSelected(
551 src_asset_id,
552 selected_asset_ids,
553 property_path,
554 ) => {
555 editor_model.root_edit_context_mut().with_undo_context(
556 "apply override",
557 |edit_context| {
558 let value = edit_context
559 .resolve_property(src_asset_id, property_path.path())
560 .unwrap()
561 .clone();
562
563 for &asset_id in &selected_asset_ids {
564 edit_context
565 .set_property_override(
566 asset_id,
567 property_path.path(),
568 Some(value.clone()),
569 )
570 .unwrap();
571 }
572 EndContextBehavior::Finish
573 },
574 );
575 }
576 UIAction::ApplyResolvedPropertyToAllSelectedForRecord(
577 src_asset_id,
578 selected_asset_ids,
579 property_path,
580 record_schema_fingerprint,
581 ) => {
582 editor_model.root_edit_context_mut().with_undo_context(
583 "apply override",
584 |edit_context| {
585 let record_schema = edit_context
586 .schema_set()
587 .find_named_type_by_fingerprint(record_schema_fingerprint)
588 .unwrap()
589 .as_record()
590 .unwrap()
591 .clone();
592
593 for field in record_schema.fields() {
594 let field_path = property_path.push(field.name());
595 let value = edit_context
596 .resolve_property(src_asset_id, field_path.path())
597 .unwrap()
598 .clone();
599
600 for &asset_id in &selected_asset_ids {
601 edit_context
602 .set_property_override(
603 asset_id,
604 field_path.path(),
605 Some(value.clone()),
606 )
607 .unwrap();
608 }
609 }
610
611 EndContextBehavior::Finish
612 },
613 );
614 }
615
616 UIAction::SetNullOverride(asset_ids, property_path, null_override) => {
617 editor_model.root_edit_context_mut().with_undo_context(
618 "set null override",
619 |edit_context| {
620 for &asset_id in &asset_ids {
621 edit_context
622 .set_null_override(
623 asset_id,
624 property_path.path(),
625 null_override,
626 )
627 .unwrap();
628 }
629 EndContextBehavior::Finish
630 },
631 );
632 }
633 UIAction::AddDynamicArrayEntry(asset_id, property_path) => {
634 editor_model.root_edit_context_mut().with_undo_context(
635 "set null override",
636 |edit_context| {
637 edit_context
638 .add_dynamic_array_entry(asset_id, property_path.path())
639 .unwrap();
640 EndContextBehavior::Finish
641 },
642 );
643 }
644 UIAction::AddMapEntry(asset_id, property_path) => {
645 editor_model.root_edit_context_mut().with_undo_context(
646 "set null override",
647 |edit_context| {
648 edit_context
649 .add_map_entry(asset_id, property_path.path())
650 .unwrap();
651 EndContextBehavior::Finish
652 },
653 );
654 }
655 UIAction::RemoveDynamicArrayEntry(asset_id, property_path, entry_uuid) => {
656 editor_model.root_edit_context_mut().with_undo_context(
657 "RemoveDynamicArrayOverride",
658 |edit_context| {
659 edit_context
660 .remove_dynamic_array_entry(
661 asset_id,
662 property_path.path(),
663 entry_uuid,
664 )
665 .unwrap();
666
667 EndContextBehavior::Finish
668 },
669 );
670 }
671 UIAction::RemoveMapEntry(asset_id, property_path, entry_uuid) => {
672 editor_model.root_edit_context_mut().with_undo_context(
673 "RemoveDynamicArrayOverride",
674 |edit_context| {
675 edit_context
676 .remove_map_entry(asset_id, property_path.path(), entry_uuid)
677 .unwrap();
678
679 EndContextBehavior::Finish
680 },
681 );
682 }
683 UIAction::MoveDynamicArrayEntryUp(asset_id, property_path, entry_uuid) => {
684 editor_model.root_edit_context_mut().with_undo_context(
685 "MoveDynamicArrayOverrideUp",
686 |edit_context| {
687 let overrides: Vec<_> = edit_context
688 .get_dynamic_array_entries(asset_id, property_path.path())
689 .unwrap()
690 .copied()
691 .collect();
692 let current_index =
693 overrides.iter().position(|x| *x == entry_uuid).unwrap();
694 if current_index > 0 {
695 edit_context
697 .remove_dynamic_array_entry(
698 asset_id,
699 property_path.path(),
700 entry_uuid,
701 )
702 .unwrap();
703 edit_context
705 .insert_dynamic_array_entry(
706 asset_id,
707 property_path.path(),
708 current_index - 1,
709 entry_uuid,
710 )
711 .unwrap();
712 }
713
714 EndContextBehavior::Finish
715 },
716 );
717 }
718 UIAction::MoveDynamicArrayEntryDown(asset_id, property_path, entry_uuid) => {
719 editor_model.root_edit_context_mut().with_undo_context(
720 "MoveDynamicArrayOverrideDown",
721 |edit_context| {
722 let overrides: Vec<_> = edit_context
723 .get_dynamic_array_entries(asset_id, property_path.path())
724 .unwrap()
725 .collect();
726 let current_index =
727 overrides.iter().position(|x| **x == entry_uuid).unwrap();
728 if current_index < overrides.len() - 1 {
729 edit_context
731 .remove_dynamic_array_entry(
732 asset_id,
733 property_path.path(),
734 entry_uuid,
735 )
736 .unwrap();
737 edit_context
739 .insert_dynamic_array_entry(
740 asset_id,
741 property_path.path(),
742 current_index + 1,
743 entry_uuid,
744 )
745 .unwrap();
746 }
747
748 EndContextBehavior::Finish
749 },
750 );
751 }
752 UIAction::MoveStaticArrayOverrideUp(asset_ids, property_path, entry_index) => {
756 editor_model.root_edit_context_mut().with_undo_context(
757 "MoveStaticArrayOverrideUp",
758 |edit_context| {
759 for &asset_id in &asset_ids {
760 let schema_set = edit_context.schema_set().clone();
761 let index_a = entry_index;
762 let property_path_a = property_path.push(&index_a.to_string());
763 let bundle_a = edit_context
764 .read_properties_bundle(
765 &schema_set,
766 asset_id,
767 property_path_a.path(),
768 )
769 .unwrap();
770
771 let index_b = entry_index - 1;
772 let property_path_b = property_path.push(&index_b.to_string());
773 let bundle_b = edit_context
774 .read_properties_bundle(
775 &schema_set,
776 asset_id,
777 property_path_b.path(),
778 )
779 .unwrap();
780
781 edit_context
782 .write_properties_bundle(
783 &schema_set,
784 asset_id,
785 property_path_a.path(),
786 &bundle_b,
787 )
788 .unwrap();
789 edit_context
790 .write_properties_bundle(
791 &schema_set,
792 asset_id,
793 property_path_b.path(),
794 &bundle_a,
795 )
796 .unwrap();
797 }
798
799 EndContextBehavior::Finish
800 },
801 );
802 }
803 UIAction::MoveStaticArrayOverrideDown(asset_ids, property_path, entry_index) => {
804 editor_model.root_edit_context_mut().with_undo_context(
805 "MoveStaticArrayOverrideDown",
806 |edit_context| {
807 for &asset_id in &asset_ids {
808 let schema_set = edit_context.schema_set().clone();
809 let index_a = entry_index;
810 let property_path_a = property_path.push(&index_a.to_string());
811 let bundle_a = edit_context
812 .read_properties_bundle(
813 &schema_set,
814 asset_id,
815 property_path_a.path(),
816 )
817 .unwrap();
818
819 let index_b = entry_index + 1;
820 let property_path_b = property_path.push(&index_b.to_string());
821 let bundle_b = edit_context
822 .read_properties_bundle(
823 &schema_set,
824 asset_id,
825 property_path_b.path(),
826 )
827 .unwrap();
828
829 edit_context
830 .write_properties_bundle(
831 &schema_set,
832 asset_id,
833 property_path_a.path(),
834 &bundle_b,
835 )
836 .unwrap();
837 edit_context
838 .write_properties_bundle(
839 &schema_set,
840 asset_id,
841 property_path_b.path(),
842 &bundle_a,
843 )
844 .unwrap();
845 }
846 EndContextBehavior::Finish
847 },
848 );
849 }
850 UIAction::OverrideWithDefault(asset_ids, property_path) => {
851 editor_model.root_edit_context_mut().with_undo_context(
852 "OverrideWithDefault",
853 |edit_context| {
854 for asset_id in asset_ids {
857 let schema = edit_context
858 .asset_schema(asset_id)
859 .unwrap()
860 .find_property_schema(
861 property_path.path(),
862 edit_context.schema_set().schemas(),
863 )
864 .unwrap();
865 println!(
866 "find schema {:?} for property {:?}",
867 schema,
868 property_path.path()
869 );
870 override_with_default_values_recursively(
871 asset_id,
872 &property_path,
873 schema,
874 edit_context,
875 );
876 }
877
878 EndContextBehavior::Finish
892 },
893 );
894 }
895 UIAction::SetOverrideBehavior(asset_ids, property_path, override_behavior) => {
896 editor_model.root_edit_context_mut().with_undo_context(
897 "SetOverrideBehavior",
898 |edit_context| {
899 for &asset_id in &asset_ids {
900 edit_context
901 .set_override_behavior(
902 asset_id,
903 property_path.path(),
904 override_behavior,
905 )
906 .unwrap();
907 }
908 EndContextBehavior::Finish
909 },
910 );
911 }
912 }
913 }
914
915 if !import_job_to_queue.is_empty() {
916 asset_engine.queue_import_operation(import_job_to_queue);
917 }
918 }
919}
920
921fn override_with_default_values_recursively(
922 asset_id: AssetId,
923 property_path: &PropertyPath,
924 schema: Schema,
925 edit_context: &mut EditContext,
926) {
927 println!("{} {:?} set to default", property_path.path(), schema);
928 match schema {
929 Schema::Boolean
930 | Schema::I32
931 | Schema::I64
932 | Schema::U32
933 | Schema::U64
934 | Schema::F32
935 | Schema::F64
936 | Schema::Bytes
937 | Schema::String
938 | Schema::AssetRef(_)
939 | Schema::Enum(_) => {
940 println!("set path {:?} {:?}", property_path.path(), schema);
941 edit_context
942 .set_property_override(
943 asset_id,
944 property_path.path(),
945 Some(Value::default_for_schema(&schema, edit_context.schema_set()).clone()),
946 )
947 .unwrap();
948 }
949 Schema::Nullable(_) => {
950 edit_context
951 .set_null_override(asset_id, property_path.path(), NullOverride::SetNull)
952 .unwrap();
953 }
954 Schema::StaticArray(schema) => {
955 for i in 0..schema.length() {
956 let element_path = property_path.push(&i.to_string());
957 override_with_default_values_recursively(
958 asset_id,
959 &element_path,
960 schema.item_type().clone(),
961 edit_context,
962 );
963 }
964 }
965 Schema::DynamicArray(_) => {
966 edit_context
967 .set_override_behavior(asset_id, property_path.path(), OverrideBehavior::Replace)
968 .unwrap();
969 }
970 Schema::Map(_) => {
971 edit_context
972 .set_override_behavior(asset_id, property_path.path(), OverrideBehavior::Replace)
973 .unwrap();
974 }
975 Schema::Record(record_schema) => {
976 let record_schema = edit_context
977 .schema_set()
978 .find_named_type_by_fingerprint(record_schema)
979 .unwrap()
980 .as_record()
981 .unwrap()
982 .clone();
983 println!(
984 "iterate fields of {:?} {:?}",
985 record_schema,
986 record_schema.fields()
987 );
988 for field in record_schema.fields() {
989 let field_path = property_path.push(field.name());
990 let field_schema = record_schema.field_schema(field.name()).unwrap();
991 override_with_default_values_recursively(
992 asset_id,
993 &field_path,
994 field_schema.clone(),
995 edit_context,
996 );
997 }
998 }
999 }
1000}