Support multiple fonts
This commit is contained in:
parent
1b8a45a514
commit
ca9333ec3e
Binary file not shown.
|
|
@ -1,7 +1,6 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
font::Font,
|
|
||||||
layout,
|
layout,
|
||||||
layout::{LayoutOptions, Region},
|
layout::{LayoutOptions, Region},
|
||||||
style,
|
style,
|
||||||
|
|
@ -48,20 +47,27 @@ pub struct Emigui {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Emigui {
|
impl Emigui {
|
||||||
pub fn new(font: Arc<Font>) -> Emigui {
|
pub fn new() -> Emigui {
|
||||||
|
let data = Arc::new(layout::Data::new());
|
||||||
|
let fonts = data.fonts.clone();
|
||||||
Emigui {
|
Emigui {
|
||||||
last_input: Default::default(),
|
last_input: Default::default(),
|
||||||
data: Arc::new(layout::Data::new(font.clone())),
|
data,
|
||||||
style: Default::default(),
|
style: Default::default(),
|
||||||
painter: Painter::new(font),
|
painter: Painter::new(fonts),
|
||||||
stats: Default::default(),
|
stats: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn texture(&self) -> (u16, u16, &[u8]) {
|
||||||
|
self.data.fonts.texture()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new_frame(&mut self, new_input: RawInput) {
|
pub fn new_frame(&mut self, new_input: RawInput) {
|
||||||
let gui_input = GuiInput::from_last_and_new(&self.last_input, &new_input);
|
let gui_input = GuiInput::from_last_and_new(&self.last_input, &new_input);
|
||||||
self.last_input = new_input;
|
self.last_input = new_input;
|
||||||
|
|
||||||
|
// TODO: avoid this clone
|
||||||
let mut new_data = (*self.data).clone();
|
let mut new_data = (*self.data).clone();
|
||||||
new_data.new_frame(gui_input);
|
new_data.new_frame(gui_input);
|
||||||
self.data = Arc::new(new_data);
|
self.data = Arc::new(new_data);
|
||||||
|
|
|
||||||
|
|
@ -64,12 +64,8 @@ pub struct Font {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Font {
|
impl Font {
|
||||||
pub fn new(scale: usize, atlas: Arc<Mutex<TextureAtlas>>) -> Font {
|
pub fn new(atlas: Arc<Mutex<TextureAtlas>>, font_data: &'static [u8], scale: usize) -> Font {
|
||||||
// TODO: figure out a way to make the wasm smaller despite including a font.
|
let font = rusttype::Font::from_bytes(font_data).expect("Error constructing Font");
|
||||||
// let font_data = include_bytes!("../fonts/ProggyClean.ttf"); // Use 13 for this. NOTHING ELSE.
|
|
||||||
// let font_data = include_bytes!("../fonts/DejaVuSans.ttf");
|
|
||||||
let font_data = include_bytes!("../fonts/Roboto-Regular.ttf");
|
|
||||||
let font = rusttype::Font::from_bytes(font_data as &[u8]).expect("Error constructing Font");
|
|
||||||
|
|
||||||
// println!(
|
// println!(
|
||||||
// "font.v_metrics: {:?}",
|
// "font.v_metrics: {:?}",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
use std::{
|
||||||
|
collections::BTreeMap,
|
||||||
|
sync::{Arc, Mutex},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{font::Font, texture_atlas::TextureAtlas};
|
||||||
|
|
||||||
|
/// TODO: rename
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Serialize)]
|
||||||
|
pub enum TextStyle {
|
||||||
|
Body,
|
||||||
|
Button,
|
||||||
|
Heading,
|
||||||
|
// Monospace,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Fonts {
|
||||||
|
fonts: BTreeMap<TextStyle, Font>,
|
||||||
|
texture: (u16, u16, Vec<u8>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Fonts {
|
||||||
|
pub fn new() -> Fonts {
|
||||||
|
let mut atlas = TextureAtlas::new(128, 8); // TODO: better default?
|
||||||
|
|
||||||
|
// Make one white pixel for use for various stuff:
|
||||||
|
let pos = atlas.allocate((1, 1));
|
||||||
|
atlas[pos] = 255;
|
||||||
|
|
||||||
|
let atlas = Arc::new(Mutex::new(atlas));
|
||||||
|
|
||||||
|
// TODO: figure out a way to make the wasm smaller despite including a font.
|
||||||
|
// let font_data = include_bytes!("../fonts/ProggyClean.ttf"); // Use 13 for this. NOTHING ELSE.
|
||||||
|
// let font_data = include_bytes!("../fonts/DejaVuSans.ttf");
|
||||||
|
let font_data = include_bytes!("../fonts/Roboto-Regular.ttf");
|
||||||
|
|
||||||
|
let mut fonts = BTreeMap::new();
|
||||||
|
fonts.insert(TextStyle::Body, Font::new(atlas.clone(), font_data, 20));
|
||||||
|
fonts.insert(TextStyle::Button, fonts[&TextStyle::Body].clone());
|
||||||
|
fonts.insert(TextStyle::Heading, Font::new(atlas.clone(), font_data, 30));
|
||||||
|
|
||||||
|
let texture = atlas.lock().unwrap().clone().into_texture();
|
||||||
|
|
||||||
|
Fonts { fonts, texture }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn texture(&self) -> (u16, u16, &[u8]) {
|
||||||
|
(self.texture.0, self.texture.1, &self.texture.2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::Index<TextStyle> for Fonts {
|
||||||
|
type Output = Font;
|
||||||
|
|
||||||
|
fn index(&self, text_style: TextStyle) -> &Font {
|
||||||
|
&self.fonts[&text_style]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,7 +5,8 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
font::{Font, TextFragment},
|
font::TextFragment,
|
||||||
|
fonts::{Fonts, TextStyle},
|
||||||
math::*,
|
math::*,
|
||||||
types::*,
|
types::*,
|
||||||
widgets::{label, Widget},
|
widgets::{label, Widget},
|
||||||
|
|
@ -143,7 +144,7 @@ impl GraphicLayers {
|
||||||
pub struct Data {
|
pub struct Data {
|
||||||
/// The default options for new regions
|
/// The default options for new regions
|
||||||
pub(crate) options: Mutex<LayoutOptions>,
|
pub(crate) options: Mutex<LayoutOptions>,
|
||||||
pub(crate) font: Arc<Font>,
|
pub(crate) fonts: Arc<Fonts>,
|
||||||
pub(crate) input: GuiInput,
|
pub(crate) input: GuiInput,
|
||||||
pub(crate) memory: Mutex<Memory>,
|
pub(crate) memory: Mutex<Memory>,
|
||||||
pub(crate) graphics: Mutex<GraphicLayers>,
|
pub(crate) graphics: Mutex<GraphicLayers>,
|
||||||
|
|
@ -153,7 +154,7 @@ impl Clone for Data {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Data {
|
Data {
|
||||||
options: Mutex::new(self.options()),
|
options: Mutex::new(self.options()),
|
||||||
font: self.font.clone(),
|
fonts: self.fonts.clone(),
|
||||||
input: self.input.clone(),
|
input: self.input.clone(),
|
||||||
memory: Mutex::new(self.memory.lock().unwrap().clone()),
|
memory: Mutex::new(self.memory.lock().unwrap().clone()),
|
||||||
graphics: Mutex::new(self.graphics.lock().unwrap().clone()),
|
graphics: Mutex::new(self.graphics.lock().unwrap().clone()),
|
||||||
|
|
@ -162,10 +163,10 @@ impl Clone for Data {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Data {
|
impl Data {
|
||||||
pub fn new(font: Arc<Font>) -> Data {
|
pub fn new() -> Data {
|
||||||
Data {
|
Data {
|
||||||
options: Default::default(),
|
options: Default::default(),
|
||||||
font,
|
fonts: Arc::new(Fonts::new()),
|
||||||
input: Default::default(),
|
input: Default::default(),
|
||||||
memory: Default::default(),
|
memory: Default::default(),
|
||||||
graphics: Default::default(),
|
graphics: Default::default(),
|
||||||
|
|
@ -277,8 +278,8 @@ impl Region {
|
||||||
self.cursor
|
self.cursor
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn font(&self) -> &Font {
|
pub fn fonts(&self) -> &Fonts {
|
||||||
&*self.data.font
|
&*self.data.fonts
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn width(&self) -> f32 {
|
pub fn width(&self) -> f32 {
|
||||||
|
|
@ -299,7 +300,9 @@ impl Region {
|
||||||
);
|
);
|
||||||
let text: String = text.into();
|
let text: String = text.into();
|
||||||
let id = self.make_child_id(&text);
|
let id = self.make_child_id(&text);
|
||||||
let (text, text_size) = self.font().layout_multiline(&text, self.width());
|
let text_style = TextStyle::Heading;
|
||||||
|
let font = &self.fonts()[text_style];
|
||||||
|
let (text, text_size) = font.layout_multiline(&text, self.width());
|
||||||
let text_cursor = self.cursor + self.options().button_padding;
|
let text_cursor = self.cursor + self.options().button_padding;
|
||||||
let (rect, interact) = self.reserve_space(
|
let (rect, interact) = self.reserve_space(
|
||||||
vec2(
|
vec2(
|
||||||
|
|
@ -328,6 +331,7 @@ impl Region {
|
||||||
});
|
});
|
||||||
self.add_text(
|
self.add_text(
|
||||||
text_cursor + vec2(self.options().start_icon_width, 0.0),
|
text_cursor + vec2(self.options().start_icon_width, 0.0),
|
||||||
|
text_style,
|
||||||
text,
|
text,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -504,11 +508,11 @@ impl Region {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_text(&mut self, pos: Vec2, text: Vec<TextFragment>) {
|
pub fn add_text(&mut self, pos: Vec2, text_style: TextStyle, text: Vec<TextFragment>) {
|
||||||
for fragment in text {
|
for fragment in text {
|
||||||
self.add_graphic(GuiCmd::Text {
|
self.add_graphic(GuiCmd::Text {
|
||||||
pos: pos + vec2(0.0, fragment.y_offset),
|
pos: pos + vec2(0.0, fragment.y_offset),
|
||||||
style: TextStyle::Label,
|
text_style,
|
||||||
text: fragment.text,
|
text: fragment.text,
|
||||||
x_offsets: fragment.x_offsets,
|
x_offsets: fragment.x_offsets,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ extern crate serde_derive;
|
||||||
|
|
||||||
mod emigui;
|
mod emigui;
|
||||||
mod font;
|
mod font;
|
||||||
|
mod fonts;
|
||||||
mod layout;
|
mod layout;
|
||||||
pub mod math;
|
pub mod math;
|
||||||
mod painter;
|
mod painter;
|
||||||
|
|
@ -18,11 +19,10 @@ pub mod widgets;
|
||||||
|
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
emigui::Emigui,
|
emigui::Emigui,
|
||||||
font::Font,
|
fonts::TextStyle,
|
||||||
layout::LayoutOptions,
|
layout::LayoutOptions,
|
||||||
layout::Region,
|
layout::Region,
|
||||||
painter::{Frame, Painter, Vertex},
|
painter::{Frame, Painter, Vertex},
|
||||||
style::Style,
|
style::Style,
|
||||||
texture_atlas::TextureAtlas,
|
|
||||||
types::RawInput,
|
types::RawInput,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ const AA_SIZE: f32 = 1.0;
|
||||||
|
|
||||||
/// Outputs render info in a format suitable for e.g. OpenGL.
|
/// Outputs render info in a format suitable for e.g. OpenGL.
|
||||||
use crate::{
|
use crate::{
|
||||||
font::Font,
|
fonts::Fonts,
|
||||||
math::{remap, vec2, Vec2, TAU},
|
math::{remap, vec2, Vec2, TAU},
|
||||||
types::{Color, PaintCmd},
|
types::{Color, PaintCmd},
|
||||||
};
|
};
|
||||||
|
|
@ -193,12 +193,12 @@ impl Frame {
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Painter {
|
pub struct Painter {
|
||||||
font: Arc<Font>,
|
fonts: Arc<Fonts>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Painter {
|
impl Painter {
|
||||||
pub fn new(font: Arc<Font>) -> Painter {
|
pub fn new(fonts: Arc<Fonts>) -> Painter {
|
||||||
Painter { font }
|
Painter { fonts }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn paint(&self, commands: &[PaintCmd]) -> Frame {
|
pub fn paint(&self, commands: &[PaintCmd]) -> Frame {
|
||||||
|
|
@ -336,10 +336,12 @@ impl Painter {
|
||||||
color,
|
color,
|
||||||
pos,
|
pos,
|
||||||
text,
|
text,
|
||||||
|
text_style,
|
||||||
x_offsets,
|
x_offsets,
|
||||||
} => {
|
} => {
|
||||||
|
let font = &self.fonts[*text_style];
|
||||||
for (c, x_offset) in text.chars().zip(x_offsets.iter()) {
|
for (c, x_offset) in text.chars().zip(x_offsets.iter()) {
|
||||||
if let Some(glyph) = self.font.uv_rect(c) {
|
if let Some(glyph) = font.uv_rect(c) {
|
||||||
let mut top_left = Vertex {
|
let mut top_left = Vertex {
|
||||||
pos: *pos
|
pos: *pos
|
||||||
+ vec2(
|
+ vec2(
|
||||||
|
|
|
||||||
|
|
@ -232,15 +232,14 @@ fn translate_cmd(out_commands: &mut Vec<PaintCmd>, style: &Style, cmd: GuiCmd) {
|
||||||
}
|
}
|
||||||
GuiCmd::Text {
|
GuiCmd::Text {
|
||||||
pos,
|
pos,
|
||||||
style: text_style,
|
text_style,
|
||||||
text,
|
text,
|
||||||
x_offsets,
|
x_offsets,
|
||||||
} => {
|
} => {
|
||||||
let color = match text_style {
|
let color = style.text_color();
|
||||||
TextStyle::Label => style.text_color(),
|
|
||||||
};
|
|
||||||
out_commands.push(PaintCmd::Text {
|
out_commands.push(PaintCmd::Text {
|
||||||
color,
|
color,
|
||||||
|
text_style,
|
||||||
pos,
|
pos,
|
||||||
text,
|
text,
|
||||||
x_offsets,
|
x_offsets,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
use crate::math::{Rect, Vec2};
|
use crate::{
|
||||||
|
fonts::TextStyle,
|
||||||
|
math::{Rect, Vec2},
|
||||||
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -88,12 +91,6 @@ pub struct InteractInfo {
|
||||||
pub active: bool,
|
pub active: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Serialize)]
|
|
||||||
#[serde(rename_all = "snake_case")]
|
|
||||||
pub enum TextStyle {
|
|
||||||
Label,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize)]
|
#[derive(Clone, Debug, Serialize)]
|
||||||
pub enum GuiCmd {
|
pub enum GuiCmd {
|
||||||
PaintCommands(Vec<PaintCmd>),
|
PaintCommands(Vec<PaintCmd>),
|
||||||
|
|
@ -130,7 +127,7 @@ pub enum GuiCmd {
|
||||||
/// The text should be vertically centered at the given position.
|
/// The text should be vertically centered at the given position.
|
||||||
Text {
|
Text {
|
||||||
pos: Vec2,
|
pos: Vec2,
|
||||||
style: TextStyle,
|
text_style: TextStyle,
|
||||||
text: String,
|
text: String,
|
||||||
/// Start each character in the text, as offset from pos.
|
/// Start each character in the text, as offset from pos.
|
||||||
x_offsets: Vec<f32>,
|
x_offsets: Vec<f32>,
|
||||||
|
|
@ -179,6 +176,7 @@ pub enum PaintCmd {
|
||||||
/// Top left corner of the first character.
|
/// Top left corner of the first character.
|
||||||
pos: Vec2,
|
pos: Vec2,
|
||||||
text: String,
|
text: String,
|
||||||
|
text_style: TextStyle,
|
||||||
/// Start each character in the text, as offset from pos.
|
/// Start each character in the text, as offset from pos.
|
||||||
x_offsets: Vec<f32>,
|
x_offsets: Vec<f32>,
|
||||||
// TODO: font info
|
// TODO: font info
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
|
fonts::TextStyle,
|
||||||
layout::{make_id, GuiResponse, Id, Region},
|
layout::{make_id, GuiResponse, Id, Region},
|
||||||
math::{remap_clamp, vec2, Vec2},
|
math::{remap_clamp, vec2, Vec2},
|
||||||
types::GuiCmd,
|
types::GuiCmd,
|
||||||
|
|
@ -15,11 +16,20 @@ pub trait Widget {
|
||||||
|
|
||||||
pub struct Label {
|
pub struct Label {
|
||||||
text: String,
|
text: String,
|
||||||
|
text_style: TextStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Label {
|
impl Label {
|
||||||
pub fn new<S: Into<String>>(text: S) -> Self {
|
pub fn new<S: Into<String>>(text: S) -> Self {
|
||||||
Label { text: text.into() }
|
Label {
|
||||||
|
text: text.into(),
|
||||||
|
text_style: TextStyle::Body,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn text_style(mut self, text_style: TextStyle) -> Self {
|
||||||
|
self.text_style = text_style;
|
||||||
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -29,8 +39,9 @@ pub fn label<S: Into<String>>(text: S) -> Label {
|
||||||
|
|
||||||
impl Widget for Label {
|
impl Widget for Label {
|
||||||
fn add_to(self, region: &mut Region) -> GuiResponse {
|
fn add_to(self, region: &mut Region) -> GuiResponse {
|
||||||
let (text, text_size) = region.font().layout_multiline(&self.text, region.width());
|
let font = ®ion.fonts()[self.text_style];
|
||||||
region.add_text(region.cursor(), text);
|
let (text, text_size) = font.layout_multiline(&self.text, region.width());
|
||||||
|
region.add_text(region.cursor(), self.text_style, text);
|
||||||
let (_, interact) = region.reserve_space(text_size, None);
|
let (_, interact) = region.reserve_space(text_size, None);
|
||||||
region.response(interact)
|
region.response(interact)
|
||||||
}
|
}
|
||||||
|
|
@ -51,12 +62,14 @@ impl Button {
|
||||||
impl Widget for Button {
|
impl Widget for Button {
|
||||||
fn add_to(self, region: &mut Region) -> GuiResponse {
|
fn add_to(self, region: &mut Region) -> GuiResponse {
|
||||||
let id = region.make_child_id(&self.text);
|
let id = region.make_child_id(&self.text);
|
||||||
let (text, text_size) = region.font().layout_multiline(&self.text, region.width());
|
let text_style = TextStyle::Button;
|
||||||
|
let font = ®ion.fonts()[text_style];
|
||||||
|
let (text, text_size) = font.layout_multiline(&self.text, region.width());
|
||||||
let text_cursor = region.cursor() + region.options().button_padding;
|
let text_cursor = region.cursor() + region.options().button_padding;
|
||||||
let (rect, interact) =
|
let (rect, interact) =
|
||||||
region.reserve_space(text_size + 2.0 * region.options().button_padding, Some(id));
|
region.reserve_space(text_size + 2.0 * region.options().button_padding, Some(id));
|
||||||
region.add_graphic(GuiCmd::Button { interact, rect });
|
region.add_graphic(GuiCmd::Button { interact, rect });
|
||||||
region.add_text(text_cursor, text);
|
region.add_text(text_cursor, text_style, text);
|
||||||
region.response(interact)
|
region.response(interact)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -81,7 +94,9 @@ impl<'a> Checkbox<'a> {
|
||||||
impl<'a> Widget for Checkbox<'a> {
|
impl<'a> Widget for Checkbox<'a> {
|
||||||
fn add_to(self, region: &mut Region) -> GuiResponse {
|
fn add_to(self, region: &mut Region) -> GuiResponse {
|
||||||
let id = region.make_child_id(&self.text);
|
let id = region.make_child_id(&self.text);
|
||||||
let (text, text_size) = region.font().layout_multiline(&self.text, region.width());
|
let text_style = TextStyle::Button;
|
||||||
|
let font = ®ion.fonts()[text_style];
|
||||||
|
let (text, text_size) = font.layout_multiline(&self.text, region.width());
|
||||||
let text_cursor = region.cursor()
|
let text_cursor = region.cursor()
|
||||||
+ region.options().button_padding
|
+ region.options().button_padding
|
||||||
+ vec2(region.options().start_icon_width, 0.0);
|
+ vec2(region.options().start_icon_width, 0.0);
|
||||||
|
|
@ -100,7 +115,7 @@ impl<'a> Widget for Checkbox<'a> {
|
||||||
interact,
|
interact,
|
||||||
rect,
|
rect,
|
||||||
});
|
});
|
||||||
region.add_text(text_cursor, text);
|
region.add_text(text_cursor, text_style, text);
|
||||||
region.response(interact)
|
region.response(interact)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -129,7 +144,9 @@ pub fn radio<S: Into<String>>(checked: bool, text: S) -> RadioButton {
|
||||||
impl Widget for RadioButton {
|
impl Widget for RadioButton {
|
||||||
fn add_to(self, region: &mut Region) -> GuiResponse {
|
fn add_to(self, region: &mut Region) -> GuiResponse {
|
||||||
let id = region.make_child_id(&self.text);
|
let id = region.make_child_id(&self.text);
|
||||||
let (text, text_size) = region.font().layout_multiline(&self.text, region.width());
|
let text_style = TextStyle::Button;
|
||||||
|
let font = ®ion.fonts()[text_style];
|
||||||
|
let (text, text_size) = font.layout_multiline(&self.text, region.width());
|
||||||
let text_cursor = region.cursor()
|
let text_cursor = region.cursor()
|
||||||
+ region.options().button_padding
|
+ region.options().button_padding
|
||||||
+ vec2(region.options().start_icon_width, 0.0);
|
+ vec2(region.options().start_icon_width, 0.0);
|
||||||
|
|
@ -145,7 +162,7 @@ impl Widget for RadioButton {
|
||||||
interact,
|
interact,
|
||||||
rect,
|
rect,
|
||||||
});
|
});
|
||||||
region.add_text(text_cursor, text);
|
region.add_text(text_cursor, text_style, text);
|
||||||
region.response(interact)
|
region.response(interact)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -187,6 +204,9 @@ impl<'a> Slider<'a> {
|
||||||
|
|
||||||
impl<'a> Widget for Slider<'a> {
|
impl<'a> Widget for Slider<'a> {
|
||||||
fn add_to(self, region: &mut Region) -> GuiResponse {
|
fn add_to(self, region: &mut Region) -> GuiResponse {
|
||||||
|
let text_style = TextStyle::Button;
|
||||||
|
let font = ®ion.fonts()[text_style];
|
||||||
|
|
||||||
if let Some(text) = &self.text {
|
if let Some(text) = &self.text {
|
||||||
let text_on_top = self.text_on_top.unwrap_or_default();
|
let text_on_top = self.text_on_top.unwrap_or_default();
|
||||||
let full_text = format!("{}: {:.3}", text, self.value);
|
let full_text = format!("{}: {:.3}", text, self.value);
|
||||||
|
|
@ -196,8 +216,8 @@ impl<'a> Widget for Slider<'a> {
|
||||||
naked.text = None;
|
naked.text = None;
|
||||||
|
|
||||||
if text_on_top {
|
if text_on_top {
|
||||||
let (text, text_size) = region.font().layout_multiline(&full_text, region.width());
|
let (text, text_size) = font.layout_multiline(&full_text, region.width());
|
||||||
region.add_text(region.cursor(), text);
|
region.add_text(region.cursor(), text_style, text);
|
||||||
region.reserve_space_inner(text_size);
|
region.reserve_space_inner(text_size);
|
||||||
naked.add_to(region)
|
naked.add_to(region)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -215,7 +235,7 @@ impl<'a> Widget for Slider<'a> {
|
||||||
let (slider_rect, interact) = region.reserve_space(
|
let (slider_rect, interact) = region.reserve_space(
|
||||||
Vec2 {
|
Vec2 {
|
||||||
x: region.available_space.x,
|
x: region.available_space.x,
|
||||||
y: region.data.font.line_spacing(),
|
y: font.line_spacing(),
|
||||||
},
|
},
|
||||||
id,
|
id,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use emigui::{math::*, types::*, widgets::*, Region};
|
use emigui::{math::*, types::*, widgets::*, Region, TextStyle};
|
||||||
|
|
||||||
pub struct App {
|
pub struct App {
|
||||||
checked: bool,
|
checked: bool,
|
||||||
|
|
@ -25,6 +25,7 @@ impl Default for App {
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
pub fn show_gui(&mut self, gui: &mut Region) {
|
pub fn show_gui(&mut self, gui: &mut Region) {
|
||||||
|
gui.add(label("Emigui").text_style(TextStyle::Heading));
|
||||||
gui.add(label("Emigui is an Immediate mode GUI written in Rust, compiled to WebAssembly, rendered with WebGL."));
|
gui.add(label("Emigui is an Immediate mode GUI written in Rust, compiled to WebAssembly, rendered with WebGL."));
|
||||||
|
|
||||||
gui.add(label(format!(
|
gui.add(label(format!(
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,7 @@ extern crate wasm_bindgen;
|
||||||
|
|
||||||
extern crate emigui;
|
extern crate emigui;
|
||||||
|
|
||||||
use std::sync::{Arc, Mutex};
|
use emigui::{widgets::label, Emigui, RawInput};
|
||||||
|
|
||||||
use emigui::{widgets::label, Emigui, Font, RawInput, TextureAtlas};
|
|
||||||
|
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
|
@ -32,20 +30,8 @@ pub struct State {
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
fn new(canvas_id: &str) -> Result<State, JsValue> {
|
fn new(canvas_id: &str) -> Result<State, JsValue> {
|
||||||
let mut atlas = TextureAtlas::new(128, 8); // TODO: better default?
|
let emigui = Emigui::new();
|
||||||
|
let webgl_painter = webgl::Painter::new(canvas_id, emigui.texture())?;
|
||||||
// Make one white pixel for use for various stuff:
|
|
||||||
let pos = atlas.allocate((1, 1));
|
|
||||||
atlas[pos] = 255;
|
|
||||||
|
|
||||||
let atlas = Arc::new(Mutex::new(atlas));
|
|
||||||
|
|
||||||
let font = Arc::new(Font::new(20, atlas.clone()));
|
|
||||||
|
|
||||||
let texture = atlas.lock().unwrap().clone().into_texture();
|
|
||||||
|
|
||||||
let emigui = Emigui::new(font);
|
|
||||||
let webgl_painter = webgl::Painter::new(canvas_id, texture)?;
|
|
||||||
Ok(State {
|
Ok(State {
|
||||||
app: Default::default(),
|
app: Default::default(),
|
||||||
emigui,
|
emigui,
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ impl Painter {
|
||||||
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
canvas_id: &str,
|
canvas_id: &str,
|
||||||
(tex_width, tex_height, pixels): (u16, u16, Vec<u8>),
|
(tex_width, tex_height, pixels): (u16, u16, &[u8]),
|
||||||
) -> Result<Painter, JsValue> {
|
) -> Result<Painter, JsValue> {
|
||||||
let document = web_sys::window().unwrap().document().unwrap();
|
let document = web_sys::window().unwrap().document().unwrap();
|
||||||
let canvas = document.get_element_by_id(canvas_id).unwrap();
|
let canvas = document.get_element_by_id(canvas_id).unwrap();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue