diff options
| -rw-r--r-- | examples/custom_shader/src/main.rs | 11 | ||||
| -rw-r--r-- | examples/custom_shader/src/primitive.rs | 15 | ||||
| -rw-r--r-- | renderer/src/lib.rs | 44 | ||||
| -rw-r--r-- | renderer/src/widget.rs | 2 | ||||
| -rw-r--r-- | wgpu/src/backend.rs | 29 | ||||
| -rw-r--r-- | wgpu/src/custom.rs | 63 | ||||
| -rw-r--r-- | wgpu/src/layer.rs | 19 | ||||
| -rw-r--r-- | wgpu/src/lib.rs | 1 | ||||
| -rw-r--r-- | wgpu/src/primitive.rs | 43 | ||||
| -rw-r--r-- | wgpu/src/primitive/pipeline.rs | 117 | ||||
| -rw-r--r-- | widget/src/lib.rs | 6 | ||||
| -rw-r--r-- | widget/src/shader.rs (renamed from renderer/src/widget/shader.rs) | 82 | ||||
| -rw-r--r-- | widget/src/shader/event.rs (renamed from renderer/src/widget/shader/event.rs) | 1 | ||||
| -rw-r--r-- | widget/src/shader/program.rs (renamed from renderer/src/widget/shader/program.rs) | 10 | 
14 files changed, 246 insertions, 197 deletions
| diff --git a/examples/custom_shader/src/main.rs b/examples/custom_shader/src/main.rs index 76fa1625..f6370f46 100644 --- a/examples/custom_shader/src/main.rs +++ b/examples/custom_shader/src/main.rs @@ -3,15 +3,20 @@ mod cubes;  mod pipeline;  mod primitive; +use crate::camera::Camera;  use crate::cubes::Cubes; +use crate::pipeline::Pipeline; + +use iced::executor; +use iced::time::Instant;  use iced::widget::{      checkbox, column, container, row, slider, text, vertical_space, Shader,  }; +use iced::window;  use iced::{ -    executor, window, Alignment, Application, Color, Command, Element, Length, -    Renderer, Subscription, Theme, +    Alignment, Application, Color, Command, Element, Length, Renderer, +    Subscription, Theme,  }; -use std::time::Instant;  fn main() -> iced::Result {      IcedCubes::run(iced::Settings::default()) diff --git a/examples/custom_shader/src/primitive.rs b/examples/custom_shader/src/primitive.rs index f81ce95d..520ceb8e 100644 --- a/examples/custom_shader/src/primitive.rs +++ b/examples/custom_shader/src/primitive.rs @@ -4,17 +4,18 @@ pub mod vertex;  mod buffer;  mod uniforms; -use crate::camera::Camera; -use crate::pipeline::Pipeline; -use crate::primitive::cube::Cube; +pub use buffer::Buffer; +pub use cube::Cube; +pub use uniforms::Uniforms; +pub use vertex::Vertex; + +use crate::Camera; +use crate::Pipeline; +  use iced::advanced::graphics::Transformation;  use iced::widget::shader;  use iced::{Color, Rectangle, Size}; -pub use crate::primitive::vertex::Vertex; -pub use buffer::Buffer; -pub use uniforms::Uniforms; -  /// A collection of `Cube`s that can be rendered.  #[derive(Debug)]  pub struct Primitive { diff --git a/renderer/src/lib.rs b/renderer/src/lib.rs index e4b1eda9..1fc4c86b 100644 --- a/renderer/src/lib.rs +++ b/renderer/src/lib.rs @@ -1,13 +1,15 @@  #![forbid(rust_2018_idioms)]  #![deny(unsafe_code, unused_results, rustdoc::broken_intra_doc_links)]  #![cfg_attr(docsrs, feature(doc_auto_cfg))] +#[cfg(feature = "wgpu")] +pub use iced_wgpu as wgpu; +  pub mod compositor;  #[cfg(feature = "geometry")]  pub mod geometry;  mod settings; -pub mod widget;  pub use iced_graphics as graphics;  pub use iced_graphics::core; @@ -60,26 +62,6 @@ impl<T> Renderer<T> {              }          }      } - -    pub fn draw_custom<P: widget::shader::Primitive>( -        &mut self, -        bounds: Rectangle, -        primitive: P, -    ) { -        match self { -            Renderer::TinySkia(_) => { -                log::warn!( -                    "Custom shader primitive is unavailable with tiny-skia." -                ); -            } -            #[cfg(feature = "wgpu")] -            Renderer::Wgpu(renderer) => { -                renderer.draw_primitive(iced_wgpu::Primitive::Custom( -                    iced_wgpu::primitive::Custom::shader(bounds, primitive), -                )); -            } -        } -    }  }  impl<T> core::Renderer for Renderer<T> { @@ -292,3 +274,23 @@ impl<T> crate::graphics::geometry::Renderer for Renderer<T> {          }      }  } + +#[cfg(feature = "wgpu")] +impl<T> iced_wgpu::primitive::pipeline::Renderer for Renderer<T> { +    fn draw_pipeline_primitive( +        &mut self, +        bounds: Rectangle, +        primitive: impl wgpu::primitive::pipeline::Primitive, +    ) { +        match self { +            Self::TinySkia(_renderer) => { +                log::warn!( +                    "Custom shader primitive is unavailable with tiny-skia." +                ); +            } +            Self::Wgpu(renderer) => { +                renderer.draw_pipeline_primitive(bounds, primitive); +            } +        } +    } +} diff --git a/renderer/src/widget.rs b/renderer/src/widget.rs deleted file mode 100644 index 4b7dad5d..00000000 --- a/renderer/src/widget.rs +++ /dev/null @@ -1,2 +0,0 @@ -#[cfg(feature = "wgpu")] -pub mod shader; diff --git a/wgpu/src/backend.rs b/wgpu/src/backend.rs index 27ef0b3c..f89bcee1 100644 --- a/wgpu/src/backend.rs +++ b/wgpu/src/backend.rs @@ -2,8 +2,11 @@ use crate::core::{Color, Size};  use crate::graphics::backend;  use crate::graphics::color;  use crate::graphics::{Transformation, Viewport}; +use crate::primitive::pipeline;  use crate::primitive::{self, Primitive}; -use crate::{custom, quad, text, triangle}; +use crate::quad; +use crate::text; +use crate::triangle;  use crate::{Layer, Settings};  #[cfg(feature = "tracing")] @@ -23,7 +26,7 @@ pub struct Backend {      quad_pipeline: quad::Pipeline,      text_pipeline: text::Pipeline,      triangle_pipeline: triangle::Pipeline, -    pipeline_storage: custom::Storage, +    pipeline_storage: pipeline::Storage,      #[cfg(any(feature = "image", feature = "svg"))]      image_pipeline: image::Pipeline, @@ -49,7 +52,7 @@ impl Backend {              quad_pipeline,              text_pipeline,              triangle_pipeline, -            pipeline_storage: custom::Storage::default(), +            pipeline_storage: pipeline::Storage::default(),              #[cfg(any(feature = "image", feature = "svg"))]              image_pipeline, @@ -183,9 +186,9 @@ impl Backend {                  );              } -            if !layer.shaders.is_empty() { -                for shader in &layer.shaders { -                    shader.primitive.prepare( +            if !layer.pipelines.is_empty() { +                for pipeline in &layer.pipelines { +                    pipeline.primitive.prepare(                          format,                          device,                          queue, @@ -323,19 +326,17 @@ impl Backend {              // kill render pass to let custom shaders get mut access to encoder              let _ = ManuallyDrop::into_inner(render_pass); -            if !layer.shaders.is_empty() { -                for shader in &layer.shaders { -                    //This extra check is needed since each custom pipeline must set it's own -                    //scissor rect, which will panic if bounds.w/h < 1 -                    let bounds = shader.bounds * scale_factor; +            if !layer.pipelines.is_empty() { +                for pipeline in &layer.pipelines { +                    let bounds = (pipeline.bounds * scale_factor).snap(); -                    if bounds.width < 1.0 || bounds.height < 1.0 { +                    if bounds.width < 1 || bounds.height < 1 {                          continue;                      } -                    shader.primitive.render( +                    pipeline.primitive.render(                          &self.pipeline_storage, -                        bounds.snap(), +                        bounds,                          target,                          target_size,                          encoder, diff --git a/wgpu/src/custom.rs b/wgpu/src/custom.rs index 65a6f133..98e2b396 100644 --- a/wgpu/src/custom.rs +++ b/wgpu/src/custom.rs @@ -1,67 +1,8 @@  //! Draw custom primitives.  use crate::core::{Rectangle, Size};  use crate::graphics::Transformation; +use crate::primitive; +  use std::any::{Any, TypeId};  use std::collections::HashMap;  use std::fmt::Debug; - -/// Stores custom, user-provided pipelines. -#[derive(Default, Debug)] -pub struct Storage { -    pipelines: HashMap<TypeId, Box<dyn Any>>, -} - -impl Storage { -    /// Returns `true` if `Storage` contains a pipeline with type `T`. -    pub fn has<T: 'static>(&self) -> bool { -        self.pipelines.get(&TypeId::of::<T>()).is_some() -    } - -    /// Inserts the pipeline `T` in to [`Storage`]. -    pub fn store<T: 'static>(&mut self, pipeline: T) { -        let _ = self.pipelines.insert(TypeId::of::<T>(), Box::new(pipeline)); -    } - -    /// Returns a reference to pipeline with type `T` if it exists in [`Storage`]. -    pub fn get<T: 'static>(&self) -> Option<&T> { -        self.pipelines.get(&TypeId::of::<T>()).map(|pipeline| { -            pipeline -                .downcast_ref::<T>() -                .expect("Pipeline with this type does not exist in Storage.") -        }) -    } - -    /// Returns a mutable reference to pipeline `T` if it exists in [`Storage`]. -    pub fn get_mut<T: 'static>(&mut self) -> Option<&mut T> { -        self.pipelines.get_mut(&TypeId::of::<T>()).map(|pipeline| { -            pipeline -                .downcast_mut::<T>() -                .expect("Pipeline with this type does not exist in Storage.") -        }) -    } -} - -/// A set of methods which allows a [`Primitive`] to be rendered. -pub trait Primitive: Debug + Send + Sync + 'static { -    /// Processes the [`Primitive`], allowing for GPU buffer allocation. -    fn prepare( -        &self, -        format: wgpu::TextureFormat, -        device: &wgpu::Device, -        queue: &wgpu::Queue, -        target_size: Size<u32>, -        scale_factor: f32, -        transform: Transformation, -        storage: &mut Storage, -    ); - -    /// Renders the [`Primitive`]. -    fn render( -        &self, -        storage: &Storage, -        bounds: Rectangle<u32>, -        target: &wgpu::TextureView, -        target_size: Size<u32>, -        encoder: &mut wgpu::CommandEncoder, -    ); -} diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index d451cbfd..33aaf670 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -35,8 +35,8 @@ pub struct Layer<'a> {      /// The images of the [`Layer`].      pub images: Vec<Image>, -    /// The custom shader primitives of this [`Layer`]. -    pub shaders: Vec<primitive::Shader>, +    /// The custom pipelines of this [`Layer`]. +    pub pipelines: Vec<primitive::Pipeline>,  }  impl<'a> Layer<'a> { @@ -48,7 +48,7 @@ impl<'a> Layer<'a> {              meshes: Vec::new(),              text: Vec::new(),              images: Vec::new(), -            shaders: Vec::new(), +            pipelines: Vec::new(),          }      } @@ -312,16 +312,21 @@ impl<'a> Layer<'a> {                          }                      }                  }, -                primitive::Custom::Shader(shader) => { +                primitive::Custom::Pipeline(pipeline) => {                      let layer = &mut layers[current_layer];                      let bounds = Rectangle::new(                          Point::new(translation.x, translation.y), -                        shader.bounds.size(), +                        pipeline.bounds.size(),                      ); -                    if layer.bounds.intersection(&bounds).is_some() { -                        layer.shaders.push(shader.clone()); +                    if let Some(clip_bounds) = +                        layer.bounds.intersection(&bounds) +                    { +                        layer.pipelines.push(primitive::Pipeline { +                            bounds: clip_bounds, +                            primitive: pipeline.primitive.clone(), +                        });                      }                  }              }, diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 13d8e886..424dfeb3 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -29,7 +29,6 @@      rustdoc::broken_intra_doc_links  )]  #![cfg_attr(docsrs, feature(doc_auto_cfg))] -pub mod custom;  pub mod layer;  pub mod primitive;  pub mod settings; diff --git a/wgpu/src/primitive.rs b/wgpu/src/primitive.rs index 4347dcda..fff927ea 100644 --- a/wgpu/src/primitive.rs +++ b/wgpu/src/primitive.rs @@ -1,10 +1,12 @@  //! Draw using different graphical primitives. +pub mod pipeline; + +pub use pipeline::Pipeline; +  use crate::core::Rectangle; -use crate::custom;  use crate::graphics::{Damage, Mesh}; -use std::any::Any; +  use std::fmt::Debug; -use std::sync::Arc;  /// The graphical primitives supported by `iced_wgpu`.  pub type Primitive = crate::graphics::Primitive<Custom>; @@ -14,44 +16,15 @@ pub type Primitive = crate::graphics::Primitive<Custom>;  pub enum Custom {      /// A mesh primitive.      Mesh(Mesh), -    /// A custom shader primitive -    Shader(Shader), -} - -impl Custom { -    /// Create a custom [`Shader`] primitive. -    pub fn shader<P: custom::Primitive>( -        bounds: Rectangle, -        primitive: P, -    ) -> Self { -        Self::Shader(Shader { -            bounds, -            primitive: Arc::new(primitive), -        }) -    } +    /// A custom pipeline primitive. +    Pipeline(Pipeline),  }  impl Damage for Custom {      fn bounds(&self) -> Rectangle {          match self {              Self::Mesh(mesh) => mesh.bounds(), -            Self::Shader(shader) => shader.bounds, +            Self::Pipeline(pipeline) => pipeline.bounds,          }      }  } - -#[derive(Clone, Debug)] -/// A custom primitive which can be used to render primitives associated with a custom pipeline. -pub struct Shader { -    /// The bounds of the [`Shader`]. -    pub bounds: Rectangle, - -    /// The [`custom::Primitive`] to render. -    pub primitive: Arc<dyn custom::Primitive>, -} - -impl PartialEq for Shader { -    fn eq(&self, other: &Self) -> bool { -        self.primitive.type_id() == other.primitive.type_id() -    } -} diff --git a/wgpu/src/primitive/pipeline.rs b/wgpu/src/primitive/pipeline.rs new file mode 100644 index 00000000..b59aeff1 --- /dev/null +++ b/wgpu/src/primitive/pipeline.rs @@ -0,0 +1,117 @@ +//! Draw primitives using custom pipelines. +use crate::core::{Rectangle, Size}; +use crate::graphics::Transformation; + +use std::any::{Any, TypeId}; +use std::collections::HashMap; +use std::fmt::Debug; +use std::sync::Arc; + +#[derive(Clone, Debug)] +/// A custom primitive which can be used to render primitives associated with a custom pipeline. +pub struct Pipeline { +    /// The bounds of the [`Shader`]. +    pub bounds: Rectangle, + +    /// The [`custom::Primitive`] to render. +    pub primitive: Arc<dyn Primitive>, +} + +impl Pipeline { +    /// Creates a new [`Pipeline`] with the given [`Primitive`]. +    pub fn new(bounds: Rectangle, primitive: impl Primitive) -> Self { +        Pipeline { +            bounds, +            primitive: Arc::new(primitive), +        } +    } +} + +impl PartialEq for Pipeline { +    fn eq(&self, other: &Self) -> bool { +        self.primitive.type_id() == other.primitive.type_id() +    } +} + +/// A set of methods which allows a [`Primitive`] to be rendered. +pub trait Primitive: Debug + Send + Sync + 'static { +    /// Processes the [`Primitive`], allowing for GPU buffer allocation. +    fn prepare( +        &self, +        format: wgpu::TextureFormat, +        device: &wgpu::Device, +        queue: &wgpu::Queue, +        target_size: Size<u32>, +        scale_factor: f32, +        transform: Transformation, +        storage: &mut Storage, +    ); + +    /// Renders the [`Primitive`]. +    fn render( +        &self, +        storage: &Storage, +        bounds: Rectangle<u32>, +        target: &wgpu::TextureView, +        target_size: Size<u32>, +        encoder: &mut wgpu::CommandEncoder, +    ); +} + +/// A renderer than can draw custom pipeline primitives. +pub trait Renderer: crate::core::Renderer { +    /// Draws a custom pipeline primitive. +    fn draw_pipeline_primitive( +        &mut self, +        bounds: Rectangle, +        primitive: impl Primitive, +    ); +} + +impl<Theme> Renderer for crate::Renderer<Theme> { +    fn draw_pipeline_primitive( +        &mut self, +        bounds: Rectangle, +        primitive: impl Primitive, +    ) { +        self.draw_primitive(super::Primitive::Custom(super::Custom::Pipeline( +            Pipeline::new(bounds, primitive), +        ))); +    } +} + +/// Stores custom, user-provided pipelines. +#[derive(Default, Debug)] +pub struct Storage { +    pipelines: HashMap<TypeId, Box<dyn Any>>, +} + +impl Storage { +    /// Returns `true` if `Storage` contains a pipeline with type `T`. +    pub fn has<T: 'static>(&self) -> bool { +        self.pipelines.get(&TypeId::of::<T>()).is_some() +    } + +    /// Inserts the pipeline `T` in to [`Storage`]. +    pub fn store<T: 'static>(&mut self, pipeline: T) { +        let _ = self.pipelines.insert(TypeId::of::<T>(), Box::new(pipeline)); +    } + +    /// Returns a reference to pipeline with type `T` if it exists in [`Storage`]. +    pub fn get<T: 'static>(&self) -> Option<&T> { +        self.pipelines.get(&TypeId::of::<T>()).map(|pipeline| { +            pipeline +                .downcast_ref::<T>() +                .expect("Pipeline with this type does not exist in Storage.") +        }) +    } + +    /// Returns a mutable reference to pipeline `T` if it exists in [`Storage`]. +    pub fn get_mut<T: 'static>(&mut self) -> Option<&mut T> { +        self.pipelines.get_mut(&TypeId::of::<T>()).map(|pipeline| { +            pipeline +                .downcast_mut::<T>() +                .expect("Pipeline with this type does not exist in Storage.") +        }) +    } +} diff --git a/widget/src/lib.rs b/widget/src/lib.rs index 5220e83a..07378d83 100644 --- a/widget/src/lib.rs +++ b/widget/src/lib.rs @@ -98,7 +98,11 @@ pub use tooltip::Tooltip;  pub use vertical_slider::VerticalSlider;  #[cfg(feature = "wgpu")] -pub use renderer::widget::shader::{self, Shader, Transformation}; +pub mod shader; + +#[cfg(feature = "wgpu")] +#[doc(no_inline)] +pub use shader::Shader;  #[cfg(feature = "svg")]  pub mod svg; diff --git a/renderer/src/widget/shader.rs b/widget/src/shader.rs index e218f35a..9d482537 100644 --- a/renderer/src/widget/shader.rs +++ b/widget/src/shader.rs @@ -1,25 +1,24 @@  //! A custom shader widget for wgpu applications. -use crate::core::event::Status; -use crate::core::layout::{Limits, Node}; -use crate::core::mouse::{Cursor, Interaction}; -use crate::core::renderer::Style; -use crate::core::widget::tree::{State, Tag}; -use crate::core::widget::{tree, Tree}; -use crate::core::{ -    self, layout, mouse, widget, window, Clipboard, Element, Layout, Length, -    Rectangle, Shell, Size, Widget, -}; -use std::marker::PhantomData; -  mod event;  mod program;  pub use event::Event; -pub use iced_graphics::Transformation; -pub use iced_wgpu::custom::Primitive; -pub use iced_wgpu::custom::Storage;  pub use program::Program; +use crate::core; +use crate::core::layout::{self, Layout}; +use crate::core::mouse; +use crate::core::renderer; +use crate::core::widget::tree::{self, Tree}; +use crate::core::widget::{self, Widget}; +use crate::core::window; +use crate::core::{Clipboard, Element, Length, Rectangle, Shell, Size}; +use crate::renderer::wgpu::primitive::pipeline; + +use std::marker::PhantomData; + +pub use pipeline::{Primitive, Storage}; +  /// A widget which can render custom shaders with Iced's `wgpu` backend.  ///  /// Must be initialized with a [`Program`], which describes the internal widget state & how @@ -56,17 +55,17 @@ impl<Message, P: Program<Message>> Shader<Message, P> {      }  } -impl<P, Message, Theme> Widget<Message, crate::Renderer<Theme>> -    for Shader<Message, P> +impl<P, Message, Renderer> Widget<Message, Renderer> for Shader<Message, P>  where      P: Program<Message>, +    Renderer: pipeline::Renderer,  { -    fn tag(&self) -> Tag { +    fn tag(&self) -> tree::Tag {          struct Tag<T>(T);          tree::Tag::of::<Tag<P::State>>()      } -    fn state(&self) -> State { +    fn state(&self) -> tree::State {          tree::State::new(P::State::default())      } @@ -81,9 +80,9 @@ where      fn layout(          &self,          _tree: &mut Tree, -        _renderer: &crate::Renderer<Theme>, -        limits: &Limits, -    ) -> Node { +        _renderer: &Renderer, +        limits: &layout::Limits, +    ) -> layout::Node {          let limits = limits.width(self.width).height(self.height);          let size = limits.resolve(Size::ZERO); @@ -95,12 +94,12 @@ where          tree: &mut Tree,          event: crate::core::Event,          layout: Layout<'_>, -        cursor: Cursor, -        _renderer: &crate::Renderer<Theme>, +        cursor: mouse::Cursor, +        _renderer: &Renderer,          _clipboard: &mut dyn Clipboard,          shell: &mut Shell<'_, Message>,          _viewport: &Rectangle, -    ) -> Status { +    ) -> event::Status {          let bounds = layout.bounds();          let custom_shader_event = match event { @@ -140,9 +139,9 @@ where          &self,          tree: &Tree,          layout: Layout<'_>, -        cursor: Cursor, +        cursor: mouse::Cursor,          _viewport: &Rectangle, -        _renderer: &crate::Renderer<Theme>, +        _renderer: &Renderer,      ) -> mouse::Interaction {          let bounds = layout.bounds();          let state = tree.state.downcast_ref::<P::State>(); @@ -153,9 +152,9 @@ where      fn draw(          &self,          tree: &widget::Tree, -        renderer: &mut crate::Renderer<Theme>, -        _theme: &Theme, -        _style: &Style, +        renderer: &mut Renderer, +        _theme: &Renderer::Theme, +        _style: &renderer::Style,          layout: Layout<'_>,          cursor_position: mouse::Cursor,          _viewport: &Rectangle, @@ -163,20 +162,21 @@ where          let bounds = layout.bounds();          let state = tree.state.downcast_ref::<P::State>(); -        renderer.draw_custom( +        renderer.draw_pipeline_primitive(              bounds,              self.program.draw(state, cursor_position, bounds),          );      }  } -impl<'a, M, P, Theme> From<Shader<M, P>> -    for Element<'a, M, crate::Renderer<Theme>> +impl<'a, Message, Renderer, P> From<Shader<Message, P>> +    for Element<'a, Message, Renderer>  where -    M: 'a, -    P: Program<M> + 'a, +    Message: 'a, +    Renderer: pipeline::Renderer, +    P: Program<Message> + 'a,  { -    fn from(custom: Shader<M, P>) -> Element<'a, M, crate::Renderer<Theme>> { +    fn from(custom: Shader<Message, P>) -> Element<'a, Message, Renderer> {          Element::new(custom)      }  } @@ -193,16 +193,16 @@ where          state: &mut Self::State,          event: Event,          bounds: Rectangle, -        cursor: Cursor, +        cursor: mouse::Cursor,          shell: &mut Shell<'_, Message>, -    ) -> (Status, Option<Message>) { +    ) -> (event::Status, Option<Message>) {          T::update(self, state, event, bounds, cursor, shell)      }      fn draw(          &self,          state: &Self::State, -        cursor: Cursor, +        cursor: mouse::Cursor,          bounds: Rectangle,      ) -> Self::Primitive {          T::draw(self, state, cursor, bounds) @@ -212,8 +212,8 @@ where          &self,          state: &Self::State,          bounds: Rectangle, -        cursor: Cursor, -    ) -> Interaction { +        cursor: mouse::Cursor, +    ) -> mouse::Interaction {          T::mouse_interaction(self, state, bounds, cursor)      }  } diff --git a/renderer/src/widget/shader/event.rs b/widget/src/shader/event.rs index 8901fb31..e4d2b03d 100644 --- a/renderer/src/widget/shader/event.rs +++ b/widget/src/shader/event.rs @@ -2,6 +2,7 @@  use crate::core::keyboard;  use crate::core::mouse;  use crate::core::touch; +  use std::time::Instant;  pub use crate::core::event::Status; diff --git a/renderer/src/widget/shader/program.rs b/widget/src/shader/program.rs index b8871688..0319844d 100644 --- a/renderer/src/widget/shader/program.rs +++ b/widget/src/shader/program.rs @@ -1,6 +1,8 @@ -use crate::core::{event, mouse, Rectangle, Shell}; -use crate::widget; -use widget::shader; +use crate::core::event; +use crate::core::mouse; +use crate::core::{Rectangle, Shell}; +use crate::renderer::wgpu::primitive::pipeline; +use crate::shader;  /// The state and logic of a [`Shader`] widget.  /// @@ -13,7 +15,7 @@ pub trait Program<Message> {      type State: Default + 'static;      /// The type of primitive this [`Program`] can draw. -    type Primitive: shader::Primitive + 'static; +    type Primitive: pipeline::Primitive + 'static;      /// Update the internal [`State`] of the [`Program`]. This can be used to reflect state changes      /// based on mouse & other events. You can use the [`Shell`] to publish messages, request a | 
