1+ #![ allow( clippy:: needless_pass_by_value) ]
2+
13use std:: collections:: HashMap ;
24
35use bevy:: input:: mouse:: { MouseMotion , MouseWheel } ;
@@ -14,45 +16,13 @@ const LAYER_CANVAS: RenderLayers = RenderLayers::layer(0);
1416#[ derive( Component ) ]
1517pub ( crate ) struct MainCamera ;
1618
17- /// Identifier for a reusable toggle interaction.
18- #[ derive( Clone , Copy , Debug , Eq , Hash , PartialEq ) ]
19- enum ToggleId {
20- LightAttachment ,
21- }
22-
23- // struct AmbientLight
24-
25- impl ToggleId {
26- fn label ( self , state : bool ) -> & ' static str {
27- match ( self , state) {
28- ( ToggleId :: LightAttachment , true ) => "Light: Attached" ,
29- ( ToggleId :: LightAttachment , false ) => "Light: Detached" ,
30- }
31- }
32- }
33-
34- // XXX: REVIEW: this is very oop like implementation, better?
35-
36- /// Stores the current on/off state for each toggle.
37- #[ derive( Resource , Default ) ]
38- pub ( crate ) struct ToggleStates {
39- states : HashMap < ToggleId , bool > ,
40- }
41-
42- impl ToggleStates {
43- fn register ( & mut self , id : ToggleId , initial_state : bool ) {
44- self . states . entry ( id) . or_insert ( initial_state) ;
45- }
46-
47- fn get ( & self , id : ToggleId ) -> bool {
48- self . states . get ( & id) . copied ( ) . unwrap_or ( false )
49- }
19+ /// Button that resets the camera to its original position/orientation.
20+ #[ derive( Component ) ]
21+ pub ( crate ) struct ResetCameraButton ;
5022
51- fn toggle ( & mut self , id : ToggleId ) -> bool {
52- let new_state = !self . get ( id) ;
53- self . states . insert ( id, new_state) ;
54- new_state
55- }
23+ #[ derive( Component ) ]
24+ pub ( crate ) struct LightAttachmentButton {
25+ attached : bool ,
5626}
5727
5828/// Marks an entity that spawned the main camera.
@@ -63,25 +33,6 @@ pub(crate) struct MainCameraEntity(pub Entity);
6333#[ derive( Resource ) ]
6434pub ( crate ) struct MainLightEntity ( pub Entity ) ;
6535
66- /// Component identifying a toggle button instance.
67- #[ derive( Component ) ]
68- pub ( crate ) struct ToggleButton {
69- id : ToggleId ,
70- }
71-
72- /// Component carried by the text to update when a toggle changes.
73- #[ derive( Component ) ]
74- pub ( crate ) struct ToggleText {
75- id : ToggleId ,
76- }
77-
78- /// Event emitted whenever a toggle switches state.
79- #[ derive( Event ) ]
80- pub struct ToggleEvent {
81- id : ToggleId ,
82- pub state : bool ,
83- }
84-
8536/// Stores camera orbit information and the original configuration so it can be restored.
8637#[ derive( Resource ) ]
8738pub ( crate ) struct CameraRig {
@@ -93,10 +44,6 @@ pub(crate) struct CameraRig {
9344 initial_scale : Vec3 ,
9445}
9546
96- /// Button that resets the camera to its original position/orientation.
97- #[ derive( Component ) ]
98- pub ( crate ) struct ResetCameraButton ;
99-
10047// System to set up the 3D scene
10148pub ( crate ) fn setup_scene (
10249 mut commands : Commands ,
@@ -148,11 +95,7 @@ pub(crate) fn setup_scene(
14895}
14996
15097// System to set up the camera
151- pub fn setup_cameras (
152- mut commands : Commands ,
153- mut toggle_states : ResMut < ToggleStates > ,
154- windows : Query < & Window > ,
155- ) {
98+ pub fn setup_cameras ( mut commands : Commands , windows : Query < & Window > ) {
15699 let window = windows. single ( ) . unwrap ( ) ;
157100 let viewport_size = UVec2 :: new ( 200 , 200 ) ;
158101 let bottom_left_y = window. physical_height ( ) - viewport_size. y - 10 ;
@@ -219,8 +162,6 @@ pub fn setup_cameras(
219162 ) )
220163 . id ( ) ;
221164
222- toggle_states. register ( ToggleId :: LightAttachment , true ) ;
223-
224165 commands. insert_resource ( MainCameraEntity ( camera_entity) ) ;
225166 commands. insert_resource ( MainLightEntity ( light_entity) ) ;
226167 commands. insert_resource ( CameraRig {
@@ -234,7 +175,7 @@ pub fn setup_cameras(
234175}
235176
236177// Setup minimal UI with toggle buttons
237- pub fn setup_buttons ( mut commands : Commands , toggle_states : Res < ToggleStates > ) {
178+ pub fn setup_buttons ( mut commands : Commands ) {
238179 // buttons at top-left
239180 commands
240181 . spawn ( (
@@ -249,38 +190,29 @@ pub fn setup_buttons(mut commands: Commands, toggle_states: Res<ToggleStates>) {
249190 BackgroundColor ( Color :: NONE ) ,
250191 ) )
251192 . with_children ( |parent| {
252- let mut spawn_button = |id : ToggleId | {
253- let state = toggle_states. get ( id) ;
254- let label = id. label ( state) ;
255-
256- parent
257- . spawn ( (
258- Button ,
259- Node {
260- padding : UiRect :: axes ( Val :: Px ( 10.0 ) , Val :: Px ( 6.0 ) ) ,
261- border : UiRect :: all ( Val :: Px ( 1.0 ) ) ,
193+ parent
194+ . spawn ( (
195+ Button ,
196+ Node {
197+ padding : UiRect :: axes ( Val :: Px ( 10.0 ) , Val :: Px ( 6.0 ) ) ,
198+ border : UiRect :: all ( Val :: Px ( 1.0 ) ) ,
199+ ..default ( )
200+ } ,
201+ BorderColor ( Color :: srgb ( 0.3 , 0.3 , 0.3 ) ) ,
202+ BackgroundColor ( Color :: srgb ( 0.15 , 0.15 , 0.15 ) ) ,
203+ LightAttachmentButton { attached : false } ,
204+ ) )
205+ . with_children ( |button| {
206+ button. spawn ( (
207+ Text :: new ( "Light: Detached" ) ,
208+ TextFont {
209+ font : default ( ) ,
210+ font_size : 12.0 ,
262211 ..default ( )
263212 } ,
264- BorderColor ( Color :: srgb ( 0.3 , 0.3 , 0.3 ) ) ,
265- BackgroundColor ( Color :: srgb ( 0.15 , 0.15 , 0.15 ) ) ,
266- ToggleButton { id } ,
267- ) )
268- . with_children ( |button| {
269- button. spawn ( (
270- Text :: new ( label) ,
271- TextFont {
272- font : default ( ) ,
273- font_size : 12.0 ,
274- ..default ( )
275- } ,
276- TextColor ( Color :: WHITE ) ,
277- ToggleText { id } ,
278- ) ) ;
279- } ) ;
280- } ;
281-
282- let id = ToggleId :: LightAttachment ;
283- spawn_button ( id) ;
213+ TextColor ( Color :: WHITE ) ,
214+ ) ) ;
215+ } ) ;
284216
285217 parent
286218 . spawn ( (
@@ -491,33 +423,47 @@ pub(crate) fn camera_controls(
491423 }
492424}
493425
494- // Handle button interaction: toggle state and update label
495426#[ allow( clippy:: type_complexity) ]
496- pub fn toggle_button (
427+ pub fn toggle_light_attachment (
428+ mut commands : Commands ,
429+ light : Res < MainLightEntity > ,
430+ camera : Res < MainCameraEntity > ,
497431 mut interactions : Query <
498- ( & Interaction , & mut BackgroundColor , & ToggleButton ) ,
499- ( Changed < Interaction > , With < Button > ) ,
432+ (
433+ & Interaction ,
434+ & mut BackgroundColor ,
435+ & mut LightAttachmentButton ,
436+ & Children ,
437+ ) ,
438+ ( Changed < Interaction > , With < LightAttachmentButton > ) ,
500439 > ,
501- mut texts : Query < ( & ToggleText , & mut Text ) > ,
502- mut toggle_states : ResMut < ToggleStates > ,
503- mut toggle_events : EventWriter < ToggleEvent > ,
440+ mut texts : Query < & mut Text > ,
504441) {
505- for ( interaction, mut background, toggle_button ) in & mut interactions {
506- match * interaction {
442+ for ( interaction, mut background, mut button_state , children ) in & mut interactions {
443+ match interaction {
507444 Interaction :: Pressed => {
508- let new_state = toggle_states. toggle ( toggle_button. id ) ;
509- toggle_events. write ( ToggleEvent {
510- id : toggle_button. id ,
511- state : new_state,
512- } ) ;
445+ * background = BackgroundColor ( Color :: srgb ( 0.25 , 0.25 , 0.25 ) ) ;
513446
514- for ( text_marker, mut text) in & mut texts {
515- if text_marker. id == toggle_button. id {
516- text. 0 = ToggleId :: label ( toggle_button. id , new_state) . into ( ) ;
447+ // Update the text inside the button
448+ for child in children. iter ( ) {
449+ if let Ok ( mut text) = texts. get_mut ( child) {
450+ text. 0 = if button_state. attached {
451+ "Light: Attached" . into ( )
452+ } else {
453+ "Light: Detached" . into ( )
454+ } ;
517455 }
518456 }
519457
520- * background = BackgroundColor ( Color :: srgb ( 0.25 , 0.25 , 0.25 ) ) ;
458+ button_state. attached = !button_state. attached ;
459+
460+ if button_state. attached {
461+ commands. entity ( light. 0 ) . insert ( ChildOf ( camera. 0 ) ) ;
462+ info ! ( "Light attached to camera" ) ;
463+ } else {
464+ commands. entity ( light. 0 ) . remove :: < ChildOf > ( ) ;
465+ info ! ( "Light detached from camera" ) ;
466+ }
521467 }
522468 Interaction :: Hovered => {
523469 * background = BackgroundColor ( Color :: srgb ( 0.2 , 0.2 , 0.2 ) ) ;
@@ -534,7 +480,7 @@ pub fn toggle_button(
534480pub fn reset_camera_button_interaction (
535481 mut interactions : Query <
536482 ( & Interaction , & mut BackgroundColor ) ,
537- ( Changed < Interaction > , With < Button > , With < ResetCameraButton > ) ,
483+ ( Changed < Interaction > , With < ResetCameraButton > ) ,
538484 > ,
539485 camera_entity : Option < Res < MainCameraEntity > > ,
540486 mut camera_query : Query < & mut Transform , With < Camera3d > > ,
@@ -568,45 +514,3 @@ pub fn reset_camera_button_interaction(
568514 }
569515 }
570516}
571-
572- // Respond to toggle events by applying the desired world changes
573- pub fn handle_toggle_events (
574- mut toggle_events : EventReader < ToggleEvent > ,
575- camera_entity : Option < Res < MainCameraEntity > > ,
576- light_entity : Option < Res < MainLightEntity > > ,
577- global_light_xforms : Query < & GlobalTransform , With < DirectionalLight > > ,
578- mut commands : Commands ,
579- ) {
580- let Some ( camera_entity) = camera_entity else {
581- return ;
582- } ;
583- let Some ( light_entity) = light_entity else {
584- return ;
585- } ;
586-
587- // XXX: only single event at the moment
588- for event in toggle_events. read ( ) {
589- match event. id {
590- ToggleId :: LightAttachment => {
591- if event. state {
592- // Re-attach to camera; use default local transform so light follows camera orientation.
593- commands
594- . entity ( light_entity. 0 )
595- . insert ( ChildOf ( camera_entity. 0 ) )
596- . insert ( Transform :: default ( ) ) ;
597- } else if let Ok ( global_transform) = global_light_xforms. get ( light_entity. 0 ) {
598- let ( scale, rotation, translation) =
599- global_transform. to_scale_rotation_translation ( ) ;
600- commands. entity ( light_entity. 0 ) . remove :: < ChildOf > ( ) ;
601- commands. entity ( light_entity. 0 ) . insert ( Transform {
602- translation,
603- rotation,
604- scale,
605- } ) ;
606- } else {
607- commands. entity ( light_entity. 0 ) . remove :: < ChildOf > ( ) ;
608- }
609- }
610- }
611- }
612- }
0 commit comments