better mouse management with multigrid

macos-click-through
keith 4 years ago
parent f14a7f7dc6
commit ee2ee53614

@ -52,6 +52,7 @@ fn main() {
window::initialize_settings(); window::initialize_settings();
redraw_scheduler::initialize_settings(); redraw_scheduler::initialize_settings();
renderer::initialize_settings();
renderer::cursor_renderer::initialize_settings(); renderer::cursor_renderer::initialize_settings();
bridge::layouts::initialize_settings(); bridge::layouts::initialize_settings();

@ -1,8 +1,8 @@
use log::error; use log::error;
use skulpin::skia_safe::{paint::Style, BlendMode, Canvas, Color, Paint, Point, Rect}; use skulpin::skia_safe::{paint::Style, BlendMode, Canvas, Color, Paint, Point, Rect};
use super::animation_utils::*;
use super::CursorSettings; use super::CursorSettings;
use crate::renderer::animation_utils::*;
use crate::editor::{Colors, Cursor}; use crate::editor::{Colors, Cursor};
use crate::settings::*; use crate::settings::*;

@ -1,4 +1,3 @@
mod animation_utils;
mod blink; mod blink;
mod cursor_vfx; mod cursor_vfx;
@ -7,10 +6,10 @@ use skulpin::skia_safe::{Canvas, Paint, Path, Point};
use crate::editor::{Colors, Cursor, CursorShape, EDITOR}; use crate::editor::{Colors, Cursor, CursorShape, EDITOR};
use crate::redraw_scheduler::REDRAW_SCHEDULER; use crate::redraw_scheduler::REDRAW_SCHEDULER;
use crate::renderer::CachingShaper; use crate::renderer::CachingShaper;
use crate::renderer::animation_utils::*;
use crate::settings::*; use crate::settings::*;
use crate::bridge::EditorMode; use crate::bridge::EditorMode;
use animation_utils::*;
use blink::*; use blink::*;
const DEFAULT_CELL_PERCENTAGE: f32 = 1.0 / 8.0; const DEFAULT_CELL_PERCENTAGE: f32 = 1.0 / 8.0;

@ -4,24 +4,93 @@ use std::sync::Arc;
use log::trace; use log::trace;
use skulpin::skia_safe::gpu::SurfaceOrigin; use skulpin::skia_safe::gpu::SurfaceOrigin;
use skulpin::skia_safe::{ use skulpin::skia_safe::{
colors, dash_path_effect, Budgeted, Canvas, ImageInfo, Paint, Rect, Surface colors, dash_path_effect, Budgeted, Canvas, ImageInfo, Paint, Rect, Surface, Point, Color, image_filters::*
}; };
use skulpin::CoordinateSystemHelper; use skulpin::CoordinateSystemHelper;
mod caching_shaper; mod caching_shaper;
pub mod cursor_renderer; pub mod cursor_renderer;
pub mod font_options; pub mod font_options;
pub mod animation_utils;
pub use caching_shaper::CachingShaper; pub use caching_shaper::CachingShaper;
pub use font_options::*; pub use font_options::*;
use animation_utils::*;
use crate::editor::{Style, WindowRenderInfo, EDITOR}; use crate::editor::{Style, WindowRenderInfo, EDITOR};
use crate::redraw_scheduler::REDRAW_SCHEDULER; use crate::redraw_scheduler::REDRAW_SCHEDULER;
use crate::settings::*;
use cursor_renderer::CursorRenderer; use cursor_renderer::CursorRenderer;
// ----------------------------------------------------------------------------
#[derive(Clone)]
pub struct RendererSettings {
animation_length: f32,
}
pub fn initialize_settings() {
SETTINGS.set(&RendererSettings {
animation_length: 0.15,
});
register_nvim_setting!("window_animation_length", RendererSettings::animation_length);
}
// ----------------------------------------------------------------------------
pub struct RenderedWindow { pub struct RenderedWindow {
surface: Surface, surface: Surface,
current_position: (f32, f32) start_position: Point,
current_position: Point,
previous_destination: Point,
t: f32
}
impl RenderedWindow {
pub fn new(surface: Surface, position: Point) -> RenderedWindow {
RenderedWindow {
surface,
start_position: position.clone(),
current_position: position.clone(),
previous_destination: position.clone(),
t: 2.0 // 2.0 is out of the 0.0 to 1.0 range and stops animation
}
}
pub fn update(
&mut self,
settings: &RendererSettings,
destination: Point,
dt: f32
) -> bool {
if destination != self.previous_destination {
self.t = 0.0;
self.start_position = self.current_position;
self.previous_destination = destination;
}
if (self.t - 1.0).abs() < std::f32::EPSILON {
return false;
}
if (self.t - 1.0).abs() < std::f32::EPSILON {
// We are at destination, move t out of 0-1 range to stop the animation
self.t = 2.0;
} else {
self.t = (self.t + dt / settings.animation_length).min(1.0);
}
self.current_position = ease_point(
ease_out_expo,
self.start_position,
destination,
self.t,
);
true
}
} }
pub struct Renderer { pub struct Renderer {
@ -195,13 +264,14 @@ impl Renderer {
pub fn draw_window( pub fn draw_window(
&mut self, &mut self,
settings: &RendererSettings,
root_canvas: &mut Canvas, root_canvas: &mut Canvas,
window_render_info: &WindowRenderInfo, window_render_info: &WindowRenderInfo,
default_style: &Arc<Style>, default_style: &Arc<Style>,
dt: f32
) -> (u64, Rect) { ) -> (u64, Rect) {
let (grid_left, grid_top) = window_render_info.grid_position; let (grid_left, grid_top) = window_render_info.grid_position;
let target_left = grid_left as f32 * self.font_width; let window_destination = Point::new(grid_left as f32 * self.font_width, grid_top as f32 * self.font_height);
let target_top = grid_top as f32 * self.font_height;
let image_width = (window_render_info.width as f32 * self.font_width) as i32; let image_width = (window_render_info.width as f32 * self.font_width) as i32;
let image_height = (window_render_info.height as f32 * self.font_height) as i32; let image_height = (window_render_info.height as f32 * self.font_height) as i32;
@ -213,10 +283,7 @@ impl Renderer {
} }
.unwrap_or_else(|| { .unwrap_or_else(|| {
let surface = self.build_window_surface(root_canvas, &default_style, (image_width, image_height)); let surface = self.build_window_surface(root_canvas, &default_style, (image_width, image_height));
RenderedWindow { RenderedWindow::new(surface, window_destination)
surface,
current_position: (target_left, target_top)
}
}); });
if rendered_window.surface.width() != image_width || rendered_window.surface.height() != image_height { if rendered_window.surface.width() != image_width || rendered_window.surface.height() != image_height {
@ -225,10 +292,7 @@ impl Renderer {
old_surface.draw(rendered_window.surface.canvas(), (0.0, 0.0), None); old_surface.draw(rendered_window.surface.canvas(), (0.0, 0.0), None);
} }
let (current_left, current_top) = rendered_window.current_position; rendered_window.update(settings, window_destination, dt);
let current_left = current_left + (target_left - current_left) * 0.4;
let current_top = current_top + (target_top - current_top) * 0.4;
rendered_window.current_position = (current_left, current_top);
let mut canvas = rendered_window.surface.canvas(); let mut canvas = rendered_window.surface.canvas();
@ -255,15 +319,17 @@ impl Renderer {
root_canvas.save_layer(&Default::default()); root_canvas.save_layer(&Default::default());
unsafe { rendered_window.surface.draw(
rendered_window.surface.draw(root_canvas.surface().unwrap().canvas(), (current_left, current_top), None); root_canvas.as_mut(),
} (rendered_window.current_position.x, rendered_window.current_position.y),
None);
root_canvas.restore(); root_canvas.restore();
let window_position = rendered_window.current_position.clone();
self.rendered_windows.insert(window_render_info.grid_id, rendered_window); self.rendered_windows.insert(window_render_info.grid_id, rendered_window);
(window_render_info.grid_id, Rect::new(current_left, current_top, current_left + image_width as f32, current_top + image_height as f32)) (window_render_info.grid_id, Rect::from_point_and_size(window_position, (image_width as f32, image_height as f32)))
} }
pub fn draw( pub fn draw(
@ -275,6 +341,7 @@ impl Renderer {
trace!("Rendering"); trace!("Rendering");
REDRAW_SCHEDULER.queue_next_frame(); REDRAW_SCHEDULER.queue_next_frame();
let settings = SETTINGS.get::<RendererSettings>();
let (render_info, default_style, cursor, guifont_setting) = { let (render_info, default_style, cursor, guifont_setting) = {
let mut editor = EDITOR.lock(); let mut editor = EDITOR.lock();
@ -300,7 +367,7 @@ impl Renderer {
self.window_regions = render_info.windows self.window_regions = render_info.windows
.iter() .iter()
.map(|window_render_info| self.draw_window(gpu_canvas, window_render_info, &default_style)) .map(|window_render_info| self.draw_window(&settings, gpu_canvas, window_render_info, &default_style, dt))
.collect(); .collect();
self.cursor_renderer.draw( self.cursor_renderer.draw(

@ -8,11 +8,11 @@ use skulpin::sdl2::event::{Event, WindowEvent};
use skulpin::sdl2::keyboard::Keycode; use skulpin::sdl2::keyboard::Keycode;
use skulpin::sdl2::video::FullscreenType; use skulpin::sdl2::video::FullscreenType;
use skulpin::sdl2::Sdl; use skulpin::sdl2::Sdl;
use skulpin::ash::prelude::VkResult;
use skulpin::{ use skulpin::{
CoordinateSystem, LogicalSize, PhysicalSize, PresentMode, Renderer as SkulpinRenderer, CoordinateSystem, LogicalSize, PhysicalSize, PresentMode, Renderer as SkulpinRenderer,
RendererBuilder, Sdl2Window, Window, RendererBuilder, Sdl2Window, Window,
}; };
use skulpin::skia_safe::Rect;
use crate::bridge::{produce_neovim_keybinding_string, UiCommand, BRIDGE}; use crate::bridge::{produce_neovim_keybinding_string, UiCommand, BRIDGE};
use crate::editor::EDITOR; use crate::editor::EDITOR;
@ -175,7 +175,7 @@ impl WindowWrapper {
transparency: 1.0, transparency: 1.0,
fullscreen: false, fullscreen: false,
cached_size: (0, 0), cached_size: (0, 0),
cached_position: (0, 0), cached_position: (0, 0)
} }
} }
@ -285,11 +285,13 @@ impl WindowWrapper {
let logical_position = PhysicalSize::new(x as u32, y as u32) let logical_position = PhysicalSize::new(x as u32, y as u32)
.to_logical(sdl_window_wrapper.scale_factor()); .to_logical(sdl_window_wrapper.scale_factor());
let mut top_window_position = (0.0, 0.0);
let mut top_grid_position = None; let mut top_grid_position = None;
for (grid_id, window_region) in self.renderer.window_regions.iter() { for (grid_id, window_region) in self.renderer.window_regions.iter() {
if logical_position.width >= window_region.left as u32 && logical_position.width < window_region.right as u32 && if logical_position.width >= window_region.left as u32 && logical_position.width < window_region.right as u32 &&
logical_position.height >= window_region.top as u32 && logical_position.height < window_region.bottom as u32 { logical_position.height >= window_region.top as u32 && logical_position.height < window_region.bottom as u32 {
top_window_position = (window_region.left, window_region.top);
top_grid_position = Some(( top_grid_position = Some((
grid_id, grid_id,
LogicalSize::new(logical_position.width - window_region.left as u32, logical_position.height - window_region.top as u32) LogicalSize::new(logical_position.width - window_region.left as u32, logical_position.height - window_region.top as u32)
@ -298,16 +300,20 @@ impl WindowWrapper {
} }
if let Some((grid_id, grid_position)) = top_grid_position { if let Some((grid_id, grid_position)) = top_grid_position {
self.grid_id_under_mouse = dbg!(*grid_id); self.grid_id_under_mouse = *grid_id;
self.mouse_position = LogicalSize::new( self.mouse_position = LogicalSize::new(
(grid_position.width as f32 / self.renderer.font_width) as u32, (grid_position.width as f32 / self.renderer.font_width) as u32,
(grid_position.height as f32 / self.renderer.font_height) as u32 (grid_position.height as f32 / self.renderer.font_height) as u32
); );
if self.mouse_down && previous_position != self.mouse_position { if self.mouse_down && previous_position != self.mouse_position {
let (window_left, window_top) = top_window_position;
let adjusted_drag_left = self.mouse_position.width + (window_left / self.renderer.font_width) as u32;
let adjusted_drag_top = self.mouse_position.height + (window_top / self.renderer.font_height) as u32;
BRIDGE.queue_command(UiCommand::Drag { BRIDGE.queue_command(UiCommand::Drag {
grid_id: self.grid_id_under_mouse, grid_id: self.grid_id_under_mouse,
position: (self.mouse_position.width, self.mouse_position.height), position: (adjusted_drag_left, adjusted_drag_top),
}); });
} }
} }
@ -370,11 +376,7 @@ impl WindowWrapper {
REDRAW_SCHEDULER.queue_next_frame(); REDRAW_SCHEDULER.queue_next_frame();
} }
pub fn draw_frame(&mut self) -> bool { pub fn draw_frame(&mut self, dt: f32) -> VkResult<bool> {
if !BRIDGE.running.load(Ordering::Relaxed) {
return false;
}
let sdl_window_wrapper = Sdl2Window::new(&self.window); let sdl_window_wrapper = Sdl2Window::new(&self.window);
let new_size = sdl_window_wrapper.logical_size(); let new_size = sdl_window_wrapper.logical_size();
if self.previous_size != new_size { if self.previous_size != new_size {
@ -388,23 +390,17 @@ impl WindowWrapper {
if REDRAW_SCHEDULER.should_draw() || SETTINGS.get::<WindowSettings>().no_idle { if REDRAW_SCHEDULER.should_draw() || SETTINGS.get::<WindowSettings>().no_idle {
let renderer = &mut self.renderer; let renderer = &mut self.renderer;
let error = self self.skulpin_renderer
.skulpin_renderer
.draw(&sdl_window_wrapper, |canvas, coordinate_system_helper| { .draw(&sdl_window_wrapper, |canvas, coordinate_system_helper| {
let dt = 1.0 / (SETTINGS.get::<WindowSettings>().refresh_rate as f32);
if renderer.draw(canvas, &coordinate_system_helper, dt) { if renderer.draw(canvas, &coordinate_system_helper, dt) {
handle_new_grid_size(current_size, &renderer) handle_new_grid_size(current_size, &renderer)
} }
}) })?;
.is_err();
if error {
error!("Render failed. Closing");
return false;
}
}
true Ok(true)
} else {
Ok(false)
}
} }
} }
@ -443,7 +439,13 @@ pub fn ui_loop() {
.event_pump() .event_pump()
.expect("Could not create sdl event pump"); .expect("Could not create sdl event pump");
let mut was_animating = false;
let mut previous_frame_start = Instant::now();
loop { loop {
if !BRIDGE.running.load(Ordering::Relaxed) {
break;
}
let frame_start = Instant::now(); let frame_start = Instant::now();
window.synchronize_settings(); window.synchronize_settings();
@ -489,16 +491,30 @@ pub fn ui_loop() {
window.handle_keyboard_input(keycode, keytext); window.handle_keyboard_input(keycode, keytext);
} }
if !window.draw_frame() { let refresh_rate = { SETTINGS.get::<WindowSettings>().refresh_rate as f32 };
let dt = if was_animating {
previous_frame_start.elapsed().as_secs_f32()
} else {
1.0 / refresh_rate
};
match window.draw_frame(dt) {
Ok(animating) => {
was_animating = animating;
},
Err(error) => {
error!("Render failed: {}", error);
break; break;
} }
}
let elapsed = frame_start.elapsed(); let elapsed = frame_start.elapsed();
let refresh_rate = { SETTINGS.get::<WindowSettings>().refresh_rate as f32 }; let expected_frame_length = Duration::from_secs_f32(1.0 / refresh_rate);
let frame_length = Duration::from_secs_f32(1.0 / refresh_rate);
previous_frame_start = frame_start;
if elapsed < frame_length { if elapsed < expected_frame_length {
sleep(frame_length - elapsed); sleep(expected_frame_length - elapsed);
} }
} }

Loading…
Cancel
Save