fix skew
This commit is contained in:
parent
9cbfefca1d
commit
1cb2aabc9c
|
|
@ -2259,7 +2259,8 @@ impl StagePane {
|
||||||
}
|
}
|
||||||
|
|
||||||
TransformMode::Skew { axis, origin } => {
|
TransformMode::Skew { axis, origin } => {
|
||||||
// Calculate skew angle such that the edge follows the mouse cursor
|
// Calculate skew angle for center-relative skewing (center stays fixed)
|
||||||
|
let center = original_bbox.center();
|
||||||
let skew_radians = match axis {
|
let skew_radians = match axis {
|
||||||
Axis::Horizontal => {
|
Axis::Horizontal => {
|
||||||
// Determine which horizontal edge we're dragging
|
// Determine which horizontal edge we're dragging
|
||||||
|
|
@ -2268,10 +2269,10 @@ impl StagePane {
|
||||||
} else {
|
} else {
|
||||||
original_bbox.y0 // Origin is bottom edge, so dragging top
|
original_bbox.y0 // Origin is bottom edge, so dragging top
|
||||||
};
|
};
|
||||||
let distance = edge_y - origin.y;
|
let distance = edge_y - center.y; // Distance from center to edge
|
||||||
if distance.abs() > 0.1 {
|
if distance.abs() > 0.1 {
|
||||||
// tan(skew) = horizontal_offset / vertical_distance
|
// tan(skew) = mouse_movement / distance_from_center
|
||||||
let tan_skew = (current_mouse.x - origin.x) / distance;
|
let tan_skew = (current_mouse.x - start_mouse.x) / distance;
|
||||||
tan_skew.atan()
|
tan_skew.atan()
|
||||||
} else {
|
} else {
|
||||||
0.0
|
0.0
|
||||||
|
|
@ -2284,10 +2285,10 @@ impl StagePane {
|
||||||
} else {
|
} else {
|
||||||
original_bbox.x0 // Origin is right edge, so dragging left
|
original_bbox.x0 // Origin is right edge, so dragging left
|
||||||
};
|
};
|
||||||
let distance = edge_x - origin.x;
|
let distance = edge_x - center.x; // Distance from center to edge
|
||||||
if distance.abs() > 0.1 {
|
if distance.abs() > 0.1 {
|
||||||
// tan(skew) = vertical_offset / horizontal_distance
|
// tan(skew) = mouse_movement / distance_from_center
|
||||||
let tan_skew = (current_mouse.y - origin.y) / distance;
|
let tan_skew = (current_mouse.y - start_mouse.y) / distance;
|
||||||
tan_skew.atan()
|
tan_skew.atan()
|
||||||
} else {
|
} else {
|
||||||
0.0
|
0.0
|
||||||
|
|
@ -2296,42 +2297,58 @@ impl StagePane {
|
||||||
};
|
};
|
||||||
let skew_degrees = skew_radians.to_degrees();
|
let skew_degrees = skew_radians.to_degrees();
|
||||||
|
|
||||||
// Calculate selection center for group skew
|
// Calculate selection center for group skew - this stays fixed
|
||||||
let selection_center = match axis {
|
let selection_center = match axis {
|
||||||
Axis::Horizontal => {
|
Axis::Horizontal => original_bbox.center().y,
|
||||||
// For horizontal skew, use center Y
|
Axis::Vertical => original_bbox.center().x,
|
||||||
original_bbox.center().y
|
|
||||||
}
|
|
||||||
Axis::Vertical => {
|
|
||||||
// For vertical skew, use center X
|
|
||||||
original_bbox.center().x
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Apply skew to all selected objects
|
// Apply skew to all selected objects
|
||||||
let tan_skew = skew_degrees.to_radians().tan();
|
// Note: skew_radians = atan(tan_skew), so tan(skew_radians) = tan_skew
|
||||||
|
let tan_skew = skew_radians.tan();
|
||||||
for (object_id, original_transform) in original_transforms {
|
for (object_id, original_transform) in original_transforms {
|
||||||
|
// Get the object to find its shape
|
||||||
|
let object = vector_layer.get_object(object_id);
|
||||||
|
|
||||||
|
// Calculate the world-space center where the renderer applies skew
|
||||||
|
// This is the shape's bounding box center transformed to world space
|
||||||
|
let shape_center_world = if let Some(obj) = object {
|
||||||
|
if let Some(shape) = vector_layer.get_shape(&obj.shape_id) {
|
||||||
|
use kurbo::Shape as KurboShape;
|
||||||
|
let shape_bbox = shape.path().bounding_box();
|
||||||
|
let local_center_x = (shape_bbox.x0 + shape_bbox.x1) / 2.0;
|
||||||
|
let local_center_y = (shape_bbox.y0 + shape_bbox.y1) / 2.0;
|
||||||
|
|
||||||
|
// Transform to world space (same as renderer)
|
||||||
|
let world_center = kurbo::Affine::translate((original_transform.x, original_transform.y))
|
||||||
|
* kurbo::Affine::rotate(original_transform.rotation.to_radians())
|
||||||
|
* kurbo::Affine::scale_non_uniform(original_transform.scale_x, original_transform.scale_y)
|
||||||
|
* kurbo::Point::new(local_center_x, local_center_y);
|
||||||
|
(world_center.x, world_center.y)
|
||||||
|
} else {
|
||||||
|
// Fallback to object position if shape not found
|
||||||
|
(original_transform.x, original_transform.y)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Fallback to object position if object not found
|
||||||
|
(original_transform.x, original_transform.y)
|
||||||
|
};
|
||||||
|
|
||||||
vector_layer.modify_object_internal(object_id, |obj| {
|
vector_layer.modify_object_internal(object_id, |obj| {
|
||||||
// Calculate distance from selection center
|
// Distance from selection center using the object's actual skew center
|
||||||
let distance_from_center = match axis {
|
let distance_from_center = match axis {
|
||||||
Axis::Horizontal => {
|
Axis::Horizontal => shape_center_world.1 - selection_center,
|
||||||
// For horizontal skew, measure Y distance
|
Axis::Vertical => shape_center_world.0 - selection_center,
|
||||||
original_transform.y - selection_center
|
|
||||||
}
|
|
||||||
Axis::Vertical => {
|
|
||||||
// For vertical skew, measure X distance
|
|
||||||
original_transform.x - selection_center
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Calculate translation to make group skew cohesive
|
// Calculate translation to make group skew around center
|
||||||
let (offset_x, offset_y) = match axis {
|
let (offset_x, offset_y) = match axis {
|
||||||
Axis::Horizontal => {
|
Axis::Horizontal => {
|
||||||
// Horizontal skew: translate X based on Y distance
|
// Horizontal skew: objects above/below center move horizontally
|
||||||
(distance_from_center * tan_skew, 0.0)
|
(distance_from_center * tan_skew, 0.0)
|
||||||
}
|
}
|
||||||
Axis::Vertical => {
|
Axis::Vertical => {
|
||||||
// Vertical skew: translate Y based on X distance
|
// Vertical skew: objects left/right of center move vertically
|
||||||
(0.0, distance_from_center * tan_skew)
|
(0.0, distance_from_center * tan_skew)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue