Skip to content

Conversation

@DuckyBlender
Copy link

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
before.mov

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
after.mov

Code Example

// 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!

@github-actions
Copy link
Contributor

Welcome, new contributor!

Please make sure you've read our contributing guide and we look forward to reviewing your pull request shortly ✨

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant