mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-07-07 15:55:00 +00:00
fix: pivot pinning and origin angle
This commit is contained in:
parent
a0115ff54e
commit
ba31408f87
5 changed files with 70 additions and 32 deletions
|
@ -1,8 +1,7 @@
|
|||
use super::utility_functions::overlay_canvas_context;
|
||||
use crate::consts::{
|
||||
COLOR_OVERLAY_BLUE, COLOR_OVERLAY_BLUE_50, COLOR_OVERLAY_GREEN, COLOR_OVERLAY_ORANGE, COLOR_OVERLAY_RED, COLOR_OVERLAY_WHITE, COLOR_OVERLAY_YELLOW, COMPASS_ROSE_ARROW_SIZE,
|
||||
COMPASS_ROSE_HOVER_RING_DIAMETER, COMPASS_ROSE_MAIN_RING_DIAMETER, COMPASS_ROSE_RING_INNER_DIAMETER, DOWEL_PIN_RADIUS, MANIPULATOR_GROUP_MARKER_SIZE, PIVOT_CROSSHAIR_LENGTH,
|
||||
PIVOT_CROSSHAIR_THICKNESS, PIVOT_DIAMETER,
|
||||
COLOR_OVERLAY_BLUE, COLOR_OVERLAY_BLUE_50, COLOR_OVERLAY_GREEN, COLOR_OVERLAY_RED, COLOR_OVERLAY_WHITE, COLOR_OVERLAY_YELLOW, COMPASS_ROSE_ARROW_SIZE, COMPASS_ROSE_HOVER_RING_DIAMETER,
|
||||
COMPASS_ROSE_MAIN_RING_DIAMETER, COMPASS_ROSE_RING_INNER_DIAMETER, DOWEL_PIN_RADIUS, MANIPULATOR_GROUP_MARKER_SIZE, PIVOT_CROSSHAIR_LENGTH, PIVOT_CROSSHAIR_THICKNESS, PIVOT_DIAMETER,
|
||||
};
|
||||
use crate::messages::prelude::Message;
|
||||
use bezier_rs::{Bezier, Subpath};
|
||||
|
@ -559,9 +558,9 @@ impl OverlayContext {
|
|||
self.end_dpi_aware_transform();
|
||||
}
|
||||
|
||||
pub fn dowel_pin(&mut self, position: DVec2, color: Option<&str>) {
|
||||
pub fn dowel_pin(&mut self, position: DVec2, angle: f64, color: Option<&str>) {
|
||||
let (x, y) = (position.round() - DVec2::splat(0.5)).into();
|
||||
let color = color.unwrap_or(COLOR_OVERLAY_ORANGE);
|
||||
let color = color.unwrap_or(COLOR_OVERLAY_YELLOW);
|
||||
|
||||
self.start_dpi_aware_transform();
|
||||
|
||||
|
@ -577,11 +576,11 @@ impl OverlayContext {
|
|||
self.render_context.begin_path();
|
||||
// Top-left sector
|
||||
self.render_context.move_to(x, y);
|
||||
self.render_context.arc(x, y, DOWEL_PIN_RADIUS, FRAC_PI_2, PI).expect("Failed to draw arc");
|
||||
self.render_context.arc(x, y, DOWEL_PIN_RADIUS, FRAC_PI_2 + angle, PI + angle).expect("Failed to draw arc");
|
||||
self.render_context.close_path();
|
||||
// Bottom-right sector
|
||||
self.render_context.move_to(x, y);
|
||||
self.render_context.arc(x, y, DOWEL_PIN_RADIUS, PI + FRAC_PI_2, TAU).expect("Failed to draw arc");
|
||||
self.render_context.arc(x, y, DOWEL_PIN_RADIUS, PI + FRAC_PI_2 + angle, TAU + angle).expect("Failed to draw arc");
|
||||
self.render_context.close_path();
|
||||
self.render_context.set_fill_style_str(color);
|
||||
self.render_context.fill();
|
||||
|
|
|
@ -171,6 +171,8 @@ pub struct Pivot {
|
|||
active: bool,
|
||||
/// Used to enable and disable the pivot
|
||||
pub pinned: bool,
|
||||
/// Had selected_visible_and_unlocked_layers
|
||||
pub empty: bool,
|
||||
}
|
||||
|
||||
impl Default for Pivot {
|
||||
|
@ -183,6 +185,7 @@ impl Default for Pivot {
|
|||
last_non_none_reference: ReferencePoint::Center,
|
||||
active: true,
|
||||
pinned: false,
|
||||
empty: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -195,9 +198,9 @@ impl Pivot {
|
|||
}
|
||||
|
||||
let selected = document.network_interface.selected_nodes();
|
||||
|
||||
self.empty = !selected.has_selected_nodes();
|
||||
if !selected.has_selected_nodes() {
|
||||
self.normalized_pivot = DVec2::splat(0.5);
|
||||
self.pivot = None;
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -221,7 +224,9 @@ impl Pivot {
|
|||
|
||||
let [min, max] = bounds.unwrap_or([DVec2::ZERO, DVec2::ONE]);
|
||||
self.transform_from_normalized = transform * DAffine2::from_translation(min) * DAffine2::from_scale(max - min);
|
||||
self.pivot = Some(self.transform_from_normalized.transform_point2(self.normalized_pivot));
|
||||
if self.old_pivot_position != ReferencePoint::None {
|
||||
self.pivot = Some(self.transform_from_normalized.transform_point2(self.normalized_pivot));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn recalculate_pivot_for_layer(&mut self, document: &DocumentMessageHandler, bounds: Option<[DVec2; 2]>) {
|
||||
|
|
|
@ -263,15 +263,15 @@ impl LayoutHolder for PathTool {
|
|||
.selected_index(Some(self.options.path_overlay_mode as u32))
|
||||
.widget_holder();
|
||||
|
||||
let [checkbox, dropdown] = {
|
||||
let [_checkbox, _dropdown] = {
|
||||
let dot_widget = dot_type_widget(self.tool_data.dot.state, Source::Path);
|
||||
[dot_widget.get(0).unwrap().clone(), dot_widget.get(2).unwrap().clone()]
|
||||
[dot_widget[0].clone(), dot_widget[2].clone()]
|
||||
};
|
||||
|
||||
let has_somrthing = !self.tool_data.saved_points_before_anchor_convert_smooth_sharp.is_empty();
|
||||
let pivot_reference = pivot_reference_point_widget(has_somrthing || !self.tool_data.dot.state.is_pivot(), self.tool_data.dot.pivot.to_pivot_position(), Source::Path);
|
||||
let _pivot_reference = pivot_reference_point_widget(has_somrthing || !self.tool_data.dot.state.is_pivot(), self.tool_data.dot.pivot.to_pivot_position(), Source::Path);
|
||||
|
||||
let pin_pivot = pin_pivot_widget(self.tool_data.dot.pin_inactive(), Source::Path);
|
||||
let _pin_pivot = pin_pivot_widget(self.tool_data.dot.pin_inactive(), Source::Path);
|
||||
|
||||
Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row {
|
||||
widgets: vec![
|
||||
|
@ -289,13 +289,13 @@ impl LayoutHolder for PathTool {
|
|||
unrelated_seperator.clone(),
|
||||
path_overlay_mode_widget,
|
||||
unrelated_seperator.clone(),
|
||||
checkbox.clone(),
|
||||
related_seperator.clone(),
|
||||
dropdown.clone(),
|
||||
unrelated_seperator,
|
||||
pivot_reference,
|
||||
related_seperator.clone(),
|
||||
pin_pivot,
|
||||
// checkbox.clone(),
|
||||
// related_seperator.clone(),
|
||||
// dropdown.clone(),
|
||||
// unrelated_seperator,
|
||||
// pivot_reference,
|
||||
// related_seperator.clone(),
|
||||
// pin_pivot,
|
||||
],
|
||||
}]))
|
||||
}
|
||||
|
@ -566,7 +566,6 @@ impl PathToolData {
|
|||
|
||||
fn update_selection_status(&mut self, shape_editor: &mut ShapeState, document: &DocumentMessageHandler) {
|
||||
let selection_status = get_selection_status(&document.network_interface, shape_editor);
|
||||
// debug!("{:?}", selection_status);
|
||||
|
||||
self.can_toggle_colinearity = match &selection_status {
|
||||
SelectionStatus::None => false,
|
||||
|
@ -610,8 +609,6 @@ impl PathToolData {
|
|||
|
||||
let old_selection = shape_editor.selected_points().cloned().collect::<Vec<_>>();
|
||||
|
||||
debug!("{old_selection:?}");
|
||||
|
||||
// Check if the point is already selected; if not, select the first point within the threshold (in pixels)
|
||||
// Don't select the points which are not shown currently in PathOverlayMode
|
||||
if let Some((already_selected, mut selection_info)) = shape_editor.get_point_selection_state(
|
||||
|
@ -1396,6 +1393,10 @@ impl Fsm for PathToolFsmState {
|
|||
update_dynamic_hints(self, responses, shape_editor, document, tool_data, tool_options);
|
||||
|
||||
let ToolMessage::Path(event) = event else { return self };
|
||||
|
||||
// TODO(mTvare6): Remove it once dots are implemented for path_tool
|
||||
tool_data.dot.state.enabled = false;
|
||||
|
||||
match (self, event) {
|
||||
(_, PathToolMessage::SelectionChanged) => {
|
||||
// Set the newly targeted layers to visible
|
||||
|
|
|
@ -538,7 +538,7 @@ impl SelectToolData {
|
|||
|
||||
fn state_from_dot(&self, mouse: DVec2) -> Option<SelectToolFsmState> {
|
||||
match self.dot.state.dot {
|
||||
DotType::Pivot if !self.dot.pivot.pinned => self.dot.pivot.is_over(mouse).then_some(SelectToolFsmState::DraggingPivot),
|
||||
DotType::Pivot => self.dot.pivot.is_over(mouse).then_some(SelectToolFsmState::DraggingPivot),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -766,21 +766,52 @@ impl Fsm for SelectToolFsmState {
|
|||
});
|
||||
|
||||
let mut active_origin = None;
|
||||
let mut origin_angle = 0.;
|
||||
if overlay_context.visibility_settings.origin() && !tool_data.dot.state.is_pivot_type() {
|
||||
let get_angle = |layer: LayerNodeIdentifier| -> f64 {
|
||||
let quad = Quad::from_box([DVec2::ZERO, DVec2::ONE]);
|
||||
let bounds = document.metadata().transform_to_viewport_with_first_transform_node_if_group(layer, &document.network_interface) * quad;
|
||||
(bounds.top_left() - bounds.top_right()).to_angle()
|
||||
};
|
||||
if tool_data.dot.state.dot == DotType::Average {
|
||||
let mut count = 0;
|
||||
|
||||
let sum: f64 = document
|
||||
.network_interface
|
||||
.selected_nodes()
|
||||
.selected_visible_and_unlocked_layers(&document.network_interface)
|
||||
.map(get_angle)
|
||||
.inspect(|_| count += 1)
|
||||
.sum();
|
||||
if count > 0 {
|
||||
origin_angle = sum / count as f64;
|
||||
}
|
||||
} else if tool_data.dot.state.dot == DotType::Active {
|
||||
origin_angle = document
|
||||
.network_interface
|
||||
.selected_nodes()
|
||||
.selected_visible_and_unlocked_layers(&document.network_interface)
|
||||
.find(|&layer| Some(layer) == tool_data.dot.layer)
|
||||
.iter()
|
||||
.map(|&layer| get_angle(layer))
|
||||
.sum();
|
||||
}
|
||||
|
||||
for layer in document.network_interface.selected_nodes().selected_visible_and_unlocked_layers(&document.network_interface) {
|
||||
let origin = graph_modification_utils::get_viewport_origin(layer, &document.network_interface);
|
||||
if Some(layer) == tool_data.dot.layer {
|
||||
active_origin = Some(origin);
|
||||
continue;
|
||||
}
|
||||
overlay_context.dowel_pin(origin, None);
|
||||
overlay_context.dowel_pin(origin, origin_angle, None);
|
||||
}
|
||||
}
|
||||
if let Some(origin) = active_origin {
|
||||
overlay_context.dowel_pin(origin, Some(COLOR_OVERLAY_YELLOW));
|
||||
overlay_context.dowel_pin(origin, origin_angle, Some(COLOR_OVERLAY_ORANGE));
|
||||
}
|
||||
|
||||
let draw_pivot = tool_data.dot.state.is_pivot() && overlay_context.visibility_settings.pivot();
|
||||
let has_layers = document.network_interface.selected_nodes().has_selected_nodes();
|
||||
let draw_pivot = tool_data.dot.state.is_pivot() && overlay_context.visibility_settings.pivot() && has_layers;
|
||||
tool_data.dot.pivot.update(document, &mut overlay_context, Some((angle,)), draw_pivot);
|
||||
|
||||
// Update compass rose
|
||||
|
@ -1009,8 +1040,10 @@ impl Fsm for SelectToolFsmState {
|
|||
let extend = input.keyboard.key(extend_selection);
|
||||
if !extend && !input.keyboard.key(remove_from_selection) {
|
||||
responses.add(DocumentMessage::DeselectAllLayers);
|
||||
let position = tool_data.dot.pivot.last_non_none_reference;
|
||||
responses.add(SelectToolMessage::SetPivot { position });
|
||||
if !tool_data.dot.pivot.pinned {
|
||||
let position = tool_data.dot.pivot.last_non_none_reference;
|
||||
responses.add(SelectToolMessage::SetPivot { position });
|
||||
}
|
||||
tool_data.layers_dragging.clear();
|
||||
}
|
||||
|
||||
|
|
|
@ -388,8 +388,8 @@ impl MessageHandler<TransformLayerMessage, TransformData<'_>> for TransformLayer
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(bounds) = self.path_bounds {
|
||||
overlay_context.quad(Quad::from_box(bounds), None, None);
|
||||
if let Some(_) = self.path_bounds {
|
||||
// overlay_context.quad(Quad::from_box(bounds), None, None);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue