Simplify integration example with Program

This commit is contained in:
Héctor Ramón Jiménez 2020-05-21 04:54:26 +02:00
parent ae5e2c6c73
commit d54f17c6aa
3 changed files with 67 additions and 116 deletions

View File

@ -1,11 +1,11 @@
use crate::Scene;
use iced_wgpu::Renderer; use iced_wgpu::Renderer;
use iced_winit::{ use iced_winit::{
slider, Align, Color, Column, Element, Length, Row, Slider, Text, slider, Align, Color, Column, Command, Element, Length, Program, Row,
Slider, Text,
}; };
pub struct Controls { pub struct Controls {
background_color: Color,
sliders: [slider::State; 3], sliders: [slider::State; 3],
} }
@ -17,58 +17,55 @@ pub enum Message {
impl Controls { impl Controls {
pub fn new() -> Controls { pub fn new() -> Controls {
Controls { Controls {
background_color: Color::BLACK,
sliders: Default::default(), sliders: Default::default(),
} }
} }
pub fn update(&self, message: Message, scene: &mut Scene) { pub fn background_color(&self) -> Color {
self.background_color
}
}
impl Program for Controls {
type Renderer = Renderer;
type Message = Message;
fn update(&mut self, message: Message) -> Command<Message> {
match message { match message {
Message::BackgroundColorChanged(color) => { Message::BackgroundColorChanged(color) => {
scene.background_color = color; self.background_color = color;
} }
} }
Command::none()
} }
pub fn view(&mut self, scene: &Scene) -> Element<Message, Renderer> { fn view(&mut self) -> Element<Message, Renderer> {
let [r, g, b] = &mut self.sliders; let [r, g, b] = &mut self.sliders;
let background_color = scene.background_color; let background_color = self.background_color;
let sliders = Row::new() let sliders = Row::new()
.width(Length::Units(500)) .width(Length::Units(500))
.spacing(20) .spacing(20)
.push(Slider::new( .push(Slider::new(r, 0.0..=1.0, background_color.r, move |r| {
r, Message::BackgroundColorChanged(Color {
0.0..=1.0, r,
scene.background_color.r, ..background_color
move |r| { })
Message::BackgroundColorChanged(Color { }))
r, .push(Slider::new(g, 0.0..=1.0, background_color.g, move |g| {
..background_color Message::BackgroundColorChanged(Color {
}) g,
}, ..background_color
)) })
.push(Slider::new( }))
g, .push(Slider::new(b, 0.0..=1.0, background_color.b, move |b| {
0.0..=1.0, Message::BackgroundColorChanged(Color {
scene.background_color.g, b,
move |g| { ..background_color
Message::BackgroundColorChanged(Color { })
g, }));
..background_color
})
},
))
.push(Slider::new(
b,
0.0..=1.0,
scene.background_color.b,
move |b| {
Message::BackgroundColorChanged(Color {
b,
..background_color
})
},
));
Row::new() Row::new()
.width(Length::Fill) .width(Length::Fill)

View File

@ -4,10 +4,8 @@ mod scene;
use controls::Controls; use controls::Controls;
use scene::Scene; use scene::Scene;
use iced_wgpu::{wgpu, Backend, Primitive, Renderer, Settings, Viewport}; use iced_wgpu::{wgpu, Backend, Renderer, Settings, Viewport};
use iced_winit::{ use iced_winit::{futures, program, winit, Debug, Size};
futures, mouse, winit, Cache, Clipboard, Size, UserInterface,
};
use winit::{ use winit::{
event::{Event, ModifiersState, WindowEvent}, event::{Event, ModifiersState, WindowEvent},
@ -28,8 +26,7 @@ pub fn main() {
); );
let mut modifiers = ModifiersState::default(); let mut modifiers = ModifiersState::default();
// Initialize WGPU // Initialize wgpu
let surface = wgpu::Surface::create(&window); let surface = wgpu::Surface::create(&window);
let (mut device, queue) = futures::executor::block_on(async { let (mut device, queue) = futures::executor::block_on(async {
let adapter = wgpu::Adapter::request( let adapter = wgpu::Adapter::request(
@ -70,17 +67,21 @@ pub fn main() {
}; };
let mut resized = false; let mut resized = false;
// Initialize scene and GUI controls
let scene = Scene::new(&mut device);
let controls = Controls::new();
// Initialize iced // Initialize iced
let mut events = Vec::new(); let mut debug = Debug::new();
let mut cache = Some(Cache::default());
let mut renderer = let mut renderer =
Renderer::new(Backend::new(&mut device, Settings::default())); Renderer::new(Backend::new(&mut device, Settings::default()));
let mut output = (Primitive::None, mouse::Interaction::default());
let clipboard = Clipboard::new(&window);
// Initialize scene and GUI controls let mut state = program::State::new(
let mut scene = Scene::new(&device); controls,
let mut controls = Controls::new(); viewport.logical_size(),
&mut renderer,
&mut debug,
);
// Run event loop // Run event loop
event_loop.run(move |event, _, control_flow| { event_loop.run(move |event, _, control_flow| {
@ -114,69 +115,18 @@ pub fn main() {
window.scale_factor(), window.scale_factor(),
modifiers, modifiers,
) { ) {
events.push(event); state.queue_event(event);
} }
} }
Event::MainEventsCleared => { Event::MainEventsCleared => {
// If no relevant events happened, we can simply skip this // We update iced
if events.is_empty() { let _ = state.update(
return; None,
}
// We need to:
// 1. Process events of our user interface.
// 2. Update state as a result of any interaction.
// 3. Generate a new output for our renderer.
// First, we build our user interface.
let mut user_interface = UserInterface::build(
controls.view(&scene),
viewport.logical_size(), viewport.logical_size(),
cache.take().unwrap(),
&mut renderer, &mut renderer,
&mut debug,
); );
// Then, we process the events, obtaining messages in return.
let messages = user_interface.update(
events.drain(..),
clipboard.as_ref().map(|c| c as _),
&renderer,
);
let user_interface = if messages.is_empty() {
// If there are no messages, no interactions we care about have
// happened. We can simply leave our user interface as it is.
user_interface
} else {
// If there are messages, we need to update our state
// accordingly and rebuild our user interface.
// We can only do this if we drop our user interface first
// by turning it into its cache.
cache = Some(user_interface.into_cache());
// In this example, `Controls` is the only part that cares
// about messages, so updating our state is pretty
// straightforward.
for message in messages {
controls.update(message, &mut scene);
}
// Once the state has been changed, we rebuild our updated
// user interface.
UserInterface::build(
controls.view(&scene),
viewport.logical_size(),
cache.take().unwrap(),
&mut renderer,
)
};
// Finally, we just need to draw a new output for our renderer,
output = user_interface.draw(&mut renderer);
// update our cache,
cache = Some(user_interface.into_cache());
// and request a redraw // and request a redraw
window.request_redraw(); window.request_redraw();
} }
@ -203,7 +153,13 @@ pub fn main() {
); );
// We draw the scene first // We draw the scene first
scene.draw(&mut encoder, &frame.view); let program = state.program();
scene.draw(
&mut encoder,
&frame.view,
program.background_color(),
);
// And then iced on top // And then iced on top
let mouse_interaction = renderer.backend_mut().draw( let mouse_interaction = renderer.backend_mut().draw(
@ -211,8 +167,8 @@ pub fn main() {
&mut encoder, &mut encoder,
&frame.view, &frame.view,
&viewport, &viewport,
&output, state.primitive(),
&["Some debug information!"], &debug.overlay(),
); );
// Then we submit the work // Then we submit the work

View File

@ -2,7 +2,6 @@ use iced_wgpu::wgpu;
use iced_winit::Color; use iced_winit::Color;
pub struct Scene { pub struct Scene {
pub background_color: Color,
pipeline: wgpu::RenderPipeline, pipeline: wgpu::RenderPipeline,
bind_group: wgpu::BindGroup, bind_group: wgpu::BindGroup,
} }
@ -12,7 +11,6 @@ impl Scene {
let (pipeline, bind_group) = build_pipeline(device); let (pipeline, bind_group) = build_pipeline(device);
Scene { Scene {
background_color: Color::BLACK,
pipeline, pipeline,
bind_group, bind_group,
} }
@ -22,6 +20,7 @@ impl Scene {
&self, &self,
encoder: &mut wgpu::CommandEncoder, encoder: &mut wgpu::CommandEncoder,
target: &wgpu::TextureView, target: &wgpu::TextureView,
background_color: Color,
) { ) {
let mut rpass = let mut rpass =
encoder.begin_render_pass(&wgpu::RenderPassDescriptor { encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
@ -32,8 +31,7 @@ impl Scene {
load_op: wgpu::LoadOp::Clear, load_op: wgpu::LoadOp::Clear,
store_op: wgpu::StoreOp::Store, store_op: wgpu::StoreOp::Store,
clear_color: { clear_color: {
let [r, g, b, a] = let [r, g, b, a] = background_color.into_linear();
self.background_color.into_linear();
wgpu::Color { wgpu::Color {
r: r as f64, r: r as f64,