mod bin;
pub mod checkbox;
pub mod on_off_button;
pub mod scroll_bar;
pub mod slider;
use std::cmp::Reverse;
use std::collections::BTreeMap;
use std::sync::{Arc, Weak};
use parking_lot::{Mutex, RwLock};
use vulkano::buffer::BufferContents;
use vulkano::pipeline::graphics::vertex_input::Vertex;
pub use self::bin::color::Color;
pub use self::bin::style::{
BinPosition, BinStyle, BinStyleError, BinStyleErrorType, BinStyleValidation, BinStyleWarn,
BinStyleWarnType, BinVert, ChildFloatMode, FontStretch, FontStyle, FontWeight, ImageEffect,
TextHoriAlign, TextVertAlign, TextWrap,
};
pub(crate) use self::bin::BinPlacement;
pub use self::bin::{Bin, BinID, BinPostUpdate, OVDPerfMetrics};
use crate::window::WindowID;
use crate::Basalt;
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct DefaultFont {
pub family: Option<String>,
pub weight: Option<FontWeight>,
pub strench: Option<FontStretch>,
pub style: Option<FontStyle>,
}
#[derive(BufferContents, Vertex, Clone, Debug)]
#[repr(C)]
pub(crate) struct ItfVertInfo {
#[format(R32G32B32_SFLOAT)]
pub position: [f32; 3],
#[format(R32G32_SFLOAT)]
pub coords: [f32; 2],
#[format(R32G32B32A32_SFLOAT)]
pub color: [f32; 4],
#[format(R32_SINT)]
pub ty: i32,
#[format(R32_UINT)]
pub tex_i: u32,
}
impl Default for ItfVertInfo {
fn default() -> Self {
ItfVertInfo {
position: [0.0; 3],
coords: [0.0; 2],
color: [0.0; 4],
ty: 0,
tex_i: 0,
}
}
}
pub(crate) fn scale_verts(win_size: &[f32; 2], scale: f32, verts: &mut Vec<ItfVertInfo>) {
for vert in verts {
vert.position[0] *= scale;
vert.position[1] *= scale;
vert.position[0] += win_size[0] / -2.0;
vert.position[0] /= win_size[0] / 2.0;
vert.position[1] += win_size[1] / -2.0;
vert.position[1] /= win_size[1] / 2.0;
}
}
pub struct Interface {
bins_state: RwLock<BinsState>,
default_font: Mutex<DefaultFont>,
binary_fonts: Mutex<Vec<Arc<dyn AsRef<[u8]> + Sync + Send>>>,
}
#[derive(Default)]
struct BinsState {
bst: Option<Arc<Basalt>>,
id: u64,
map: BTreeMap<BinID, Weak<Bin>>,
}
impl Interface {
pub(crate) fn new(binary_fonts: Vec<Arc<dyn AsRef<[u8]> + Sync + Send>>) -> Arc<Self> {
Arc::new(Interface {
bins_state: RwLock::new(BinsState::default()),
default_font: Mutex::new(DefaultFont::default()),
binary_fonts: Mutex::new(binary_fonts),
})
}
pub(crate) fn associate_basalt(&self, basalt: Arc<Basalt>) {
let mut bins_state = self.bins_state.write();
bins_state.bst = Some(basalt);
}
pub(crate) fn binary_fonts(&self) -> Vec<Arc<dyn AsRef<[u8]> + Sync + Send>> {
self.binary_fonts.lock().clone()
}
pub fn default_font(&self) -> DefaultFont {
self.default_font.lock().clone()
}
pub fn set_default_font(&self, default_font: DefaultFont) {
*self.default_font.lock() = default_font.clone();
self.bins_state
.read()
.bst
.as_ref()
.unwrap()
.window_manager_ref()
.set_default_font(default_font);
}
pub fn add_binary_font<T: AsRef<[u8]> + Sync + Send + 'static>(&self, data: T) {
let binary_font = Arc::new(data);
self.binary_fonts.lock().push(binary_font.clone());
self.bins_state
.read()
.bst
.as_ref()
.unwrap()
.window_manager_ref()
.add_binary_font(binary_font);
}
#[inline]
pub fn get_bin_atop(&self, window: WindowID, x: f32, y: f32) -> Option<Arc<Bin>> {
self.get_bins_atop(window, x, y).into_iter().next()
}
pub fn get_bins_atop(&self, window_id: WindowID, mut x: f32, mut y: f32) -> Vec<Arc<Bin>> {
let state = self.bins_state.read();
let window = match state
.bst
.as_ref()
.unwrap()
.window_manager_ref()
.window(window_id)
{
Some(some) => some,
None => return Vec::new(),
};
let effective_scale = window.effective_interface_scale();
x /= effective_scale;
y /= effective_scale;
let mut bins = window
.associated_bins()
.into_iter()
.filter(|bin| bin.mouse_inside(x, y))
.collect::<Vec<_>>();
bins.sort_by_cached_key(|bin| Reverse(bin.post_update().z_index));
bins
}
#[inline]
pub fn get_bin_id_atop(&self, window: WindowID, x: f32, y: f32) -> Option<BinID> {
self.get_bins_atop(window, x, y)
.into_iter()
.next()
.map(|bin| bin.id())
}
#[inline]
pub fn get_bin_ids_atop(&self, window: WindowID, x: f32, y: f32) -> Vec<BinID> {
self.get_bins_atop(window, x, y)
.into_iter()
.map(|bin| bin.id())
.collect()
}
pub fn bins(&self) -> Vec<Arc<Bin>> {
self.bins_state
.read()
.map
.iter()
.filter_map(|(_, b)| b.upgrade())
.collect()
}
pub fn new_bin(&self) -> Arc<Bin> {
self.new_bins(1).pop().unwrap()
}
pub fn new_bins(&self, amt: usize) -> Vec<Arc<Bin>> {
let mut out = Vec::with_capacity(amt);
let mut bins_state = self.bins_state.write();
for _ in 0..amt {
let id = BinID(bins_state.id);
bins_state.id += 1;
let bin = Bin::new(id, bins_state.bst.clone().unwrap());
bins_state.map.insert(id, Arc::downgrade(&bin));
out.push(bin);
}
out
}
pub fn get_bin(&self, id: BinID) -> Option<Arc<Bin>> {
match self.bins_state.read().map.get(&id) {
Some(some) => some.upgrade(),
None => None,
}
}
pub fn mouse_inside(&self, window_id: WindowID, mut x: f32, mut y: f32) -> bool {
let state = self.bins_state.read();
let window = match state
.bst
.as_ref()
.unwrap()
.window_manager_ref()
.window(window_id)
{
Some(some) => some,
None => return false,
};
let effective_scale = window.effective_interface_scale();
x /= effective_scale;
y /= effective_scale;
for bin in window.associated_bins() {
if bin.mouse_inside(x, y) {
return true;
}
}
false
}
}