Skip to content

Commit 0cb62b6

Browse files
committed
address review
1 parent a367f54 commit 0cb62b6

6 files changed

Lines changed: 95 additions & 54 deletions

File tree

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ webgl2 = ["bevy/webgl2"]
2626
# need both, cdylib for wasm, rlib for main.rs
2727
crate-type = ["cdylib", "rlib"]
2828

29+
[[bin]]
30+
name = "vizmat-native"
31+
path = "src/main.rs"
32+
2933
# optimize for smaller WASM binary size
3034
[profile.release]
3135
lto = "thin"

index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
</style>
2020
</head>
2121
<body>
22-
<!-- Trunk will inject the WASM bundle here -->
22+
<link data-trunk rel="rust" data-target-name="vizmat" />
2323
</body>
2424
</html>
2525

src/io.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::parse::parse_xyz_content;
66
use crate::structure::{Atom, Crystal};
77

88
// System to load default crystal data
9-
pub fn load_default_crystal(mut commands: Commands) {
9+
pub(crate) fn load_default_crystal(mut commands: Commands) {
1010
println!("Loading default water molecule structure");
1111

1212
let crystal = Crystal {
@@ -37,13 +37,19 @@ pub fn load_default_crystal(mut commands: Commands) {
3737

3838
// Resource to handle file drag and drop
3939
#[derive(Resource, Default)]
40-
pub struct FileDragDrop {
41-
pub dragged_file: Option<PathBuf>,
42-
pub loaded_crystal: Option<Crystal>,
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+
}
4349
}
4450

4551
// System to handle file drag and drop events
46-
pub fn handle_file_drag_drop(
52+
pub(crate) fn handle_file_drag_drop(
4753
mut drag_drop_events: EventReader<bevy::window::FileDragAndDrop>,
4854
mut file_drag_drop: ResMut<FileDragDrop>,
4955
) {
@@ -71,7 +77,7 @@ pub fn handle_file_drag_drop(
7177
}
7278

7379
// System to load crystal from dropped file
74-
pub fn load_dropped_file(
80+
pub(crate) fn load_dropped_file(
7581
mut file_drag_drop: ResMut<FileDragDrop>,
7682
mut crystal_loaded: Local<bool>,
7783
) {
@@ -97,7 +103,7 @@ pub fn load_dropped_file(
97103
}
98104

99105
// System to update crystal resource when new file is loaded
100-
pub fn update_crystal_from_file(
106+
pub(crate) fn update_crystal_from_file(
101107
mut commands: Commands,
102108
file_drag_drop: Res<FileDragDrop>,
103109
current_crystal: Option<Res<Crystal>>,

src/lib.rs

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ pub(crate) mod parse;
99
pub(crate) mod structure;
1010

1111
use crate::io::{
12-
handle_file_drag_drop, load_default_crystal, load_dropped_file, update_crystal_from_file,
13-
FileDragDrop,
12+
handle_file_drag_drop, load_dropped_file, update_crystal_from_file, FileDragDrop,
1413
};
1514
use crate::ui::{
16-
camera_controls, setup_camera, setup_file_ui, setup_scene, update_file_ui, update_scene,
15+
camera_controls, handle_load_default_button, setup_camera, setup_file_ui, setup_scene,
16+
update_file_ui, update_scene,
1717
};
1818

1919
#[cfg(target_arch = "wasm32")]
@@ -36,15 +36,7 @@ pub fn run_app() {
3636
}))
3737
.init_resource::<FileDragDrop>()
3838
.add_event::<bevy::window::FileDragAndDrop>()
39-
.add_systems(
40-
Startup,
41-
(
42-
load_default_crystal,
43-
setup_scene,
44-
setup_camera,
45-
setup_file_ui,
46-
),
47-
)
39+
.add_systems(Startup, (setup_scene, setup_camera, setup_file_ui))
4840
.add_systems(
4941
Update,
5042
(
@@ -53,6 +45,7 @@ pub fn run_app() {
5345
update_crystal_from_file,
5446
update_file_ui,
5547
update_scene,
48+
handle_load_default_button,
5649
camera_controls,
5750
),
5851
)

src/parse.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
// parse.rs
21
use crate::structure::{Atom, Crystal};
32
use anyhow::{Context, Result};
43

54
// Function to parse XYZ file format from string content
6-
pub fn parse_xyz_content(contents: &str) -> Result<Crystal> {
5+
pub(crate) fn parse_xyz_content(contents: &str) -> Result<Crystal> {
76
let lines = contents.lines().collect::<Vec<&str>>();
87

98
if lines.len() < 2 {
@@ -48,8 +47,7 @@ pub fn parse_xyz_content(contents: &str) -> Result<Crystal> {
4847
}
4948

5049
// Function to read XYZ file from path
51-
#[allow(dead_code)]
52-
pub fn read_xyz_file(path: &str) -> Result<Crystal> {
50+
fn read_xyz_file(path: &str) -> Result<Crystal> {
5351
let contents =
5452
std::fs::read_to_string(path).context(format!("Failed to read XYZ file: {}", path))?;
5553
parse_xyz_content(&contents)

src/ui.rs

Lines changed: 70 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,12 @@ use crate::structure::{AtomEntity, Crystal};
88
#[derive(Component)]
99
pub(crate) struct FileUploadText;
1010

11+
// Component for load default button
12+
#[derive(Component)]
13+
pub(crate) struct LoadDefaultButton;
14+
1115
// System to set up file upload UI
12-
pub fn setup_file_ui(mut commands: Commands) {
16+
pub(crate) fn setup_file_ui(mut commands: Commands) {
1317
commands.spawn((
1418
Text::new("Drag and drop an XYZ file here to visualize"),
1519
TextFont {
@@ -25,15 +29,40 @@ pub fn setup_file_ui(mut commands: Commands) {
2529
},
2630
FileUploadText,
2731
));
32+
33+
// Add button to load default structure
34+
commands
35+
.spawn((
36+
Button,
37+
Node {
38+
position_type: PositionType::Absolute,
39+
top: Val::Px(40.0),
40+
left: Val::Px(10.0),
41+
padding: UiRect::all(Val::Px(10.0)),
42+
..default()
43+
},
44+
BackgroundColor(Color::srgb(0.15, 0.15, 0.15)),
45+
LoadDefaultButton,
46+
))
47+
.with_children(|parent| {
48+
parent.spawn((
49+
Text::new("Load Default Structure"),
50+
TextFont {
51+
font_size: 18.0,
52+
..default()
53+
},
54+
TextColor(Color::WHITE),
55+
));
56+
});
2857
}
2958

3059
// System to update file upload UI
31-
pub fn update_file_ui(
60+
pub(crate) fn update_file_ui(
3261
file_drag_drop: Res<crate::io::FileDragDrop>,
3362
mut text_query: Query<&mut Text, With<FileUploadText>>,
3463
) {
3564
if let Ok(mut text) = text_query.single_mut() {
36-
if let Some(ref path) = file_drag_drop.dragged_file {
65+
if let Some(path) = file_drag_drop.dragged_file() {
3766
if let Some(file_name) = path.file_name().and_then(|n| n.to_str()) {
3867
// Update the text content
3968
**text = format!("Loaded: {}", file_name);
@@ -44,25 +73,34 @@ pub fn update_file_ui(
4473
}
4574
}
4675

47-
// System to clear existing atoms when new crystal is loaded
48-
#[allow(dead_code)]
49-
pub fn clear_old_atoms(mut commands: Commands, atom_query: Query<Entity, With<AtomEntity>>) {
50-
for entity in atom_query.iter() {
51-
commands.entity(entity).despawn();
76+
// System to handle button click to load default structure
77+
pub(crate) fn handle_load_default_button(
78+
mut interaction_query: Query<
79+
(&Interaction, &mut BackgroundColor),
80+
(Changed<Interaction>, With<LoadDefaultButton>),
81+
>,
82+
mut commands: Commands,
83+
) {
84+
for (interaction, mut color) in &mut interaction_query {
85+
match *interaction {
86+
Interaction::Pressed => {
87+
*color = BackgroundColor(Color::srgb(0.35, 0.35, 0.35));
88+
// Load default water molecule
89+
crate::io::load_default_crystal(commands.reborrow());
90+
}
91+
Interaction::Hovered => {
92+
*color = BackgroundColor(Color::srgb(0.25, 0.25, 0.25));
93+
}
94+
Interaction::None => {
95+
*color = BackgroundColor(Color::srgb(0.15, 0.15, 0.15));
96+
}
97+
}
5298
}
5399
}
54100

55101
// Updated setup_scene to handle crystal changes
56-
pub fn setup_scene(
57-
mut commands: Commands,
58-
mut meshes: ResMut<Assets<Mesh>>,
59-
mut materials: ResMut<Assets<StandardMaterial>>,
60-
crystal: Res<Crystal>,
61-
) {
62-
// Only spawn atoms if we have a crystal resource
63-
spawn_atoms(&mut commands, &mut meshes, &mut materials, &crystal);
64-
65-
// Add ambient light
102+
pub(crate) fn setup_scene(mut commands: Commands) {
103+
// Start with empty scene - only add ambient light
66104
commands.insert_resource(AmbientLight {
67105
color: Color::WHITE,
68106
brightness: 0.3,
@@ -71,23 +109,25 @@ pub fn setup_scene(
71109
}
72110

73111
// System to respawn atoms when crystal changes
74-
pub fn update_scene(
112+
pub(crate) fn update_scene(
75113
mut commands: Commands,
76114
mut meshes: ResMut<Assets<Mesh>>,
77115
mut materials: ResMut<Assets<StandardMaterial>>,
78-
crystal: Res<Crystal>,
116+
crystal: Option<Res<Crystal>>,
79117
atom_query: Query<Entity, With<AtomEntity>>,
80118
) {
81-
if crystal.is_changed() {
82-
// Clear existing atoms
83-
for entity in atom_query.iter() {
84-
commands.entity(entity).despawn();
85-
}
119+
if let Some(crystal) = crystal {
120+
if crystal.is_changed() {
121+
// Clear existing atoms
122+
for entity in atom_query.iter() {
123+
commands.entity(entity).despawn();
124+
}
86125

87-
// Spawn new atoms
88-
spawn_atoms(&mut commands, &mut meshes, &mut materials, &crystal);
126+
// Spawn new atoms
127+
spawn_atoms(&mut commands, &mut meshes, &mut materials, &crystal);
89128

90-
println!("Scene updated with new crystal structure");
129+
println!("Scene updated with new crystal structure");
130+
}
91131
}
92132
}
93133

@@ -130,7 +170,7 @@ fn spawn_atoms(
130170
}
131171

132172
// System to set up the camera
133-
pub fn setup_camera(mut commands: Commands) {
173+
pub(crate) fn setup_camera(mut commands: Commands) {
134174
// Spawn camera
135175
commands
136176
.spawn((
@@ -150,7 +190,7 @@ pub fn setup_camera(mut commands: Commands) {
150190
}
151191

152192
// Simple camera controls
153-
pub fn camera_controls(
193+
pub(crate) fn camera_controls(
154194
mut camera_query: Query<&mut Transform, With<Camera3d>>,
155195
keyboard_input: Res<ButtonInput<KeyCode>>,
156196
time: Res<Time>,

0 commit comments

Comments
 (0)