mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-25 03:18:11 +08:00
Add Path tool feature for angle locking upon pressing Ctrl while dragging handle over anchor (#2612)
* almost_fixed * fix need to refactor * fixed issed need to refactor * refactor-done fixed issue * move function to common_functionality --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
co-authored by
Keavon Chambers
parent
3d37ef79ac
commit
d39308c048
@@ -729,7 +729,9 @@ impl ShapeState {
|
||||
let length = transform.transform_vector2(unselected_position - anchor).length();
|
||||
let position = transform.inverse().transform_vector2(direction * length);
|
||||
let modification_type = unselected_handle.set_relative_position(position);
|
||||
responses.add(GraphOperationMessage::Vector { layer, modification_type });
|
||||
if (anchor - selected_position).length() > 1e-6 {
|
||||
responses.add(GraphOperationMessage::Vector { layer, modification_type });
|
||||
}
|
||||
}
|
||||
// If both handles are selected, average the angles of the handles
|
||||
else {
|
||||
@@ -775,6 +777,7 @@ impl ShapeState {
|
||||
in_viewport_space: bool,
|
||||
was_alt_dragging: bool,
|
||||
opposite_handle_position: Option<DVec2>,
|
||||
skip_opposite_handle: bool,
|
||||
responses: &mut VecDeque<Message>,
|
||||
) {
|
||||
for (&layer, state) in &self.selected_shape_state {
|
||||
@@ -816,6 +819,11 @@ impl ShapeState {
|
||||
responses.add(GraphOperationMessage::Vector { layer, modification_type });
|
||||
|
||||
let Some(other) = vector_data.other_colinear_handle(handle) else { continue };
|
||||
|
||||
if skip_opposite_handle {
|
||||
continue;
|
||||
}
|
||||
|
||||
if state.is_selected(other.to_manipulator_point()) {
|
||||
// If two colinear handles are being dragged at the same time but not the anchor, it is necessary to break the colinear state.
|
||||
let handles = [handle, other];
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::messages::tool::common_functionality::graph_modification_utils::get_t
|
||||
use glam::DVec2;
|
||||
use graphene_core::renderer::Quad;
|
||||
use graphene_core::text::{FontCache, load_face};
|
||||
use graphene_std::vector::PointId;
|
||||
use graphene_std::vector::{ManipulatorPointId, PointId, SegmentId, VectorData};
|
||||
|
||||
/// Determines if a path should be extended. Goal in viewport space. Returns the path and if it is extending from the start, if applicable.
|
||||
pub fn should_extend(
|
||||
@@ -66,3 +66,30 @@ pub fn text_bounding_box(layer: LayerNodeIdentifier, document: &DocumentMessageH
|
||||
|
||||
Quad::from_box([DVec2::ZERO, far])
|
||||
}
|
||||
|
||||
pub fn calculate_segment_angle(anchor: PointId, segment: SegmentId, vector_data: &VectorData, pen_tool: bool) -> Option<f64> {
|
||||
let is_start = |point: PointId, segment: SegmentId| vector_data.segment_start_from_id(segment) == Some(point);
|
||||
let anchor_position = vector_data.point_domain.position_from_id(anchor)?;
|
||||
let end_handle = ManipulatorPointId::EndHandle(segment).get_position(vector_data);
|
||||
let start_handle = ManipulatorPointId::PrimaryHandle(segment).get_position(vector_data);
|
||||
|
||||
let start_point = if is_start(anchor, segment) {
|
||||
vector_data.segment_end_from_id(segment).and_then(|id| vector_data.point_domain.position_from_id(id))
|
||||
} else {
|
||||
vector_data.segment_start_from_id(segment).and_then(|id| vector_data.point_domain.position_from_id(id))
|
||||
};
|
||||
|
||||
let required_handle = if is_start(anchor, segment) {
|
||||
start_handle
|
||||
.filter(|&handle| pen_tool && handle != anchor_position)
|
||||
.or(end_handle.filter(|&handle| Some(handle) != start_point))
|
||||
.or(start_point)
|
||||
} else {
|
||||
end_handle
|
||||
.filter(|&handle| pen_tool && handle != anchor_position)
|
||||
.or(start_handle.filter(|&handle| Some(handle) != start_point))
|
||||
.or(start_point)
|
||||
};
|
||||
|
||||
required_handle.map(|handle| -(handle - anchor_position).angle_to(DVec2::X))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user