mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-23 21:08:12 +08:00
Add a Select tool overlay for the layer origin (#3471)
* Add blue layer origin cross overlay * Apply suggestion from @Keavon * Skip layers without local transforms * Disable the Custom Pivot by default --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
co-authored by
Keavon Chambers
parent
20a595db39
commit
c46060db44
@@ -0,0 +1,46 @@
|
||||
use crate::consts::{COLOR_OVERLAY_BLUE, LAYER_ORIGIN_CROSS_DIAMETER, LAYER_ORIGIN_CROSS_THICKNESS};
|
||||
use crate::messages::portfolio::document::overlays::utility_types::OverlayContext;
|
||||
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
|
||||
use crate::messages::tool::tool_messages::tool_prelude::DocumentMessageHandler;
|
||||
use glam::DVec2;
|
||||
|
||||
/// Draws a cross overlay at the origin point of the layers in layer space.
|
||||
/// This cross is orientated based on the +X vector of the layer.
|
||||
pub fn draw_for_selected_layers(overlay_context: &mut OverlayContext, document: &DocumentMessageHandler) {
|
||||
// Don't draw if it is a disabled overlay
|
||||
if !overlay_context.visibility_settings.layer_origin_cross() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only show for layers that are visible, unlocked, and selected
|
||||
for layer in document.network_interface.selected_nodes().selected_visible_and_unlocked_layers(&document.network_interface) {
|
||||
// Don't show for artboards
|
||||
if document.network_interface.is_artboard(&layer.to_node(), &[]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Don't crash if we accidentally have the root
|
||||
if layer == LayerNodeIdentifier::ROOT_PARENT {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Some layers such as groups don't have a local transform (although we'll likely design a fix for that fact later)
|
||||
if !document.metadata().local_transforms.contains_key(&layer.to_node()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// A transformation from the layer's local space to the viewport space (where overlays are drawn)
|
||||
let transform_to_viewport = document.metadata().transform_to_viewport(layer);
|
||||
|
||||
// The origin of the layer in viewport space which is the center of the origin cross
|
||||
let origin_viewport = transform_to_viewport.transform_point2(DVec2::ZERO);
|
||||
// The forward +X direction vector from layer space (used to orient the origin cross)
|
||||
let forward = transform_to_viewport.transform_vector2(DVec2::X).normalize_or_zero();
|
||||
|
||||
// Draw the origin cross
|
||||
let offsets = [forward + forward.perp(), forward - forward.perp()].map(|offset| offset * core::f64::consts::FRAC_1_SQRT_2 * LAYER_ORIGIN_CROSS_DIAMETER / 2.);
|
||||
for offset in offsets {
|
||||
overlay_context.line(origin_viewport - offset, origin_viewport + offset, Some(COLOR_OVERLAY_BLUE), Some(LAYER_ORIGIN_CROSS_THICKNESS));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ pub mod color_selector;
|
||||
pub mod compass_rose;
|
||||
pub mod gizmos;
|
||||
pub mod graph_modification_utils;
|
||||
pub mod layer_origin_cross;
|
||||
pub mod measure;
|
||||
pub mod pivot;
|
||||
pub mod resize;
|
||||
|
||||
@@ -63,7 +63,7 @@ pub fn pivot_gizmo_type_widget(state: PivotGizmoState, source: PivotToolSource)
|
||||
.collect();
|
||||
|
||||
vec![
|
||||
CheckboxInput::new(!state.disabled)
|
||||
CheckboxInput::new(state.enabled)
|
||||
.tooltip_label("Pivot Gizmo")
|
||||
.tooltip_description(
|
||||
"
|
||||
@@ -74,11 +74,11 @@ pub fn pivot_gizmo_type_widget(state: PivotGizmoState, source: PivotToolSource)
|
||||
)
|
||||
.on_update(move |optional_input: &CheckboxInput| match source {
|
||||
PivotToolSource::Select => SelectToolMessage::SelectOptions {
|
||||
options: SelectOptionsUpdate::TogglePivotGizmoType(optional_input.checked),
|
||||
options: SelectOptionsUpdate::SetPivotGizmoEnabled(optional_input.checked),
|
||||
}
|
||||
.into(),
|
||||
PivotToolSource::Path => PathToolMessage::UpdateOptions {
|
||||
options: PathOptionsUpdate::TogglePivotGizmoType(optional_input.checked),
|
||||
options: PathOptionsUpdate::SetPivotGizmoEnabled(optional_input.checked),
|
||||
}
|
||||
.into(),
|
||||
})
|
||||
@@ -101,7 +101,7 @@ pub fn pivot_gizmo_type_widget(state: PivotGizmoState, source: PivotToolSource)
|
||||
"
|
||||
.trim(),
|
||||
)
|
||||
.disabled(state.disabled)
|
||||
.disabled(!state.enabled)
|
||||
.widget_instance(),
|
||||
]
|
||||
}
|
||||
@@ -124,7 +124,7 @@ pub struct PivotGizmo {
|
||||
impl PivotGizmo {
|
||||
pub fn position(&self, document: &DocumentMessageHandler) -> DVec2 {
|
||||
let network = &document.network_interface;
|
||||
(!self.state.disabled)
|
||||
(self.state.enabled)
|
||||
.then_some({
|
||||
match self.state.gizmo_type {
|
||||
PivotGizmoType::Average => Some(network.selected_nodes().selected_visible_and_unlocked_layers_mean_average_origin(network)),
|
||||
@@ -163,18 +163,18 @@ pub enum PivotGizmoType {
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Default, Debug, Hash, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
pub struct PivotGizmoState {
|
||||
pub disabled: bool,
|
||||
pub enabled: bool,
|
||||
pub gizmo_type: PivotGizmoType,
|
||||
}
|
||||
|
||||
impl PivotGizmoState {
|
||||
pub fn is_pivot_type(&self) -> bool {
|
||||
// A disabled pivot is considered a pivot-type gizmo that is always centered
|
||||
self.gizmo_type == PivotGizmoType::Pivot || self.disabled
|
||||
self.gizmo_type == PivotGizmoType::Pivot || !self.enabled
|
||||
}
|
||||
|
||||
pub fn is_pivot(&self) -> bool {
|
||||
self.gizmo_type == PivotGizmoType::Pivot && !self.disabled
|
||||
self.gizmo_type == PivotGizmoType::Pivot && self.enabled
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user