Implemented settings-based control for cursor animations

macos-click-through
Jon Valdés 5 years ago
parent c517f00033
commit 47eaf0c418

@ -25,6 +25,7 @@ pub const INITIAL_DIMENSIONS: (u64, u64) = (100, 50);
fn main() {
window::initialize_settings();
redraw_scheduler::initialize_settings();
renderer::cursor_renderer::initialize_settings();
initialize(&BRIDGE);
ui_loop();

@ -1,21 +1,76 @@
use skulpin::skia_safe::{paint::Style, BlendMode, Canvas, Color, Paint, Point, Rect};
use log::error;
use super::animation_utils::*;
use crate::editor::{Colors, Cursor};
use crate::settings::*;
pub trait CursorVFX {
pub trait CursorVfx {
fn update(&mut self, current_cursor_destination: Point, dt: f32) -> bool;
fn restart(&mut self, position: Point);
fn render(&self, canvas: &mut Canvas, cursor: &Cursor, colors: &Colors, font_size: (f32, f32));
}
#[allow(dead_code)]
#[derive(Clone, PartialEq)]
pub enum HighlightMode {
SonicBoom,
Ripple,
Wireframe,
}
#[derive(Clone, PartialEq)]
pub enum TrailMode {
Railgun,
}
#[derive(Clone, PartialEq)]
pub enum VfxMode {
Highlight(HighlightMode),
Trail(TrailMode),
Disabled,
}
impl FromValue for VfxMode {
fn from_value(&mut self, value: Value) {
if value.is_str() {
*self = match value.as_str().unwrap() {
"sonicboom" => VfxMode::Highlight(HighlightMode::SonicBoom),
"ripple" => VfxMode::Highlight(HighlightMode::Ripple),
"wireframe" => VfxMode::Highlight(HighlightMode::Wireframe),
"railgun" => VfxMode::Trail(TrailMode::Railgun),
"" => VfxMode::Disabled,
value => {
error!("Expected a VfxMode name, but received {:?}", value);
return;
}
};
}else{
error!("Expected a VfxMode string, but received {:?}", value);
}
}
}
impl From<VfxMode> for Value {
fn from(mode: VfxMode) -> Self {
match mode {
VfxMode::Highlight(HighlightMode::SonicBoom) => Value::from("sonicboom"),
VfxMode::Highlight(HighlightMode::Ripple) => Value::from("ripple"),
VfxMode::Highlight(HighlightMode::Wireframe) => Value::from("wireframe"),
VfxMode::Trail(TrailMode::Railgun) => Value::from("railgun"),
VfxMode::Disabled => Value::from(""),
}
}
}
pub fn new_cursor_vfx(mode: &VfxMode) -> Option<Box<dyn CursorVfx>> {
match mode {
VfxMode::Highlight(mode) => Some(Box::new(PointHighlight::new(mode))),
VfxMode::Trail(_) => Some(Box::new(ParticleTrail::new())),
VfxMode::Disabled => None,
}
}
pub struct PointHighlight {
t: f32,
center_position: Point,
@ -23,16 +78,16 @@ pub struct PointHighlight {
}
impl PointHighlight {
pub fn new(center: Point, mode: HighlightMode) -> PointHighlight {
pub fn new(mode: &HighlightMode) -> PointHighlight {
PointHighlight {
t: 0.0,
center_position: center,
mode,
center_position: Point::new(0.0, 0.0),
mode: mode.clone(),
}
}
}
impl CursorVFX for PointHighlight {
impl CursorVfx for PointHighlight {
fn update(&mut self, _current_cursor_destination: Point, dt: f32) -> bool {
self.t = (self.t + dt * 5.0).min(1.0); // TODO - speed config
self.t < 1.0
@ -121,7 +176,7 @@ impl ParticleTrail {
const PARTICLE_DENSITY: f32 = 0.008;
const PARTICLE_LIFETIME: f32 = 1.2;
impl CursorVFX for ParticleTrail {
impl CursorVfx for ParticleTrail {
fn update(&mut self, current_cursor_dest: Point, dt: f32) -> bool {
// Update lifetimes and remove dead particles
let mut i = 0;

@ -2,7 +2,7 @@ use std::time::{Duration, Instant};
use skulpin::skia_safe::{Canvas, Paint, Path, Point};
use crate::settings::SETTINGS;
use crate::settings::*;
use crate::renderer::CachingShaper;
use crate::editor::{EDITOR, Colors, Cursor, CursorShape};
use crate::redraw_scheduler::REDRAW_SCHEDULER;
@ -11,15 +11,32 @@ mod animation_utils;
use animation_utils::*;
mod cursor_vfx;
use cursor_vfx::*;
const BASE_ANIMATION_LENGTH_SECONDS: f32 = 0.06;
const CURSOR_TRAIL_SIZE: f32 = 0.7;
const COMMAND_LINE_DELAY_FRAMES: u64 = 5;
const DEFAULT_CELL_PERCENTAGE: f32 = 1.0 / 8.0;
const STANDARD_CORNERS: &[(f32, f32); 4] = &[(-0.5, -0.5), (0.5, -0.5), (0.5, 0.5), (-0.5, 0.5)];
#[derive(Clone)]
pub struct CursorSettings {
animation_length: f32,
vfx_mode: cursor_vfx::VfxMode,
}
pub fn initialize_settings() {
SETTINGS.set(&CursorSettings {
animation_length: 0.06,
vfx_mode: cursor_vfx::VfxMode::Disabled,
});
register_nvim_setting!("cursor_animation_length", CursorSettings::animation_length);
register_nvim_setting!("cursor_vfx_mode", CursorSettings::vfx_mode);
}
enum BlinkState {
Waiting,
On,
@ -110,7 +127,7 @@ impl Corner {
}
}
pub fn update(&mut self, font_dimensions: Point, destination: Point, dt: f32) -> bool {
pub fn update(&mut self, settings: &CursorSettings, font_dimensions: Point, destination: Point, dt: f32) -> bool {
// Update destination if needed
let mut immediate_movement = false;
if destination != self.previous_destination {
@ -170,7 +187,7 @@ impl Corner {
self.t = 2.0;
} else {
let corner_dt = dt * lerp(1.0, 1.0 - CURSOR_TRAIL_SIZE, -direction_alignment);
self.t = (self.t + corner_dt / BASE_ANIMATION_LENGTH_SECONDS).min(1.0)
self.t = (self.t + corner_dt / settings.animation_length).min(1.0)
}
true
@ -183,7 +200,8 @@ pub struct CursorRenderer {
pub command_line_delay: u64,
blink_status: BlinkStatus,
previous_cursor_shape: Option<CursorShape>,
cursor_vfx: Box<dyn CursorVFX>,
cursor_vfx: Option<Box<dyn cursor_vfx::CursorVfx>>,
previous_vfx_mode: cursor_vfx::VfxMode,
}
impl CursorRenderer {
@ -195,7 +213,8 @@ impl CursorRenderer {
blink_status: BlinkStatus::new(),
previous_cursor_shape: None,
//cursor_vfx: Box::new(PointHighlight::new(Point{x:0.0, y:0.0}, HighlightMode::Ripple)),
cursor_vfx: Box::new(ParticleTrail::new()),
cursor_vfx: None,
previous_vfx_mode: cursor_vfx::VfxMode::Disabled,
};
renderer.set_cursor_shape(&CursorShape::Block, DEFAULT_CELL_PERCENTAGE);
renderer
@ -234,6 +253,13 @@ impl CursorRenderer {
dt: f32) {
let render = self.blink_status.update_status(&cursor);
let settings = SETTINGS.get::<CursorSettings>();
if settings.vfx_mode != self.previous_vfx_mode {
self.cursor_vfx = cursor_vfx::new_cursor_vfx(&settings.vfx_mode);
self.previous_vfx_mode = settings.vfx_mode.clone();
}
let mut paint = Paint::new(skulpin::skia_safe::colors::WHITE, None);
paint.set_anti_alias(true);
@ -284,17 +310,25 @@ impl CursorRenderer {
if self.previous_cursor_shape != new_cursor {
self.previous_cursor_shape = new_cursor;
self.set_cursor_shape(&cursor.shape, cursor.cell_percentage.unwrap_or(DEFAULT_CELL_PERCENTAGE));
self.cursor_vfx.restart(center_destination);
if let Some(vfx) = self.cursor_vfx.as_mut() {
vfx.restart(center_destination);
}
}
let mut animating = false;
if !center_destination.is_zero() {
for corner in self.corners.iter_mut() {
let corner_animating = corner.update(font_dimensions, center_destination, dt);
let corner_animating = corner.update(&settings, font_dimensions, center_destination, dt);
animating |= corner_animating;
}
let vfx_animating = self.cursor_vfx.update(center_destination, dt);
let vfx_animating = if let Some(vfx) = self.cursor_vfx.as_mut() {
vfx.update(center_destination, dt)
}else{
false
};
animating |= vfx_animating;
}
@ -326,7 +360,10 @@ impl CursorRenderer {
canvas.draw_text_blob(&blob, destination, &paint);
}
canvas.restore();
self.cursor_vfx.render(canvas, &cursor, &default_colors, (font_width, font_height));
if let Some(vfx) = self.cursor_vfx.as_ref() {
vfx.render(canvas, &cursor, &default_colors, (font_width, font_height));
}
}
}
}

@ -6,7 +6,7 @@ use skulpin::skia_safe::gpu::SurfaceOrigin;
use log::trace;
mod caching_shaper;
mod cursor_renderer;
pub mod cursor_renderer;
pub use caching_shaper::CachingShaper;

@ -26,7 +26,7 @@ pub trait FromValue {
// FromValue implementations for most typical types
impl FromValue for f32 {
fn from_value(&mut self, value: Value) {
if value.is_f32() {
if value.is_f64() {
*self = value.as_f64().unwrap() as f32;
}else{
error!("Setting expected an f32, but received {:?}", value);

Loading…
Cancel
Save