|
| 1 | +// io.rs |
1 | 2 | use bevy::prelude::*; |
| 3 | +use std::path::PathBuf; |
2 | 4 |
|
| 5 | +use crate::parse::parse_xyz_content; |
3 | 6 | use crate::structure::{Atom, Crystal}; |
4 | 7 |
|
5 | | -// System to load crystal data |
6 | | -pub fn load_crystal(mut commands: Commands) { |
7 | | - // For now, use the default water molecule structure |
8 | | - // In the future, this can be extended to load from embedded assets or user input |
| 8 | +// System to load default crystal data |
| 9 | +pub(crate) fn load_default_crystal(mut commands: Commands) { |
9 | 10 | println!("Loading default water molecule structure"); |
10 | 11 |
|
11 | 12 | let crystal = Crystal { |
@@ -33,3 +34,90 @@ pub fn load_crystal(mut commands: Commands) { |
33 | 34 |
|
34 | 35 | commands.insert_resource(crystal); |
35 | 36 | } |
| 37 | + |
| 38 | +// Resource to handle file drag and drop |
| 39 | +#[derive(Resource, Default)] |
| 40 | +pub(crate) struct FileDragDrop { |
| 41 | + dragged_file: Option<PathBuf>, |
| 42 | + loaded_crystal: Option<Crystal>, |
| 43 | +} |
| 44 | + |
| 45 | +impl FileDragDrop { |
| 46 | + pub(crate) fn dragged_file(&self) -> Option<&PathBuf> { |
| 47 | + self.dragged_file.as_ref() |
| 48 | + } |
| 49 | +} |
| 50 | + |
| 51 | +// System to handle file drag and drop events |
| 52 | +pub(crate) fn handle_file_drag_drop( |
| 53 | + mut drag_drop_events: EventReader<bevy::window::FileDragAndDrop>, |
| 54 | + mut file_drag_drop: ResMut<FileDragDrop>, |
| 55 | +) { |
| 56 | + for event in drag_drop_events.read() { |
| 57 | + match event { |
| 58 | + bevy::window::FileDragAndDrop::DroppedFile { path_buf, .. } => { |
| 59 | + println!("File dropped: {:?}", path_buf); |
| 60 | + |
| 61 | + if let Some(extension) = path_buf.extension() { |
| 62 | + if extension == "xyz" { |
| 63 | + file_drag_drop.dragged_file = Some(path_buf.clone()); |
| 64 | + } else { |
| 65 | + println!("Unsupported file type. Please drop an XYZ file."); |
| 66 | + } |
| 67 | + } |
| 68 | + } |
| 69 | + bevy::window::FileDragAndDrop::HoveredFile { path_buf, .. } => { |
| 70 | + println!("File hovered: {:?}", path_buf); |
| 71 | + } |
| 72 | + bevy::window::FileDragAndDrop::HoveredFileCanceled { .. } => { |
| 73 | + println!("File hover canceled"); |
| 74 | + } |
| 75 | + } |
| 76 | + } |
| 77 | +} |
| 78 | + |
| 79 | +// System to load crystal from dropped file |
| 80 | +pub(crate) fn load_dropped_file( |
| 81 | + mut file_drag_drop: ResMut<FileDragDrop>, |
| 82 | + mut crystal_loaded: Local<bool>, |
| 83 | +) { |
| 84 | + if let Some(ref path) = file_drag_drop.dragged_file { |
| 85 | + if !*crystal_loaded { |
| 86 | + match std::fs::read_to_string(path) { |
| 87 | + Ok(contents) => match parse_xyz_content(&contents) { |
| 88 | + Ok(crystal) => { |
| 89 | + println!("Successfully loaded crystal from: {:?}", path); |
| 90 | + file_drag_drop.loaded_crystal = Some(crystal); |
| 91 | + *crystal_loaded = true; |
| 92 | + } |
| 93 | + Err(e) => { |
| 94 | + eprintln!("Failed to parse XYZ file: {}", e); |
| 95 | + } |
| 96 | + }, |
| 97 | + Err(e) => { |
| 98 | + eprintln!("Failed to read file: {}", e); |
| 99 | + } |
| 100 | + } |
| 101 | + } |
| 102 | + } |
| 103 | +} |
| 104 | + |
| 105 | +// System to update crystal resource when new file is loaded |
| 106 | +pub(crate) fn update_crystal_from_file( |
| 107 | + mut commands: Commands, |
| 108 | + file_drag_drop: Res<FileDragDrop>, |
| 109 | + current_crystal: Option<Res<Crystal>>, |
| 110 | +) { |
| 111 | + if let Some(crystal) = &file_drag_drop.loaded_crystal { |
| 112 | + // Only update if this is a new crystal |
| 113 | + if let Some(current) = current_crystal { |
| 114 | + if current.atoms.len() != crystal.atoms.len() { |
| 115 | + commands.insert_resource(crystal.clone()); |
| 116 | + println!("Crystal updated with {} atoms", crystal.atoms.len()); |
| 117 | + } |
| 118 | + } else { |
| 119 | + commands.insert_resource(crystal.clone()); |
| 120 | + println!("Crystal loaded with {} atoms", crystal.atoms.len()); |
| 121 | + } |
| 122 | + } |
| 123 | +} |
0 commit comments