mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-23 21:18:12 +08:00
Split out viewport handling into its own message handler (#3331)
* extract viewport handeling * fix web overlays * some cleanup * remove some physical conversions * fix resize snapping * fixup * apply some review feedback * make viewport api more ergonomic * fix * fix web overlay canvas clear size * clear workaround for canvas * rename trigger message --------- Co-authored-by: Dennis Kobert <dennis@kobert.dev>
This commit is contained in:
@@ -34,9 +34,9 @@ impl AutoPanning {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setup_by_mouse_position(&mut self, input: &InputPreprocessorMessageHandler, messages: &[Message], responses: &mut VecDeque<Message>) {
|
||||
pub fn setup_by_mouse_position(&mut self, input: &InputPreprocessorMessageHandler, viewport: &ViewportMessageHandler, messages: &[Message], responses: &mut VecDeque<Message>) {
|
||||
let mouse_position = input.mouse.position;
|
||||
let viewport_size = input.viewport_bounds.size();
|
||||
let viewport_size = viewport.size().into_dvec2();
|
||||
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 {
|
||||
@@ -50,12 +50,12 @@ impl AutoPanning {
|
||||
/// 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, and to the duration of the frame.
|
||||
/// It is also guaranteed to be integral.
|
||||
pub fn shift_viewport(&self, input: &InputPreprocessorMessageHandler, responses: &mut VecDeque<Message>) -> Option<DVec2> {
|
||||
pub fn shift_viewport(&self, input: &InputPreprocessorMessageHandler, viewport: &ViewportMessageHandler, responses: &mut VecDeque<Message>) -> Option<DVec2> {
|
||||
if !self.subscribed_to_animation_frame {
|
||||
return None;
|
||||
}
|
||||
|
||||
let viewport_size = input.viewport_bounds.size();
|
||||
let viewport_size = viewport.size().into_dvec2();
|
||||
let mouse_position = input.mouse.position.clamp(
|
||||
DVec2::ZERO - DVec2::splat(DRAG_BEYOND_VIEWPORT_MAX_OVEREXTENSION_PIXELS),
|
||||
viewport_size + DVec2::splat(DRAG_BEYOND_VIEWPORT_MAX_OVEREXTENSION_PIXELS),
|
||||
|
||||
+2
-2
@@ -142,7 +142,7 @@ impl PointRadiusHandle {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn overlays(&self, selected_star_layer: Option<LayerNodeIdentifier>, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, overlay_context: &mut OverlayContext) {
|
||||
pub fn overlays(&self, selected_star_layer: Option<LayerNodeIdentifier>, document: &DocumentMessageHandler, overlay_context: &mut OverlayContext) {
|
||||
match &self.handle_state {
|
||||
PointRadiusHandleState::Inactive => {
|
||||
let Some(layer) = selected_star_layer else { return };
|
||||
@@ -187,7 +187,7 @@ impl PointRadiusHandle {
|
||||
|
||||
let viewport = document.metadata().transform_to_viewport(layer);
|
||||
let center = viewport.transform_point2(DVec2::ZERO);
|
||||
let viewport_diagonal = input.viewport_bounds.size().length();
|
||||
let viewport_diagonal = overlay_context.viewport.size().into_dvec2().length();
|
||||
|
||||
// Star
|
||||
if let Some((sides, radius1, radius2)) = extract_star_parameters(Some(layer), document) {
|
||||
|
||||
@@ -15,10 +15,10 @@ pub struct Resize {
|
||||
|
||||
impl Resize {
|
||||
/// Starts a resize, assigning the snap targets and snapping the starting position.
|
||||
pub fn start(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler) {
|
||||
pub fn start(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, viewport: &ViewportMessageHandler) {
|
||||
let root_transform = document.metadata().document_to_viewport;
|
||||
let point = SnapCandidatePoint::handle(root_transform.inverse().transform_point2(input.mouse.position));
|
||||
let snapped = self.snap_manager.free_snap(&SnapData::new(document, input), &point, SnapTypeConfiguration::default());
|
||||
let snapped = self.snap_manager.free_snap(&SnapData::new(document, input, viewport), &point, SnapTypeConfiguration::default());
|
||||
self.drag_start = snapped.snapped_point_document;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,14 @@ impl Resize {
|
||||
|
||||
/// Compute the drag start and end based on the current mouse position. If the layer doesn't exist, returns [`None`].
|
||||
/// If you want to draw even without a layer, use [`Resize::calculate_points_ignore_layer`].
|
||||
pub fn calculate_points(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, center: Key, lock_ratio: Key) -> Option<[DVec2; 2]> {
|
||||
pub fn calculate_points(
|
||||
&mut self,
|
||||
document: &DocumentMessageHandler,
|
||||
input: &InputPreprocessorMessageHandler,
|
||||
viewport: &ViewportMessageHandler,
|
||||
center: Key,
|
||||
lock_ratio: Key,
|
||||
) -> Option<[DVec2; 2]> {
|
||||
let layer = self.layer?;
|
||||
|
||||
if layer == LayerNodeIdentifier::ROOT_PARENT {
|
||||
@@ -42,21 +49,37 @@ impl Resize {
|
||||
self.layer.take();
|
||||
return None;
|
||||
}
|
||||
Some(self.calculate_points_ignore_layer(document, input, center, lock_ratio, false))
|
||||
Some(self.calculate_points_ignore_layer(document, input, viewport, center, lock_ratio, false))
|
||||
}
|
||||
|
||||
/// Compute the drag start and end based on the current mouse position. Ignores the state of the layer.
|
||||
/// If you want to only draw whilst a layer exists, use [`Resize::calculate_points`].
|
||||
pub fn calculate_points_ignore_layer(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, center: Key, lock_ratio: Key, in_document: bool) -> [DVec2; 2] {
|
||||
pub fn calculate_points_ignore_layer(
|
||||
&mut self,
|
||||
document: &DocumentMessageHandler,
|
||||
input: &InputPreprocessorMessageHandler,
|
||||
viewport: &ViewportMessageHandler,
|
||||
center: Key,
|
||||
lock_ratio: Key,
|
||||
in_document: bool,
|
||||
) -> [DVec2; 2] {
|
||||
let ratio = input.keyboard.get(lock_ratio as usize);
|
||||
let center = input.keyboard.get(center as usize);
|
||||
|
||||
// Use shared snapping logic with optional center and ratio constraints, considering if coordinates are in document space.
|
||||
self.compute_snapped_resize_points(document, input, center, ratio, in_document)
|
||||
self.compute_snapped_resize_points(document, input, viewport, center, ratio, in_document)
|
||||
}
|
||||
|
||||
pub fn calculate_transform(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, center: Key, lock_ratio: Key, skip_rerender: bool) -> Option<Message> {
|
||||
let points_viewport = self.calculate_points(document, input, center, lock_ratio)?;
|
||||
pub fn calculate_transform(
|
||||
&mut self,
|
||||
document: &DocumentMessageHandler,
|
||||
input: &InputPreprocessorMessageHandler,
|
||||
viewport: &ViewportMessageHandler,
|
||||
center: Key,
|
||||
lock_ratio: Key,
|
||||
skip_rerender: bool,
|
||||
) -> Option<Message> {
|
||||
let points_viewport = self.calculate_points(document, input, viewport, center, lock_ratio)?;
|
||||
Some(
|
||||
GraphOperationMessage::TransformSet {
|
||||
layer: self.layer?,
|
||||
@@ -68,23 +91,33 @@ impl Resize {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn calculate_circle_points(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, center: Key) -> [DVec2; 2] {
|
||||
pub fn calculate_circle_points(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, viewport: &ViewportMessageHandler, center: Key) -> [DVec2; 2] {
|
||||
let center = input.keyboard.get(center as usize);
|
||||
|
||||
// Use shared snapping logic with enforced aspect ratio and optional center snapping.
|
||||
self.compute_snapped_resize_points(document, input, center, true, false)
|
||||
self.compute_snapped_resize_points(document, input, viewport, center, true, false)
|
||||
}
|
||||
|
||||
/// Calculates two points in viewport space from a drag, applying snapping, optional center mode, and aspect ratio locking.
|
||||
fn compute_snapped_resize_points(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, center: bool, lock_ratio: bool, in_document: bool) -> [DVec2; 2] {
|
||||
fn compute_snapped_resize_points(
|
||||
&mut self,
|
||||
document: &DocumentMessageHandler,
|
||||
input: &InputPreprocessorMessageHandler,
|
||||
viewport: &ViewportMessageHandler,
|
||||
center: bool,
|
||||
lock_ratio: bool,
|
||||
in_document: bool,
|
||||
) -> [DVec2; 2] {
|
||||
let start = self.viewport_drag_start(document);
|
||||
let mouse = input.mouse.position;
|
||||
let document_to_viewport = document.navigation_handler.calculate_offset_transform(input.viewport_bounds.center(), &document.document_ptz);
|
||||
let document_to_viewport = document
|
||||
.navigation_handler
|
||||
.calculate_offset_transform(viewport.center_in_viewport_space().into(), &document.document_ptz);
|
||||
let drag_start = self.drag_start;
|
||||
let mut points_viewport = [start, mouse];
|
||||
|
||||
let ignore = if let Some(layer) = self.layer { vec![layer] } else { vec![] };
|
||||
let snap_data = &SnapData::ignore(document, input, &ignore);
|
||||
let snap_data = &SnapData::ignore(document, input, viewport, &ignore);
|
||||
|
||||
if lock_ratio {
|
||||
let viewport_size = points_viewport[1] - points_viewport[0];
|
||||
|
||||
@@ -503,8 +503,16 @@ impl ShapeState {
|
||||
}
|
||||
|
||||
// Snap, returning a viewport delta
|
||||
pub fn snap(&self, snap_manager: &mut SnapManager, snap_cache: &SnapCache, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, previous_mouse: DVec2) -> DVec2 {
|
||||
let snap_data = SnapData::new_snap_cache(document, input, snap_cache);
|
||||
pub fn snap(
|
||||
&self,
|
||||
snap_manager: &mut SnapManager,
|
||||
snap_cache: &SnapCache,
|
||||
document: &DocumentMessageHandler,
|
||||
input: &InputPreprocessorMessageHandler,
|
||||
viewport: &ViewportMessageHandler,
|
||||
previous_mouse: DVec2,
|
||||
) -> DVec2 {
|
||||
let snap_data = SnapData::new_snap_cache(document, input, viewport, snap_cache);
|
||||
|
||||
let mouse_delta = document
|
||||
.network_interface
|
||||
|
||||
@@ -146,13 +146,14 @@ impl Arc {
|
||||
pub fn update_shape(
|
||||
document: &DocumentMessageHandler,
|
||||
ipp: &InputPreprocessorMessageHandler,
|
||||
viewport: &ViewportMessageHandler,
|
||||
layer: LayerNodeIdentifier,
|
||||
shape_tool_data: &mut ShapeToolData,
|
||||
modifier: ShapeToolModifierKey,
|
||||
responses: &mut VecDeque<Message>,
|
||||
) {
|
||||
let (center, lock_ratio) = (modifier[0], modifier[1]);
|
||||
if let Some([start, end]) = shape_tool_data.data.calculate_points(document, ipp, center, lock_ratio) {
|
||||
if let Some([start, end]) = shape_tool_data.data.calculate_points(document, ipp, viewport, center, lock_ratio) {
|
||||
let Some(node_id) = graph_modification_utils::get_arc_id(layer, &document.network_interface) else {
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -89,13 +89,14 @@ impl Circle {
|
||||
pub fn update_shape(
|
||||
document: &DocumentMessageHandler,
|
||||
ipp: &InputPreprocessorMessageHandler,
|
||||
viewport: &ViewportMessageHandler,
|
||||
layer: LayerNodeIdentifier,
|
||||
shape_tool_data: &mut ShapeToolData,
|
||||
modifier: ShapeToolModifierKey,
|
||||
responses: &mut VecDeque<Message>,
|
||||
) {
|
||||
let center = modifier[0];
|
||||
let [start, end] = shape_tool_data.data.calculate_circle_points(document, ipp, center);
|
||||
let [start, end] = shape_tool_data.data.calculate_circle_points(document, ipp, viewport, center);
|
||||
let Some(node_id) = graph_modification_utils::get_circle_id(layer, &document.network_interface) else {
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -23,6 +23,7 @@ impl Ellipse {
|
||||
pub fn update_shape(
|
||||
document: &DocumentMessageHandler,
|
||||
ipp: &InputPreprocessorMessageHandler,
|
||||
viewport: &ViewportMessageHandler,
|
||||
layer: LayerNodeIdentifier,
|
||||
shape_tool_data: &mut ShapeToolData,
|
||||
modifier: ShapeToolModifierKey,
|
||||
@@ -30,7 +31,7 @@ impl Ellipse {
|
||||
) {
|
||||
let [center, lock_ratio, _] = modifier;
|
||||
|
||||
if let Some([start, end]) = shape_tool_data.data.calculate_points(document, ipp, center, lock_ratio) {
|
||||
if let Some([start, end]) = shape_tool_data.data.calculate_points(document, ipp, viewport, center, lock_ratio) {
|
||||
let Some(node_id) = graph_modification_utils::get_ellipse_id(layer, &document.network_interface) else {
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -48,6 +48,7 @@ impl Line {
|
||||
pub fn update_shape(
|
||||
document: &DocumentMessageHandler,
|
||||
ipp: &InputPreprocessorMessageHandler,
|
||||
viewport: &ViewportMessageHandler,
|
||||
layer: LayerNodeIdentifier,
|
||||
shape_tool_data: &mut ShapeToolData,
|
||||
modifier: ShapeToolModifierKey,
|
||||
@@ -59,7 +60,7 @@ impl Line {
|
||||
|
||||
let keyboard = &ipp.keyboard;
|
||||
let ignore = [layer];
|
||||
let snap_data = SnapData::ignore(document, ipp, &ignore);
|
||||
let snap_data = SnapData::ignore(document, ipp, viewport, &ignore);
|
||||
let mut document_points = generate_line(shape_tool_data, snap_data, keyboard.key(lock_angle), keyboard.key(snap_angle), keyboard.key(center));
|
||||
|
||||
if shape_tool_data.line_data.dragging_endpoint == Some(LineEnd::Start) {
|
||||
|
||||
@@ -58,13 +58,13 @@ impl ShapeGizmoHandler for PolygonGizmoHandler {
|
||||
&self,
|
||||
document: &DocumentMessageHandler,
|
||||
selected_polygon_layer: Option<LayerNodeIdentifier>,
|
||||
input: &InputPreprocessorMessageHandler,
|
||||
_input: &InputPreprocessorMessageHandler,
|
||||
shape_editor: &mut &mut ShapeState,
|
||||
mouse_position: DVec2,
|
||||
overlay_context: &mut OverlayContext,
|
||||
) {
|
||||
self.number_of_points_dial.overlays(document, selected_polygon_layer, shape_editor, mouse_position, overlay_context);
|
||||
self.point_radius_handle.overlays(selected_polygon_layer, document, input, overlay_context);
|
||||
self.point_radius_handle.overlays(selected_polygon_layer, document, overlay_context);
|
||||
|
||||
polygon_outline(selected_polygon_layer, document, overlay_context);
|
||||
}
|
||||
@@ -72,7 +72,7 @@ impl ShapeGizmoHandler for PolygonGizmoHandler {
|
||||
fn dragging_overlays(
|
||||
&self,
|
||||
document: &DocumentMessageHandler,
|
||||
input: &InputPreprocessorMessageHandler,
|
||||
_input: &InputPreprocessorMessageHandler,
|
||||
shape_editor: &mut &mut ShapeState,
|
||||
mouse_position: DVec2,
|
||||
overlay_context: &mut OverlayContext,
|
||||
@@ -82,7 +82,7 @@ impl ShapeGizmoHandler for PolygonGizmoHandler {
|
||||
}
|
||||
|
||||
if self.point_radius_handle.is_dragging_or_snapped() {
|
||||
self.point_radius_handle.overlays(None, document, input, overlay_context);
|
||||
self.point_radius_handle.overlays(None, document, overlay_context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,6 +116,7 @@ impl Polygon {
|
||||
pub fn update_shape(
|
||||
document: &DocumentMessageHandler,
|
||||
ipp: &InputPreprocessorMessageHandler,
|
||||
viewport: &ViewportMessageHandler,
|
||||
layer: LayerNodeIdentifier,
|
||||
shape_tool_data: &mut ShapeToolData,
|
||||
modifier: ShapeToolModifierKey,
|
||||
@@ -123,7 +124,7 @@ impl Polygon {
|
||||
) {
|
||||
let [center, lock_ratio, _] = modifier;
|
||||
|
||||
if let Some([start, end]) = shape_tool_data.data.calculate_points(document, ipp, center, lock_ratio) {
|
||||
if let Some([start, end]) = shape_tool_data.data.calculate_points(document, ipp, viewport, center, lock_ratio) {
|
||||
// TODO: We need to determine how to allow the polygon node to make irregular shapes
|
||||
update_radius_sign(end, start, layer, document, responses);
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ impl Rectangle {
|
||||
pub fn update_shape(
|
||||
document: &DocumentMessageHandler,
|
||||
ipp: &InputPreprocessorMessageHandler,
|
||||
viewport: &ViewportMessageHandler,
|
||||
layer: LayerNodeIdentifier,
|
||||
shape_tool_data: &mut ShapeToolData,
|
||||
modifier: ShapeToolModifierKey,
|
||||
@@ -30,7 +31,7 @@ impl Rectangle {
|
||||
) {
|
||||
let [center, lock_ratio, _] = modifier;
|
||||
|
||||
if let Some([start, end]) = shape_tool_data.data.calculate_points(document, ipp, center, lock_ratio) {
|
||||
if let Some([start, end]) = shape_tool_data.data.calculate_points(document, ipp, viewport, center, lock_ratio) {
|
||||
let Some(node_id) = graph_modification_utils::get_rectangle_id(layer, &document.network_interface) else {
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -36,13 +36,20 @@ impl Spiral {
|
||||
])
|
||||
}
|
||||
|
||||
pub fn update_shape(document: &DocumentMessageHandler, ipp: &InputPreprocessorMessageHandler, layer: LayerNodeIdentifier, shape_tool_data: &mut ShapeToolData, responses: &mut VecDeque<Message>) {
|
||||
pub fn update_shape(
|
||||
document: &DocumentMessageHandler,
|
||||
ipp: &InputPreprocessorMessageHandler,
|
||||
viewport: &ViewportMessageHandler,
|
||||
layer: LayerNodeIdentifier,
|
||||
shape_tool_data: &mut ShapeToolData,
|
||||
responses: &mut VecDeque<Message>,
|
||||
) {
|
||||
use graphene_std::vector::generator_nodes::spiral::*;
|
||||
|
||||
let viewport_drag_start = shape_tool_data.data.viewport_drag_start(document);
|
||||
|
||||
let ignore = vec![layer];
|
||||
let snap_data = SnapData::ignore(document, ipp, &ignore);
|
||||
let snap_data = SnapData::ignore(document, ipp, viewport, &ignore);
|
||||
let config = SnapTypeConfiguration::default();
|
||||
let document_mouse = document.metadata().document_to_viewport.inverse().transform_point2(ipp.mouse.position);
|
||||
let snapped = shape_tool_data.data.snap_manager.free_snap(&snap_data, &SnapCandidatePoint::handle(document_mouse), config);
|
||||
|
||||
@@ -58,13 +58,13 @@ impl ShapeGizmoHandler for StarGizmoHandler {
|
||||
&self,
|
||||
document: &DocumentMessageHandler,
|
||||
selected_star_layer: Option<LayerNodeIdentifier>,
|
||||
input: &InputPreprocessorMessageHandler,
|
||||
_input: &InputPreprocessorMessageHandler,
|
||||
shape_editor: &mut &mut ShapeState,
|
||||
mouse_position: DVec2,
|
||||
overlay_context: &mut OverlayContext,
|
||||
) {
|
||||
self.number_of_points_dial.overlays(document, selected_star_layer, shape_editor, mouse_position, overlay_context);
|
||||
self.point_radius_handle.overlays(selected_star_layer, document, input, overlay_context);
|
||||
self.point_radius_handle.overlays(selected_star_layer, document, overlay_context);
|
||||
|
||||
star_outline(selected_star_layer, document, overlay_context);
|
||||
}
|
||||
@@ -72,7 +72,7 @@ impl ShapeGizmoHandler for StarGizmoHandler {
|
||||
fn dragging_overlays(
|
||||
&self,
|
||||
document: &DocumentMessageHandler,
|
||||
input: &InputPreprocessorMessageHandler,
|
||||
_input: &InputPreprocessorMessageHandler,
|
||||
shape_editor: &mut &mut ShapeState,
|
||||
mouse_position: DVec2,
|
||||
overlay_context: &mut OverlayContext,
|
||||
@@ -82,7 +82,7 @@ impl ShapeGizmoHandler for StarGizmoHandler {
|
||||
}
|
||||
|
||||
if self.point_radius_handle.is_dragging_or_snapped() {
|
||||
self.point_radius_handle.overlays(None, document, input, overlay_context);
|
||||
self.point_radius_handle.overlays(None, document, overlay_context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,6 +121,7 @@ impl Star {
|
||||
pub fn update_shape(
|
||||
document: &DocumentMessageHandler,
|
||||
ipp: &InputPreprocessorMessageHandler,
|
||||
viewport: &ViewportMessageHandler,
|
||||
layer: LayerNodeIdentifier,
|
||||
shape_tool_data: &mut ShapeToolData,
|
||||
modifier: ShapeToolModifierKey,
|
||||
@@ -128,7 +129,7 @@ impl Star {
|
||||
) {
|
||||
let [center, lock_ratio, _] = modifier;
|
||||
|
||||
if let Some([start, end]) = shape_tool_data.data.calculate_points(document, ipp, center, lock_ratio) {
|
||||
if let Some([start, end]) = shape_tool_data.data.calculate_points(document, ipp, viewport, center, lock_ratio) {
|
||||
// TODO: We need to determine how to allow the polygon node to make irregular shapes
|
||||
update_radius_sign(end, start, layer, document, responses);
|
||||
|
||||
|
||||
@@ -206,29 +206,31 @@ pub struct SnapCache {
|
||||
pub struct SnapData<'a> {
|
||||
pub document: &'a DocumentMessageHandler,
|
||||
pub input: &'a InputPreprocessorMessageHandler,
|
||||
pub viewport: &'a ViewportMessageHandler,
|
||||
pub ignore: &'a [LayerNodeIdentifier],
|
||||
pub node_snap_cache: Option<&'a SnapCache>,
|
||||
pub candidates: Option<&'a Vec<LayerNodeIdentifier>>,
|
||||
pub alignment_candidates: Option<&'a Vec<LayerNodeIdentifier>>,
|
||||
}
|
||||
impl<'a> SnapData<'a> {
|
||||
pub fn new(document: &'a DocumentMessageHandler, input: &'a InputPreprocessorMessageHandler) -> Self {
|
||||
Self::ignore(document, input, &[])
|
||||
pub fn new(document: &'a DocumentMessageHandler, input: &'a InputPreprocessorMessageHandler, viewport: &'a ViewportMessageHandler) -> Self {
|
||||
Self::ignore(document, input, viewport, &[])
|
||||
}
|
||||
pub fn ignore(document: &'a DocumentMessageHandler, input: &'a InputPreprocessorMessageHandler, ignore: &'a [LayerNodeIdentifier]) -> Self {
|
||||
pub fn ignore(document: &'a DocumentMessageHandler, input: &'a InputPreprocessorMessageHandler, viewport: &'a ViewportMessageHandler, ignore: &'a [LayerNodeIdentifier]) -> Self {
|
||||
Self {
|
||||
document,
|
||||
input,
|
||||
viewport,
|
||||
ignore,
|
||||
candidates: None,
|
||||
alignment_candidates: None,
|
||||
node_snap_cache: None,
|
||||
}
|
||||
}
|
||||
pub fn new_snap_cache(document: &'a DocumentMessageHandler, input: &'a InputPreprocessorMessageHandler, snap_cache: &'a SnapCache) -> Self {
|
||||
pub fn new_snap_cache(document: &'a DocumentMessageHandler, input: &'a InputPreprocessorMessageHandler, viewport: &'a ViewportMessageHandler, snap_cache: &'a SnapCache) -> Self {
|
||||
Self {
|
||||
node_snap_cache: Some(snap_cache),
|
||||
..Self::new(document, input)
|
||||
..Self::new(document, input, viewport)
|
||||
}
|
||||
}
|
||||
fn get_candidates(&self) -> &[LayerNodeIdentifier] {
|
||||
@@ -301,7 +303,7 @@ impl SnapManager {
|
||||
|
||||
for point in snapped_points {
|
||||
let viewport_point = document.metadata().document_to_viewport.transform_point2(point.snapped_point_document);
|
||||
let on_screen = viewport_point.cmpgt(DVec2::ZERO).all() && viewport_point.cmplt(snap_data.input.viewport_bounds.size()).all();
|
||||
let on_screen = viewport_point.cmpgt(DVec2::ZERO).all() && viewport_point.cmplt(snap_data.viewport.size().into()).all();
|
||||
if !on_screen && !off_screen {
|
||||
continue;
|
||||
}
|
||||
@@ -337,7 +339,7 @@ impl SnapManager {
|
||||
return;
|
||||
};
|
||||
let layer_bounds = document.metadata().transform_to_document(layer) * Quad::from_box(bounds);
|
||||
let screen_bounds = document.metadata().document_to_viewport.inverse() * Quad::from_box([DVec2::ZERO, snap_data.input.viewport_bounds.size()]);
|
||||
let screen_bounds = document.metadata().document_to_viewport.inverse() * Quad::from_box([DVec2::ZERO, snap_data.viewport.size().into()]);
|
||||
if screen_bounds.intersects(layer_bounds) {
|
||||
if self.alignment_candidates.as_ref().is_none_or(|candidates| candidates.len() <= 100) {
|
||||
self.alignment_candidates.get_or_insert_with(Vec::new).push(layer);
|
||||
|
||||
@@ -76,7 +76,7 @@ impl DistributionSnapper {
|
||||
self.down.clear();
|
||||
self.up.clear();
|
||||
|
||||
let screen_bounds = (document.metadata().document_to_viewport.inverse() * Quad::from_box([DVec2::ZERO, snap_data.input.viewport_bounds.size()])).bounding_box();
|
||||
let screen_bounds = (document.metadata().document_to_viewport.inverse() * Quad::from_box([DVec2::ZERO, snap_data.viewport.size().into()])).bounding_box();
|
||||
let max_extent = (screen_bounds[1] - screen_bounds[0]).abs().max_element();
|
||||
|
||||
// Collect artboard bounds
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use super::snapping::{self, SnapCandidatePoint, SnapConstraint, SnapData, SnapManager, SnappedPoint};
|
||||
use crate::consts::{
|
||||
BOUNDS_ROTATE_THRESHOLD, BOUNDS_SELECT_THRESHOLD, COLOR_OVERLAY_WHITE, MAX_LENGTH_FOR_NO_WIDTH_OR_HEIGHT, MAXIMUM_ALT_SCALE_FACTOR, MIN_LENGTH_FOR_CORNERS_VISIBILITY,
|
||||
MIN_LENGTH_FOR_EDGE_RESIZE_PRIORITY_OVER_CORNERS, MIN_LENGTH_FOR_MIDPOINT_VISIBILITY, MIN_LENGTH_FOR_RESIZE_TO_INCLUDE_INTERIOR, MIN_LENGTH_FOR_SKEW_TRIANGLE_VISIBILITY, RESIZE_HANDLE_SIZE,
|
||||
SELECTION_DRAG_ANGLE, SKEW_TRIANGLE_OFFSET, SKEW_TRIANGLE_SIZE,
|
||||
BOUNDS_ROTATE_THRESHOLD, BOUNDS_SELECT_THRESHOLD, MAX_LENGTH_FOR_NO_WIDTH_OR_HEIGHT, MAXIMUM_ALT_SCALE_FACTOR, MIN_LENGTH_FOR_CORNERS_VISIBILITY, MIN_LENGTH_FOR_EDGE_RESIZE_PRIORITY_OVER_CORNERS,
|
||||
MIN_LENGTH_FOR_MIDPOINT_VISIBILITY, MIN_LENGTH_FOR_RESIZE_TO_INCLUDE_INTERIOR, MIN_LENGTH_FOR_SKEW_TRIANGLE_VISIBILITY, RESIZE_HANDLE_SIZE, SELECTION_DRAG_ANGLE, SKEW_TRIANGLE_OFFSET,
|
||||
SKEW_TRIANGLE_SIZE,
|
||||
};
|
||||
use crate::messages::frontend::utility_types::MouseCursorIcon;
|
||||
use crate::messages::portfolio::document::overlays::utility_types::OverlayContext;
|
||||
@@ -489,13 +489,7 @@ impl BoundingBoxManager {
|
||||
if (end - start).length() < MIN_LENGTH_FOR_SKEW_TRIANGLE_VISIBILITY {
|
||||
return;
|
||||
}
|
||||
|
||||
let edge_dir = (end - start).normalize();
|
||||
let mid = end.midpoint(start);
|
||||
|
||||
for edge in [edge_dir, -edge_dir] {
|
||||
overlay_context.draw_triangle(mid + edge * (3. + SKEW_TRIANGLE_OFFSET), edge, SKEW_TRIANGLE_SIZE, None, None);
|
||||
}
|
||||
overlay_context.skew_handles(start, end);
|
||||
};
|
||||
|
||||
if let Some([start, end]) = self.edge_endpoints_vector_from_edge_bool(hover_edge) {
|
||||
@@ -565,11 +559,6 @@ impl BoundingBoxManager {
|
||||
self.render_quad(overlay_context);
|
||||
}
|
||||
|
||||
let mut draw_handle = |point: DVec2, angle: f64| {
|
||||
let quad = DAffine2::from_angle_translation(angle, point) * Quad::from_box([DVec2::splat(-RESIZE_HANDLE_SIZE / 2.), DVec2::splat(RESIZE_HANDLE_SIZE / 2.)]);
|
||||
overlay_context.quad(quad, None, Some(COLOR_OVERLAY_WHITE));
|
||||
};
|
||||
|
||||
let horizontal_angle = (quad.top_left() - quad.bottom_left()).to_angle();
|
||||
let vertical_angle = (quad.top_left() - quad.top_right()).to_angle();
|
||||
|
||||
@@ -579,7 +568,7 @@ impl BoundingBoxManager {
|
||||
TransformCageSizeCategory::Full | TransformCageSizeCategory::Narrow | TransformCageSizeCategory::ReducedLandscape
|
||||
) {
|
||||
for point in horizontal_edges {
|
||||
draw_handle(point, horizontal_angle);
|
||||
overlay_context.resize_handle(point, horizontal_angle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -589,7 +578,7 @@ impl BoundingBoxManager {
|
||||
TransformCageSizeCategory::Full | TransformCageSizeCategory::Narrow | TransformCageSizeCategory::ReducedPortrait
|
||||
) {
|
||||
for point in vertical_edges {
|
||||
draw_handle(point, vertical_angle);
|
||||
overlay_context.resize_handle(point, vertical_angle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -606,14 +595,14 @@ impl BoundingBoxManager {
|
||||
TransformCageSizeCategory::Full | TransformCageSizeCategory::ReducedBoth | TransformCageSizeCategory::ReducedLandscape | TransformCageSizeCategory::ReducedPortrait
|
||||
) {
|
||||
for point in quad.0 {
|
||||
draw_handle(point, angle);
|
||||
overlay_context.resize_handle(point, angle);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the flat line endpoint drag handles
|
||||
if category == TransformCageSizeCategory::Flat {
|
||||
draw_handle(self.transform.transform_point2(self.bounds[0]), angle);
|
||||
draw_handle(self.transform.transform_point2(self.bounds[1]), angle);
|
||||
overlay_context.resize_handle(self.transform.transform_point2(self.bounds[0]), angle);
|
||||
overlay_context.resize_handle(self.transform.transform_point2(self.bounds[1]), angle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -262,6 +262,7 @@ pub fn resize_bounds(
|
||||
snap_manager: &mut SnapManager,
|
||||
snap_candidates: &mut Vec<SnapCandidatePoint>,
|
||||
input: &InputPreprocessorMessageHandler,
|
||||
viewport: &ViewportMessageHandler,
|
||||
center: bool,
|
||||
constrain: bool,
|
||||
tool: ToolType,
|
||||
@@ -271,7 +272,7 @@ pub fn resize_bounds(
|
||||
let snap = Some(SizeSnapData {
|
||||
manager: snap_manager,
|
||||
points: snap_candidates,
|
||||
snap_data: SnapData::ignore(document, input, dragging_layers),
|
||||
snap_data: SnapData::ignore(document, input, viewport, dragging_layers),
|
||||
});
|
||||
let (position, size) = movement.new_size(input.mouse.position, bounds.original_bound_transform, center, constrain, snap);
|
||||
let (delta, mut pivot) = movement.bounds_to_scale_transform(position, size);
|
||||
|
||||
Reference in New Issue
Block a user