diff --git a/Cargo.toml b/Cargo.toml index 7c99461f..2d63fbda 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,10 +6,3 @@ members = [ "example_glium", "example_wasm", ] - -# Optimize for small code size: -[profile.dev] -opt-level = "s" - -[profile.release] -opt-level = "s" diff --git a/emigui/src/color.rs b/emigui/src/color.rs new file mode 100644 index 00000000..24c551aa --- /dev/null +++ b/emigui/src/color.rs @@ -0,0 +1,34 @@ +/// 0-255 sRGBA +#[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd, Serialize)] +pub struct Color { + pub r: u8, + pub g: u8, + pub b: u8, + pub a: u8, +} + +impl Color { + pub fn transparent(self) -> Color { + Color { + r: self.r, + g: self.g, + b: self.b, + a: 0, + } + } +} + +pub const fn srgba(r: u8, g: u8, b: u8, a: u8) -> Color { + Color { r, g, b, a } +} + +pub const fn gray(l: u8, a: u8) -> Color { + Color { + r: l, + g: l, + b: l, + a, + } +} + +pub const WHITE: Color = srgba(255, 255, 255, 255); diff --git a/emigui/src/emigui.rs b/emigui/src/emigui.rs index 131944d4..5938d418 100644 --- a/emigui/src/emigui.rs +++ b/emigui/src/emigui.rs @@ -1,12 +1,13 @@ use std::sync::Arc; use crate::{ + color::WHITE, label, layout, layout::{show_popup, Region}, math::{clamp, remap_clamp, vec2}, mesher::{Mesher, Vertex}, style::Style, - types::{Color, GuiInput, PaintCmd}, + types::{GuiInput, PaintCmd}, widgets::*, FontSizes, Fonts, Mesh, RawInput, Texture, }; @@ -54,12 +55,12 @@ fn show_font_texture(texture: &Texture, gui: &mut Region) { let top_left = Vertex { pos: rect.min(), uv: (0, 0), - color: Color::WHITE, + color: WHITE, }; let bottom_right = Vertex { pos: rect.max(), uv: (texture.width as u16 - 1, texture.height as u16 - 1), - color: Color::WHITE, + color: WHITE, }; let mut mesh = Mesh::default(); mesh.add_rect(top_left, bottom_right); @@ -93,12 +94,12 @@ fn show_font_texture(texture: &Texture, gui: &mut Region) { let top_left = Vertex { pos: zoom_rect.min(), uv: ((u - texel_radius) as u16, (v - texel_radius) as u16), - color: Color::WHITE, + color: WHITE, }; let bottom_right = Vertex { pos: zoom_rect.max(), uv: ((u + texel_radius) as u16, (v + texel_radius) as u16), - color: Color::WHITE, + color: WHITE, }; let mut mesh = Mesh::default(); mesh.add_rect(top_left, bottom_right); diff --git a/emigui/src/layout.rs b/emigui/src/layout.rs index 8be6ec3f..5a8d21af 100644 --- a/emigui/src/layout.rs +++ b/emigui/src/layout.rs @@ -5,6 +5,7 @@ use std::{ }; use crate::{ + color::{self, Color}, font::TextFragment, fonts::{Fonts, TextStyle}, math::*, @@ -227,7 +228,7 @@ where corner_radius: 5.0, fill_color: Some(style.background_fill_color()), outline: Some(Outline { - color: gray(255, 255), // TODO + color: color::gray(255, 255), // TODO width: 1.0, }), rect, @@ -315,6 +316,10 @@ impl Region { self.cursor } + pub fn set_align(&mut self, align: Align) { + self.align = align; + } + // ------------------------------------------------------------------------ // Sub-regions: @@ -423,32 +428,43 @@ impl Region { self.reserve_space_without_padding(indent + size); } - /// A left-aligned column on the left - pub fn left_column(&mut self, width: f32) -> Region { + /// Return a sub-region relative to the parent + pub fn relative_region(&mut self, rect: Rect) -> Region { Region { data: self.data.clone(), style: self.style, id: self.id, dir: self.dir, - cursor: self.cursor, - align: Align::Min, + cursor: self.cursor + rect.min(), + align: self.align, bounding_size: vec2(0.0, 0.0), - available_space: vec2(width, self.available_space.y), + available_space: rect.size(), } } - /// A horizontally centered region of the given width. - pub fn centered_column(&mut self, width: f32, align: Align) -> Region { - Region { - data: self.data.clone(), - style: self.style, - id: self.id, - dir: self.dir, - cursor: self.cursor + vec2((self.available_space.x - width) / 2.0, 0.0), - align, - bounding_size: vec2(0.0, 0.0), - available_space: vec2(width, self.available_space.y), - } + /// A column region with a given width. + pub fn column(&mut self, column_position: Align, width: f32) -> Region { + let x = match column_position { + Align::Min => 0.0, + Align::Center => self.available_space.x / 2.0 - width / 2.0, + Align::Max => self.available_space.x - width, + }; + self.relative_region(Rect::from_min_size( + vec2(x, 0.0), + vec2(width, self.available_space.y), + )) + } + + pub fn left_column(&mut self, width: f32) -> Region { + self.column(Align::Min, width) + } + + pub fn centered_column(&mut self, width: f32) -> Region { + self.column(Align::Center, width) + } + + pub fn right_column(&mut self, width: f32) -> Region { + self.column(Align::Max, width) } pub fn inner_layout(&mut self, dir: Direction, align: Align, add_contents: F) diff --git a/emigui/src/lib.rs b/emigui/src/lib.rs index 6f92484e..f4804bd4 100644 --- a/emigui/src/lib.rs +++ b/emigui/src/lib.rs @@ -6,6 +6,7 @@ extern crate serde; #[macro_use] // TODO: get rid of this extern crate serde_derive; +pub mod color; mod emigui; mod font; mod fonts; @@ -18,11 +19,12 @@ pub mod types; pub mod widgets; pub use crate::{ + color::Color, emigui::Emigui, fonts::{FontSizes, Fonts, TextStyle}, layout::{Align, Region}, mesher::{Mesh, Vertex}, style::Style, texture_atlas::Texture, - types::{Color, RawInput}, + types::RawInput, }; diff --git a/emigui/src/math.rs b/emigui/src/math.rs index 446dc9cc..3e700cab 100644 --- a/emigui/src/math.rs +++ b/emigui/src/math.rs @@ -5,8 +5,9 @@ pub struct Vec2 { } impl Vec2 { + #[must_use] pub fn normalized(self) -> Vec2 { - let len = self.x.hypot(self.y); + let len = self.length(); if len <= 0.0 { self } else { @@ -25,6 +26,18 @@ impl Vec2 { pub fn length_sq(self) -> f32 { self.x * self.x + self.y * self.y } + + pub fn dist(a: Vec2, b: Vec2) -> f32 { + (a - b).length() + } + + pub fn dist_sq(a: Vec2, b: Vec2) -> f32 { + (a - b).length_sq() + } + + pub fn angled(angle: f32) -> Vec2 { + vec2(angle.cos(), angle.sin()) + } } impl std::ops::AddAssign for Vec2 { @@ -183,7 +196,11 @@ impl Rect { // ---------------------------------------------------------------------------- -pub fn lerp(min: f32, max: f32, t: f32) -> f32 { +pub fn lerp(min: T, max: T, t: f32) -> T +where + f32: std::ops::Mul, + T: std::ops::Add, +{ (1.0 - t) * min + t * max } @@ -213,4 +230,9 @@ pub fn clamp(x: f32, min: f32, max: f32) -> f32 { } } +/// For t=[0,1], returns [0,1] with a derivate of zero at both ends +pub fn ease_in_ease_out(t: f32) -> f32 { + return 3.0 * t * t - 2.0 * t * t * t; +} + pub const TAU: f32 = 2.0 * std::f32::consts::PI; diff --git a/emigui/src/mesher.rs b/emigui/src/mesher.rs index 575471a8..396ec526 100644 --- a/emigui/src/mesher.rs +++ b/emigui/src/mesher.rs @@ -2,9 +2,10 @@ /// Outputs render info in a format suitable for e.g. OpenGL. use crate::{ + color::Color, fonts::Fonts, math::{remap, vec2, Vec2, TAU}, - types::{Color, PaintCmd}, + types::PaintCmd, }; #[derive(Clone, Copy, Debug, Default, Serialize)] diff --git a/emigui/src/style.rs b/emigui/src/style.rs index ff2f43bd..5a6dff98 100644 --- a/emigui/src/style.rs +++ b/emigui/src/style.rs @@ -1,4 +1,4 @@ -use crate::{math::*, types::*}; +use crate::{color::*, math::*, types::*}; #[derive(Clone, Copy, Debug, Serialize)] pub struct Style { diff --git a/emigui/src/types.rs b/emigui/src/types.rs index 543c9f2b..0fd1ea40 100644 --- a/emigui/src/types.rs +++ b/emigui/src/types.rs @@ -1,4 +1,5 @@ use crate::{ + color::Color, fonts::TextStyle, math::{Rect, Vec2}, mesher::Mesh, @@ -59,43 +60,6 @@ impl GuiInput { // ---------------------------------------------------------------------------- -/// 0-255 sRGBA -#[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd, Serialize)] -pub struct Color { - pub r: u8, - pub g: u8, - pub b: u8, - pub a: u8, -} - -impl Color { - pub const WHITE: Color = srgba(255, 255, 255, 255); - - pub fn transparent(self) -> Color { - Color { - r: self.r, - g: self.g, - b: self.b, - a: 0, - } - } -} - -pub const fn srgba(r: u8, g: u8, b: u8, a: u8) -> Color { - Color { r, g, b, a } -} - -pub const fn gray(l: u8, a: u8) -> Color { - Color { - r: l, - g: l, - b: l, - a, - } -} - -// ---------------------------------------------------------------------------- - #[derive(Clone, Copy, Debug, Default, Serialize)] pub struct InteractInfo { /// The mouse is hovering above this diff --git a/emigui/src/widgets.rs b/emigui/src/widgets.rs index 449cff51..457df985 100644 --- a/emigui/src/widgets.rs +++ b/emigui/src/widgets.rs @@ -1,10 +1,11 @@ #![allow(clippy::new_without_default_derive)] use crate::{ + color::{self, Color}, fonts::TextStyle, layout::{make_id, Align, Direction, GuiResponse, Id, Region}, math::{remap_clamp, vec2, Rect, Vec2}, - types::{gray, Color, Outline, PaintCmd}, + types::{Outline, PaintCmd}, }; // ---------------------------------------------------------------------------- @@ -325,6 +326,11 @@ impl<'a> Slider<'a> { self.text_color = Some(text_color); self } + + pub fn precision(mut self, precision: usize) -> Self { + self.precision = precision; + self + } } impl<'a> Widget for Slider<'a> { @@ -404,7 +410,7 @@ impl<'a> Widget for Slider<'a> { corner_radius: 4.0, fill_color: Some(region.style().background_fill_color()), outline: Some(Outline { - color: gray(200, 255), // TODO + color: color::gray(200, 255), // TODO width: 1.0, }), rect: thin_rect, @@ -479,7 +485,7 @@ impl Widget for Separator { }; region.add_paint_cmd(PaintCmd::Line { points, - color: Color::WHITE, + color: color::WHITE, width: self.line_width, }); region.response(interact) diff --git a/example_glium/src/main.rs b/example_glium/src/main.rs index ee7108dd..4f399cfb 100644 --- a/example_glium/src/main.rs +++ b/example_glium/src/main.rs @@ -68,7 +68,16 @@ fn main() { return glutin::ControlFlow::Break; } } - _ => (), + glutin::WindowEvent::KeyboardInput { input, .. } => { + if input.virtual_keycode == Some(glutin::VirtualKeyCode::Q) + && input.modifiers.logo + { + return glutin::ControlFlow::Break; + } + } + _ => { + // dbg!(event); + } }, _ => (), } diff --git a/example_wasm/src/lib.rs b/example_wasm/src/lib.rs index 8e4b8652..b6efc357 100644 --- a/example_wasm/src/lib.rs +++ b/example_wasm/src/lib.rs @@ -39,7 +39,7 @@ impl State { self.emigui.new_frame(raw_input); let mut region = self.emigui.whole_screen_region(); - let mut region = region.centered_column(region.width().min(480.0), Align::Min); + let mut region = region.centered_column(region.width().min(480.0)); self.app.show_gui(&mut region); self.emigui.example(&mut region);