1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
use super::{parts::*, *}; use crate::uses::{math::*, GL::font::Font, GL::window::*, *}; #[derive(Default)] pub struct Theme { pub easing: f32, pub bg: Color, pub bg_focus: Color, pub fg: Color, pub fg_focus: Color, pub highlight: Color, pub text: Color, pub text_focus: Color, pub text_highlight: Color, pub font: Font, pub font_size: f32, } pub fn hex_to_rgba(c: u32) -> Color { Color::to(((c & 0xff000000) >> 24, (c & 0xff0000) >> 16, (c & 0xff00) >> 8, c & 0xff)).div(255) } impl Renderer { pub fn new(t: Theme) -> Self { let s = Self::default(); s.set_theme(t); s } pub fn set_theme(&self, t: Theme) { ASSERT!(borrow_map().is_empty(), "Cannot change theme mid-draw"); *theme() = t; } } pub trait GuiStorage { fn storage(id: u32) -> &'static mut Self; } impl GuiStorage for Button { fn storage(id: u32) -> &'static mut Self { UnsafeOnce!(HashMap<u32, Button>, { HashMap::new() }).entry(id).or_default() } } impl GuiStorage for Label { fn storage(id: u32) -> &'static mut Self { UnsafeOnce!(HashMap<u32, Label>, { HashMap::new() }).entry(id).or_default() } } impl GuiStorage for Layout { fn storage(id: u32) -> &'static mut Self { UnsafeOnce!(HashMap<u32, Layout>, { HashMap::new() }).entry(id).or_default() } } impl GuiStorage for LineEdit { fn storage(id: u32) -> &'static mut Self { UnsafeOnce!(HashMap<u32, LineEdit>, { HashMap::new() }).entry(id).or_default() } } impl GuiStorage for Selector { fn storage(id: u32) -> &'static mut Self { UnsafeOnce!(HashMap<u32, Selector>, { HashMap::new() }).entry(id).or_default() } } impl GuiStorage for Slider { fn storage(id: u32) -> &'static mut Self { UnsafeOnce!(HashMap<u32, Slider>, { HashMap::new() }).entry(id).or_default() } } impl GuiStorage for TextEdit { fn storage(id: u32) -> &'static mut Self { UnsafeOnce!(HashMap<u32, TextEdit>, { HashMap::new() }).entry(id).or_default() } } impl<'l> RenderLock<'l> { pub fn Button(&mut self, id: u32, pos: Vec2, size: Vec2, text: &str) -> bool { check_borrow(id); Button::storage(id).draw(self, t(), pos, size, text) } pub fn Label(&mut self, id: u32, pos: Vec2, size: Vec2, text: &str) { check_borrow(id); Label::storage(id).draw(self, t(), pos, size, text) } pub fn Layout<F: FnOnce(&mut RenderLock<'l>, Crop)>(&mut self, id: u32, content: F) { check_borrow(id); Layout::storage(id).draw(self, t(), content) } pub fn LineEdit(&mut self, id: u32, pos: Vec2, size: Vec2) { check_borrow(id); LineEdit::storage(id).draw(self, t(), pos, size) } pub fn Selector(&mut self, id: u32, pos: Vec2, size: Vec2, options: &'l mut [String]) -> usize { check_borrow(id); Selector::storage(id).draw(self, t(), pos, size, options) } pub fn Slider(&mut self, id: u32, pos: Vec2, size: Vec2, pip_size: f32) -> f32 { check_borrow(id); Slider::storage(id).draw(self, t(), pos, size, pip_size) } pub fn TextEdit(&mut self, id: u32, pos: Vec2, size: Vec2, scale: f32) { check_borrow(id); TextEdit::storage(id).draw(self, t(), pos, size, scale, false) } pub fn TextList(&mut self, id: u32, pos: Vec2, size: Vec2, scale: f32) { check_borrow(id); TextEdit::storage(id).draw(self, t(), pos, size, scale, true) } pub fn clipboard() -> &'l str { let (str, _) = clip_store(); str } pub fn set_clipboard(s: &str) { *clip_store() = (s.into(), true); } pub fn sync_clipboard(&self, w: &mut Window) { let (str, changed) = clip_store(); if *changed { w.set_clipboard(str); *changed = false; } } } pub fn borrow_map() -> &'static mut HashSet<u32> { UnsafeOnce!(HashSet<u32>, { HashSet::new() }) } fn check_borrow(id: u32) { ASSERT!( borrow_map().get(&id).is_none(), "An element `{}' cannot be drawn more than once per frame", chksum::collision_map().get(&id).unwrap() ); borrow_map().insert(id); } fn clip_store() -> &'static mut (String, bool) { UnsafeOnce!((String, bool), { ("".into(), false) }) } fn theme() -> &'static mut Theme { UnsafeOnce!(Theme, { Def() }) } fn t() -> &'static Theme { let t = theme(); ASSERT!(!t.font.glyphs.is_empty(), "No theme set for gui"); t }