Enable colored text (and other misc fixes)
This commit is contained in:
parent
4dab7a1504
commit
7f83876005
9 changed files with 104 additions and 82 deletions
|
@ -6,7 +6,7 @@ use crate::{
|
|||
style,
|
||||
types::GuiInput,
|
||||
widgets::*,
|
||||
Frame, Painter, RawInput,
|
||||
Frame, RawInput,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
|
@ -42,19 +42,15 @@ pub struct Emigui {
|
|||
pub last_input: RawInput,
|
||||
pub data: Arc<layout::Data>,
|
||||
pub style: style::Style,
|
||||
pub painter: Painter,
|
||||
stats: Stats,
|
||||
}
|
||||
|
||||
impl Emigui {
|
||||
pub fn new() -> Emigui {
|
||||
let data = Arc::new(layout::Data::new());
|
||||
let fonts = data.fonts.clone();
|
||||
Emigui {
|
||||
last_input: Default::default(),
|
||||
data,
|
||||
data: Arc::new(layout::Data::new()),
|
||||
style: Default::default(),
|
||||
painter: Painter::new(fonts),
|
||||
stats: Default::default(),
|
||||
}
|
||||
}
|
||||
|
@ -90,7 +86,7 @@ impl Emigui {
|
|||
pub fn paint(&mut self) -> Frame {
|
||||
let gui_commands = self.data.graphics.lock().unwrap().drain();
|
||||
let paint_commands = style::into_paint_commands(gui_commands, &self.style);
|
||||
let frame = self.painter.paint(&paint_commands);
|
||||
let frame = Frame::paint(&self.data.fonts, &paint_commands);
|
||||
self.stats.num_vertices = frame.vertices.len();
|
||||
self.stats.num_triangles = frame.indices.len() / 3;
|
||||
frame
|
||||
|
|
|
@ -51,7 +51,7 @@ impl Default for LayoutOptions {
|
|||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// TODO: rename
|
||||
// TODO: rename GuiResponse
|
||||
pub struct GuiResponse {
|
||||
/// The mouse is hovering above this
|
||||
pub hovered: bool,
|
||||
|
@ -181,7 +181,7 @@ impl Clone for Data {
|
|||
Data {
|
||||
options: Mutex::new(self.options()),
|
||||
fonts: self.fonts.clone(),
|
||||
input: self.input.clone(),
|
||||
input: self.input,
|
||||
memory: Mutex::new(self.memory.lock().unwrap().clone()),
|
||||
graphics: Mutex::new(self.graphics.lock().unwrap().clone()),
|
||||
}
|
||||
|
@ -358,6 +358,7 @@ impl Region {
|
|||
text_cursor + vec2(self.options().start_icon_width, 0.0),
|
||||
text_style,
|
||||
text,
|
||||
None,
|
||||
);
|
||||
|
||||
if open {
|
||||
|
@ -475,13 +476,15 @@ impl Region {
|
|||
|
||||
pub fn reserve_space(&mut self, size: Vec2, interaction_id: Option<Id>) -> InteractInfo {
|
||||
let pos = self.reserve_space_without_padding(size + self.options().item_spacing);
|
||||
|
||||
let rect = Rect::from_min_size(pos, size);
|
||||
let mut memory = self.data.memory.lock().unwrap();
|
||||
|
||||
let hovered = rect.contains(self.input().mouse_pos);
|
||||
let is_something_else_active =
|
||||
memory.active_id.is_some() && memory.active_id != interaction_id;
|
||||
|
||||
let hovered = !is_something_else_active && rect.contains(self.input().mouse_pos);
|
||||
let clicked = hovered && self.input().mouse_clicked;
|
||||
let active = if interaction_id.is_some() {
|
||||
let mut memory = self.data.memory.lock().unwrap();
|
||||
if clicked {
|
||||
memory.active_id = interaction_id;
|
||||
}
|
||||
|
@ -543,12 +546,19 @@ impl Region {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn add_text(&mut self, pos: Vec2, text_style: TextStyle, text: Vec<TextFragment>) {
|
||||
pub fn add_text(
|
||||
&mut self,
|
||||
pos: Vec2,
|
||||
text_style: TextStyle,
|
||||
text: Vec<TextFragment>,
|
||||
color: Option<Color>,
|
||||
) {
|
||||
for fragment in text {
|
||||
self.add_graphic(GuiCmd::Text {
|
||||
color,
|
||||
pos: pos + vec2(0.0, fragment.y_offset),
|
||||
text_style,
|
||||
text: fragment.text,
|
||||
text_style,
|
||||
x_offsets: fragment.x_offsets,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ mod font;
|
|||
mod fonts;
|
||||
mod layout;
|
||||
pub mod math;
|
||||
mod painter;
|
||||
mod mesher;
|
||||
mod style;
|
||||
mod texture_atlas;
|
||||
pub mod types;
|
||||
|
@ -21,7 +21,7 @@ pub use crate::{
|
|||
emigui::Emigui,
|
||||
fonts::TextStyle,
|
||||
layout::{Align, LayoutOptions, Region},
|
||||
painter::{Frame, Painter, Vertex},
|
||||
mesher::{Frame, Vertex},
|
||||
style::Style,
|
||||
types::RawInput,
|
||||
};
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
const ANTI_ALIAS: bool = true;
|
||||
const AA_SIZE: f32 = 1.0;
|
||||
|
||||
|
@ -22,7 +20,6 @@ pub struct Vertex {
|
|||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct Frame {
|
||||
pub clear_color: Option<Color>,
|
||||
/// Draw as triangles (i.e. the length is a multiple of three)
|
||||
pub indices: Vec<u32>,
|
||||
pub vertices: Vec<Vertex>,
|
||||
|
@ -189,19 +186,8 @@ impl Frame {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Painter {
|
||||
fonts: Arc<Fonts>,
|
||||
}
|
||||
|
||||
impl Painter {
|
||||
pub fn new(fonts: Arc<Fonts>) -> Painter {
|
||||
Painter { fonts }
|
||||
}
|
||||
|
||||
pub fn paint(&self, commands: &[PaintCmd]) -> Frame {
|
||||
pub fn paint(fonts: &Fonts, commands: &[PaintCmd]) -> Frame {
|
||||
let mut path_points = Vec::new();
|
||||
let mut path_normals = Vec::new();
|
||||
|
||||
|
@ -238,9 +224,6 @@ impl Painter {
|
|||
);
|
||||
}
|
||||
}
|
||||
PaintCmd::Clear { fill_color } => {
|
||||
frame.clear_color = Some(*fill_color);
|
||||
}
|
||||
PaintCmd::Line {
|
||||
points,
|
||||
color,
|
||||
|
@ -338,7 +321,7 @@ impl Painter {
|
|||
text_style,
|
||||
x_offsets,
|
||||
} => {
|
||||
let font = &self.fonts[*text_style];
|
||||
let font = &fonts[*text_style];
|
||||
for (c, x_offset) in text.chars().zip(x_offsets.iter()) {
|
||||
if let Some(glyph) = font.uv_rect(c) {
|
||||
let mut top_left = Vertex {
|
|
@ -129,8 +129,6 @@ fn translate_cmd(out_commands: &mut Vec<PaintCmd>, style: &Style, cmd: GuiCmd) {
|
|||
rect: interact.rect,
|
||||
});
|
||||
|
||||
// TODO: paint a little triangle or arrow or something instead of this
|
||||
|
||||
let (small_icon_rect, _) = style.icon_rectangles(&interact.rect);
|
||||
// Draw a minus:
|
||||
out_commands.push(PaintCmd::Line {
|
||||
|
@ -215,12 +213,13 @@ fn translate_cmd(out_commands: &mut Vec<PaintCmd>, style: &Style, cmd: GuiCmd) {
|
|||
}
|
||||
}
|
||||
GuiCmd::Text {
|
||||
color,
|
||||
pos,
|
||||
text_style,
|
||||
text,
|
||||
text_style,
|
||||
x_offsets,
|
||||
} => {
|
||||
let color = style.text_color();
|
||||
let color = color.unwrap_or_else(|| style.text_color());
|
||||
out_commands.push(PaintCmd::Text {
|
||||
color,
|
||||
text_style,
|
||||
|
@ -237,7 +236,7 @@ fn translate_cmd(out_commands: &mut Vec<PaintCmd>, style: &Style, cmd: GuiCmd) {
|
|||
color: srgba(255, 255, 255, 255), // TODO
|
||||
width: 1.0,
|
||||
}),
|
||||
rect: rect,
|
||||
rect,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@ pub struct TextureAtlas {
|
|||
impl TextureAtlas {
|
||||
pub fn new(width: usize, height: usize) -> Self {
|
||||
TextureAtlas {
|
||||
width: width,
|
||||
height: height,
|
||||
width,
|
||||
height,
|
||||
pixels: vec![0; width * height],
|
||||
..Default::default()
|
||||
}
|
||||
|
|
|
@ -120,13 +120,12 @@ pub enum GuiCmd {
|
|||
min: f32,
|
||||
value: f32,
|
||||
},
|
||||
/// Paint a single line of mono-space text.
|
||||
/// The text should start at the given position and flow to the right.
|
||||
/// The text should be vertically centered at the given position.
|
||||
/// A string of text with a position for each character.
|
||||
Text {
|
||||
color: Option<Color>,
|
||||
pos: Vec2,
|
||||
text_style: TextStyle,
|
||||
text: String,
|
||||
text_style: TextStyle,
|
||||
/// Start each character in the text, as offset from pos.
|
||||
x_offsets: Vec<f32>,
|
||||
},
|
||||
|
@ -153,9 +152,6 @@ pub enum PaintCmd {
|
|||
outline: Option<Outline>,
|
||||
radius: f32,
|
||||
},
|
||||
Clear {
|
||||
fill_color: Color,
|
||||
},
|
||||
Line {
|
||||
points: Vec<Vec2>,
|
||||
color: Color,
|
||||
|
|
|
@ -17,6 +17,7 @@ pub trait Widget {
|
|||
pub struct Label {
|
||||
text: String,
|
||||
text_style: TextStyle,
|
||||
text_color: Option<Color>,
|
||||
}
|
||||
|
||||
impl Label {
|
||||
|
@ -24,6 +25,7 @@ impl Label {
|
|||
Label {
|
||||
text: text.into(),
|
||||
text_style: TextStyle::Body,
|
||||
text_color: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,6 +33,11 @@ impl Label {
|
|||
self.text_style = text_style;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn text_color(mut self, text_color: Color) -> Self {
|
||||
self.text_color = Some(text_color);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn label<S: Into<String>>(text: S) -> Label {
|
||||
|
@ -42,7 +49,7 @@ impl Widget for Label {
|
|||
let font = ®ion.fonts()[self.text_style];
|
||||
let (text, text_size) = font.layout_multiline(&self.text, region.width());
|
||||
let interact = region.reserve_space(text_size, None);
|
||||
region.add_text(interact.rect.min(), self.text_style, text);
|
||||
region.add_text(interact.rect.min(), self.text_style, text, self.text_color);
|
||||
region.response(interact)
|
||||
}
|
||||
}
|
||||
|
@ -51,11 +58,20 @@ impl Widget for Label {
|
|||
|
||||
pub struct Button {
|
||||
text: String,
|
||||
text_color: Option<Color>,
|
||||
}
|
||||
|
||||
impl Button {
|
||||
pub fn new<S: Into<String>>(text: S) -> Self {
|
||||
Button { text: text.into() }
|
||||
Button {
|
||||
text: text.into(),
|
||||
text_color: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn text_color(mut self, text_color: Color) -> Self {
|
||||
self.text_color = Some(text_color);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,7 +85,7 @@ impl Widget for Button {
|
|||
region.reserve_space(text_size + 2.0 * region.options().button_padding, Some(id));
|
||||
let text_cursor = interact.rect.min() + region.options().button_padding;
|
||||
region.add_graphic(GuiCmd::Button { interact });
|
||||
region.add_text(text_cursor, text_style, text);
|
||||
region.add_text(text_cursor, text_style, text, self.text_color);
|
||||
region.response(interact)
|
||||
}
|
||||
}
|
||||
|
@ -80,6 +96,7 @@ impl Widget for Button {
|
|||
pub struct Checkbox<'a> {
|
||||
checked: &'a mut bool,
|
||||
text: String,
|
||||
text_color: Option<Color>,
|
||||
}
|
||||
|
||||
impl<'a> Checkbox<'a> {
|
||||
|
@ -87,8 +104,14 @@ impl<'a> Checkbox<'a> {
|
|||
Checkbox {
|
||||
checked,
|
||||
text: text.into(),
|
||||
text_color: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn text_color(mut self, text_color: Color) -> Self {
|
||||
self.text_color = Some(text_color);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Widget for Checkbox<'a> {
|
||||
|
@ -114,7 +137,7 @@ impl<'a> Widget for Checkbox<'a> {
|
|||
checked: *self.checked,
|
||||
interact,
|
||||
});
|
||||
region.add_text(text_cursor, text_style, text);
|
||||
region.add_text(text_cursor, text_style, text, self.text_color);
|
||||
region.response(interact)
|
||||
}
|
||||
}
|
||||
|
@ -125,6 +148,7 @@ impl<'a> Widget for Checkbox<'a> {
|
|||
pub struct RadioButton {
|
||||
checked: bool,
|
||||
text: String,
|
||||
text_color: Option<Color>,
|
||||
}
|
||||
|
||||
impl RadioButton {
|
||||
|
@ -132,8 +156,14 @@ impl RadioButton {
|
|||
RadioButton {
|
||||
checked,
|
||||
text: text.into(),
|
||||
text_color: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn text_color(mut self, text_color: Color) -> Self {
|
||||
self.text_color = Some(text_color);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn radio<S: Into<String>>(checked: bool, text: S) -> RadioButton {
|
||||
|
@ -160,7 +190,7 @@ impl Widget for RadioButton {
|
|||
checked: self.checked,
|
||||
interact,
|
||||
});
|
||||
region.add_text(text_cursor, text_style, text);
|
||||
region.add_text(text_cursor, text_style, text, self.text_color);
|
||||
region.response(interact)
|
||||
}
|
||||
}
|
||||
|
@ -174,6 +204,7 @@ pub struct Slider<'a> {
|
|||
max: f32,
|
||||
id: Option<Id>,
|
||||
text: Option<String>,
|
||||
text_color: Option<Color>,
|
||||
text_on_top: Option<bool>,
|
||||
}
|
||||
|
||||
|
@ -186,6 +217,7 @@ impl<'a> Slider<'a> {
|
|||
id: None,
|
||||
text: None,
|
||||
text_on_top: None,
|
||||
text_color: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,6 +230,11 @@ impl<'a> Slider<'a> {
|
|||
self.text = Some(text.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn text_color(mut self, text_color: Color) -> Self {
|
||||
self.text_color = Some(text_color);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Widget for Slider<'a> {
|
||||
|
@ -207,8 +244,9 @@ impl<'a> Widget for Slider<'a> {
|
|||
|
||||
if let Some(text) = &self.text {
|
||||
let text_on_top = self.text_on_top.unwrap_or_default();
|
||||
let text_color = self.text_color;
|
||||
let full_text = format!("{}: {:.3}", text, self.value);
|
||||
let id = Some(self.id.unwrap_or(make_id(text)));
|
||||
let id = Some(self.id.unwrap_or_else(|| make_id(text)));
|
||||
let mut naked = self;
|
||||
naked.id = id;
|
||||
naked.text = None;
|
||||
|
@ -216,7 +254,7 @@ impl<'a> Widget for Slider<'a> {
|
|||
if text_on_top {
|
||||
let (text, text_size) = font.layout_multiline(&full_text, region.width());
|
||||
let pos = region.reserve_space_without_padding(text_size);
|
||||
region.add_text(pos, text_style, text);
|
||||
region.add_text(pos, text_style, text, text_color);
|
||||
naked.add_to(region)
|
||||
} else {
|
||||
region.columns(2, |columns| {
|
||||
|
|
|
@ -3,7 +3,7 @@ use emigui::{math::*, types::*, widgets::*, Align, Region, TextStyle};
|
|||
pub struct App {
|
||||
checked: bool,
|
||||
count: i32,
|
||||
selected_alternative: i32,
|
||||
radio: i32,
|
||||
|
||||
size: Vec2,
|
||||
corner_radius: f32,
|
||||
|
@ -14,7 +14,7 @@ impl Default for App {
|
|||
fn default() -> App {
|
||||
App {
|
||||
checked: true,
|
||||
selected_alternative: 0,
|
||||
radio: 0,
|
||||
count: 0,
|
||||
size: vec2(100.0, 50.0),
|
||||
corner_radius: 5.0,
|
||||
|
@ -35,6 +35,11 @@ impl App {
|
|||
gui.input().screen_size.y,
|
||||
)));
|
||||
|
||||
gui.horizontal(Align::Min, |gui| {
|
||||
gui.add(label("Text can have").text_color(srgba(110, 255, 110, 255)));
|
||||
gui.add(label("color").text_color(srgba(128, 140, 255, 255)));
|
||||
});
|
||||
|
||||
gui.add(label("Hover me")).tooltip_text(
|
||||
"This is a multiline tooltip that demonstrates that you can easily add tooltips to any element.\nThis is the second line.\nThis is the third.",
|
||||
);
|
||||
|
@ -42,26 +47,18 @@ impl App {
|
|||
gui.add(Checkbox::new(&mut self.checked, "checkbox"));
|
||||
|
||||
gui.horizontal(Align::Min, |gui| {
|
||||
if gui
|
||||
.add(radio(self.selected_alternative == 0, "First"))
|
||||
.clicked
|
||||
{
|
||||
self.selected_alternative = 0;
|
||||
if gui.add(radio(self.radio == 0, "First")).clicked {
|
||||
self.radio = 0;
|
||||
}
|
||||
if gui
|
||||
.add(radio(self.selected_alternative == 1, "Second"))
|
||||
.clicked
|
||||
{
|
||||
self.selected_alternative = 1;
|
||||
if gui.add(radio(self.radio == 1, "Second")).clicked {
|
||||
self.radio = 1;
|
||||
}
|
||||
if gui
|
||||
.add(radio(self.selected_alternative == 2, "Final"))
|
||||
.clicked
|
||||
{
|
||||
self.selected_alternative = 2;
|
||||
if gui.add(radio(self.radio == 2, "Final")).clicked {
|
||||
self.radio = 2;
|
||||
}
|
||||
});
|
||||
|
||||
gui.horizontal(Align::Min, |gui| {
|
||||
if gui
|
||||
.add(Button::new("Click me"))
|
||||
.tooltip_text("This will just increase a counter.")
|
||||
|
@ -69,8 +66,11 @@ impl App {
|
|||
{
|
||||
self.count += 1;
|
||||
}
|
||||
|
||||
gui.add(label(format!("This is a multiline label.\nThe button have been clicked {} times.\nBelow are more options.", self.count)));
|
||||
gui.add(label(format!(
|
||||
"The button have been clicked {} times",
|
||||
self.count
|
||||
)));
|
||||
});
|
||||
|
||||
gui.foldable("Test box rendering", |gui| {
|
||||
gui.add(Slider::new(&mut self.size.x, 0.0, 500.0).text("width"));
|
||||
|
|
Loading…
Reference in a new issue