Add painter region as example

This commit is contained in:
Emil Ernerfeldt 2020-04-24 18:32:27 +02:00
parent 7459aa60a4
commit 39e17a7562
7 changed files with 105 additions and 23 deletions

View file

@ -31,8 +31,9 @@ pub const fn gray(l: u8, a: u8) -> Color {
}
}
pub const WHITE: Color = srgba(255, 255, 255, 255);
pub const BLACK: Color = srgba(0, 0, 0, 255);
pub const LIGHT_GRAY: Color = srgba(220, 220, 220, 255);
pub const WHITE: Color = srgba(255, 255, 255, 255);
pub const RED: Color = srgba(255, 0, 0, 255);
pub const GREEN: Color = srgba(0, 255, 0, 255);
pub const BLUE: Color = srgba(0, 0, 255, 255);

View file

@ -112,11 +112,6 @@ impl Emigui {
} else {
region.add_label("mouse_pos: None");
}
region.add(label!(
"region cursor: {} x {}",
region.cursor().x,
region.cursor().y,
));
region.add(label!("num_batches: {}", self.stats.num_batches));
region.add(label!("num_vertices: {}", self.stats.num_vertices));
region.add(label!("num_triangles: {}", self.stats.num_triangles));

View file

@ -17,6 +17,8 @@ pub struct ExampleApp {
num_columns: usize,
slider_value: usize,
painting: Painting,
}
impl Default for ExampleApp {
@ -33,6 +35,8 @@ impl Default for ExampleApp {
num_columns: 2,
slider_value: 100,
painting: Default::default(),
}
}
}
@ -51,7 +55,7 @@ impl ExampleApp {
});
CollapsingHeader::new("Widgets")
.default_open()
// .default_open()
.show(region, |region| {
region.horizontal(Align::Min, |region| {
region.add(label!("Text can have").text_color(srgba(110, 255, 110, 255)));
@ -147,6 +151,10 @@ impl ExampleApp {
});
});
CollapsingHeader::new("Painting")
.default_open()
.show(region, |region| self.painting.ui(region));
region.collapsing("Name clash example", |region| {
region.add_label("\
Regions that store state require unique identifiers so we can track their state between frames. \
@ -173,6 +181,62 @@ impl ExampleApp {
}
}
#[derive(Default)]
struct Painting {
lines: Vec<Vec<Pos2>>,
current_line: Vec<Pos2>,
}
impl Painting {
pub fn ui(&mut self, region: &mut Region) {
region.add_label("Draw with your mouse to paint");
if region.add(Button::new("Clear")).clicked {
self.lines.clear();
self.current_line.clear();
}
region.add_custom_contents(vec2(std::f32::INFINITY, 200.0), |region| {
let interact = region.reserve_space(region.available_space(), Some(region.id));
region.clip_rect = interact.rect; // Make sure we don't paint out of bounds
if interact.active {
if let Some(mouse_pos) = region.input().mouse_pos {
if self.current_line.last() != Some(&mouse_pos) {
self.current_line.push(mouse_pos);
}
}
} else if !self.current_line.is_empty() {
self.lines.push(std::mem::take(&mut self.current_line));
}
for line in &self.lines {
if line.len() >= 2 {
region.add_paint_cmd(PaintCmd::Line {
points: line.clone(),
color: LIGHT_GRAY,
width: 2.0,
});
}
}
if self.current_line.len() >= 2 {
region.add_paint_cmd(PaintCmd::Line {
points: self.current_line.clone(),
color: WHITE,
width: 2.0,
});
}
// Frame it:
region.add_paint_cmd(PaintCmd::Rect {
rect: region.desired_rect,
corner_radius: 0.0,
fill_color: None,
outline: Some(Outline::new(1.0, WHITE)),
});
});
}
}
const LOREM_IPSUM: &str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Curabitur pretium tincidunt lacus. Nulla gravida orci a odio. Nullam varius, turpis et commodo pharetra, est eros bibendum elit, nec luctus magna felis sollicitudin mauris. Integer in mauris eu nibh euismod gravida. Duis ac tellus et risus vulputate vehicula. Donec lobortis risus a elit. Etiam tempor. Ut ullamcorper, ligula eu tempor congue, eros est euismod turpis, id tincidunt sapien risus a quam. Maecenas fermentum consequat mi. Donec fermentum. Pellentesque malesuada nulla a mi. Duis sapien sem, aliquet nec, commodo eget, consequat quis, neque. Aliquam faucibus, elit ut dictum aliquet, felis nisl adipiscing sapien, sed malesuada diam lacus eget erat. Cras mollis scelerisque nunc. Nullam arcu. Aliquam consequat. Curabitur augue lorem, dapibus quis, laoreet et, pretium ac, nisi. Aenean magna nisl, mollis quis, molestie eu, feugiat in, orci. In hac habitasse platea dictumst.";

View file

@ -43,14 +43,14 @@ impl Id {
Self(1)
}
pub fn new<H: Hash>(source: H) -> Id {
pub fn new(source: impl Hash) -> Id {
use std::hash::Hasher;
let mut hasher = DefaultHasher::new();
source.hash(&mut hasher);
Id(hasher.finish())
}
pub fn with<H: Hash>(self, child: H) -> Id {
pub fn with(self, child: impl Hash) -> Id {
use std::hash::Hasher;
let mut hasher = DefaultHasher::new();
hasher.write_u64(self.0);

View file

@ -451,10 +451,11 @@ pub fn mesh_command(
fill_closed_path(out_mesh, options, &path.0, fill_color);
}
if let Some(outline) = outline {
let typ = if closed { Closed } else { Open };
paint_path(
out_mesh,
options,
Closed,
typ,
&path.0,
outline.color,
outline.width,

View file

@ -166,11 +166,25 @@ impl Region {
// ------------------------------------------------------------------------
// Sub-regions:
/// Create a child region at the current cursor.
/// `size` is the desired size.
/// Actual size may be much smaller if `avilable_size()` is not enough.
/// Set `size` to `Vec::infinity()` to get as much space as possible.
/// Just because you ask for a lot of space does not mean you have to use it!
/// After `add_contents` is called the contents of `bounding_size`
/// will decide how much space will be used in the parent region.
pub fn add_custom_contents(&mut self, size: Vec2, add_contents: impl FnOnce(&mut Region)) {
let size = size.min(self.available_space());
let child_rect = Rect::from_min_size(self.cursor, size);
let mut child_region = Region {
..self.child_region(child_rect)
};
add_contents(&mut child_region);
self.reserve_space_without_padding(child_region.bounding_size);
}
/// Create a child region which is indented to the right
pub fn indent<F>(&mut self, id: Id, add_contents: F)
where
F: FnOnce(&mut Region),
{
pub fn indent(&mut self, id_source: impl Hash, add_contents: impl FnOnce(&mut Region)) {
assert!(
self.dir == Direction::Vertical,
"You can only indent vertical layouts"
@ -178,7 +192,7 @@ impl Region {
let indent = vec2(self.style.indent, 0.0);
let child_rect = Rect::from_min_max(self.cursor + indent, self.desired_rect.max());
let mut child_region = Region {
id,
id: self.id.with(id_source),
align: Align::Min,
..self.child_region(child_rect)
};
@ -297,6 +311,14 @@ impl Region {
// ------------------------------------------------------------------------
/// Check for clicks on this entire region (desired_rect)
pub fn interact(&self) -> InteractInfo {
self.ctx
.interact(self.layer, self.desired_rect, Some(self.id))
}
// ------------------------------------------------------------------------
pub fn add<W: Widget>(&mut self, widget: W) -> GuiResponse {
widget.add_to(self)
}
@ -355,15 +377,14 @@ impl Region {
/// Will warn if the returned id is not guaranteed unique.
/// Use this to generate widget ids for widgets that have persistent state in Memory.
/// If the child_id_source is not unique within this region
/// If the id_source is not unique within this region
/// then an error will be printed at the current cursor position.
pub fn make_unique_id<IdSource>(&self, child_id_source: &IdSource) -> Id
pub fn make_unique_id<IdSource>(&self, id_source: &IdSource) -> Id
where
IdSource: Hash + std::fmt::Debug,
{
let id = self.id.with(child_id_source);
self.ctx
.register_unique_id(id, child_id_source, self.cursor)
let id = self.id.with(id_source);
self.ctx.register_unique_id(id, id_source, self.cursor)
}
/// Make an Id that is unique to this positon.
@ -373,8 +394,8 @@ impl Region {
self.id.with(&Id::from_pos(self.cursor))
}
pub fn make_child_id<H: Hash>(&self, child_id: &H) -> Id {
self.id.with(child_id)
pub fn make_child_id(&self, id_seed: impl Hash) -> Id {
self.id.with(id_seed)
}
/// Show some text anywhere in the region.

View file

@ -61,7 +61,7 @@ impl State {
region.set_align(Align::Min);
region.add_label("WebGl painter info:");
region.indent(Id::new("webgl region"), |region| {
region.indent("webgl region", |region| {
region.add_label(self.webgl_painter.debug_info());
});