Get resizing working

This commit is contained in:
Imbris 2020-03-16 17:56:50 -04:00
parent bbbede68fc
commit 0305c1979a
2 changed files with 105 additions and 37 deletions

View File

@ -10,25 +10,39 @@ pub use renderer::IcedRenderer;
pub use widget::image::Image;
pub use winit_conversion::window_event;
use super::graphic::{self, Graphic};
use super::{
graphic::{self, Graphic},
scale::{Scale, ScaleMode},
};
use crate::{render::Renderer, window::Window, Error};
use clipboard::Clipboard;
use iced::{Cache, Element, MouseCursor, Size, UserInterface};
use vek::*;
pub struct IcedUi {
renderer: IcedRenderer,
cache: Option<Cache>,
events: Vec<Event>,
clipboard: Clipboard,
// Scaling of the ui
scale: Scale,
window_resized: Option<Vec2<u32>>,
}
impl IcedUi {
pub fn new(window: &mut Window) -> Result<Self, Error> {
let scale = Scale::new(window, ScaleMode::Absolute(1.0));
let renderer = window.renderer_mut();
let scaled_dims = scale.scaled_window_size().map(|e| e as f32);
Ok(Self {
renderer: IcedRenderer::new(window)?,
renderer: IcedRenderer::new(renderer, scaled_dims)?,
cache: Some(Cache::new()),
events: Vec::new(),
// TODO: handle None
clipboard: Clipboard::new(window.window()).unwrap(),
scale,
window_resized: None,
})
}
@ -37,8 +51,40 @@ impl IcedUi {
self.renderer.add_graphic(graphic)
}
// TODO: handle scaling here
pub fn handle_event(&mut self, event: Event) { self.events.push(event); }
pub fn handle_event(&mut self, event: Event) {
use iced::{input::mouse, window};
match event {
// Intercept resizing events
Event::Window(window::Event::Resized { width, height }) => {
self.window_resized = Some(Vec2::new(width, height));
},
// Scale cursor movement events
// Note: in some cases the scaling could be off if a resized event occured in the same
// frame, in practice this shouldn't be an issue
Event::Mouse(mouse::Event::CursorMoved { x, y }) => {
// TODO: return f32 here
let scale = self.scale.scale_factor_logical() as f32;
self.events.push(Event::Mouse(mouse::Event::CursorMoved {
x: x * scale,
y: y * scale,
}));
},
// Scale pixel scrolling events
Event::Mouse(mouse::Event::WheelScrolled {
delta: mouse::ScrollDelta::Pixels { x, y },
}) => {
// TODO: return f32 here
let scale = self.scale.scale_factor_logical() as f32;
self.events.push(Event::Mouse(mouse::Event::WheelScrolled {
delta: mouse::ScrollDelta::Pixels {
x: x * scale,
y: y * scale,
},
}));
},
event => self.events.push(event),
}
}
// TODO: produce root internally???
pub fn maintain<'a, M, E: Into<Element<'a, M, IcedRenderer>>>(
@ -46,8 +92,33 @@ impl IcedUi {
root: E,
renderer: &mut Renderer,
) -> (Vec<M>, MouseCursor) {
// Handle window resizing
if let Some(new_dims) = self.window_resized.take() {
let old_scaled_dims = self.scale.scaled_window_size();
// TODO maybe use u32 in Scale to be consistent with iced
self.scale
.window_resized(new_dims.map(|e| e as f64), renderer);
let scaled_dims = self.scale.scaled_window_size();
self.events
.push(Event::Window(iced::window::Event::Resized {
width: scaled_dims.x as u32,
height: scaled_dims.y as u32,
}));
// Avoid panic in graphic cache when minimizing.
// Avoid resetting cache if window size didn't change
// Somewhat inefficient for elements that won't change size after a window
// resize
let res = renderer.get_resolution();
if res.x > 0 && res.y > 0 && scaled_dims != old_scaled_dims {
self.renderer
.resize(scaled_dims.map(|e| e as f32), renderer);
}
}
// TODO: convert to f32 at source
let window_size = self.renderer.scaled_window_size().map(|e| e as f32);
let window_size = self.scale.scaled_window_size().map(|e| e as f32);
let mut user_interface = UserInterface::build(
root,

View File

@ -5,7 +5,6 @@ use super::{
super::{
cache::Cache,
graphic::{self, Graphic, TexId},
scale::{Scale, ScaleMode},
},
widget,
};
@ -13,7 +12,6 @@ use crate::{
render::{
create_ui_quad, Consts, DynamicModel, Globals, Mesh, Renderer, UiLocals, UiMode, UiPipeline,
},
window::Window,
Error,
};
//use log::warn;
@ -73,13 +71,8 @@ pub struct IcedRenderer {
interface_locals: Consts<UiLocals>,
default_globals: Consts<Globals>,
// Window size for updating scaling
//window_resized: Option<Vec2<f64>>,
// Used to delay cache resizing until after current frame is drawn
//need_cache_resize: bool,
// Scaling of the ui
scale: Scale,
half_res: Vec2<f32>,
// Pixel perfection alignment
align: Vec2<f32>,
@ -95,16 +88,8 @@ pub struct IcedRenderer {
//current_scissor: Aabr<u16>,
}
impl IcedRenderer {
pub fn new(window: &mut Window) -> Result<Self, Error> {
let scale = Scale::new(window, ScaleMode::Absolute(1.0));
// TODO: looks like we can just get this from scale
let win_dims = scale.scaled_window_size().map(|e| e as f32);
let renderer = window.renderer_mut();
let res = renderer.get_resolution();
let half_res = res.map(|e| e as f32 / 2.0);
let align = align(res);
pub fn new(renderer: &mut Renderer, scaled_dims: Vec2<f32>) -> Result<Self, Error> {
let (half_res, align) = Self::calculate_resolution_dependents(renderer.get_resolution());
Ok(Self {
cache: Cache::new(renderer)?,
@ -113,35 +98,32 @@ impl IcedRenderer {
interface_locals: renderer.create_consts(&[UiLocals::default()])?,
default_globals: renderer.create_consts(&[Globals::default()])?,
ingame_locals: Vec::new(),
//window_resized: None,
//need_cache_resize: false,
mesh: Mesh::new(),
current_state: State::Plain,
scale,
half_res,
align,
win_dims,
win_dims: scaled_dims,
start: 0,
//current_scissor: default_scissor(renderer),
})
}
pub fn scaled_window_size(&self) -> Vec2<f64> { self.scale.scaled_window_size() }
pub fn add_graphic(&mut self, graphic: Graphic) -> graphic::Id {
self.cache.add_graphic(graphic)
}
pub fn resize(&mut self, scaled_dims: Vec2<f32>, renderer: &mut Renderer) {
self.win_dims = scaled_dims;
self.update_resolution_dependents(renderer.get_resolution());
// Resize graphic cache
self.cache.resize_graphic_cache(renderer);
// Resize glyph cache
self.cache.resize_glyph_cache(renderer).unwrap();
}
pub fn draw(&mut self, primitive: Primitive, renderer: &mut Renderer) {
/*if self.need_cache_resize {
// Resize graphic cache
self.cache.resize_graphic_cache(renderer).unwrap();
// Resize glyph cache
self.cache.resize_glyph_cache(renderer).unwrap();
self.need_cache_resize = false;
}*/
// Re-use memory
self.draw_commands.clear();
self.mesh.clear();
@ -203,6 +185,20 @@ impl IcedRenderer {
}*/
}
// Returns (half_res, align)
fn calculate_resolution_dependents(res: Vec2<u16>) -> (Vec2<f32>, Vec2<f32>) {
let half_res = res.map(|e| e as f32 / 2.0);
let align = align(res);
(half_res, align)
}
fn update_resolution_dependents(&mut self, res: Vec2<u16>) {
let (half_res, align) = Self::calculate_resolution_dependents(res);
self.half_res = half_res;
self.align = align;
}
fn gl_aabr(&self, bounds: iced::Rectangle) -> Aabr<f32> {
/*let (ui_win_w, ui_win_h) = self.win_dims.into_tuple();
let (l, b) = aabr.min.into_tuple();
@ -360,6 +356,7 @@ impl IcedRenderer {
// Given the the resolution determines the offset needed to align integer
// offsets from the center of the sceen to pixels
#[inline(always)]
fn align(res: Vec2<u16>) -> Vec2<f32> {
// If the resolution is odd then the center of the screen will be within the
// middle of a pixel so we need to offset by 0.5 pixels to be on the edge of