Commit 8a0367e
Add vertical slider support to bevy_ui_widgets slider (#21827)
# Objective
- Fixes the issue of vertical sliders not being functional. Previously,
when creating a vertical slider, the slider drag behavior was still
horizontal, meaning dragging left/right would change the value instead
of dragging up/down. Additionally, clicking on the slider track was
offset and didn't correctly map to the clicked position.
## Solution
The slider widget now automatically detects its orientation based on the
node's dimensions (`height > width` for vertical, otherwise horizontal)
and adjusts its interaction behavior accordingly:
1. **Orientation Detection**: Added automatic detection of slider
orientation by comparing `node.size().y` to `node.size().x` in both
`slider_on_pointer_down` and `slider_on_drag` functions.
2. **Drag Direction Fix**:
- For vertical sliders, the drag calculation now uses the Y-axis
(`distance.y`) instead of X-axis
- The Y coordinate is properly inverted (since screen Y increases
downward) to match expected behavior (dragging up increases value)
- Thumb size calculation uses `thumb.size().y` for vertical sliders
instead of always using `thumb.size().x`
3. **Click Position Fix**:
- Fixed coordinate conversion from Bevy's center-origin coordinate
system to top/left-origin coordinates
- For vertical sliders: converts `local_pos.y` from `[-height/2,
+height/2]` to `[0, height]` before calculating the slider value
- Accounts for thumb size offset to center the calculation properly
- Inverts the Y coordinate for vertical sliders since Y increases
downward
4. **Track Size Calculation**: Uses `node.size().y - thumb_size` for
vertical sliders and `node.size().x - thumb_size` for horizontal sliders
when calculating the available track space.
The changes are backward compatible - horizontal sliders continue to
work exactly as before, and the orientation detection is transparent to
users of the API.
## Testing
- **Manual Testing**: Created test application with both vertical and
horizontal sliders to verify:
- Vertical sliders respond correctly to vertical drag movements (up =
increase, down = decrease)
- Horizontal sliders continue to work correctly with horizontal drag
movements
- Clicking anywhere on the slider track correctly snaps to that position
for both orientations
- Thumb positioning updates correctly during drag operations
- Multiple sliders can coexist without interfering with each other
- **Edge Cases Tested**:
- Clicking at the very top/bottom of vertical sliders
- Clicking at the very left/right of horizontal sliders
- Dragging from one extreme to the other
- Rapid clicking and dragging interactions
**Areas that may need more testing:**
- Sliders with non-standard aspect ratios (very wide vertical sliders or
very tall horizontal sliders)
- Sliders with custom transforms/rotations applied
- Sliders in nested UI hierarchies with complex transforms
**How reviewers can test:**
1. Create a vertical slider (height > width) and verify:
- Dragging up increases the value
- Dragging down decreases the value
- Clicking anywhere on the track snaps to that exact position
2. Create a horizontal slider (width > height) and verify it still works
as before
3. Test with multiple sliders of both orientations simultaneously
**Platforms tested:**
- macOS (Apple Silicon)
## Showcase
### Before
- Vertical sliders were unusable - dragging would move horizontally
instead of vertically
- Clicking on vertical slider tracks was offset, with clicks near the
bottom snapping to the middle instead
https://github.com/user-attachments/assets/9bda83e7-f46b-4626-9df3-a558526a8ab2
### After
- Vertical sliders work correctly with intuitive up/down drag behavior
- Clicking anywhere on the slider track accurately snaps to the clicked
position
- Both vertical and horizontal sliders work seamlessly together
https://github.com/user-attachments/assets/cca24288-4cbc-4ceb-828f-9ce7a735ade0
### Code Example
```rust
// Vertical slider - now works correctly!
commands.spawn((
Node {
width: Val::Px(12.0),
height: Val::Px(300.0), // height > width = vertical
..default()
},
Slider::default(),
SliderValue(50.0),
SliderRange::new(0.0, 100.0),
// ... thumb and track children
));
// Horizontal slider - continues to work as before
commands.spawn((
Node {
width: Val::Px(300.0),
height: Val::Px(12.0), // width > height = horizontal
..default()
},
Slider::default(),
SliderValue(50.0),
SliderRange::new(0.0, 100.0),
// ... thumb and track children
));
```
The orientation is automatically detected based on the node dimensions -
no API changes required!
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>1 parent 8c6e490 commit 8a0367e
File tree
4 files changed
+386
-17
lines changed- crates/bevy_ui_widgets/src
- examples
- ui
4 files changed
+386
-17
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3491 | 3491 | | |
3492 | 3492 | | |
3493 | 3493 | | |
| 3494 | + | |
| 3495 | + | |
| 3496 | + | |
| 3497 | + | |
| 3498 | + | |
| 3499 | + | |
| 3500 | + | |
| 3501 | + | |
| 3502 | + | |
| 3503 | + | |
| 3504 | + | |
| 3505 | + | |
3494 | 3506 | | |
3495 | 3507 | | |
3496 | 3508 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
264 | 264 | | |
265 | 265 | | |
266 | 266 | | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
267 | 270 | | |
268 | 271 | | |
269 | 272 | | |
270 | | - | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
271 | 282 | | |
272 | 283 | | |
273 | 284 | | |
274 | 285 | | |
275 | 286 | | |
276 | 287 | | |
277 | | - | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
278 | 294 | | |
279 | | - | |
280 | | - | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
281 | 308 | | |
282 | | - | |
| 309 | + | |
283 | 310 | | |
284 | 311 | | |
285 | 312 | | |
| |||
330 | 357 | | |
331 | 358 | | |
332 | 359 | | |
333 | | - | |
334 | 360 | | |
335 | 361 | | |
336 | 362 | | |
| |||
345 | 371 | | |
346 | 372 | | |
347 | 373 | | |
348 | | - | |
349 | | - | |
| 374 | + | |
350 | 375 | | |
351 | 376 | | |
352 | 377 | | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
353 | 381 | | |
354 | 382 | | |
355 | 383 | | |
| 384 | + | |
356 | 385 | | |
357 | 386 | | |
358 | 387 | | |
359 | | - | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
360 | 397 | | |
361 | | - | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
362 | 407 | | |
363 | 408 | | |
364 | | - | |
| 409 | + | |
365 | 410 | | |
366 | 411 | | |
367 | 412 | | |
| |||
371 | 416 | | |
372 | 417 | | |
373 | 418 | | |
374 | | - | |
375 | | - | |
376 | | - | |
377 | | - | |
378 | | - | |
379 | | - | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
380 | 423 | | |
381 | 424 | | |
382 | 425 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
595 | 595 | | |
596 | 596 | | |
597 | 597 | | |
| 598 | + | |
598 | 599 | | |
599 | 600 | | |
600 | 601 | | |
| |||
0 commit comments