-
-
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 #183 from hecrj/feature/wgpu-integration
Integration with existing `wgpu` projects
- Loading branch information
Showing
25 changed files
with
893 additions
and
377 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
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,11 @@ | ||
[package] | ||
name = "integration" | ||
version = "0.1.0" | ||
authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"] | ||
edition = "2018" | ||
publish = false | ||
|
||
[dependencies] | ||
iced_winit = { path = "../../winit" } | ||
iced_wgpu = { path = "../../wgpu" } | ||
env_logger = "0.7" |
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,102 @@ | ||
use crate::Scene; | ||
|
||
use iced_wgpu::Renderer; | ||
use iced_winit::{ | ||
slider, Align, Color, Column, Element, Length, Row, Slider, Text, | ||
}; | ||
|
||
pub struct Controls { | ||
sliders: [slider::State; 3], | ||
} | ||
|
||
#[derive(Debug)] | ||
pub enum Message { | ||
BackgroundColorChanged(Color), | ||
} | ||
|
||
impl Controls { | ||
pub fn new() -> Controls { | ||
Controls { | ||
sliders: Default::default(), | ||
} | ||
} | ||
|
||
pub fn update(&self, message: Message, scene: &mut Scene) { | ||
match message { | ||
Message::BackgroundColorChanged(color) => { | ||
scene.background_color = color; | ||
} | ||
} | ||
} | ||
|
||
pub fn view<'a>( | ||
&'a mut self, | ||
scene: &Scene, | ||
) -> Element<'a, Message, Renderer> { | ||
let [r, g, b] = &mut self.sliders; | ||
let background_color = scene.background_color; | ||
|
||
let sliders = Row::new() | ||
.width(Length::Units(500)) | ||
.spacing(20) | ||
.push(Slider::new( | ||
r, | ||
0.0..=1.0, | ||
scene.background_color.r, | ||
move |r| { | ||
Message::BackgroundColorChanged(Color { | ||
r, | ||
..background_color | ||
}) | ||
}, | ||
)) | ||
.push(Slider::new( | ||
g, | ||
0.0..=1.0, | ||
scene.background_color.g, | ||
move |g| { | ||
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() | ||
.width(Length::Fill) | ||
.height(Length::Fill) | ||
.align_items(Align::End) | ||
.push( | ||
Column::new() | ||
.width(Length::Fill) | ||
.align_items(Align::End) | ||
.push( | ||
Column::new() | ||
.padding(10) | ||
.spacing(10) | ||
.push( | ||
Text::new("Background color") | ||
.color(Color::WHITE), | ||
) | ||
.push(sliders) | ||
.push( | ||
Text::new(format!("{:?}", background_color)) | ||
.size(14) | ||
.color(Color::WHITE), | ||
), | ||
), | ||
) | ||
.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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
mod controls; | ||
mod scene; | ||
|
||
use controls::Controls; | ||
use scene::Scene; | ||
|
||
use iced_wgpu::{ | ||
wgpu, window::SwapChain, Primitive, Renderer, Settings, Target, | ||
}; | ||
use iced_winit::{winit, Cache, Clipboard, MouseCursor, Size, UserInterface}; | ||
|
||
use winit::{ | ||
event::{DeviceEvent, Event, ModifiersState, WindowEvent}, | ||
event_loop::{ControlFlow, EventLoop}, | ||
}; | ||
|
||
pub fn main() { | ||
env_logger::init(); | ||
|
||
// Initialize winit | ||
let event_loop = EventLoop::new(); | ||
let window = winit::window::Window::new(&event_loop).unwrap(); | ||
let mut logical_size = | ||
window.inner_size().to_logical(window.scale_factor()); | ||
let mut modifiers = ModifiersState::default(); | ||
|
||
// Initialize WGPU | ||
let adapter = wgpu::Adapter::request(&wgpu::RequestAdapterOptions { | ||
power_preference: wgpu::PowerPreference::Default, | ||
backends: wgpu::BackendBit::PRIMARY, | ||
}) | ||
.expect("Request adapter"); | ||
|
||
let (mut device, mut queue) = | ||
adapter.request_device(&wgpu::DeviceDescriptor { | ||
extensions: wgpu::Extensions { | ||
anisotropic_filtering: false, | ||
}, | ||
limits: wgpu::Limits::default(), | ||
}); | ||
|
||
let surface = wgpu::Surface::create(&window); | ||
|
||
let mut swap_chain = { | ||
let size = window.inner_size(); | ||
|
||
SwapChain::new(&device, &surface, size.width, size.height) | ||
}; | ||
let mut resized = false; | ||
|
||
// Initialize iced | ||
let mut events = Vec::new(); | ||
let mut cache = Some(Cache::default()); | ||
let mut renderer = Renderer::new(&mut device, Settings::default()); | ||
let mut output = (Primitive::None, MouseCursor::OutOfBounds); | ||
let clipboard = Clipboard::new(&window); | ||
|
||
// Initialize scene and GUI controls | ||
let mut scene = Scene::new(&device); | ||
let mut controls = Controls::new(); | ||
|
||
// Run event loop | ||
event_loop.run(move |event, _, control_flow| { | ||
// You should change this if you want to render continuosly | ||
*control_flow = ControlFlow::Wait; | ||
|
||
match event { | ||
Event::DeviceEvent { | ||
event: DeviceEvent::ModifiersChanged(new_modifiers), | ||
.. | ||
} => { | ||
modifiers = new_modifiers; | ||
} | ||
Event::WindowEvent { event, .. } => { | ||
match event { | ||
WindowEvent::Resized(new_size) => { | ||
logical_size = | ||
new_size.to_logical(window.scale_factor()); | ||
resized = true; | ||
} | ||
WindowEvent::CloseRequested => { | ||
*control_flow = ControlFlow::Exit; | ||
} | ||
_ => {} | ||
} | ||
|
||
// Map window event to iced event | ||
if let Some(event) = iced_winit::conversion::window_event( | ||
event, | ||
window.scale_factor(), | ||
modifiers, | ||
) { | ||
events.push(event); | ||
} | ||
} | ||
Event::MainEventsCleared => { | ||
// If no relevant events happened, we can simply skip this | ||
if events.is_empty() { | ||
return; | ||
} | ||
|
||
// 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), | ||
Size::new(logical_size.width, logical_size.height), | ||
cache.take().unwrap(), | ||
&mut renderer, | ||
); | ||
|
||
// 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), | ||
Size::new(logical_size.width, logical_size.height), | ||
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 | ||
window.request_redraw(); | ||
} | ||
Event::RedrawRequested(_) => { | ||
if resized { | ||
let size = window.inner_size(); | ||
|
||
swap_chain = SwapChain::new( | ||
&device, | ||
&surface, | ||
size.width, | ||
size.height, | ||
); | ||
} | ||
|
||
let (frame, viewport) = swap_chain.next_frame(); | ||
|
||
let mut encoder = device.create_command_encoder( | ||
&wgpu::CommandEncoderDescriptor { todo: 0 }, | ||
); | ||
|
||
// We draw the scene first | ||
scene.draw(&mut encoder, &frame.view); | ||
|
||
// And then iced on top | ||
let mouse_cursor = renderer.draw( | ||
&mut device, | ||
&mut encoder, | ||
Target { | ||
texture: &frame.view, | ||
viewport, | ||
}, | ||
&output, | ||
window.scale_factor(), | ||
&["Some debug information!"], | ||
); | ||
|
||
// Then we submit the work | ||
queue.submit(&[encoder.finish()]); | ||
|
||
// And update the mouse cursor | ||
window.set_cursor_icon(iced_winit::conversion::mouse_cursor( | ||
mouse_cursor, | ||
)); | ||
} | ||
_ => {} | ||
} | ||
}) | ||
} |
Oops, something went wrong.