2020-10-05 08:35:24 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
2019-04-26 04:29:35 +00:00
|
|
|
use vek::*;
|
|
|
|
|
2019-05-17 09:22:32 +00:00
|
|
|
/// Type of scaling to use.
|
2020-11-14 01:16:42 +00:00
|
|
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq)]
|
2019-04-26 04:29:35 +00:00
|
|
|
pub enum ScaleMode {
|
2019-05-17 09:22:32 +00:00
|
|
|
// Scale against physical size.
|
2019-04-26 04:29:35 +00:00
|
|
|
Absolute(f64),
|
2019-05-17 09:22:32 +00:00
|
|
|
// Scale based on the window's physical size, but maintain aspect ratio of widgets.
|
2020-02-01 20:39:39 +00:00
|
|
|
// Contains width and height of the "default" window size (ie where there should be no
|
|
|
|
// scaling).
|
2019-04-26 04:29:35 +00:00
|
|
|
RelativeToWindow(Vec2<f64>),
|
2020-11-11 17:37:26 +00:00
|
|
|
// Use the dpi factor provided by the windowing system (i.e. use logical size).
|
|
|
|
#[serde(other)]
|
|
|
|
// Would be `RelativeToWindow([1920.0, 1080.0].into())`, but only supported on unit variants
|
|
|
|
DpiFactor,
|
2019-04-26 04:29:35 +00:00
|
|
|
}
|
|
|
|
|
2019-07-26 02:28:53 +00:00
|
|
|
#[derive(Clone, Copy)]
|
2019-04-26 04:29:35 +00:00
|
|
|
pub struct Scale {
|
|
|
|
mode: ScaleMode,
|
|
|
|
// Current dpi factor
|
2020-02-20 23:41:51 +00:00
|
|
|
scale_factor: f64,
|
2021-10-01 01:15:51 +00:00
|
|
|
// Current pixel size of the window
|
|
|
|
physical_resolution: Vec2<u32>,
|
2020-10-31 20:04:20 +00:00
|
|
|
// TEMP
|
|
|
|
extra_factor: f64,
|
2019-04-26 04:29:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Scale {
|
2021-10-01 01:15:51 +00:00
|
|
|
pub fn new(
|
|
|
|
physical_resolution: Vec2<u32>,
|
|
|
|
scale_factor: f64,
|
|
|
|
mode: ScaleMode,
|
|
|
|
extra_factor: f64,
|
|
|
|
) -> Self {
|
2019-04-26 04:29:35 +00:00
|
|
|
Scale {
|
|
|
|
mode,
|
2020-02-20 23:41:51 +00:00
|
|
|
scale_factor,
|
2021-10-01 01:15:51 +00:00
|
|
|
physical_resolution,
|
2020-10-31 20:04:20 +00:00
|
|
|
extra_factor,
|
2019-04-26 04:29:35 +00:00
|
|
|
}
|
|
|
|
}
|
2020-02-01 20:39:39 +00:00
|
|
|
|
2019-05-17 09:22:32 +00:00
|
|
|
// Change the scaling mode.
|
2020-11-14 01:16:42 +00:00
|
|
|
// Returns false if the mode matches the current mode
|
|
|
|
pub fn set_scaling_mode(&mut self, mode: ScaleMode) -> bool {
|
|
|
|
let old_mode = self.mode;
|
|
|
|
self.mode = mode;
|
|
|
|
old_mode != mode
|
|
|
|
}
|
2020-02-01 20:39:39 +00:00
|
|
|
|
2019-07-26 02:28:53 +00:00
|
|
|
// Get scaling mode transformed into absolute scaling
|
|
|
|
pub fn scaling_mode_as_absolute(&self) -> ScaleMode {
|
|
|
|
ScaleMode::Absolute(self.scale_factor_physical())
|
|
|
|
}
|
2020-02-01 20:39:39 +00:00
|
|
|
|
|
|
|
// Get scaling mode transformed to be relative to the window with the same
|
|
|
|
// aspect ratio as the current window
|
2019-07-26 02:28:53 +00:00
|
|
|
pub fn scaling_mode_as_relative(&self) -> ScaleMode {
|
2021-10-01 01:15:51 +00:00
|
|
|
ScaleMode::RelativeToWindow(self.scaled_resolution())
|
2019-07-26 02:28:53 +00:00
|
|
|
}
|
2020-02-01 20:39:39 +00:00
|
|
|
|
2021-10-01 01:15:51 +00:00
|
|
|
/// Calculate factor to transform between physical coordinates and our
|
|
|
|
/// scaled coordinates.
|
|
|
|
/// Multiply by scaled coordinates to get the physical coordinates
|
|
|
|
pub fn scale_factor_physical(&self) -> f64 {
|
2020-10-31 20:04:20 +00:00
|
|
|
self.extra_factor
|
|
|
|
* match self.mode {
|
2021-10-01 01:15:51 +00:00
|
|
|
ScaleMode::Absolute(scale) => scale,
|
|
|
|
ScaleMode::DpiFactor => 1.0 * self.scale_factor,
|
|
|
|
ScaleMode::RelativeToWindow(dims) => (f64::from(self.physical_resolution.x)
|
|
|
|
/ dims.x)
|
|
|
|
.min(f64::from(self.physical_resolution.y) / dims.y),
|
2020-10-31 20:04:20 +00:00
|
|
|
}
|
2019-04-26 04:29:35 +00:00
|
|
|
}
|
2020-02-01 20:39:39 +00:00
|
|
|
|
2021-10-01 01:15:51 +00:00
|
|
|
/// Calculate factor to transform between logical coordinates and our scaled
|
|
|
|
/// coordinates.
|
|
|
|
/// Multiply by scaled coordinates to get the logical coordinates
|
|
|
|
///
|
|
|
|
/// Used to scale coordinates from window events (e.g. the mouse cursor
|
|
|
|
/// position)
|
|
|
|
pub fn scale_factor_logical(&self) -> f64 { self.scale_factor_physical() / self.scale_factor }
|
2020-02-01 20:39:39 +00:00
|
|
|
|
2020-11-13 04:39:47 +00:00
|
|
|
/// Updates window size
|
|
|
|
/// Returns true if the value was changed
|
2021-10-01 01:15:51 +00:00
|
|
|
pub fn surface_resized(&mut self, new_res: Vec2<u32>) -> bool {
|
|
|
|
let old_res = self.physical_resolution;
|
|
|
|
self.physical_resolution = new_res;
|
|
|
|
old_res != self.physical_resolution
|
2020-11-13 04:39:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Updates scale factor
|
|
|
|
/// Returns true if the value was changed
|
|
|
|
pub fn scale_factor_changed(&mut self, scale_factor: f64) -> bool {
|
|
|
|
let old_scale_factor = self.scale_factor;
|
|
|
|
self.scale_factor = scale_factor;
|
|
|
|
old_scale_factor != self.scale_factor
|
2019-04-26 04:29:35 +00:00
|
|
|
}
|
2020-02-01 20:39:39 +00:00
|
|
|
|
2021-10-04 19:51:36 +00:00
|
|
|
/// Get physical resolution.
|
|
|
|
pub fn physical_resolution(&self) -> Vec2<u32> { self.physical_resolution }
|
|
|
|
|
2020-10-31 20:04:20 +00:00
|
|
|
/// Get scaled window size.
|
2021-10-01 01:15:51 +00:00
|
|
|
pub fn scaled_resolution(&self) -> Vec2<f64> {
|
|
|
|
self.physical_resolution.map(f64::from) / self.scale_factor_physical()
|
|
|
|
}
|
2020-11-13 04:39:47 +00:00
|
|
|
|
2019-05-17 09:22:32 +00:00
|
|
|
// Transform point from logical to scaled coordinates.
|
2020-02-01 20:39:39 +00:00
|
|
|
pub fn scale_point(&self, point: Vec2<f64>) -> Vec2<f64> { point / self.scale_factor_logical() }
|
2019-04-26 04:29:35 +00:00
|
|
|
}
|