Introduce `Translate` primitive in `iced_wgpu`

This commit is contained in:
Héctor Ramón Jiménez 2020-04-28 03:18:31 +02:00
parent 2381a9310c
commit 59b1e90661
10 changed files with 127 additions and 104 deletions

View File

@ -172,12 +172,14 @@ mod bezier {
) )
.unwrap(); .unwrap();
let mesh = Primitive::Mesh2D { let mesh = Primitive::Translate {
origin: Point::new(bounds.x, bounds.y), translation: Vector::new(bounds.x, bounds.y),
content: Box::new(Primitive::Mesh2D {
buffers: Mesh2D { buffers: Mesh2D {
vertices: buffer.vertices, vertices: buffer.vertices,
indices: buffer.indices, indices: buffer.indices,
}, },
}),
}; };
( (

View File

@ -12,7 +12,7 @@ mod rainbow {
// implemented by `iced_wgpu` and other renderers. // implemented by `iced_wgpu` and other renderers.
use iced_native::{ use iced_native::{
layout, Element, Hasher, Layout, Length, MouseCursor, Point, Size, layout, Element, Hasher, Layout, Length, MouseCursor, Point, Size,
Widget, Vector, Widget,
}; };
use iced_wgpu::{ use iced_wgpu::{
triangle::{Mesh2D, Vertex2D}, triangle::{Mesh2D, Vertex2D},
@ -85,8 +85,9 @@ mod rainbow {
let posn_l = [0.0, b.height / 2.0]; let posn_l = [0.0, b.height / 2.0];
( (
Primitive::Mesh2D { Primitive::Translate {
origin: Point::new(b.x, b.y), translation: Vector::new(b.x, b.y),
content: Box::new(Primitive::Mesh2D {
buffers: Mesh2D { buffers: Mesh2D {
vertices: vec![ vertices: vec![
Vertex2D { Vertex2D {
@ -137,6 +138,7 @@ mod rainbow {
0, 8, 1, // L 0, 8, 1, // L
], ],
}, },
}),
}, },
MouseCursor::OutOfBounds, MouseCursor::OutOfBounds,
) )

View File

@ -1,5 +1,5 @@
use iced_native::{ use iced_native::{
image, svg, Background, Color, Font, HorizontalAlignment, Point, Rectangle, image, svg, Background, Color, Font, HorizontalAlignment, Rectangle,
Vector, VerticalAlignment, Vector, VerticalAlignment,
}; };
@ -70,13 +70,18 @@ pub enum Primitive {
/// The content of the clip /// The content of the clip
content: Box<Primitive>, content: Box<Primitive>,
}, },
/// A primitive that applies a translation
Translate {
/// The top-left coordinate of the mesh
translation: Vector,
/// The primitive to translate
content: Box<Primitive>,
},
/// A low-level primitive to render a mesh of triangles. /// A low-level primitive to render a mesh of triangles.
/// ///
/// It can be used to render many kinds of geometry freely. /// It can be used to render many kinds of geometry freely.
Mesh2D { Mesh2D {
/// The top-left coordinate of the mesh
origin: Point,
/// The vertex and index buffers of the mesh /// The vertex and index buffers of the mesh
buffers: triangle::Mesh2D, buffers: triangle::Mesh2D,
}, },
@ -85,9 +90,6 @@ pub enum Primitive {
/// This can be useful if you are implementing a widget where primitive /// This can be useful if you are implementing a widget where primitive
/// generation is expensive. /// generation is expensive.
Cached { Cached {
/// The origin of the coordinate system of the cached primitives
origin: Point,
/// The cached primitive /// The cached primitive
cache: Arc<Primitive>, cache: Arc<Primitive>,
}, },

View File

@ -29,7 +29,7 @@ pub struct Renderer {
struct Layer<'a> { struct Layer<'a> {
bounds: Rectangle<u32>, bounds: Rectangle<u32>,
quads: Vec<Quad>, quads: Vec<Quad>,
meshes: Vec<(Point, &'a triangle::Mesh2D)>, meshes: Vec<(Vector, &'a triangle::Mesh2D)>,
text: Vec<wgpu_glyph::Section<'a>>, text: Vec<wgpu_glyph::Section<'a>>,
#[cfg(any(feature = "image", feature = "svg"))] #[cfg(any(feature = "image", feature = "svg"))]
@ -214,10 +214,10 @@ impl Renderer {
border_color: border_color.into_linear(), border_color: border_color.into_linear(),
}); });
} }
Primitive::Mesh2D { origin, buffers } => { Primitive::Mesh2D { buffers } => {
let layer = layers.last_mut().unwrap(); let layer = layers.last_mut().unwrap();
layer.meshes.push((*origin + translation, buffers)); layer.meshes.push((translation, buffers));
} }
Primitive::Clip { Primitive::Clip {
bounds, bounds,
@ -249,15 +249,21 @@ impl Renderer {
layers.push(new_layer); layers.push(new_layer);
} }
} }
Primitive::Translate {
Primitive::Cached { origin, cache } => { translation: new_translation,
content,
} => {
self.draw_primitive( self.draw_primitive(
translation + Vector::new(origin.x, origin.y), translation + *new_translation,
&cache, &content,
layers, layers,
); );
} }
Primitive::Cached { cache } => {
self.draw_primitive(translation, &cache, layers);
}
#[cfg(feature = "image")] #[cfg(feature = "image")]
Primitive::Image { handle, bounds } => { Primitive::Image { handle, bounds } => {
let layer = layers.last_mut().unwrap(); let layer = layers.last_mut().unwrap();

View File

@ -59,12 +59,12 @@ impl pane_grid::Renderer for Renderer {
height: bounds.height + 0.5, height: bounds.height + 0.5,
}, },
offset: Vector::new(0, 0), offset: Vector::new(0, 0),
content: Box::new(Primitive::Cached { content: Box::new(Primitive::Translate {
origin: Point::new( translation: Vector::new(
cursor_position.x - bounds.x - bounds.width / 2.0, cursor_position.x - bounds.x - bounds.width / 2.0,
cursor_position.y - bounds.y - bounds.height / 2.0, cursor_position.y - bounds.y - bounds.height / 2.0,
), ),
cache: std::sync::Arc::new(pane), content: Box::new(pane),
}), }),
}; };

View File

@ -1,6 +1,6 @@
//! Draw meshes of triangles. //! Draw meshes of triangles.
use crate::{settings, Transformation}; use crate::{settings, Transformation};
use iced_native::{Point, Rectangle}; use iced_native::{Rectangle, Vector};
use std::mem; use std::mem;
use zerocopy::AsBytes; use zerocopy::AsBytes;
@ -201,7 +201,7 @@ impl Pipeline {
target_width: u32, target_width: u32,
target_height: u32, target_height: u32,
transformation: Transformation, transformation: Transformation,
meshes: &[(Point, &Mesh2D)], meshes: &[(Vector, &Mesh2D)],
bounds: Rectangle<u32>, bounds: Rectangle<u32>,
) { ) {
// This looks a bit crazy, but we are just counting how many vertices // This looks a bit crazy, but we are just counting how many vertices

View File

@ -10,7 +10,7 @@ use crate::{Defaults, Primitive, Renderer};
use iced_native::{ use iced_native::{
input::mouse, layout, Clipboard, Element, Hasher, Layout, Length, input::mouse, layout, Clipboard, Element, Hasher, Layout, Length,
MouseCursor, Point, Size, Widget, MouseCursor, Point, Size, Vector, Widget,
}; };
use std::hash::Hash; use std::hash::Hash;
@ -190,20 +190,20 @@ impl<Message, S: State> Widget<Message, Renderer> for Canvas<S> {
_cursor_position: Point, _cursor_position: Point,
) -> (Primitive, MouseCursor) { ) -> (Primitive, MouseCursor) {
let bounds = layout.bounds(); let bounds = layout.bounds();
let origin = Point::new(bounds.x, bounds.y); let translation = Vector::new(bounds.x, bounds.y);
let size = Size::new(bounds.width, bounds.height); let size = Size::new(bounds.width, bounds.height);
( (
Primitive::Group { Primitive::Translate {
translation,
content: Box::new(Primitive::Group {
primitives: self primitives: self
.state .state
.draw(size) .draw(size)
.into_iter() .into_iter()
.map(|geometry| Primitive::Cached { .map(Geometry::into_primitive)
origin,
cache: geometry.into_primitive(),
})
.collect(), .collect(),
}),
}, },
MouseCursor::Idle, MouseCursor::Idle,
) )

View File

@ -57,21 +57,27 @@ impl Cache {
if let State::Filled { bounds, primitive } = self.state.borrow().deref() if let State::Filled { bounds, primitive } = self.state.borrow().deref()
{ {
if *bounds == new_bounds { if *bounds == new_bounds {
return Geometry::from_primitive(primitive.clone()); return Geometry::from_primitive(Primitive::Cached {
cache: primitive.clone(),
});
} }
} }
let mut frame = Frame::new(new_bounds); let mut frame = Frame::new(new_bounds);
input.draw(&mut frame); input.draw(&mut frame);
let primitive = Arc::new(frame.into_primitive()); let primitive = {
let geometry = frame.into_geometry();
Arc::new(geometry.into_primitive())
};
*self.state.borrow_mut() = State::Filled { *self.state.borrow_mut() = State::Filled {
bounds: new_bounds, bounds: new_bounds,
primitive: primitive.clone(), primitive: primitive.clone(),
}; };
Geometry::from_primitive(primitive) Geometry::from_primitive(Primitive::Cached { cache: primitive })
} }
pub fn with<'a, T>(&'a self, input: T) -> impl crate::canvas::State + 'a pub fn with<'a, T>(&'a self, input: T) -> impl crate::canvas::State + 'a

View File

@ -1,7 +1,7 @@
use iced_native::{Point, Rectangle, Size, Vector}; use iced_native::{Point, Rectangle, Size, Vector};
use crate::{ use crate::{
canvas::{Fill, Path, Stroke, Text}, canvas::{Fill, Geometry, Path, Stroke, Text},
triangle, Primitive, triangle, Primitive,
}; };
@ -260,13 +260,13 @@ impl Frame {
self.transforms.current.is_identity = false; self.transforms.current.is_identity = false;
} }
/// Produces the primitive representing everything drawn on the [`Frame`]. /// Produces the [`Geometry`] representing everything drawn on the [`Frame`].
/// ///
/// [`Frame`]: struct.Frame.html /// [`Frame`]: struct.Frame.html
pub fn into_primitive(mut self) -> Primitive { /// [`Geometry`]: struct.Geometry.html
pub fn into_geometry(mut self) -> Geometry {
if !self.buffers.indices.is_empty() { if !self.buffers.indices.is_empty() {
self.primitives.push(Primitive::Mesh2D { self.primitives.push(Primitive::Mesh2D {
origin: Point::ORIGIN,
buffers: triangle::Mesh2D { buffers: triangle::Mesh2D {
vertices: self.buffers.vertices, vertices: self.buffers.vertices,
indices: self.buffers.indices, indices: self.buffers.indices,
@ -274,9 +274,9 @@ impl Frame {
}); });
} }
Primitive::Group { Geometry::from_primitive(Primitive::Group {
primitives: self.primitives, primitives: self.primitives,
} })
} }
} }

View File

@ -1,15 +1,20 @@
use crate::Primitive; use crate::Primitive;
use std::sync::Arc;
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct Geometry(Arc<Primitive>); pub struct Geometry(Primitive);
impl Geometry { impl Geometry {
pub(crate) fn from_primitive(primitive: Arc<Primitive>) -> Self { pub(crate) fn from_primitive(primitive: Primitive) -> Self {
Self(primitive) Self(primitive)
} }
pub(crate) fn into_primitive(self) -> Arc<Primitive> { pub fn into_primitive(self) -> Primitive {
self.0 self.0
} }
} }
impl From<Geometry> for Primitive {
fn from(geometry: Geometry) -> Primitive {
geometry.0
}
}