mod controls;
mod scene;
use controls::Controls;
use scene::Scene;
use glow::*;
use glutin::dpi::PhysicalPosition;
use glutin::event::{Event, ModifiersState, WindowEvent};
use glutin::event_loop::ControlFlow;
use iced_glow::glow;
use iced_glow::{Backend, Renderer, Settings, Viewport};
use iced_glutin::conversion;
use iced_glutin::glutin;
use iced_glutin::{program, Clipboard, Debug, Size};
pub fn main() {
env_logger::init();
let (gl, event_loop, windowed_context, shader_version) = {
let el = glutin::event_loop::EventLoop::new();
let wb = glutin::window::WindowBuilder::new()
.with_title("OpenGL integration example")
.with_inner_size(glutin::dpi::LogicalSize::new(1024.0, 768.0));
let windowed_context = glutin::ContextBuilder::new()
.with_vsync(true)
.build_windowed(wb, &el)
.unwrap();
unsafe {
let windowed_context = windowed_context.make_current().unwrap();
let gl = glow::Context::from_loader_function(|s| {
windowed_context.get_proc_address(s) as *const _
});
// Enable auto-conversion from/to sRGB
gl.enable(glow::FRAMEBUFFER_SRGB);
// Enable alpha blending
gl.enable(glow::BLEND);
gl.blend_func(glow::SRC_ALPHA, glow::ONE_MINUS_SRC_ALPHA);
// Disable multisampling by default
gl.disable(glow::MULTISAMPLE);
(gl, el, windowed_context, "#version 410")
}
};
let physical_size = windowed_context.window().inner_size();
let mut viewport = Viewport::with_physical_size(
Size::new(physical_size.width, physical_size.height),
windowed_context.window().scale_factor(),
);
let mut cursor_position = PhysicalPosition::new(-1.0, -1.0);
let mut modifiers = ModifiersState::default();
let mut clipboard = Clipboard::connect(&windowed_context.window());
let mut renderer = Renderer::new(Backend::new(&gl, Settings::default()));
let mut debug = Debug::new();
let controls = Controls::new();
let mut state = program::State::new(
controls,
viewport.logical_size(),
&mut renderer,
&mut debug,
);
let mut resized = false;
let scene = Scene::new(&gl, &shader_version);
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Wait;
match event {
Event::LoopDestroyed => return,
Event::WindowEvent { event, .. } => {
match event {
WindowEvent::CursorMoved { position, .. } => {
cursor_position = position;
}
WindowEvent::ModifiersChanged(new_modifiers) => {
modifiers = new_modifiers;
}
WindowEvent::Resized(physical_size) => {
viewport = Viewport::with_physical_size(
Size::new(
physical_size.width,
physical_size.height,
),
windowed_context.window().scale_factor(),
);
resized = true;
}
WindowEvent::CloseRequested => {
scene.cleanup(&gl);
*control_flow = ControlFlow::Exit
}
_ => (),
}
// Map window event to iced event
if let Some(event) = iced_winit::conversion::window_event(
&event,
windowed_context.window().scale_factor(),
modifiers,
) {
state.queue_event(event);
}
}
Event::MainEventsCleared => {
// If there are events pending
if !state.is_queue_empty() {
// We update iced
let _ = state.update(
viewport.logical_size(),
conversion::cursor_position(
cursor_position,
viewport.scale_factor(),
),
&mut renderer,
&mut clipboard,
&mut debug,
);
// and request a redraw
windowed_context.window().request_redraw();
}
}
Event::RedrawRequested(_) => {
if resized {
let size = windowed_context.window().inner_size();
unsafe {
gl.viewport(
0,
0,
size.width as i32,
size.height as i32,
);
}
resized = false;
}
let program = state.program();
{
// We clear the frame
scene.clear(&gl, program.background_color());
// Draw the scene
scene.draw(&gl);
}
// And then iced on top
renderer.with_primitives(|backend, primitive| {
backend.present(
&gl,
primitive,
&viewport,
&debug.overlay(),
);
});
// Update the mouse cursor
windowed_context.window().set_cursor_icon(
iced_winit::conversion::mouse_interaction(
state.mouse_interaction(),
),
);
windowed_context.swap_buffers().unwrap();
}
_ => (),
}
});
}