🎉 Improve frame rendering

This commit is contained in:
AzazelN28 2024-11-20 13:49:45 +01:00
parent 59fdf64c66
commit 2db1740ce8
6 changed files with 59 additions and 31 deletions

View file

@ -285,16 +285,11 @@
(mf/with-effect [base-objects canvas-init?] (mf/with-effect [base-objects canvas-init?]
(when @canvas-init? (when @canvas-init?
(wasm.api/set-objects base-objects) (wasm.api/set-objects base-objects)))
(wasm.api/draw-objects zoom vbox)))
(mf/with-effect [modifiers canvas-init?]
(when (and @canvas-init? modifiers)
(wasm.api/draw-objects zoom vbox)))
(mf/with-effect [vbox canvas-init?] (mf/with-effect [vbox canvas-init?]
(let [frame-id (when @canvas-init? (wasm.api/draw-objects zoom vbox))] (when @canvas-init?
(partial wasm.api/cancel-draw frame-id))) (wasm.api/set-view zoom vbox)))
(hooks/setup-dom-events zoom disable-paste in-viewport? read-only? drawing-tool drawing-path?) (hooks/setup-dom-events zoom disable-paste in-viewport? read-only? drawing-tool drawing-path?)
(hooks/setup-viewport-size vport viewport-ref) (hooks/setup-viewport-size vport viewport-ref)

View file

@ -13,13 +13,27 @@
[app.render-wasm.helpers :as h] [app.render-wasm.helpers :as h]
[promesa.core :as p])) [promesa.core :as p]))
(defonce internal-frame-id nil)
(defonce internal-module #js {}) (defonce internal-module #js {})
(defn create-shape ;; This should never be called from the outside.
[id] ;; This function receives a "time" parameter that we're not using but maybe in the future could be useful (it is the time since
(let [buffer (uuid/get-u32 id)] ;; the window started rendering elements so it could be useful to measure time between frames).
(h/call internal-module "_create_shape" (defn- render
(aget buffer 0) (aget buffer 1) (aget buffer 2) (aget buffer 3)))) [_]
(h/call internal-module "_render")
(set! internal-frame-id nil))
(defn cancel-render
[]
(when internal-frame-id
(js/cancelAnimationFrame internal-frame-id)
(set! internal-frame-id nil)))
(defn request-render
[]
(when internal-frame-id (cancel-render))
(set! internal-frame-id (js/requestAnimationFrame render)))
(defn use-shape (defn use-shape
[id] [id]
@ -105,6 +119,11 @@
;; https://rust-skia.github.io/doc/skia_safe/enum.BlendMode.html ;; https://rust-skia.github.io/doc/skia_safe/enum.BlendMode.html
(h/call internal-module "_set_shape_blend_mode" (translate-blend-mode blend-mode))) (h/call internal-module "_set_shape_blend_mode" (translate-blend-mode blend-mode)))
(defn set-view
[zoom vbox]
(h/call internal-module "_set_view" zoom (- (:x vbox)) (- (:y vbox)))
(request-render))
(defn set-objects (defn set-objects
[objects] [objects]
(let [shapes (into [] (vals objects)) (let [shapes (into [] (vals objects))
@ -127,23 +146,11 @@
(set-shape-fills fills) (set-shape-fills fills)
(set-shape-blend-mode blend-mode) (set-shape-blend-mode blend-mode)
(set-shape-children children) (set-shape-children children)
(recur (inc index))))))) (recur (inc index))))))
(request-render))
(defn draw-objects
[zoom vbox]
(js/requestAnimationFrame
(fn []
(let [pan-x (- (dm/get-prop vbox :x))
pan-y (- (dm/get-prop vbox :y))]
(h/call internal-module "_draw_all_shapes" zoom pan-x pan-y)))))
(defn cancel-draw
[frame-id]
(when (some? frame-id)
(js/cancelAnimationFrame frame-id)))
(def ^:private canvas-options (def ^:private canvas-options
#js {:antialias true #js {:antialias false
:depth true :depth true
:stencil true :stencil true
:alpha true}) :alpha true})

View file

@ -101,7 +101,11 @@
:fills (api/set-shape-fills v) :fills (api/set-shape-fills v)
:blend-mode (api/set-shape-blend-mode v) :blend-mode (api/set-shape-blend-mode v)
:shapes (api/set-shape-children v) :shapes (api/set-shape-children v)
nil)) nil)
;; when something synced with wasm
;; is modified, we need to request
;; a new render.
(api/request-render))
(let [delegate (.-delegate ^ShapeProxy self) (let [delegate (.-delegate ^ShapeProxy self)
delegate' (assoc delegate k v)] delegate' (assoc delegate k v)]
(if (identical? delegate' delegate) (if (identical? delegate' delegate)

View file

@ -2,6 +2,7 @@ pub mod render;
pub mod shapes; pub mod shapes;
pub mod state; pub mod state;
pub mod utils; pub mod utils;
pub mod view;
use skia_safe as skia; use skia_safe as skia;
@ -43,9 +44,9 @@ pub unsafe extern "C" fn resize_surface(width: i32, height: i32) {
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn draw_all_shapes(zoom: f32, pan_x: f32, pan_y: f32) { pub unsafe extern "C" fn render() {
let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer"); let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer");
state.draw_all_shapes(zoom, pan_x, pan_y); state.draw_all_shapes(state.view.zoom, state.view.x, state.view.y);
} }
#[no_mangle] #[no_mangle]
@ -54,6 +55,14 @@ pub extern "C" fn reset_canvas() {
state.render_state().reset_canvas(); state.render_state().reset_canvas();
} }
#[no_mangle]
pub extern "C" fn set_view(zoom: f32, x: f32, y: f32) {
let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer");
state.view.x = x;
state.view.y = y;
state.view.zoom = zoom;
}
#[no_mangle] #[no_mangle]
pub extern "C" fn use_shape(a: u32, b: u32, c: u32, d: u32) { pub extern "C" fn use_shape(a: u32, b: u32, c: u32, d: u32) {
let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer"); let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer");

View file

@ -3,6 +3,7 @@ use uuid::Uuid;
use crate::render::RenderState; use crate::render::RenderState;
use crate::shapes::Shape; use crate::shapes::Shape;
use crate::view::View;
/// This struct holds the state of the Rust application between JS calls. /// This struct holds the state of the Rust application between JS calls.
/// ///
@ -14,6 +15,7 @@ pub(crate) struct State<'a> {
pub current_id: Option<Uuid>, pub current_id: Option<Uuid>,
pub current_shape: Option<&'a mut Shape>, pub current_shape: Option<&'a mut Shape>,
pub shapes: HashMap<Uuid, Shape>, pub shapes: HashMap<Uuid, Shape>,
pub view: View,
} }
impl<'a> State<'a> { impl<'a> State<'a> {
@ -23,6 +25,11 @@ impl<'a> State<'a> {
current_id: None, current_id: None,
current_shape: None, current_shape: None,
shapes: HashMap::with_capacity(capacity), shapes: HashMap::with_capacity(capacity),
view: View {
x: 0.,
y: 0.,
zoom: 1.,
}
} }
} }

6
render-wasm/src/view.rs Normal file
View file

@ -0,0 +1,6 @@
pub(crate) struct View
{
pub x: f32,
pub y: f32,
pub zoom: f32,
}