@@ -91,7 +91,7 @@ pub(crate) fn update_file_ui(
9191 if let Some ( path) = file_drag_drop. dragged_file ( ) {
9292 if let Some ( file_name) = path. file_name ( ) . and_then ( |n| n. to_str ( ) ) {
9393 // Update the text content
94- * * text = format ! ( "Loaded: {}" , file_name ) ;
94+ * * text = format ! ( "Loaded: {file_name}" ) ;
9595 }
9696 } else {
9797 * * text = "Drag and drop an XYZ file here to visualize" . to_string ( ) ;
@@ -127,10 +127,6 @@ pub(crate) struct CameraRig {
127127 initial_scale : Vec3 ,
128128}
129129
130- /// Button that resets the camera to its original position/orientation.
131- #[ derive( Component ) ]
132- pub ( crate ) struct CameraButton ;
133-
134130// System to clear existing atoms when new crystal is loaded
135131#[ allow( dead_code) ]
136132pub fn clear_old_atoms ( mut commands : Commands , atom_query : Query < Entity , With < AtomEntity > > ) {
@@ -140,6 +136,7 @@ pub fn clear_old_atoms(mut commands: Commands, atom_query: Query<Entity, With<At
140136}
141137
142138// System to handle button click to load default structure
139+ #[ allow( clippy:: type_complexity) ]
143140pub ( crate ) fn handle_load_default_button (
144141 mut interaction_query : Query <
145142 ( & Interaction , & mut BackgroundColor ) ,
@@ -164,16 +161,6 @@ pub(crate) fn handle_load_default_button(
164161 }
165162}
166163
167- // System to set up the 3D scene
168- pub ( crate ) fn setup_scene ( mut commands : Commands ) {
169- // Add ambient light
170- commands. insert_resource ( AmbientLight {
171- color : Color :: WHITE ,
172- brightness : 0.3 ,
173- ..default ( )
174- } ) ;
175- }
176-
177164// System to respawn atoms when crystal changes
178165pub ( crate ) fn update_scene (
179166 mut commands : Commands ,
@@ -281,19 +268,7 @@ pub fn setup_cameras(mut commands: Commands, windows: Query<&Window>) {
281268 } )
282269 . id ( ) ;
283270
284- let light_entity = commands
285- . spawn ( (
286- DirectionalLight {
287- shadows_enabled : true ,
288- ..default ( )
289- } ,
290- Transform :: from_rotation ( Quat :: from_rotation_x ( -std:: f32:: consts:: FRAC_PI_4 ) ) ,
291- ChildOf ( camera_entity) ,
292- ) )
293- . id ( ) ;
294-
295271 commands. insert_resource ( MainCameraEntity ( camera_entity) ) ;
296- commands. insert_resource ( MainLightEntity ( light_entity) ) ;
297272 commands. insert_resource ( CameraRig {
298273 target : initial_target,
299274 distance : initial_translation. distance ( initial_target) ,
@@ -304,6 +279,18 @@ pub fn setup_cameras(mut commands: Commands, windows: Query<&Window>) {
304279 } ) ;
305280}
306281
282+ pub ( crate ) fn setup_light ( mut commands : Commands , camera : Res < MainCameraEntity > ) {
283+ let light_entity = commands
284+ . spawn ( (
285+ DirectionalLight { ..default ( ) } ,
286+ Transform :: from_rotation ( Quat :: from_rotation_x ( -std:: f32:: consts:: FRAC_PI_4 ) ) ,
287+ ChildOf ( camera. 0 ) ,
288+ ) )
289+ . id ( ) ;
290+
291+ commands. insert_resource ( MainLightEntity ( light_entity) ) ;
292+ }
293+
307294// Setup minimal UI with toggle buttons
308295pub fn setup_buttons ( mut commands : Commands ) {
309296 // buttons at top-left
@@ -334,7 +321,7 @@ pub fn setup_buttons(mut commands: Commands) {
334321 ) )
335322 . with_children ( |button| {
336323 button. spawn ( (
337- Text :: new ( "Light: Detached " ) ,
324+ Text :: new ( "light not follow cam " ) ,
338325 TextFont {
339326 font : default ( ) ,
340327 font_size : 12.0 ,
@@ -571,33 +558,54 @@ pub fn toggle_light_attachment(
571558 ) ,
572559 ( Changed < Interaction > , With < LightAttachmentButton > ) ,
573560 > ,
561+ q_trans : Query < & GlobalTransform > ,
574562 mut texts : Query < & mut Text > ,
575563) {
576564 for ( interaction, mut background, mut button_state, children) in & mut interactions {
577565 match interaction {
578566 Interaction :: Pressed => {
579567 * background = BackgroundColor ( Color :: srgb ( 0.25 , 0.25 , 0.25 ) ) ;
580568
569+ let old_state = button_state. attached ;
570+ let new_state = !button_state. attached ;
571+
572+ button_state. attached = new_state;
573+
574+ if old_state {
575+ let light_trans = q_trans
576+ . get ( light. 0 )
577+ . expect ( "light must have global transform when disattach" ) ;
578+ let camera_trans = q_trans
579+ . get ( camera. 0 )
580+ . expect ( "camera must have global transform" ) ;
581+ let local = light_trans. reparented_to ( camera_trans) ;
582+ commands
583+ . entity ( light. 0 )
584+ . insert ( local)
585+ . insert ( ChildOf ( camera. 0 ) ) ;
586+ info ! ( "Light attached to camera" ) ;
587+ } else {
588+ let glb_trans = q_trans
589+ . get ( light. 0 )
590+ . expect ( "light must have global transform when disattach" ) ;
591+ commands
592+ . entity ( light. 0 )
593+ // preserve the world transform when detach
594+ . insert ( Transform :: from ( * glb_trans) )
595+ . remove :: < ChildOf > ( ) ;
596+ info ! ( "Light detached from camera" ) ;
597+ }
598+
581599 // Update the text inside the button
582600 for child in children. iter ( ) {
583601 if let Ok ( mut text) = texts. get_mut ( child) {
584- text. 0 = if button_state . attached {
585- "Light: Attached " . into ( )
602+ text. 0 = if new_state {
603+ "light follow cam " . into ( )
586604 } else {
587- "Light: Detached " . into ( )
605+ "light not follow cam " . into ( )
588606 } ;
589607 }
590608 }
591-
592- button_state. attached = !button_state. attached ;
593-
594- if button_state. attached {
595- commands. entity ( light. 0 ) . insert ( ChildOf ( camera. 0 ) ) ;
596- info ! ( "Light attached to camera" ) ;
597- } else {
598- commands. entity ( light. 0 ) . remove :: < ChildOf > ( ) ;
599- info ! ( "Light detached from camera" ) ;
600- }
601609 }
602610 Interaction :: Hovered => {
603611 * background = BackgroundColor ( Color :: srgb ( 0.2 , 0.2 , 0.2 ) ) ;
0 commit comments