|
|
|
@ -1,6 +1,6 @@
|
|
|
|
|
use std::time::{Duration, Instant};
|
|
|
|
|
|
|
|
|
|
use skulpin::skia_safe::{Canvas, Paint, Path, Point};
|
|
|
|
|
use skulpin::skia_safe::{BlendMode, Canvas, Color, Paint, Path, Point, Rect};
|
|
|
|
|
|
|
|
|
|
use crate::settings::SETTINGS;
|
|
|
|
|
use crate::renderer::animation_utils::*;
|
|
|
|
@ -9,9 +9,8 @@ use crate::editor::{EDITOR, Colors, Cursor, CursorShape};
|
|
|
|
|
use crate::redraw_scheduler::REDRAW_SCHEDULER;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const BASE_ANIMATION_LENGTH_SECONDS: f32 = 0.06;
|
|
|
|
|
const CURSOR_TRAIL_SIZE: f32 = 0.6;
|
|
|
|
|
const CURSOR_TRAIL_SIZE: f32 = 0.9;
|
|
|
|
|
const COMMAND_LINE_DELAY_FRAMES: u64 = 5;
|
|
|
|
|
const DEFAULT_CELL_PERCENTAGE: f32 = 1.0 / 8.0;
|
|
|
|
|
|
|
|
|
@ -151,10 +150,10 @@ impl Corner {
|
|
|
|
|
d
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let direction_alignment = corner_direction.dot(self.relative_position);
|
|
|
|
|
let direction_alignment = -corner_direction.dot(self.relative_position); // TODO -- Fix math below so this doesn't have to be negated
|
|
|
|
|
|
|
|
|
|
self.current_position =
|
|
|
|
|
ease_point(ease_linear, self.start_position, corner_destination, self.t);
|
|
|
|
|
ease_point(ease_out_quad, self.start_position, corner_destination, self.t);
|
|
|
|
|
|
|
|
|
|
if self.t == 1.0 {
|
|
|
|
|
// We are at destination, move t out of 0-1 range to stop the animation
|
|
|
|
@ -168,12 +167,52 @@ impl Corner {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO -- Split into own file, make it a trait to have several impls
|
|
|
|
|
// TODO -- Rename this impl as SonicBoom
|
|
|
|
|
pub struct CursorVFX {
|
|
|
|
|
t: f32,
|
|
|
|
|
center_position: Point,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl CursorVFX {
|
|
|
|
|
fn update(&mut self, dt: f32) -> bool {
|
|
|
|
|
self.t = (self.t + dt * 5.0).min(1.0); // TODO - speed config
|
|
|
|
|
return self.t < 1.0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn reset(&mut self, position: Point) {
|
|
|
|
|
self.t = 0.0;
|
|
|
|
|
self.center_position = position;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn render(&self, _paint: &mut Paint, canvas: &mut Canvas, cursor: &Cursor, colors: &Colors) {
|
|
|
|
|
if self.t == 1.0 {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
let mut paint = Paint::new(skulpin::skia_safe::colors::WHITE, None);
|
|
|
|
|
paint.set_blend_mode(BlendMode::SrcOver);
|
|
|
|
|
|
|
|
|
|
let base_color : Color = cursor.background(&colors).to_color();
|
|
|
|
|
let alpha = ((1.0 - self.t) * 255.0) as u8;
|
|
|
|
|
let color = Color::from_argb(alpha, base_color.r(), base_color.g(), base_color.b());
|
|
|
|
|
paint.set_color(color);
|
|
|
|
|
|
|
|
|
|
let size = 40.0; // TODO -- Compute from font size
|
|
|
|
|
let radius = self.t * size;
|
|
|
|
|
let hr = radius * 0.5;
|
|
|
|
|
let rect = Rect::from_xywh(self.center_position.x - hr, self.center_position.y - hr, radius, radius);
|
|
|
|
|
|
|
|
|
|
canvas.draw_oval(&rect, &paint);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct CursorRenderer {
|
|
|
|
|
pub corners: Vec<Corner>,
|
|
|
|
|
pub previous_position: (u64, u64),
|
|
|
|
|
pub command_line_delay: u64,
|
|
|
|
|
blink_status: BlinkStatus,
|
|
|
|
|
previous_cursor_shape: Option<CursorShape>,
|
|
|
|
|
cursor_vfx: CursorVFX,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl CursorRenderer {
|
|
|
|
@ -184,19 +223,13 @@ impl CursorRenderer {
|
|
|
|
|
command_line_delay: 0,
|
|
|
|
|
blink_status: BlinkStatus::new(),
|
|
|
|
|
previous_cursor_shape: None,
|
|
|
|
|
cursor_vfx: CursorVFX{t: 0.0, center_position: Point{x:0.0, y:0.0}},
|
|
|
|
|
};
|
|
|
|
|
renderer.set_cursor_shape(&CursorShape::Block, DEFAULT_CELL_PERCENTAGE);
|
|
|
|
|
renderer
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn set_cursor_shape(&mut self, cursor_shape: &CursorShape, cell_percentage: f32) {
|
|
|
|
|
let new_cursor = Some(cursor_shape.clone());
|
|
|
|
|
if self.previous_cursor_shape == new_cursor {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self.previous_cursor_shape = new_cursor;
|
|
|
|
|
|
|
|
|
|
self.corners = self.corners
|
|
|
|
|
.clone()
|
|
|
|
|
.into_iter().enumerate()
|
|
|
|
@ -229,6 +262,8 @@ impl CursorRenderer {
|
|
|
|
|
canvas: &mut Canvas) {
|
|
|
|
|
let render = self.blink_status.update_status(&cursor);
|
|
|
|
|
|
|
|
|
|
paint.set_anti_alias(true);
|
|
|
|
|
|
|
|
|
|
self.previous_position = {
|
|
|
|
|
let editor = EDITOR.lock();
|
|
|
|
|
let (_, grid_y) = cursor.position;
|
|
|
|
@ -247,6 +282,7 @@ impl CursorRenderer {
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let (grid_x, grid_y) = self.previous_position;
|
|
|
|
|
|
|
|
|
|
let (character, font_dimensions): (String, Point) = {
|
|
|
|
@ -270,7 +306,14 @@ impl CursorRenderer {
|
|
|
|
|
let destination: Point = (grid_x as f32 * font_width, grid_y as f32 * font_height).into();
|
|
|
|
|
let center_destination = destination + font_dimensions * 0.5;
|
|
|
|
|
|
|
|
|
|
self.set_cursor_shape(&cursor.shape, cursor.cell_percentage.unwrap_or(DEFAULT_CELL_PERCENTAGE));
|
|
|
|
|
let new_cursor = Some(cursor.shape.clone());
|
|
|
|
|
|
|
|
|
|
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.reset(center_destination);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let dt = 1.0 / (SETTINGS.get("refresh_rate").read_u16() as f32);
|
|
|
|
|
|
|
|
|
@ -280,6 +323,8 @@ impl CursorRenderer {
|
|
|
|
|
let corner_animating = corner.update(font_dimensions, center_destination, dt);
|
|
|
|
|
animating |= corner_animating;
|
|
|
|
|
}
|
|
|
|
|
let vfx_animating = self.cursor_vfx.update(dt);
|
|
|
|
|
animating |= vfx_animating;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if animating || self.command_line_delay != 0 {
|
|
|
|
@ -310,6 +355,7 @@ impl CursorRenderer {
|
|
|
|
|
canvas.draw_text_blob(&blob, destination, &paint);
|
|
|
|
|
}
|
|
|
|
|
canvas.restore();
|
|
|
|
|
self.cursor_vfx.render(paint, canvas, &cursor, &default_colors);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|