use concinnity_core::components::{FrameInput, SettingCommand, SettingOp};
use concinnity_core::ecs::PipelineContext;
use concinnity_core::ecs::Ref;
use concinnity_core::ecs::asset_id::AssetId;
use concinnity_core::gfx::overlay::OverlayTransform;
use super::{UiInputSystem, point_in_rect, region_rect};
fn track_fraction(qx: f32, rect: [f32; 4]) -> f32 {
((qx - rect[0]) / rect[2]).clamp(0.0, 1.0)
}
impl UiInputSystem {
pub(super) fn step_slider_drag(
&mut self,
input: &FrameInput,
active_screen: Option<AssetId>,
overlay: &OverlayTransform,
ctx: &mut PipelineContext,
) {
let (qx, qy) = overlay.inverse(input.mouse_x, input.mouse_y);
if !input.left_button_down {
if let Some(i) = self.dragging.take()
&& self.regions[i].screen == active_screen
&& let Some(key) = self.regions[i].slider_key
{
let r = &self.regions[i].region;
ctx.events_mut::<SettingCommand>().send(SettingCommand {
setting: key,
op: SettingOp::SetFraction(track_fraction(qx, region_rect(r))),
value_label: r.label.map(Ref::id),
persist: true,
});
}
return;
}
for (i, entry) in self.regions.iter().enumerate() {
if entry.screen != active_screen {
continue;
}
let Some(key) = entry.slider_key else {
continue;
};
let rect = region_rect(&entry.region);
if self.dragging.is_none() && input.left_click && point_in_rect(qx, qy, rect) {
self.dragging = Some(i);
}
if self.dragging == Some(i) {
ctx.events_mut::<SettingCommand>().send(SettingCommand {
setting: key,
op: SettingOp::SetFraction(track_fraction(qx, rect)),
value_label: entry.region.label.map(Ref::id),
persist: false,
});
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
const TRACK: [f32; 4] = [100.0, 50.0, 200.0, 20.0];
#[test]
fn below_the_track_clamps_to_zero() {
assert_eq!(track_fraction(40.0, TRACK), 0.0);
}
#[test]
fn inside_the_track_is_proportional() {
assert_eq!(track_fraction(100.0, TRACK), 0.0);
assert_eq!(track_fraction(150.0, TRACK), 0.25);
assert_eq!(track_fraction(300.0, TRACK), 1.0);
}
#[test]
fn past_the_track_clamps_to_one() {
assert_eq!(track_fraction(900.0, TRACK), 1.0);
}
}