diff options
author | 2022-11-28 19:42:53 +0100 | |
---|---|---|
committer | 2022-11-28 19:42:53 +0100 | |
commit | 324d60db6319017304bf0b514b76db98b3637929 (patch) | |
tree | ba770b2fbc6be4fa7708c9ab8967d67ccb21dfb6 | |
parent | 633150581f442b35b52a52a384b7d935171223ff (diff) | |
download | iced-324d60db6319017304bf0b514b76db98b3637929.tar.gz iced-324d60db6319017304bf0b514b76db98b3637929.tar.bz2 iced-324d60db6319017304bf0b514b76db98b3637929.zip |
Re-introduce the `geometry` example
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | examples/README.md | 1 | ||||
-rw-r--r-- | examples/geometry/Cargo.toml | 11 | ||||
-rw-r--r-- | examples/geometry/README.md | 18 | ||||
-rw-r--r-- | examples/geometry/src/main.rs | 213 |
5 files changed, 244 insertions, 0 deletions
@@ -66,6 +66,7 @@ members = [ "examples/events", "examples/exit", "examples/game_of_life", + "examples/geometry", "examples/integration_opengl", "examples/integration_wgpu", "examples/lazy", diff --git a/examples/README.md b/examples/README.md index 8d9718a4..bb15dc2e 100644 --- a/examples/README.md +++ b/examples/README.md @@ -92,6 +92,7 @@ A bunch of simpler examples exist: - [`custom_widget`](custom_widget), a demonstration of how to build a custom widget that draws a circle. - [`download_progress`](download_progress), a basic application that asynchronously downloads a dummy file of 100 MB and tracks the download progress. - [`events`](events), a log of native events displayed using a conditional `Subscription`. +- [`geometry`](geometry), a custom widget showcasing how to draw geometry with the `Mesh2D` primitive in [`iced_wgpu`](../wgpu). - [`integration_opengl`](integration_opengl), a demonstration of how to integrate Iced in an existing OpenGL application. - [`integration_wgpu`](integration_wgpu), a demonstration of how to integrate Iced in an existing [`wgpu`] application. - [`pane_grid`](pane_grid), a grid of panes that can be split, resized, and reorganized. diff --git a/examples/geometry/Cargo.toml b/examples/geometry/Cargo.toml new file mode 100644 index 00000000..22ede0e0 --- /dev/null +++ b/examples/geometry/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "geometry" +version = "0.1.0" +authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"] +edition = "2021" +publish = false + +[dependencies] +iced = { path = "../.." } +iced_native = { path = "../../native" } +iced_graphics = { path = "../../graphics" } diff --git a/examples/geometry/README.md b/examples/geometry/README.md new file mode 100644 index 00000000..4d5c81cb --- /dev/null +++ b/examples/geometry/README.md @@ -0,0 +1,18 @@ +## Geometry + +A custom widget showcasing how to draw geometry with the `Mesh2D` primitive in [`iced_wgpu`](../../wgpu). + +The __[`main`]__ file contains all the code of the example. + +<div align="center"> + <a href="https://gfycat.com/activeunfitkangaroo"> + <img src="https://thumbs.gfycat.com/ActiveUnfitKangaroo-small.gif"> + </a> +</div> + +You can run it with `cargo run`: +``` +cargo run --package geometry +``` + +[`main`]: src/main.rs diff --git a/examples/geometry/src/main.rs b/examples/geometry/src/main.rs new file mode 100644 index 00000000..4de281fe --- /dev/null +++ b/examples/geometry/src/main.rs @@ -0,0 +1,213 @@ +//! 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_graphics::renderer::{self, Renderer}; + use iced_graphics::triangle::ColoredVertex2D; + use iced_graphics::{Backend, Primitive}; + + use iced_native::layout; + use iced_native::widget::{self, Widget}; + use iced_native::{ + Element, Layout, Length, Point, Rectangle, Size, Vector, + }; + + pub struct Rainbow; + + impl Rainbow { + pub fn new() -> Self { + Self + } + } + + impl<Message, B, T> Widget<Message, Renderer<B, T>> for Rainbow + where + B: Backend, + { + fn width(&self) -> Length { + Length::Fill + } + + fn height(&self) -> Length { + Length::Shrink + } + + fn layout( + &self, + _renderer: &Renderer<B, T>, + limits: &layout::Limits, + ) -> layout::Node { + let size = limits.width(Length::Fill).resolve(Size::ZERO); + + layout::Node::new(Size::new(size.width, size.width)) + } + + fn draw( + &self, + _tree: &widget::Tree, + renderer: &mut Renderer<B, T>, + _theme: &T, + _style: &renderer::Style, + layout: Layout<'_>, + cursor_position: Point, + _viewport: &Rectangle, + ) { + use iced_graphics::triangle::Mesh2D; + use iced_native::Renderer as _; + + 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 - b.x, cursor_position.y - b.y] + } else { + [b.width / 2.0, b.height / 2.0] + } + }; + + let posn_tl = [0.0, 0.0]; + let posn_t = [b.width / 2.0, 0.0]; + let posn_tr = [b.width, 0.0]; + let posn_r = [b.width, b.height / 2.0]; + let posn_br = [b.width, b.height]; + let posn_b = [(b.width / 2.0), b.height]; + let posn_bl = [0.0, b.height]; + let posn_l = [0.0, b.height / 2.0]; + + let mesh = Primitive::SolidMesh { + size: b.size(), + buffers: Mesh2D { + vertices: vec![ + ColoredVertex2D { + position: posn_center, + color: [1.0, 1.0, 1.0, 1.0], + }, + ColoredVertex2D { + position: posn_tl, + color: color_r, + }, + ColoredVertex2D { + position: posn_t, + color: color_o, + }, + ColoredVertex2D { + position: posn_tr, + color: color_y, + }, + ColoredVertex2D { + position: posn_r, + color: color_g, + }, + ColoredVertex2D { + position: posn_br, + color: color_gb, + }, + ColoredVertex2D { + position: posn_b, + color: color_b, + }, + ColoredVertex2D { + position: posn_bl, + color: color_i, + }, + ColoredVertex2D { + 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 + ], + }, + }; + + renderer.with_translation(Vector::new(b.x, b.y), |renderer| { + renderer.draw_primitive(mesh); + }); + } + } + + impl<'a, Message, B, T> From<Rainbow> for Element<'a, Message, Renderer<B, T>> + where + B: Backend, + { + fn from(rainbow: Rainbow) -> Self { + Self::new(rainbow) + } + } +} + +use iced::widget::{column, container, scrollable}; +use iced::{Element, Length, Sandbox, Settings}; +use rainbow::Rainbow; + +pub fn main() -> iced::Result { + Example::run(Settings::default()) +} + +struct Example; + +impl Sandbox for Example { + type Message = (); + + fn new() -> Self { + Self + } + + fn title(&self) -> String { + String::from("Custom 2D geometry - Iced") + } + + fn update(&mut self, _: ()) {} + + fn view(&self) -> Element<()> { + let content = column![ + Rainbow::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.", + "Move your cursor over it, and see the center vertex \ + follow you!", + "Every Vertex2D defines its own color. You could use the \ + Mesh2D primitive to render virtually any two-dimensional \ + geometry for your widget.", + ] + .padding(20) + .spacing(20) + .max_width(500); + + let scrollable = + scrollable(container(content).width(Length::Fill).center_x()); + + container(scrollable) + .width(Length::Fill) + .height(Length::Fill) + .center_y() + .into() + } +} |