@@ -27,7 +27,6 @@ fn main() {
27
27
// as vanilla components or resources
28
28
. add_event :: < CycleColorAction > ( )
29
29
. add_event :: < AddNumberAction > ( )
30
- . init_resource :: < Selected > ( )
31
30
. add_startup_system ( setup. system ( ) )
32
31
. add_system ( select_entity. system ( ) )
33
32
. add_system (
@@ -38,29 +37,32 @@ fn main() {
38
37
)
39
38
. add_system ( cycle_color. system ( ) . label ( "action_handling" ) )
40
39
. add_system ( add_number. system ( ) . label ( "action_handling" ) )
40
+ . add_system ( scale_selected. system ( ) . after ( "action_handling" ) )
41
41
. add_system ( update_text_color. system ( ) . after ( "action_handling" ) )
42
42
. run ( )
43
43
}
44
44
45
45
// Tracks which entity is selected
46
- #[ derive( Default ) ]
47
- struct Selected ( Option < Entity > ) ;
46
+ struct Selected {
47
+ entity : Entity ,
48
+ }
48
49
// Marks entities as selectable
49
50
struct Selectable ;
50
51
#[ derive( Bundle ) ]
51
52
struct InteractableBundle {
52
53
#[ bundle]
53
- text_bundle : Text2dBundle ,
54
+ text_bundle : TextBundle ,
54
55
selectable : Selectable ,
55
56
rainbow : Rainbow ,
56
57
cycle_color_events : Events < CycleColorAction > ,
57
58
add_number_events : Events < AddNumberAction > ,
58
59
}
59
60
60
61
impl InteractableBundle {
62
+ // FIXME: fix position
61
63
fn new ( x : f32 , y : f32 , font_handle : & Handle < Font > ) -> Self {
62
64
InteractableBundle {
63
- text_bundle : Text2dBundle {
65
+ text_bundle : TextBundle {
64
66
text : Text :: with_section (
65
67
"0" ,
66
68
TextStyle {
@@ -127,38 +129,145 @@ impl From<&Rainbow> for Color {
127
129
struct CycleColorAction ;
128
130
// Or store data to be responded to
129
131
struct AddNumberAction {
130
- number : u32 ,
132
+ number : u8 ,
131
133
}
132
134
133
135
fn setup ( mut commands : Commands , asset_server : Res < AssetServer > ) {
136
+ // Don't forget to include a camera!
137
+ commands. spawn_bundle ( UiCameraBundle :: default ( ) ) ;
138
+
134
139
let font_handle = asset_server. load ( "fonts/FiraSans-Bold.ttf" ) ;
135
- commands. spawn_bundle ( InteractableBundle :: new ( -200.0 , 0.0 , & font_handle) ) ;
136
- commands. spawn_bundle ( InteractableBundle :: new ( 0.0 , 0.0 , & font_handle) ) ;
137
- commands. spawn_bundle ( InteractableBundle :: new ( 200.0 , 0.0 , & font_handle) ) ;
140
+ // Spawns the first entity, and grabs the Entity id that is being allocated
141
+ let first_entity = commands
142
+ . spawn_bundle ( InteractableBundle :: new ( -200.0 , 400.0 , & font_handle) )
143
+ . id ( ) ;
144
+ commands. insert_resource ( Selected {
145
+ entity : first_entity,
146
+ } ) ;
147
+
148
+ commands. spawn_bundle ( InteractableBundle :: new ( 0.0 , 400.0 , & font_handle) ) ;
149
+ commands. spawn_bundle ( InteractableBundle :: new ( 200.0 , 400.0 , & font_handle) ) ;
150
+ }
151
+
152
+ enum CycleBehavior {
153
+ Forward ,
154
+ Back ,
138
155
}
139
156
140
157
/// Cycles through entities appropriately based on input
141
- fn select_entity ( mut query : Query < ( Entity , & mut Text ) , With < Selectable > > , selected : Res < Selected > ) {
158
+ fn select_entity (
159
+ mut query : Query < Entity , With < Selectable > > ,
160
+ mut selected : ResMut < Selected > ,
161
+ keyboard_input : Res < Input < KeyCode > > ,
162
+ ) {
163
+ let cycle_behavior: CycleBehavior = if keyboard_input. just_pressed ( KeyCode :: Tab ) {
164
+ if keyboard_input. pressed ( KeyCode :: LShift ) || keyboard_input. pressed ( KeyCode :: RShift ) {
165
+ CycleBehavior :: Back
166
+ } else {
167
+ CycleBehavior :: Forward
168
+ }
169
+ } else if keyboard_input. just_pressed ( KeyCode :: Right ) {
170
+ CycleBehavior :: Forward
171
+ } else if keyboard_input. just_pressed ( KeyCode :: Left ) {
172
+ CycleBehavior :: Back
173
+ } else {
174
+ return ;
175
+ } ;
176
+
177
+ let mut entities = Vec :: < Entity > :: new ( ) ;
178
+ // FIXME: Move to `.for_each` when https://github.com/bevyengine/bevy/issues/753 is resolved
179
+ query. for_each_mut ( |entity| entities. push ( entity. clone ( ) ) ) ;
180
+
181
+ let current_position = entities. iter ( ) . position ( |& e| e == selected. entity ) . unwrap ( ) as isize ;
182
+
183
+ let new_position = match cycle_behavior {
184
+ // We have to convert to isize for this step to avoid underflows when current_postion == 0
185
+ CycleBehavior :: Forward => ( current_position + 1 ) . rem_euclid ( entities. len ( ) as isize ) ,
186
+ CycleBehavior :: Back => ( current_position - 1 ) . rem_euclid ( entities. len ( ) as isize ) ,
187
+ } ;
188
+
189
+ selected. entity = entities[ new_position as usize ] ;
190
+ }
191
+
192
+ fn scale_selected (
193
+ mut query : Query < ( Entity , & mut Text ) , With < Selectable > > ,
194
+ selected : Res < Selected > ,
195
+ ) {
196
+ // Only do work when the selection is changed
197
+ if !selected. is_changed ( ) {
198
+ return ;
199
+ }
200
+
201
+ for ( entity, mut text) in query. iter_mut ( ) {
202
+ if entity == selected. entity {
203
+ text. sections [ 0 ] . style . font_size = 90.0 ;
204
+ } else {
205
+ text. sections [ 0 ] . style . font_size = 60.0 ;
206
+ }
207
+ }
142
208
}
143
209
144
210
// FIXME: make this work using `EventWriter<T>` syntax and specialized behavior
211
+ // FIXME: all input events are duplicated, due to just_pressed behavior
145
212
/// Dispatches actions to entities based on the input
146
213
/// Note that we can store several events at once!
147
- /// Try pressing both "Enter" and "Space" at once to cycle colors twice,
148
- /// Or both "1" and "3" to add 4 all at once to the selected display
214
+ /// Try pressing both "Enter" and "Space" at the same time to cycle colors twice,
215
+ /// Or both "1" and "3" to add 4 all at the same time to the selected display
149
216
fn input_dispatch (
150
- mut query : Query < (
151
- & ' static EventWriter < CycleColorAction > ,
152
- & ' static EventWriter < AddNumberAction > ,
153
- ) > ,
217
+ mut query : Query <
218
+ ( & mut Events < CycleColorAction > , & mut Events < AddNumberAction > ) ,
219
+ With < Selectable > ,
220
+ > ,
154
221
selected : Res < Selected > ,
222
+ keyboard_input : Res < Input < KeyCode > > ,
155
223
) {
224
+ let ( mut cycle_actions, mut add_actions) = query. get_mut ( selected. entity ) . unwrap ( ) ;
225
+
226
+ // Inputs for cycling colors
227
+ // Normally, you'd probably want to use || on the inputs here,
228
+ // but we're demonstrating the ability to process multiple events at once
229
+ if keyboard_input. just_pressed ( KeyCode :: Return ) {
230
+ cycle_actions. send ( CycleColorAction ) ;
231
+ }
232
+ if keyboard_input. just_pressed ( KeyCode :: Space ) {
233
+ cycle_actions. send ( CycleColorAction ) ;
234
+ }
235
+
236
+ // Inputs for sending numbers to be added
237
+ if keyboard_input. just_pressed ( KeyCode :: Key1 ) {
238
+ add_actions. send ( AddNumberAction { number : 1 } ) ;
239
+ }
240
+ if keyboard_input. just_pressed ( KeyCode :: Key2 ) {
241
+ add_actions. send ( AddNumberAction { number : 2 } ) ;
242
+ }
243
+ if keyboard_input. just_pressed ( KeyCode :: Key3 ) {
244
+ add_actions. send ( AddNumberAction { number : 3 } ) ;
245
+ }
246
+ if keyboard_input. just_pressed ( KeyCode :: Key4 ) {
247
+ add_actions. send ( AddNumberAction { number : 4 } ) ;
248
+ }
249
+ if keyboard_input. just_pressed ( KeyCode :: Key5 ) {
250
+ add_actions. send ( AddNumberAction { number : 5 } ) ;
251
+ }
252
+ if keyboard_input. just_pressed ( KeyCode :: Key6 ) {
253
+ add_actions. send ( AddNumberAction { number : 6 } ) ;
254
+ }
255
+ if keyboard_input. just_pressed ( KeyCode :: Key7 ) {
256
+ add_actions. send ( AddNumberAction { number : 7 } ) ;
257
+ }
258
+ if keyboard_input. just_pressed ( KeyCode :: Key8 ) {
259
+ add_actions. send ( AddNumberAction { number : 8 } ) ;
260
+ }
261
+ if keyboard_input. just_pressed ( KeyCode :: Key9 ) {
262
+ add_actions. send ( AddNumberAction { number : 9 } ) ;
263
+ }
156
264
}
157
265
158
266
// FIXME: make this work using `EventReader<T>` syntax and specialized behavior
159
- fn cycle_color ( mut query : Query < ( & mut Rainbow , & ' static EventReader < CycleColorAction > ) > ) {
160
- for ( mut rainbow, cycle_color_action_queue) in query. iter_mut ( ) {
161
- for _ in cycle_color_action_queue. iter ( ) {
267
+ fn cycle_color ( mut query : Query < ( & mut Rainbow , & mut Events < CycleColorAction > ) > ) {
268
+ for ( mut rainbow, action_queue) in query. iter_mut ( ) {
269
+ let mut reader = action_queue. get_reader ( ) ;
270
+ for _ in reader. iter ( & action_queue) {
162
271
* rainbow = rainbow. next ( ) . unwrap ( ) ;
163
272
}
164
273
}
@@ -177,7 +286,10 @@ fn add_number(mut query: Query<(&mut Text, &Events<AddNumberAction>)>) {
177
286
for ( mut text, action_queue) in query. iter_mut ( ) {
178
287
let mut reader = action_queue. get_reader ( ) ;
179
288
for action in reader. iter ( & action_queue) {
180
- // TODO: add the number
289
+ let current_number: u8 = text. sections [ 0 ] . value . clone ( ) . parse ( ) . unwrap ( ) ;
290
+ // Wrap addition, rather than overflowing
291
+ let new_number = ( current_number + action. number ) % std:: u8:: MAX ;
292
+ text. sections [ 0 ] . value = new_number. to_string ( ) ;
181
293
}
182
294
}
183
295
}
0 commit comments