#[derive(Debug, Clone, Copy, PartialEq, Default, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "bitcode", derive(bitcode::Encode, bitcode::Decode))]
#[cfg_attr(
feature = "wincode",
derive(wincode::SchemaWrite, wincode::SchemaRead)
)]
#[cfg_attr(feature = "c_compatible", repr(C))]
pub struct ScrollableCamera {
pub container_width: f32,
pub container_height: f32,
pub content_width: f32,
pub content_height: f32,
pub offset_x: f32,
pub offset_y: f32,
pub scroll_multiplier_x: f32,
pub scroll_multiplier_y: f32,
pub horizontal_context_switch_multipliers: bool,
pub allow_free_scroll: bool,
}
impl ScrollableCamera {
pub fn scroll(&mut self, by: (f32, f32), vertical: bool) {
if vertical {
self.offset_x += by.0 * self.scroll_multiplier_x;
self.offset_y += by.1 * self.scroll_multiplier_y;
} else if !self.horizontal_context_switch_multipliers {
self.offset_x += by.1 * self.scroll_multiplier_y;
self.offset_y += by.0 * self.scroll_multiplier_x;
} else {
self.offset_x += by.1 * self.scroll_multiplier_x;
self.offset_y += by.0 * self.scroll_multiplier_y;
}
self.clamp_to_bounds();
}
#[allow(clippy::tuple_array_conversions)]
pub fn clamp_to_bounds(&mut self) {
let y_range = if self.allow_free_scroll {
[self.container_height - self.content_height, 0.0]
} else {
[(self.container_height - self.content_height).min(0.0), 0.0]
};
let (y_min, y_max) = if y_range[0] <= y_range[1] {
(y_range[0], y_range[1])
} else {
(y_range[1], y_range[0])
};
self.offset_y = self.offset_y.clamp(y_min, y_max);
let x_range = if self.allow_free_scroll {
[self.container_width - self.content_width, 0.0]
} else {
[(self.container_width - self.content_width).min(0.0), 0.0]
};
let (x_min, x_max) = if x_range[0] <= x_range[1] {
(x_range[0], x_range[1])
} else {
(x_range[1], x_range[0])
};
self.offset_x = self.offset_x.clamp(x_min, x_max);
}
}