@@ -6,18 +6,18 @@ use bevy_ecs::{
66 entity:: Entity ,
77 hierarchy:: { ChildOf , Children } ,
88 observer:: On ,
9- query:: { Has , With } ,
9+ query:: { Has , With , Without } ,
1010 reflect:: ReflectComponent ,
1111 system:: { Commands , Query } ,
1212} ;
1313use bevy_input:: keyboard:: { KeyCode , KeyboardInput } ;
1414use bevy_input:: ButtonState ;
1515use bevy_input_focus:: FocusedInput ;
16- use bevy_picking:: events:: { Click , Pointer } ;
16+ use bevy_picking:: events:: { Cancel , Click , DragEnd , Pointer , Press , Release } ;
1717use bevy_reflect:: Reflect ;
18- use bevy_ui:: { Checkable , Checked , InteractionDisabled } ;
18+ use bevy_ui:: { Checkable , Checked , InteractionDisabled , Pressed } ;
1919
20- use crate :: ValueChange ;
20+ use crate :: { ActivateOnPress , ValueChange } ;
2121
2222/// Headless widget implementation for a "radio button group". This component is used to group
2323/// multiple [`RadioButton`] components together, allowing them to behave as a single unit. It
@@ -188,32 +188,108 @@ fn radio_button_on_key_input(
188188}
189189
190190fn radio_button_on_click (
191- mut ev : On < Pointer < Click > > ,
191+ mut click : On < Pointer < Click > > ,
192192 q_group : Query < ( ) , With < RadioGroup > > ,
193- q_radio : Query < ( Has < InteractionDisabled > , Has < Checked > ) , With < RadioButton > > ,
193+ q_radio : Query <
194+ ( Has < InteractionDisabled > , Has < Checked > ) ,
195+ ( With < RadioButton > , Without < ActivateOnPress > ) ,
196+ > ,
194197 q_parents : Query < & ChildOf > ,
195198 mut commands : Commands ,
196199) {
197- let Ok ( ( disabled, checked) ) = q_radio. get ( ev . entity ) else {
200+ let Ok ( ( disabled, checked) ) = q_radio. get ( click . entity ) else {
198201 // Not a radio button
199202 return ;
200203 } ;
201204
202- ev . propagate ( false ) ;
205+ click . propagate ( false ) ;
203206
204207 // Radio button is disabled or already checked
205208 if disabled || checked {
206209 return ;
207210 }
208211
209212 trigger_radio_button_and_radio_group_value_change (
210- ev . entity ,
213+ click . entity ,
211214 & q_group,
212215 & q_parents,
213216 & mut commands,
214217 ) ;
215218}
216219
220+ fn radio_button_on_pointer_down (
221+ mut press : On < Pointer < Press > > ,
222+ q_group : Query < ( ) , With < RadioGroup > > ,
223+ mut q_radio : Query <
224+ (
225+ Entity ,
226+ Has < InteractionDisabled > ,
227+ Has < Checked > ,
228+ Has < Pressed > ,
229+ Has < ActivateOnPress > ,
230+ ) ,
231+ With < RadioButton > ,
232+ > ,
233+ q_parents : Query < & ChildOf > ,
234+ mut commands : Commands ,
235+ ) {
236+ if let Ok ( ( radio, disabled, checked, pressed, activate_on_press) ) =
237+ q_radio. get_mut ( press. entity )
238+ {
239+ press. propagate ( false ) ;
240+ if !disabled && !pressed {
241+ commands. entity ( radio) . insert ( Pressed ) ;
242+ if activate_on_press && !checked {
243+ trigger_radio_button_and_radio_group_value_change (
244+ press. entity ,
245+ & q_group,
246+ & q_parents,
247+ & mut commands,
248+ ) ;
249+ }
250+ }
251+ }
252+ }
253+
254+ fn radio_button_on_pointer_up (
255+ mut release : On < Pointer < Release > > ,
256+ mut q_radio : Query < ( Entity , Has < InteractionDisabled > , Has < Pressed > ) , With < RadioButton > > ,
257+ mut commands : Commands ,
258+ ) {
259+ if let Ok ( ( radio, disabled, pressed) ) = q_radio. get_mut ( release. entity ) {
260+ release. propagate ( false ) ;
261+ if !disabled && pressed {
262+ commands. entity ( radio) . remove :: < Pressed > ( ) ;
263+ }
264+ }
265+ }
266+
267+ fn radio_button_on_pointer_drag_end (
268+ mut drag_end : On < Pointer < DragEnd > > ,
269+ mut q_radio : Query < ( Entity , Has < InteractionDisabled > , Has < Pressed > ) , With < RadioButton > > ,
270+ mut commands : Commands ,
271+ ) {
272+ if let Ok ( ( radio, disabled, pressed) ) = q_radio. get_mut ( drag_end. entity ) {
273+ drag_end. propagate ( false ) ;
274+ if !disabled && pressed {
275+ commands. entity ( radio) . remove :: < Pressed > ( ) ;
276+ }
277+ }
278+ }
279+
280+ fn checkbox_on_pointer_cancel (
281+ mut cancel : On < Pointer < Cancel > > ,
282+ mut q_radio : Query < ( Entity , Has < InteractionDisabled > , Has < Pressed > ) , With < RadioButton > > ,
283+ mut commands : Commands ,
284+ ) {
285+ if let Ok ( ( radio, disabled, pressed) ) = q_radio. get_mut ( cancel. entity ) {
286+ cancel. propagate ( false ) ;
287+ if !disabled && pressed {
288+ commands. entity ( radio) . remove :: < Pressed > ( ) ;
289+ }
290+ }
291+ }
292+
217293fn trigger_radio_button_and_radio_group_value_change (
218294 radio_button : Entity ,
219295 q_group : & Query < ( ) , With < RadioGroup > > ,
@@ -247,6 +323,10 @@ impl Plugin for RadioGroupPlugin {
247323 fn build ( & self , app : & mut App ) {
248324 app. add_observer ( radio_group_on_key_input)
249325 . add_observer ( radio_button_on_click)
250- . add_observer ( radio_button_on_key_input) ;
326+ . add_observer ( radio_button_on_key_input)
327+ . add_observer ( radio_button_on_pointer_down)
328+ . add_observer ( radio_button_on_pointer_up)
329+ . add_observer ( radio_button_on_pointer_drag_end)
330+ . add_observer ( checkbox_on_pointer_cancel) ;
251331 }
252332}
0 commit comments