-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #140 from artursapek/artur/canvas
Mesh2D primitive for rendering arbitrary geometry in `iced_wgpu`
- Loading branch information
Showing
9 changed files
with
512 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,209 @@ | ||
//! This example showcases a simple native custom widget that renders using | ||
//! arbitrary low-level geometry. | ||
mod rainbow { | ||
// For now, to implement a custom native widget you will need to add | ||
// `iced_native` and `iced_wgpu` to your dependencies. | ||
// | ||
// Then, you simply need to define your widget type and implement the | ||
// `iced_native::Widget` trait with the `iced_wgpu::Renderer`. | ||
// | ||
// Of course, you can choose to make the implementation renderer-agnostic, | ||
// if you wish to, by creating your own `Renderer` trait, which could be | ||
// implemented by `iced_wgpu` and other renderers. | ||
use iced_native::{ | ||
layout, Element, Hasher, Layout, Length, MouseCursor, Point, Size, | ||
Widget, | ||
}; | ||
use iced_wgpu::{ | ||
triangle::{Mesh2D, Vertex2D}, | ||
Primitive, Renderer, | ||
}; | ||
|
||
pub struct Rainbow; | ||
|
||
impl Rainbow { | ||
pub fn new() -> Self { | ||
Self | ||
} | ||
} | ||
|
||
impl<Message> Widget<Message, Renderer> for Rainbow { | ||
fn width(&self) -> Length { | ||
Length::Fill | ||
} | ||
|
||
fn height(&self) -> Length { | ||
Length::Shrink | ||
} | ||
|
||
fn layout( | ||
&self, | ||
_renderer: &Renderer, | ||
limits: &layout::Limits, | ||
) -> layout::Node { | ||
let size = limits.width(Length::Fill).resolve(Size::ZERO); | ||
|
||
layout::Node::new(Size::new(size.width, size.width)) | ||
} | ||
|
||
fn hash_layout(&self, _state: &mut Hasher) {} | ||
|
||
fn draw( | ||
&self, | ||
_renderer: &mut Renderer, | ||
layout: Layout<'_>, | ||
cursor_position: Point, | ||
) -> (Primitive, MouseCursor) { | ||
let b = layout.bounds(); | ||
|
||
// R O Y G B I V | ||
let color_r = [1.0, 0.0, 0.0, 1.0]; | ||
let color_o = [1.0, 0.5, 0.0, 1.0]; | ||
let color_y = [1.0, 1.0, 0.0, 1.0]; | ||
let color_g = [0.0, 1.0, 0.0, 1.0]; | ||
let color_gb = [0.0, 1.0, 0.5, 1.0]; | ||
let color_b = [0.0, 0.2, 1.0, 1.0]; | ||
let color_i = [0.5, 0.0, 1.0, 1.0]; | ||
let color_v = [0.75, 0.0, 0.5, 1.0]; | ||
|
||
let posn_center = { | ||
if b.contains(cursor_position) { | ||
[cursor_position.x, cursor_position.y] | ||
} else { | ||
[b.x + (b.width / 2.0), b.y + (b.height / 2.0)] | ||
} | ||
}; | ||
|
||
let posn_tl = [b.x, b.y]; | ||
let posn_t = [b.x + (b.width / 2.0), b.y]; | ||
let posn_tr = [b.x + b.width, b.y]; | ||
let posn_r = [b.x + b.width, b.y + (b.height / 2.0)]; | ||
let posn_br = [b.x + b.width, b.y + b.height]; | ||
let posn_b = [b.x + (b.width / 2.0), b.y + b.height]; | ||
let posn_bl = [b.x, b.y + b.height]; | ||
let posn_l = [b.x, b.y + (b.height / 2.0)]; | ||
|
||
( | ||
Primitive::Mesh2D(std::sync::Arc::new(Mesh2D { | ||
vertices: vec![ | ||
Vertex2D { | ||
position: posn_center, | ||
color: [1.0, 1.0, 1.0, 1.0], | ||
}, | ||
Vertex2D { | ||
position: posn_tl, | ||
color: color_r, | ||
}, | ||
Vertex2D { | ||
position: posn_t, | ||
color: color_o, | ||
}, | ||
Vertex2D { | ||
position: posn_tr, | ||
color: color_y, | ||
}, | ||
Vertex2D { | ||
position: posn_r, | ||
color: color_g, | ||
}, | ||
Vertex2D { | ||
position: posn_br, | ||
color: color_gb, | ||
}, | ||
Vertex2D { | ||
position: posn_b, | ||
color: color_b, | ||
}, | ||
Vertex2D { | ||
position: posn_bl, | ||
color: color_i, | ||
}, | ||
Vertex2D { | ||
position: posn_l, | ||
color: color_v, | ||
}, | ||
], | ||
indices: vec![ | ||
0, 1, 2, // TL | ||
0, 2, 3, // T | ||
0, 3, 4, // TR | ||
0, 4, 5, // R | ||
0, 5, 6, // BR | ||
0, 6, 7, // B | ||
0, 7, 8, // BL | ||
0, 8, 1, // L | ||
], | ||
})), | ||
MouseCursor::OutOfBounds, | ||
) | ||
} | ||
} | ||
|
||
impl<'a, Message> Into<Element<'a, Message, Renderer>> for Rainbow { | ||
fn into(self) -> Element<'a, Message, Renderer> { | ||
Element::new(self) | ||
} | ||
} | ||
} | ||
|
||
use iced::{ | ||
scrollable, Align, Column, Container, Element, Length, Sandbox, Scrollable, | ||
Settings, Text, | ||
}; | ||
use rainbow::Rainbow; | ||
|
||
pub fn main() { | ||
Example::run(Settings::default()) | ||
} | ||
|
||
struct Example { | ||
scroll: scrollable::State, | ||
} | ||
|
||
impl Sandbox for Example { | ||
type Message = (); | ||
|
||
fn new() -> Self { | ||
Example { | ||
scroll: scrollable::State::new(), | ||
} | ||
} | ||
|
||
fn title(&self) -> String { | ||
String::from("Custom 2D geometry - Iced") | ||
} | ||
|
||
fn update(&mut self, _: ()) {} | ||
|
||
fn view(&mut self) -> Element<()> { | ||
let content = Column::new() | ||
.padding(20) | ||
.spacing(20) | ||
.max_width(500) | ||
.align_items(Align::Start) | ||
.push(Rainbow::new()) | ||
.push(Text::new( | ||
"In this example we draw a custom widget Rainbow, using \ | ||
the Mesh2D primitive. This primitive supplies a list of \ | ||
triangles, expressed as vertices and indices.", | ||
)) | ||
.push(Text::new( | ||
"Move your cursor over it, and see the center vertex \ | ||
follow you!", | ||
)) | ||
.push(Text::new( | ||
"Every Vertex2D defines its own color. You could use the \ | ||
Mesh2D primitive to render virtually any two-dimensional \ | ||
geometry for your widget.", | ||
)); | ||
|
||
let scrollable = Scrollable::new(&mut self.scroll) | ||
.push(Container::new(content).width(Length::Fill).center_x()); | ||
|
||
Container::new(scrollable) | ||
.width(Length::Fill) | ||
.height(Length::Fill) | ||
.center_y() | ||
.into() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#version 450 | ||
|
||
layout(location = 0) in vec4 i_Color; | ||
layout(location = 0) out vec4 o_Color; | ||
|
||
void main() { | ||
o_Color = i_Color; | ||
} |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#version 450 | ||
|
||
layout(location = 0) in vec2 i_Position; | ||
layout(location = 1) in vec4 i_Color; | ||
|
||
layout(location = 0) out vec4 o_Color; | ||
|
||
layout (set = 0, binding = 0) uniform Globals { | ||
mat4 u_Transform; | ||
float u_Scale; | ||
}; | ||
|
||
void main() { | ||
vec2 p_Position = i_Position * u_Scale; | ||
gl_Position = u_Transform * vec4(p_Position, 0.0, 1.0); | ||
o_Color = i_Color; | ||
} |
Binary file not shown.
Oops, something went wrong.