Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
weblate committed Dec 7, 2024
2 parents 5bb65fc + c8d5f6d commit f274d62
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 2 deletions.
51 changes: 50 additions & 1 deletion crates/rnote-engine/src/engine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use std::sync::Arc;
use std::time::Instant;
use tracing::error;
use tracing::{debug, error};

/// An immutable view into the engine, excluding the penholder.
#[derive(Debug)]
Expand All @@ -45,6 +45,7 @@ pub struct EngineView<'a> {
pub store: &'a StrokeStore,
pub camera: &'a Camera,
pub audioplayer: &'a Option<AudioPlayer>,
pub animation: &'a Animation,
}

/// Constructs an `EngineView` from an identifier containing an `Engine` instance.
Expand All @@ -58,6 +59,7 @@ macro_rules! engine_view {
store: &$engine.store,
camera: &$engine.camera,
audioplayer: &$engine.audioplayer,
animation: &$engine.animation,
}
};
}
Expand All @@ -71,6 +73,7 @@ pub struct EngineViewMut<'a> {
pub store: &'a mut StrokeStore,
pub camera: &'a mut Camera,
pub audioplayer: &'a mut Option<AudioPlayer>,
pub animation: &'a mut Animation,
}

/// Constructs an `EngineViewMut` from an identifier containing an `Engine` instance.
Expand All @@ -84,6 +87,7 @@ macro_rules! engine_view_mut {
store: &mut $engine.store,
camera: &mut $engine.camera,
audioplayer: &mut $engine.audioplayer,
animation: &mut $engine.animation,
}
};
}
Expand All @@ -98,6 +102,7 @@ impl EngineViewMut<'_> {
store: self.store,
camera: self.camera,
audioplayer: self.audioplayer,
animation: self.animation,
}
}
}
Expand Down Expand Up @@ -179,6 +184,39 @@ impl EngineTaskReceiver {
}
}

#[derive(Debug, Clone, Default)]
pub struct Animation {
frame_in_flight: bool,
}

impl Animation {
/// Claim an animation frame.
///
/// Returns whether an animation frame was already claimed.
pub fn claim_frame(&mut self) -> bool {
if self.frame_in_flight {
debug!("Animation frame already in flight, skipping");
true
} else {
self.frame_in_flight = true;
false
}
}

pub fn frame_in_flight(&self) -> bool {
self.frame_in_flight
}

pub fn process_frame(&mut self) -> bool {
if self.frame_in_flight {
self.frame_in_flight = false;
true
} else {
false
}
}
}

/// The engine.
#[derive(Debug, Serialize, Deserialize)]
#[serde(default, rename = "engine")]
Expand All @@ -205,6 +243,8 @@ pub struct Engine {
#[serde(skip)]
audioplayer: Option<AudioPlayer>,
#[serde(skip)]
pub animation: Animation,
#[serde(skip)]
visual_debug: bool,
// the task sender. Must not be modified, only cloned.
#[serde(skip)]
Expand Down Expand Up @@ -241,6 +281,7 @@ impl Default for Engine {
optimize_epd: false,

audioplayer: None,
animation: Animation::default(),
visual_debug: false,
tasks_tx: EngineTaskSender(tasks_tx),
tasks_rx: Some(EngineTaskReceiver(tasks_rx)),
Expand Down Expand Up @@ -885,4 +926,12 @@ impl Engine {
}
widget_flags
}

/// Handle a requested animation frame.
///
/// Can request another frame using `EngineViewMut#animation.claim_frame()`.
pub fn handle_animation_frame(&mut self, optimize_epd: bool) {
self.penholder
.handle_animation_frame(&mut engine_view_mut!(self), optimize_epd);
}
}
5 changes: 5 additions & 0 deletions crates/rnote-engine/src/pens/penbehaviour.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ pub trait PenBehaviour: DrawableOnDoc {
engine_view: &mut EngineViewMut,
) -> (EventResult<PenProgress>, WidgetFlags);

/// Handle a requested animation frame.
///
/// Can request another frame using `EngineViewMut#animation.claim_frame()`.
fn handle_animation_frame(&mut self, _engine_view: &mut EngineViewMut, _optimize_epd: bool) {}

/// Fetch clipboard content from the pen.
///
/// The fetched content can be available in multiple formats,
Expand Down
12 changes: 11 additions & 1 deletion crates/rnote-engine/src/pens/penholder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,12 +253,22 @@ impl PenHolder {
widget_flags |= wf;
}

// Always redraw after handling a pen event
// Always redraw after handling a pen event.
//
// This is also needed because pens might have claimed/requested an animation frame.
widget_flags.redraw = true;

(event_result.propagate, widget_flags)
}

/// Handle a requested animation frame.
///
/// Can request another frame using `EngineViewMut#animation.claim_frame()`.
pub fn handle_animation_frame(&mut self, engine_view: &mut EngineViewMut, optimize_epd: bool) {
self.current_pen
.handle_animation_frame(engine_view, optimize_epd);
}

/// Handle a pressed shortcut key.
pub fn handle_pressed_shortcut_key(
&mut self,
Expand Down
25 changes: 25 additions & 0 deletions crates/rnote-ui/src/canvas/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ mod imp {

pub(crate) engine: RefCell<Engine>,
pub(crate) engine_task_handler_handle: RefCell<Option<glib::JoinHandle<()>>>,
pub(crate) animation_callback_id: RefCell<Option<gtk4::TickCallbackId>>,

pub(crate) output_file: RefCell<Option<gio::File>>,
pub(crate) output_file_watcher_task: RefCell<Option<glib::JoinHandle<()>>>,
Expand Down Expand Up @@ -168,6 +169,7 @@ mod imp {

engine: RefCell::new(engine),
engine_task_handler_handle: RefCell::new(None),
animation_callback_id: RefCell::new(None),

output_file: RefCell::new(None),
output_file_watcher_task: RefCell::new(None),
Expand Down Expand Up @@ -245,6 +247,29 @@ mod imp {

*self.engine_task_handler_handle.borrow_mut() = Some(engine_task_handler_handle);

let animation_callback_id = obj.add_tick_callback(clone!(
#[weak(rename_to=canvas)]
obj,
#[upgrade_or]
glib::ControlFlow::Break,
move |_widget, _frame_clock| {
if canvas.engine_mut().animation.process_frame() {
let optimize_epd = canvas.engine_ref().optimize_epd();
canvas.engine_mut().handle_animation_frame(optimize_epd);

// if optimize_epd is enabled, we only redraw the canvas
// when no follow-up frame has been requested (i.e. the animation is done)
if !optimize_epd || !canvas.engine_ref().animation.frame_in_flight() {
canvas.queue_draw();
}
}

glib::ControlFlow::Continue
}
));

*self.animation_callback_id.borrow_mut() = Some(animation_callback_id);

self.setup_input();
}

Expand Down

0 comments on commit f274d62

Please sign in to comment.