Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 63 additions & 17 deletions crates/bevy_ui_widgets/src/slider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,22 +264,52 @@ pub(crate) fn slider_on_pointer_down(
return;
}

// Detect orientation: vertical if height > width
let is_vertical = node.size().y > node.size().x;

// Find thumb size by searching descendants for the first entity with SliderThumb
let thumb_size = q_children
.iter_descendants(press.entity)
.find_map(|child_id| q_thumb.get(child_id).ok().map(|thumb| thumb.size().x))
.find_map(|child_id| {
q_thumb.get(child_id).ok().map(|thumb| {
if is_vertical {
thumb.size().y
} else {
thumb.size().x
}
})
})
.unwrap_or(0.0);

// Detect track click.
let local_pos = transform.try_inverse().unwrap().transform_point2(
press.pointer_location.position * node_target.scale_factor() / ui_scale.0,
);
let track_width = node.size().x - thumb_size;
let track_size = if is_vertical {
node.size().y - thumb_size
} else {
node.size().x - thumb_size
};

// Avoid division by zero
let click_val = if track_width > 0. {
local_pos.x * range.span() / track_width + range.center()
let click_val = if track_size > 0. {
if is_vertical {
// For vertical sliders: convert from center-origin to top-origin coordinates
// local_pos.y ranges from -height/2 to +height/2
// Convert to: 0 at top, height at bottom
let y_from_top = local_pos.y + node.size().y / 2.0;
// Offset by half thumb size to center the calculation
let adjusted_y = y_from_top - thumb_size / 2.0;
// Invert because Y increases downward
range.end() - (adjusted_y * range.span() / track_size)
} else {
// For horizontal sliders: convert from center-origin to left-origin
let x_from_left = local_pos.x + node.size().x / 2.0;
let adjusted_x = x_from_left - thumb_size / 2.0;
adjusted_x * range.span() / track_size + range.start()
}
} else {
0.
range.center()
};

// Compute new value from click position
Expand Down Expand Up @@ -330,7 +360,6 @@ pub(crate) fn slider_on_drag(
mut event: On<Pointer<Drag>>,
mut q_slider: Query<
(
&SliderValue,
&ComputedNode,
&SliderRange,
Option<&SliderPrecision>,
Expand All @@ -345,23 +374,42 @@ pub(crate) fn slider_on_drag(
mut commands: Commands,
ui_scale: Res<UiScale>,
) {
if let Ok((value, node, range, precision, transform, drag, disabled)) =
q_slider.get_mut(event.entity)
if let Ok((node, range, precision, transform, drag, disabled)) = q_slider.get_mut(event.entity)
{
event.propagate(false);
if drag.dragging && !disabled {
// Detect orientation: vertical if height > width
let is_vertical = node.size().y > node.size().x;

let mut distance = event.distance / ui_scale.0;
distance.y *= -1.;
let distance = transform.transform_vector2(distance);

// Find thumb size by searching descendants for the first entity with SliderThumb
let thumb_size = q_children
.iter_descendants(event.entity)
.find_map(|child_id| q_thumb.get(child_id).ok().map(|thumb| thumb.size().x))
.find_map(|child_id| {
q_thumb.get(child_id).ok().map(|thumb| {
if is_vertical {
thumb.size().y
} else {
thumb.size().x
}
})
})
.unwrap_or(0.0);
let slider_width = ((node.size().x - thumb_size) * node.inverse_scale_factor).max(1.0);

let slider_size = if is_vertical {
((node.size().y - thumb_size) * node.inverse_scale_factor).max(1.0)
} else {
((node.size().x - thumb_size) * node.inverse_scale_factor).max(1.0)
};

let drag_distance = if is_vertical { distance.y } else { distance.x };

let span = range.span();
let new_value = if span > 0. {
drag.offset + (distance.x * span) / slider_width
drag.offset + (drag_distance * span) / slider_size
} else {
range.start() + span * 0.5
};
Expand All @@ -371,12 +419,10 @@ pub(crate) fn slider_on_drag(
.unwrap_or(new_value),
);

if rounded_value != value.0 {
commands.trigger(ValueChange {
source: event.entity,
value: rounded_value,
});
}
commands.trigger(ValueChange {
source: event.entity,
value: rounded_value,
});
}
}
}
Expand Down
Loading