mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-02 03:28:11 +08:00
Add auto-panning when pointer goes beyond viewport edge with Select tool (#1625)
* Add code to shift viewport if mouse is beyond edge * Allow shifting viewport if mouse is stationary too * Group all modifier keys into SelectToolPointerKeys * Cleanup message ordering to remove shifting during resize * Slow down shifting by half * Clamp speed; code review cleanup --------- Co-authored-by: 0hypercube <0hypercube@gmail.com> Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
committed by
Keavon Chambers
co-authored by
0hypercube
Keavon Chambers
parent
4405e01f55
commit
8e769e37f6
@@ -18,6 +18,9 @@ pub const VIEWPORT_ROTATE_SNAP_INTERVAL: f64 = 15.;
|
|||||||
|
|
||||||
pub const VIEWPORT_ZOOM_TO_FIT_PADDING_SCALE_FACTOR: f64 = 0.95;
|
pub const VIEWPORT_ZOOM_TO_FIT_PADDING_SCALE_FACTOR: f64 = 0.95;
|
||||||
|
|
||||||
|
pub const DRAG_BEYOND_VIEWPORT_MAX_OVEREXTENSION_PIXELS: f64 = 50.;
|
||||||
|
pub const DRAG_BEYOND_VIEWPORT_SPEED_FACTOR: f64 = 0.5;
|
||||||
|
|
||||||
// Snapping point
|
// Snapping point
|
||||||
pub const SNAP_POINT_TOLERANCE: f64 = 5.;
|
pub const SNAP_POINT_TOLERANCE: f64 = 5.;
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize, Hash)]
|
#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize, Hash)]
|
||||||
#[impl_message(Message, BroadcastMessage, TriggerEvent)]
|
#[impl_message(Message, BroadcastMessage, TriggerEvent)]
|
||||||
pub enum BroadcastEvent {
|
pub enum BroadcastEvent {
|
||||||
|
AnimationFrame,
|
||||||
CanvasTransformed,
|
CanvasTransformed,
|
||||||
ToolAbort,
|
ToolAbort,
|
||||||
SelectionChanged,
|
SelectionChanged,
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ use crate::messages::portfolio::document::utility_types::clipboards::Clipboard;
|
|||||||
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
|
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
|
||||||
use crate::messages::prelude::*;
|
use crate::messages::prelude::*;
|
||||||
use crate::messages::tool::tool_messages::brush_tool::BrushToolMessageOptionsUpdate;
|
use crate::messages::tool::tool_messages::brush_tool::BrushToolMessageOptionsUpdate;
|
||||||
|
use crate::messages::tool::tool_messages::select_tool::SelectToolPointerKeys;
|
||||||
|
|
||||||
use glam::DVec2;
|
use glam::DVec2;
|
||||||
|
|
||||||
@@ -71,7 +72,7 @@ pub fn default_mapping() -> Mapping {
|
|||||||
entry!(PointerMove; refresh_keys=[Control, Shift], action_dispatch=TransformLayerMessage::PointerMove { slow_key: Shift, snap_key: Control }),
|
entry!(PointerMove; refresh_keys=[Control, Shift], action_dispatch=TransformLayerMessage::PointerMove { slow_key: Shift, snap_key: Control }),
|
||||||
//
|
//
|
||||||
// SelectToolMessage
|
// SelectToolMessage
|
||||||
entry!(PointerMove; refresh_keys=[Control, Alt, Shift], action_dispatch=SelectToolMessage::PointerMove { axis_align: Shift, snap_angle: Control, center: Alt, duplicate: Alt }),
|
entry!(PointerMove; refresh_keys=[Control, Alt, Shift], action_dispatch=SelectToolMessage::PointerMove(SelectToolPointerKeys { axis_align: Shift, snap_angle: Control, center: Alt, duplicate: Alt })),
|
||||||
entry!(KeyDown(Lmb); action_dispatch=SelectToolMessage::DragStart { add_to_selection: Shift, select_deepest: Accel }),
|
entry!(KeyDown(Lmb); action_dispatch=SelectToolMessage::DragStart { add_to_selection: Shift, select_deepest: Accel }),
|
||||||
entry!(KeyUp(Lmb); action_dispatch=SelectToolMessage::DragStop { remove_from_selection: Shift }),
|
entry!(KeyUp(Lmb); action_dispatch=SelectToolMessage::DragStop { remove_from_selection: Shift }),
|
||||||
entry!(KeyDown(Enter); action_dispatch=SelectToolMessage::Enter),
|
entry!(KeyDown(Enter); action_dispatch=SelectToolMessage::Enter),
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use super::tool_prelude::*;
|
use super::tool_prelude::*;
|
||||||
use crate::application::generate_uuid;
|
use crate::application::generate_uuid;
|
||||||
use crate::consts::{ROTATE_SNAP_ANGLE, SELECTION_TOLERANCE};
|
use crate::consts::{DRAG_BEYOND_VIEWPORT_MAX_OVEREXTENSION_PIXELS, DRAG_BEYOND_VIEWPORT_SPEED_FACTOR, ROTATE_SNAP_ANGLE, SELECTION_TOLERANCE};
|
||||||
use crate::messages::input_mapper::utility_types::input_mouse::ViewportPosition;
|
use crate::messages::input_mapper::utility_types::input_mouse::ViewportPosition;
|
||||||
use crate::messages::portfolio::document::overlays::utility_types::OverlayContext;
|
use crate::messages::portfolio::document::overlays::utility_types::OverlayContext;
|
||||||
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
|
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
|
||||||
@@ -52,6 +52,14 @@ impl fmt::Display for NestedSelectionBehavior {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Clone, Debug, Serialize, Deserialize, specta::Type)]
|
||||||
|
pub struct SelectToolPointerKeys {
|
||||||
|
pub axis_align: Key,
|
||||||
|
pub snap_angle: Key,
|
||||||
|
pub center: Key,
|
||||||
|
pub duplicate: Key,
|
||||||
|
}
|
||||||
|
|
||||||
#[remain::sorted]
|
#[remain::sorted]
|
||||||
#[impl_message(Message, ToolMessage, Select)]
|
#[impl_message(Message, ToolMessage, Select)]
|
||||||
#[derive(PartialEq, Clone, Debug, Serialize, Deserialize, specta::Type)]
|
#[derive(PartialEq, Clone, Debug, Serialize, Deserialize, specta::Type)]
|
||||||
@@ -72,16 +80,13 @@ pub enum SelectToolMessage {
|
|||||||
},
|
},
|
||||||
EditLayer,
|
EditLayer,
|
||||||
Enter,
|
Enter,
|
||||||
PointerMove {
|
PointerMove(SelectToolPointerKeys),
|
||||||
axis_align: Key,
|
PointerOutsideViewport(SelectToolPointerKeys),
|
||||||
snap_angle: Key,
|
|
||||||
center: Key,
|
|
||||||
duplicate: Key,
|
|
||||||
},
|
|
||||||
SelectOptions(SelectOptionsUpdate),
|
SelectOptions(SelectOptionsUpdate),
|
||||||
SetPivot {
|
SetPivot {
|
||||||
position: PivotPosition,
|
position: PivotPosition,
|
||||||
},
|
},
|
||||||
|
ShiftViewport,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToolMetadata for SelectTool {
|
impl ToolMetadata for SelectTool {
|
||||||
@@ -269,6 +274,7 @@ struct SelectToolData {
|
|||||||
selected_layers_count: usize,
|
selected_layers_count: usize,
|
||||||
selected_layers_changed: bool,
|
selected_layers_changed: bool,
|
||||||
snap_candidates: Vec<SnapCandidatePoint>,
|
snap_candidates: Vec<SnapCandidatePoint>,
|
||||||
|
subscribed_to_animation_frame: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SelectToolData {
|
impl SelectToolData {
|
||||||
@@ -590,16 +596,16 @@ impl Fsm for SelectToolFsmState {
|
|||||||
|
|
||||||
state
|
state
|
||||||
}
|
}
|
||||||
(SelectToolFsmState::Dragging, SelectToolMessage::PointerMove { axis_align, duplicate, .. }) => {
|
(SelectToolFsmState::Dragging, SelectToolMessage::PointerMove(modifier_keys)) => {
|
||||||
tool_data.has_dragged = true;
|
tool_data.has_dragged = true;
|
||||||
|
|
||||||
if input.keyboard.key(duplicate) && tool_data.non_duplicated_layers.is_none() {
|
if input.keyboard.key(modifier_keys.duplicate) && tool_data.non_duplicated_layers.is_none() {
|
||||||
tool_data.start_duplicates(document, responses);
|
tool_data.start_duplicates(document, responses);
|
||||||
} else if !input.keyboard.key(duplicate) && tool_data.non_duplicated_layers.is_some() {
|
} else if !input.keyboard.key(modifier_keys.duplicate) && tool_data.non_duplicated_layers.is_some() {
|
||||||
tool_data.stop_duplicates(document, responses);
|
tool_data.stop_duplicates(document, responses);
|
||||||
}
|
}
|
||||||
|
|
||||||
let axis_align = input.keyboard.key(axis_align);
|
let axis_align = input.keyboard.key(modifier_keys.axis_align);
|
||||||
let mouse_position = axis_align_drag(axis_align, input.mouse.position, tool_data.drag_start);
|
let mouse_position = axis_align_drag(axis_align, input.mouse.position, tool_data.drag_start);
|
||||||
let total_mouse_delta_document = document.metadata.document_to_viewport.inverse().transform_vector2(mouse_position - tool_data.drag_start);
|
let total_mouse_delta_document = document.metadata.document_to_viewport.inverse().transform_vector2(mouse_position - tool_data.drag_start);
|
||||||
|
|
||||||
@@ -644,12 +650,14 @@ impl Fsm for SelectToolFsmState {
|
|||||||
}
|
}
|
||||||
tool_data.drag_current += mouse_delta;
|
tool_data.drag_current += mouse_delta;
|
||||||
|
|
||||||
|
setup_pointer_outside_edge_event(input.mouse.position, input.viewport_bounds.size(), tool_data, modifier_keys, responses);
|
||||||
|
|
||||||
SelectToolFsmState::Dragging
|
SelectToolFsmState::Dragging
|
||||||
}
|
}
|
||||||
(SelectToolFsmState::ResizingBounds, SelectToolMessage::PointerMove { axis_align, center, .. }) => {
|
(SelectToolFsmState::ResizingBounds, SelectToolMessage::PointerMove(modifier_keys)) => {
|
||||||
if let Some(bounds) = &mut tool_data.bounding_box_manager {
|
if let Some(ref mut bounds) = &mut tool_data.bounding_box_manager {
|
||||||
if let Some(movement) = &mut bounds.selected_edges {
|
if let Some(movement) = &mut bounds.selected_edges {
|
||||||
let (center, constrain) = (input.keyboard.key(center), input.keyboard.key(axis_align));
|
let (center, constrain) = (input.keyboard.key(modifier_keys.center), input.keyboard.key(modifier_keys.axis_align));
|
||||||
|
|
||||||
let center = center.then_some(bounds.center_of_transformation);
|
let center = center.then_some(bounds.center_of_transformation);
|
||||||
let snap = Some(SizeSnapData {
|
let snap = Some(SizeSnapData {
|
||||||
@@ -677,11 +685,13 @@ impl Fsm for SelectToolFsmState {
|
|||||||
);
|
);
|
||||||
|
|
||||||
selected.apply_transformation(bounds.original_bound_transform * transformation * bounds.original_bound_transform.inverse());
|
selected.apply_transformation(bounds.original_bound_transform * transformation * bounds.original_bound_transform.inverse());
|
||||||
|
|
||||||
|
setup_pointer_outside_edge_event(input.mouse.position, input.viewport_bounds.size(), tool_data, modifier_keys, responses);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SelectToolFsmState::ResizingBounds
|
SelectToolFsmState::ResizingBounds
|
||||||
}
|
}
|
||||||
(SelectToolFsmState::RotatingBounds, SelectToolMessage::PointerMove { snap_angle, .. }) => {
|
(SelectToolFsmState::RotatingBounds, SelectToolMessage::PointerMove(modifier_keys)) => {
|
||||||
if let Some(bounds) = &mut tool_data.bounding_box_manager {
|
if let Some(bounds) = &mut tool_data.bounding_box_manager {
|
||||||
let angle = {
|
let angle = {
|
||||||
let start_offset = tool_data.drag_start - bounds.center_of_transformation;
|
let start_offset = tool_data.drag_start - bounds.center_of_transformation;
|
||||||
@@ -690,7 +700,7 @@ impl Fsm for SelectToolFsmState {
|
|||||||
start_offset.angle_between(end_offset)
|
start_offset.angle_between(end_offset)
|
||||||
};
|
};
|
||||||
|
|
||||||
let snapped_angle = if input.keyboard.key(snap_angle) {
|
let snapped_angle = if input.keyboard.key(modifier_keys.snap_angle) {
|
||||||
let snap_resolution = ROTATE_SNAP_ANGLE.to_radians();
|
let snap_resolution = ROTATE_SNAP_ANGLE.to_radians();
|
||||||
(angle / snap_resolution).round() * snap_resolution
|
(angle / snap_resolution).round() * snap_resolution
|
||||||
} else {
|
} else {
|
||||||
@@ -716,20 +726,24 @@ impl Fsm for SelectToolFsmState {
|
|||||||
|
|
||||||
SelectToolFsmState::RotatingBounds
|
SelectToolFsmState::RotatingBounds
|
||||||
}
|
}
|
||||||
(SelectToolFsmState::DraggingPivot, SelectToolMessage::PointerMove { .. }) => {
|
(SelectToolFsmState::DraggingPivot, SelectToolMessage::PointerMove(modifier_keys)) => {
|
||||||
let mouse_position = input.mouse.position;
|
let mouse_position = input.mouse.position;
|
||||||
let snapped_mouse_position = mouse_position; //tool_data.snap_manager.snap_position(responses, document, mouse_position);
|
let snapped_mouse_position = mouse_position; //tool_data.snap_manager.snap_position(responses, document, mouse_position);
|
||||||
tool_data.pivot.set_viewport_position(snapped_mouse_position, document, responses);
|
tool_data.pivot.set_viewport_position(snapped_mouse_position, document, responses);
|
||||||
|
|
||||||
|
setup_pointer_outside_edge_event(mouse_position, input.viewport_bounds.size(), tool_data, modifier_keys, responses);
|
||||||
|
|
||||||
SelectToolFsmState::DraggingPivot
|
SelectToolFsmState::DraggingPivot
|
||||||
}
|
}
|
||||||
(SelectToolFsmState::DrawingBox, SelectToolMessage::PointerMove { .. }) => {
|
(SelectToolFsmState::DrawingBox, SelectToolMessage::PointerMove(modifier_keys)) => {
|
||||||
tool_data.drag_current = input.mouse.position;
|
tool_data.drag_current = input.mouse.position;
|
||||||
responses.add(OverlaysMessage::Draw);
|
responses.add(OverlaysMessage::Draw);
|
||||||
|
|
||||||
|
setup_pointer_outside_edge_event(input.mouse.position, input.viewport_bounds.size(), tool_data, modifier_keys, responses);
|
||||||
|
|
||||||
SelectToolFsmState::DrawingBox
|
SelectToolFsmState::DrawingBox
|
||||||
}
|
}
|
||||||
(SelectToolFsmState::Ready, SelectToolMessage::PointerMove { .. }) => {
|
(SelectToolFsmState::Ready, SelectToolMessage::PointerMove(_)) => {
|
||||||
let mut cursor = tool_data.bounding_box_manager.as_ref().map_or(MouseCursorIcon::Default, |bounds| bounds.get_cursor(input, true));
|
let mut cursor = tool_data.bounding_box_manager.as_ref().map_or(MouseCursorIcon::Default, |bounds| bounds.get_cursor(input, true));
|
||||||
|
|
||||||
// Dragging the pivot overrules the other operations
|
// Dragging the pivot overrules the other operations
|
||||||
@@ -747,6 +761,50 @@ impl Fsm for SelectToolFsmState {
|
|||||||
|
|
||||||
SelectToolFsmState::Ready
|
SelectToolFsmState::Ready
|
||||||
}
|
}
|
||||||
|
(SelectToolFsmState::Dragging, SelectToolMessage::PointerOutsideViewport(modifier_keys)) => {
|
||||||
|
responses.add(SelectToolMessage::PointerMove(modifier_keys));
|
||||||
|
|
||||||
|
if let Some(shift) = shift_viewport_if_mouse_beyond_edge(input.mouse.position, input.viewport_bounds.size(), responses) {
|
||||||
|
tool_data.drag_current += shift;
|
||||||
|
tool_data.drag_start += shift;
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectToolFsmState::Dragging
|
||||||
|
}
|
||||||
|
(SelectToolFsmState::ResizingBounds | SelectToolFsmState::DraggingPivot | SelectToolFsmState::DrawingBox, SelectToolMessage::PointerOutsideViewport(modifier_keys)) => {
|
||||||
|
responses.add(SelectToolMessage::PointerMove(modifier_keys));
|
||||||
|
|
||||||
|
responses.add(SelectToolMessage::ShiftViewport);
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
(SelectToolFsmState::ResizingBounds, SelectToolMessage::ShiftViewport) => {
|
||||||
|
if let Some(shift) = shift_viewport_if_mouse_beyond_edge(input.mouse.position, input.viewport_bounds.size(), responses) {
|
||||||
|
if let Some(ref mut bounds) = &mut tool_data.bounding_box_manager {
|
||||||
|
bounds.center_of_transformation += shift;
|
||||||
|
bounds.original_bound_transform.translation += shift;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
(SelectToolFsmState::DraggingPivot, SelectToolMessage::ShiftViewport) => {
|
||||||
|
let _ = shift_viewport_if_mouse_beyond_edge(input.mouse.position, input.viewport_bounds.size(), responses);
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
(SelectToolFsmState::DrawingBox, SelectToolMessage::ShiftViewport) => {
|
||||||
|
if let Some(shift) = shift_viewport_if_mouse_beyond_edge(input.mouse.position, input.viewport_bounds.size(), responses) {
|
||||||
|
tool_data.drag_start += shift;
|
||||||
|
}
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
(state, SelectToolMessage::PointerOutsideViewport(modifier_keys)) => {
|
||||||
|
unsubscribe_animation_frame(tool_data, modifier_keys, responses);
|
||||||
|
|
||||||
|
state
|
||||||
|
}
|
||||||
(SelectToolFsmState::Dragging, SelectToolMessage::Enter) => {
|
(SelectToolFsmState::Dragging, SelectToolMessage::Enter) => {
|
||||||
let response = match input.mouse.position.distance(tool_data.drag_start) < 10. * f64::EPSILON {
|
let response = match input.mouse.position.distance(tool_data.drag_start) < 10. * f64::EPSILON {
|
||||||
true => DocumentMessage::Undo,
|
true => DocumentMessage::Undo,
|
||||||
@@ -1011,3 +1069,68 @@ fn edit_layer_deepest_manipulation(layer: LayerNodeIdentifier, document_network:
|
|||||||
responses.add_front(ToolMessage::ActivateTool { tool_type: ToolType::Path });
|
responses.add_front(ToolMessage::ActivateTool { tool_type: ToolType::Path });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Shifts the viewport when the mouse reaches the edge of the viewport.
|
||||||
|
///
|
||||||
|
/// If the mouse was beyond any edge, it returns the amount shifted. Otherwise it returns None.
|
||||||
|
/// The shift is proportional to the distance between edge and mouse. It is also guaranteed to be integral.
|
||||||
|
fn shift_viewport_if_mouse_beyond_edge(mouse_position: DVec2, viewport_size: DVec2, responses: &mut VecDeque<Message>) -> Option<DVec2> {
|
||||||
|
let mouse_position = mouse_position.clamp(
|
||||||
|
DVec2::ZERO - DVec2::splat(DRAG_BEYOND_VIEWPORT_MAX_OVEREXTENSION_PIXELS),
|
||||||
|
viewport_size + DVec2::splat(DRAG_BEYOND_VIEWPORT_MAX_OVEREXTENSION_PIXELS),
|
||||||
|
);
|
||||||
|
let mouse_position_percent = mouse_position / viewport_size;
|
||||||
|
|
||||||
|
let mut shift_percent = DVec2::ZERO;
|
||||||
|
|
||||||
|
if mouse_position_percent.x < 0. {
|
||||||
|
shift_percent.x = -mouse_position_percent.x;
|
||||||
|
} else if mouse_position_percent.x > 1. {
|
||||||
|
shift_percent.x = 1. - mouse_position_percent.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if mouse_position_percent.y < 0. {
|
||||||
|
shift_percent.y = -mouse_position_percent.y;
|
||||||
|
} else if mouse_position_percent.y > 1. {
|
||||||
|
shift_percent.y = 1. - mouse_position_percent.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if shift_percent.x == 0. && shift_percent.y == 0. {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let delta = (shift_percent * DRAG_BEYOND_VIEWPORT_SPEED_FACTOR * viewport_size).round();
|
||||||
|
responses.add(NavigationMessage::TranslateCanvas { delta });
|
||||||
|
Some(delta)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_pointer_outside_edge_event(mouse_position: DVec2, viewport_size: DVec2, tool_data: &mut SelectToolData, modifier_keys: SelectToolPointerKeys, responses: &mut VecDeque<Message>) {
|
||||||
|
let is_pointer_outside_edge = mouse_position.x < 0. || mouse_position.x > viewport_size.x || mouse_position.y < 0. || mouse_position.y > viewport_size.y;
|
||||||
|
|
||||||
|
match is_pointer_outside_edge {
|
||||||
|
true => subscribe_animation_frame(tool_data, modifier_keys, responses),
|
||||||
|
false => unsubscribe_animation_frame(tool_data, modifier_keys, responses),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn subscribe_animation_frame(tool_data: &mut SelectToolData, modifier_keys: SelectToolPointerKeys, responses: &mut VecDeque<Message>) {
|
||||||
|
if !tool_data.subscribed_to_animation_frame {
|
||||||
|
tool_data.subscribed_to_animation_frame = true;
|
||||||
|
|
||||||
|
responses.add(BroadcastMessage::SubscribeEvent {
|
||||||
|
on: BroadcastEvent::AnimationFrame,
|
||||||
|
send: Box::new(SelectToolMessage::PointerOutsideViewport(modifier_keys).into()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unsubscribe_animation_frame(tool_data: &mut SelectToolData, modifier_keys: SelectToolPointerKeys, responses: &mut VecDeque<Message>) {
|
||||||
|
if tool_data.subscribed_to_animation_frame {
|
||||||
|
tool_data.subscribed_to_animation_frame = false;
|
||||||
|
|
||||||
|
responses.add(BroadcastMessage::UnsubscribeEvent {
|
||||||
|
on: BroadcastEvent::AnimationFrame,
|
||||||
|
message: Box::new(SelectToolMessage::PointerOutsideViewport(modifier_keys).into()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -239,6 +239,12 @@ impl JsEditorHandle {
|
|||||||
*g.borrow_mut() = Some(Closure::new(move || {
|
*g.borrow_mut() = Some(Closure::new(move || {
|
||||||
wasm_bindgen_futures::spawn_local(poll_node_graph_evaluation());
|
wasm_bindgen_futures::spawn_local(poll_node_graph_evaluation());
|
||||||
|
|
||||||
|
call_closure_with_editor_and_handle(|editor, handle| {
|
||||||
|
for message in editor.handle_message(BroadcastMessage::TriggerEvent(BroadcastEvent::AnimationFrame)) {
|
||||||
|
handle.send_frontend_message_to_js(message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Schedule ourself for another requestAnimationFrame callback
|
// Schedule ourself for another requestAnimationFrame callback
|
||||||
request_animation_frame(f.borrow().as_ref().unwrap());
|
request_animation_frame(f.borrow().as_ref().unwrap());
|
||||||
}));
|
}));
|
||||||
|
|||||||
Reference in New Issue
Block a user