mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-02 18:48:11 +08:00
Fix tests & gradient tool
This commit is contained in:
@@ -165,7 +165,7 @@ pub fn input_mappings() -> Mapping {
|
|||||||
entry!(KeyDown(MouseLeft); action_dispatch=GradientToolMessage::PointerDown),
|
entry!(KeyDown(MouseLeft); action_dispatch=GradientToolMessage::PointerDown),
|
||||||
entry!(PointerMove; refresh_keys=[Shift], action_dispatch=GradientToolMessage::PointerMove { constrain_axis: Shift }),
|
entry!(PointerMove; refresh_keys=[Shift], action_dispatch=GradientToolMessage::PointerMove { constrain_axis: Shift }),
|
||||||
entry!(KeyUp(MouseLeft); action_dispatch=GradientToolMessage::PointerUp),
|
entry!(KeyUp(MouseLeft); action_dispatch=GradientToolMessage::PointerUp),
|
||||||
entry!(DoubleClick(MouseButton::Left); action_dispatch=GradientToolMessage::InsertStop),
|
entry!(DoubleClick(MouseButton::Left); action_dispatch=GradientToolMessage::InsertStopProxy),
|
||||||
entry!(KeyDown(Delete); action_dispatch=GradientToolMessage::DeleteStop),
|
entry!(KeyDown(Delete); action_dispatch=GradientToolMessage::DeleteStop),
|
||||||
entry!(KeyDown(Backspace); action_dispatch=GradientToolMessage::DeleteStop),
|
entry!(KeyDown(Backspace); action_dispatch=GradientToolMessage::DeleteStop),
|
||||||
entry!(KeyDown(MouseRight); action_dispatch=GradientToolMessage::Abort),
|
entry!(KeyDown(MouseRight); action_dispatch=GradientToolMessage::Abort),
|
||||||
|
|||||||
@@ -200,6 +200,7 @@ impl core::hash::Hash for OverlayContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl OverlayContext {
|
impl OverlayContext {
|
||||||
|
#[cfg(not(test))]
|
||||||
pub(super) fn new(size: DVec2, device_pixel_ratio: f64, visibility_settings: OverlaysVisibilitySettings) -> Self {
|
pub(super) fn new(size: DVec2, device_pixel_ratio: f64, visibility_settings: OverlaysVisibilitySettings) -> Self {
|
||||||
Self {
|
Self {
|
||||||
internal: Arc::new(Mutex::new(OverlayContextInternal::new(size, device_pixel_ratio, visibility_settings))),
|
internal: Arc::new(Mutex::new(OverlayContextInternal::new(size, device_pixel_ratio, visibility_settings))),
|
||||||
@@ -421,6 +422,7 @@ impl Default for OverlayContextInternal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl OverlayContextInternal {
|
impl OverlayContextInternal {
|
||||||
|
#[cfg(not(test))]
|
||||||
pub(super) fn new(size: DVec2, device_pixel_ratio: f64, visibility_settings: OverlaysVisibilitySettings) -> Self {
|
pub(super) fn new(size: DVec2, device_pixel_ratio: f64, visibility_settings: OverlaysVisibilitySettings) -> Self {
|
||||||
Self {
|
Self {
|
||||||
scene: Scene::new(),
|
scene: Scene::new(),
|
||||||
|
|||||||
@@ -354,33 +354,27 @@ mod test_line_tool {
|
|||||||
|
|
||||||
let artboard_id = editor.get_selected_layer().await.expect("Should have selected the artboard");
|
let artboard_id = editor.get_selected_layer().await.expect("Should have selected the artboard");
|
||||||
|
|
||||||
|
let transform = DAffine2::from_angle(45_f64.to_radians());
|
||||||
editor
|
editor
|
||||||
.handle_message(GraphOperationMessage::TransformChange {
|
.handle_message(GraphOperationMessage::TransformChange {
|
||||||
layer: artboard_id,
|
layer: artboard_id,
|
||||||
transform: DAffine2::from_angle(45_f64.to_radians()),
|
transform,
|
||||||
transform_in: TransformIn::Local,
|
transform_in: TransformIn::Local,
|
||||||
skip_rerender: false,
|
skip_rerender: false,
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
editor.drag_tool(ToolType::Line, 50., 50., 150., 150., ModifierKeys::empty()).await;
|
let expected_start = DVec2::new(55., 42.);
|
||||||
|
let expected_end = DVec2::new(124., 142.);
|
||||||
|
editor
|
||||||
|
.drag_tool(ToolType::Line, expected_start.x, expected_start.y, expected_end.x, expected_end.y, ModifierKeys::empty())
|
||||||
|
.await;
|
||||||
|
|
||||||
let (start_input, end_input) = get_line_node_inputs(&mut editor).await.expect("Line was not created successfully within transformed artboard");
|
let (start_input, end_input) = get_line_node_inputs(&mut editor).await.expect("Line was not created successfully within transformed artboard");
|
||||||
// The line should still be diagonal with equal change in x and y
|
let document = editor.editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap();
|
||||||
let line_vector = end_input - start_input;
|
assert_eq!(document.metadata().document_to_viewport, DAffine2::IDENTITY);
|
||||||
// Verifying the line is approximately 100*sqrt(2) units in length (diagonal of 100x100 square)
|
let [start_viewport, end_viewport] = [start_input, end_input].map(|point| transform.transform_point2(point));
|
||||||
let line_length = line_vector.length();
|
assert!(start_viewport.abs_diff_eq(expected_start, 1e-10), "expected line to start at {expected_start} not {start_viewport}");
|
||||||
assert!(
|
assert!(end_viewport.abs_diff_eq(expected_end, 1e-10), "expected line to end at {expected_end} not {end_viewport}");
|
||||||
(line_length - 141.42).abs() < 1., // 100 * sqrt(2) ~= 141.42
|
|
||||||
"Line length should be approximately 141.42 units. Got: {line_length}"
|
|
||||||
);
|
|
||||||
assert!((line_vector.x - 100.).abs() < 1., "X-component of line vector should be approximately 100. Got: {}", line_vector.x);
|
|
||||||
assert!(
|
|
||||||
(line_vector.y.abs() - 100.).abs() < 1.,
|
|
||||||
"Absolute Y-component of line vector should be approximately 100. Got: {}",
|
|
||||||
line_vector.y.abs()
|
|
||||||
);
|
|
||||||
let angle_degrees = line_vector.angle_to(DVec2::X).to_degrees();
|
|
||||||
assert!((angle_degrees - (-45.)).abs() < 1., "Line angle should be close to -45 degrees. Got: {angle_degrees}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use super::tool_prelude::*;
|
use super::tool_prelude::*;
|
||||||
use crate::consts::{LINE_ROTATE_SNAP_ANGLE, MANIPULATOR_GROUP_MARKER_SIZE, SELECTION_THRESHOLD};
|
use crate::consts::{DRAG_THRESHOLD, LINE_ROTATE_SNAP_ANGLE, MANIPULATOR_GROUP_MARKER_SIZE, SELECTION_THRESHOLD};
|
||||||
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;
|
||||||
use crate::messages::tool::common_functionality::auto_panning::AutoPanning;
|
use crate::messages::tool::common_functionality::auto_panning::AutoPanning;
|
||||||
@@ -29,6 +29,7 @@ pub enum GradientToolMessage {
|
|||||||
// Tool-specific messages
|
// Tool-specific messages
|
||||||
DeleteStop,
|
DeleteStop,
|
||||||
InsertStop,
|
InsertStop,
|
||||||
|
InsertStopProxy,
|
||||||
PointerDown,
|
PointerDown,
|
||||||
PointerMove { constrain_axis: Key },
|
PointerMove { constrain_axis: Key },
|
||||||
PointerOutsideViewport { constrain_axis: Key },
|
PointerOutsideViewport { constrain_axis: Key },
|
||||||
@@ -84,6 +85,7 @@ impl<'a> MessageHandler<ToolMessage, &mut ToolActionMessageContext<'a>> for Grad
|
|||||||
PointerMove,
|
PointerMove,
|
||||||
Abort,
|
Abort,
|
||||||
InsertStop,
|
InsertStop,
|
||||||
|
InsertStopProxy,
|
||||||
DeleteStop,
|
DeleteStop,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -117,6 +119,7 @@ enum GradientToolFsmState {
|
|||||||
/// Computes the transform from gradient space to viewport space (where gradient space is 0..1)
|
/// Computes the transform from gradient space to viewport space (where gradient space is 0..1)
|
||||||
fn gradient_space_transform(layer: LayerNodeIdentifier, document: &DocumentMessageHandler) -> DAffine2 {
|
fn gradient_space_transform(layer: LayerNodeIdentifier, document: &DocumentMessageHandler) -> DAffine2 {
|
||||||
let bounds = document.metadata().nonzero_bounding_box(layer);
|
let bounds = document.metadata().nonzero_bounding_box(layer);
|
||||||
|
println!("Bounds {bounds:?}");
|
||||||
let bound_transform = DAffine2::from_scale_angle_translation(bounds[1] - bounds[0], 0., bounds[0]);
|
let bound_transform = DAffine2::from_scale_angle_translation(bounds[1] - bounds[0], 0., bounds[0]);
|
||||||
|
|
||||||
let multiplied = document.metadata().transform_to_viewport(layer);
|
let multiplied = document.metadata().transform_to_viewport(layer);
|
||||||
@@ -237,6 +240,7 @@ struct GradientToolData {
|
|||||||
snap_manager: SnapManager,
|
snap_manager: SnapManager,
|
||||||
drag_start: DVec2,
|
drag_start: DVec2,
|
||||||
auto_panning: AutoPanning,
|
auto_panning: AutoPanning,
|
||||||
|
pointer_up_abort: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Fsm for GradientToolFsmState {
|
impl Fsm for GradientToolFsmState {
|
||||||
@@ -343,6 +347,7 @@ impl Fsm for GradientToolFsmState {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
(_, GradientToolMessage::InsertStop) => {
|
(_, GradientToolMessage::InsertStop) => {
|
||||||
|
println!("GradientToolMessage::InsertStop insert stop --------------------------");
|
||||||
for layer in document.network_interface.selected_nodes().selected_visible_layers(&document.network_interface) {
|
for layer in document.network_interface.selected_nodes().selected_visible_layers(&document.network_interface) {
|
||||||
let Some(mut gradient) = get_gradient(layer, &document.network_interface) else { continue };
|
let Some(mut gradient) = get_gradient(layer, &document.network_interface) else { continue };
|
||||||
// TODO: This transform is incorrect. I think this is since it is based on the Footprint which has not been updated yet
|
// TODO: This transform is incorrect. I think this is since it is based on the Footprint which has not been updated yet
|
||||||
@@ -351,8 +356,9 @@ impl Fsm for GradientToolFsmState {
|
|||||||
let (start, end) = (transform.transform_point2(gradient.start), transform.transform_point2(gradient.end));
|
let (start, end) = (transform.transform_point2(gradient.start), transform.transform_point2(gradient.end));
|
||||||
|
|
||||||
// Compute the distance from the mouse to the gradient line in viewport space
|
// Compute the distance from the mouse to the gradient line in viewport space
|
||||||
let direction = (end - start).normalize_or_zero();
|
let distance = (end - start).normalize_or_zero().perp_dot(mouse - start).abs();
|
||||||
let distance = direction.dot(mouse - start);
|
|
||||||
|
println!("> distance {distance} start {start} end {end} mouse {mouse}");
|
||||||
|
|
||||||
// If click is on the line then insert point
|
// If click is on the line then insert point
|
||||||
if distance < (SELECTION_THRESHOLD * 2.) {
|
if distance < (SELECTION_THRESHOLD * 2.) {
|
||||||
@@ -377,6 +383,20 @@ impl Fsm for GradientToolFsmState {
|
|||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
// The undo system clears all clear targets only for double click messages after an abort. This hack fixes that.
|
||||||
|
(_, GradientToolMessage::InsertStopProxy) => {
|
||||||
|
if tool_data.pointer_up_abort {
|
||||||
|
let metadata = document.metadata();
|
||||||
|
let all_empty = metadata.click_targets.is_empty() && metadata.upstream_footprints.is_empty() && metadata.local_transforms.is_empty();
|
||||||
|
assert!(all_empty, "document metada is properly implemented so the InsertStopProxy should be removed {metadata:#?}");
|
||||||
|
}
|
||||||
|
responses.add(DeferMessage::AfterGraphRun {
|
||||||
|
messages: vec![GradientToolMessage::InsertStop.into()],
|
||||||
|
});
|
||||||
|
responses.add(NodeGraphMessage::RunDocumentGraph);
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
(GradientToolFsmState::Ready, GradientToolMessage::PointerDown) => {
|
(GradientToolFsmState::Ready, GradientToolMessage::PointerDown) => {
|
||||||
let mouse = input.mouse.position;
|
let mouse = input.mouse.position;
|
||||||
tool_data.drag_start = mouse;
|
tool_data.drag_start = mouse;
|
||||||
@@ -494,7 +514,10 @@ impl Fsm for GradientToolFsmState {
|
|||||||
state
|
state
|
||||||
}
|
}
|
||||||
(GradientToolFsmState::Drawing, GradientToolMessage::PointerUp) => {
|
(GradientToolFsmState::Drawing, GradientToolMessage::PointerUp) => {
|
||||||
input.mouse.finish_transaction(tool_data.drag_start, responses);
|
let drag_too_small = tool_data.drag_start.distance(input.mouse.position) <= DRAG_THRESHOLD;
|
||||||
|
responses.add(if drag_too_small { DocumentMessage::AbortTransaction } else { DocumentMessage::EndTransaction });
|
||||||
|
tool_data.pointer_up_abort = drag_too_small;
|
||||||
|
|
||||||
tool_data.snap_manager.cleanup(responses);
|
tool_data.snap_manager.cleanup(responses);
|
||||||
let was_dragging = tool_data.selected_gradient.is_some();
|
let was_dragging = tool_data.selected_gradient.is_some();
|
||||||
|
|
||||||
@@ -694,6 +717,17 @@ mod test_gradient {
|
|||||||
assert!(transform.transform_point2(gradient.end).abs_diff_eq(DVec2::new(24., 4.), 1e-10));
|
assert!(transform.transform_point2(gradient.end).abs_diff_eq(DVec2::new(24., 4.), 1e-10));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn double_click_empty_space() {
|
||||||
|
let mut editor = EditorTestUtils::create();
|
||||||
|
editor.new_document().await;
|
||||||
|
editor.drag_tool(ToolType::Rectangle, -5., -5., 105., 105., ModifierKeys::empty()).await;
|
||||||
|
editor.drag_tool(ToolType::Gradient, 0., 0., 100., 0., ModifierKeys::empty()).await;
|
||||||
|
editor.pointer_up_double_click(DVec2::new(300., 300.)).await;
|
||||||
|
let (updated_gradient, _) = get_gradient(&mut editor).await;
|
||||||
|
assert_eq!(updated_gradient.stops.len(), 2, "Expected 2 stops, found {}", updated_gradient.stops.len());
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn double_click_insert_stop() {
|
async fn double_click_insert_stop() {
|
||||||
let mut editor = EditorTestUtils::create();
|
let mut editor = EditorTestUtils::create();
|
||||||
@@ -709,7 +743,7 @@ mod test_gradient {
|
|||||||
assert_eq!(initial_gradient.stops.len(), 2, "Expected 2 stops, found {}", initial_gradient.stops.len());
|
assert_eq!(initial_gradient.stops.len(), 2, "Expected 2 stops, found {}", initial_gradient.stops.len());
|
||||||
|
|
||||||
editor.select_tool(ToolType::Gradient).await;
|
editor.select_tool(ToolType::Gradient).await;
|
||||||
editor.double_click(DVec2::new(50., 0.)).await;
|
editor.pointer_up_double_click(DVec2::new(50., 0.)).await;
|
||||||
|
|
||||||
// Check that a new stop has been added
|
// Check that a new stop has been added
|
||||||
let (updated_gradient, _) = get_gradient(&mut editor).await;
|
let (updated_gradient, _) = get_gradient(&mut editor).await;
|
||||||
@@ -803,7 +837,7 @@ mod test_gradient {
|
|||||||
editor.select_tool(ToolType::Gradient).await;
|
editor.select_tool(ToolType::Gradient).await;
|
||||||
|
|
||||||
// Add a middle stop at 50%
|
// Add a middle stop at 50%
|
||||||
editor.double_click(DVec2::new(50., 0.)).await;
|
editor.pointer_up_double_click(DVec2::new(50., 0.)).await;
|
||||||
|
|
||||||
let (initial_gradient, _) = get_gradient(&mut editor).await;
|
let (initial_gradient, _) = get_gradient(&mut editor).await;
|
||||||
assert_eq!(initial_gradient.stops.len(), 3, "Expected 3 stops, found {}", initial_gradient.stops.len());
|
assert_eq!(initial_gradient.stops.len(), 3, "Expected 3 stops, found {}", initial_gradient.stops.len());
|
||||||
@@ -878,8 +912,8 @@ mod test_gradient {
|
|||||||
editor.select_tool(ToolType::Gradient).await;
|
editor.select_tool(ToolType::Gradient).await;
|
||||||
|
|
||||||
// Add two middle stops
|
// Add two middle stops
|
||||||
editor.double_click(DVec2::new(25., 0.)).await;
|
editor.pointer_up_double_click(DVec2::new(25., 0.)).await;
|
||||||
editor.double_click(DVec2::new(75., 0.)).await;
|
editor.pointer_up_double_click(DVec2::new(75., 0.)).await;
|
||||||
|
|
||||||
let (updated_gradient, _) = get_gradient(&mut editor).await;
|
let (updated_gradient, _) = get_gradient(&mut editor).await;
|
||||||
assert_eq!(updated_gradient.stops.len(), 4, "Expected 4 stops, found {}", updated_gradient.stops.len());
|
assert_eq!(updated_gradient.stops.len(), 4, "Expected 4 stops, found {}", updated_gradient.stops.len());
|
||||||
|
|||||||
@@ -83,6 +83,13 @@ impl NodeGraphExecutor {
|
|||||||
};
|
};
|
||||||
(node_runtime, node_executor)
|
(node_runtime, node_executor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// It is useful to get the current execution id for tests to check if any more exeuctions have been queued.
|
||||||
|
#[cfg(test)]
|
||||||
|
pub(crate) fn current_execution_id(&self) -> u64 {
|
||||||
|
self.current_execution_id
|
||||||
|
}
|
||||||
|
|
||||||
/// Execute the network by flattening it and creating a borrow stack.
|
/// Execute the network by flattening it and creating a borrow stack.
|
||||||
fn queue_execution(&mut self, render_config: RenderConfig) -> u64 {
|
fn queue_execution(&mut self, render_config: RenderConfig) -> u64 {
|
||||||
let execution_id = self.current_execution_id;
|
let execution_id = self.current_execution_id;
|
||||||
|
|||||||
+36
-13
@@ -41,7 +41,8 @@ impl EditorTestUtils {
|
|||||||
async fn run<'a>(editor: &'a mut Editor, runtime: &'a mut NodeRuntime) -> Result<Instrumented, String> {
|
async fn run<'a>(editor: &'a mut Editor, runtime: &'a mut NodeRuntime) -> Result<Instrumented, String> {
|
||||||
let portfolio = &mut editor.dispatcher.message_handlers.portfolio_message_handler;
|
let portfolio = &mut editor.dispatcher.message_handlers.portfolio_message_handler;
|
||||||
let exector = &mut portfolio.executor;
|
let exector = &mut portfolio.executor;
|
||||||
let document = portfolio.documents.get_mut(&portfolio.active_document_id.unwrap()).unwrap();
|
let document_id = portfolio.active_document_id.unwrap();
|
||||||
|
let document = portfolio.documents.get_mut(&document_id).unwrap();
|
||||||
|
|
||||||
let instrumented = match exector.update_node_graph_instrumented(document) {
|
let instrumented = match exector.update_node_graph_instrumented(document) {
|
||||||
Ok(instrumented) => instrumented,
|
Ok(instrumented) => instrumented,
|
||||||
@@ -49,19 +50,29 @@ impl EditorTestUtils {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let viewport_resolution = glam::UVec2::ONE;
|
let viewport_resolution = glam::UVec2::ONE;
|
||||||
if let Err(e) = exector.submit_current_node_graph_evaluation(document, DocumentId(0), viewport_resolution, Default::default()) {
|
if let Err(e) = exector.submit_current_node_graph_evaluation(document, document_id, viewport_resolution, Default::default()) {
|
||||||
return Err(format!("submit_current_node_graph_evaluation failed\n\n{e}"));
|
return Err(format!("submit_current_node_graph_evaluation failed\n\n{e}"));
|
||||||
}
|
}
|
||||||
runtime.run().await;
|
|
||||||
|
|
||||||
let mut messages = VecDeque::new();
|
// Run until no more executions are queued.
|
||||||
if let Err(e) = editor.poll_node_graph_evaluation(&mut messages) {
|
loop {
|
||||||
return Err(format!("Graph should render\n\n{e}"));
|
println!("Running graph");
|
||||||
}
|
let execution_id = editor.dispatcher.message_handlers.portfolio_message_handler.executor.current_execution_id();
|
||||||
let frontend_messages = messages.into_iter().flat_map(|message| editor.handle_message(message));
|
runtime.run().await;
|
||||||
|
|
||||||
for message in frontend_messages {
|
let mut messages = VecDeque::new();
|
||||||
message.check_node_graph_error();
|
if let Err(e) = editor.poll_node_graph_evaluation(&mut messages) {
|
||||||
|
return Err(format!("Graph should render\n\n{e}"));
|
||||||
|
}
|
||||||
|
let frontend_messages = messages.into_iter().flat_map(|message| editor.handle_message(message));
|
||||||
|
|
||||||
|
for message in frontend_messages {
|
||||||
|
message.check_node_graph_error();
|
||||||
|
}
|
||||||
|
let next_execution_id = editor.dispatcher.message_handlers.portfolio_message_handler.executor.current_execution_id();
|
||||||
|
if next_execution_id == execution_id {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(instrumented)
|
Ok(instrumented)
|
||||||
@@ -258,12 +269,24 @@ impl EditorTestUtils {
|
|||||||
self.active_document().network_interface.selected_nodes().selected_layers(self.active_document().metadata()).next()
|
self.active_document().network_interface.selected_nodes().selected_layers(self.active_document().metadata()).next()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn double_click(&mut self, position: DVec2) {
|
/// Simulate a pointer up then a double click without seperation of a graph render.
|
||||||
|
///
|
||||||
|
/// This seems to be what WASM does to the test.
|
||||||
|
pub async fn pointer_up_double_click(&mut self, editor_position: DVec2) {
|
||||||
|
self.left_mousedown(editor_position.x, editor_position.y, ModifierKeys::empty()).await;
|
||||||
|
// Simulate a mouse up then double click event without a rerender then double click
|
||||||
|
self.editor.handle_message(InputPreprocessorMessage::PointerUp {
|
||||||
|
editor_mouse_state: EditorMouseState {
|
||||||
|
editor_position,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
modifier_keys: ModifierKeys::empty(),
|
||||||
|
});
|
||||||
self.handle_message(InputPreprocessorMessage::DoubleClick {
|
self.handle_message(InputPreprocessorMessage::DoubleClick {
|
||||||
editor_mouse_state: EditorMouseState {
|
editor_mouse_state: EditorMouseState {
|
||||||
editor_position: position,
|
editor_position,
|
||||||
mouse_keys: MouseKeys::LEFT,
|
mouse_keys: MouseKeys::LEFT,
|
||||||
scroll_delta: ScrollDelta::default(),
|
..Default::default()
|
||||||
},
|
},
|
||||||
modifier_keys: ModifierKeys::empty(),
|
modifier_keys: ModifierKeys::empty(),
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user