Add draggable skew triangles to the transform cage (#2300)

* Add triangle handles to transform cage for skew transform

Fixes #2299

* Add skew triangles

* Fix conflicts which github didn't show

* cargo fmt

* Fix needed

* remove unreachable

* use the trap and rect logic

* fix quad checks

* cursor fix; no triangles if already dragging and not skewing

* cargo fmt

* Resolve Clippy lints

* Add min length for triangle visibility

* Code review

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
mTvare
2025-03-01 10:24:56 +00:00
committed by GitHub
co-authored by Keavon Chambers
parent bc6e76208d
commit 1510ad820c
10 changed files with 304 additions and 51 deletions
@@ -42,6 +42,30 @@ impl OverlayContext {
self.dashed_polygon(&quad.0, color_fill, None, None, None);
}
pub fn draw_triangle(&mut self, base: DVec2, direction: DVec2, size: f64, color_fill: Option<&str>, color_stroke: Option<&str>) {
let color_fill = color_fill.unwrap_or(COLOR_OVERLAY_WHITE);
let color_stroke = color_stroke.unwrap_or(COLOR_OVERLAY_BLUE);
let normal = direction.perp();
let top = base + direction * size;
let edge1 = base + normal * size / 2.;
let edge2 = base - normal * size / 2.;
self.start_dpi_aware_transform();
self.render_context.begin_path();
self.render_context.move_to(top.x, top.y);
self.render_context.line_to(edge1.x, edge1.y);
self.render_context.line_to(edge2.x, edge2.y);
self.render_context.close_path();
self.render_context.set_fill_style_str(color_fill);
self.render_context.set_stroke_style_str(color_stroke);
self.render_context.fill();
self.render_context.stroke();
self.end_dpi_aware_transform();
}
pub fn dashed_quad(&mut self, quad: Quad, color_fill: Option<&str>, dash_width: Option<f64>, dash_gap_width: Option<f64>, dash_offset: Option<f64>) {
self.dashed_polygon(&quad.0, color_fill, dash_width, dash_gap_width, dash_offset);
}
@@ -5334,7 +5334,7 @@ impl NodeNetworkInterface {
// If a non artboard layer is attempted to be connected to the exports, and there is already an artboard connected, then connect the layer to the artboard.
if let Some(first_layer) = LayerNodeIdentifier::ROOT_PARENT.children(&self.document_metadata).next() {
if parent == LayerNodeIdentifier::ROOT_PARENT
&& !self.reference(&layer.to_node(), network_path).is_some_and(|reference| *reference == Some("Artboard".to_string()))
&& self.reference(&layer.to_node(), network_path).is_none_or(|reference| *reference != Some("Artboard".to_string()))
&& self.is_artboard(&first_layer.to_node(), network_path)
{
parent = first_layer;
@@ -306,6 +306,7 @@ pub enum TransformOperation {
}
impl TransformOperation {
#[allow(clippy::too_many_arguments)]
pub fn apply_transform_operation(&self, selected: &mut Selected, increment_mode: bool, local: bool, quad: Quad, transform: DAffine2, pivot: DVec2, local_transform: DAffine2) {
let local_axis_transform_angle = (quad.top_left() - quad.top_right()).to_angle();
if self != &TransformOperation::None {
@@ -351,6 +352,7 @@ impl TransformOperation {
self.is_constraint_to_axis() || !matches!(self, TransformOperation::Grabbing(_))
}
#[allow(clippy::too_many_arguments)]
pub fn constrain_axis(&mut self, axis: Axis, selected: &mut Selected, increment_mode: bool, mut local: bool, quad: Quad, transform: DAffine2, pivot: DVec2, local_transform: DAffine2) -> bool {
(*self, local) = match self {
TransformOperation::Grabbing(translation) => {
@@ -367,6 +369,7 @@ impl TransformOperation {
local
}
#[allow(clippy::too_many_arguments)]
pub fn grs_typed(&mut self, typed: Option<f64>, selected: &mut Selected, increment_mode: bool, local: bool, quad: Quad, transform: DAffine2, pivot: DVec2, local_transform: DAffine2) {
match self {
TransformOperation::None => (),
@@ -457,6 +460,7 @@ impl TransformOperation {
}
}
#[allow(clippy::too_many_arguments)]
pub fn negate(&mut self, selected: &mut Selected, increment_mode: bool, local: bool, quad: Quad, transform: DAffine2, pivot: DVec2, local_transform: DAffine2) {
if *self != TransformOperation::None {
*self = match self {