mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-25 20:58:12 +08:00
Add a pivot widget to selected layer(s) to control the origin(s) (#772)
* Add pivot * Add dragging pivot * Cleanup * Remove tabs * Fix multiplication order * Restyle pivot * Add move cursor icon * Update pivot size * Code review tweaks * Fix alt with non-centred pivot * Comment for add one * Pivot sets layer panel origin * Tweek alt centre thing * Fix division by zero case * Add pivot dots to properties * FIx some typos Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
committed by
Keavon Chambers
co-authored by
Keavon Chambers
parent
0f6f3be6e7
commit
1e109dc552
@@ -1,4 +1,5 @@
|
||||
use super::utility_types::TransformOp;
|
||||
use crate::messages::layout::utility_types::widgets::assist_widgets::PivotPosition;
|
||||
use crate::messages::portfolio::document::utility_types::misc::TargetDocument;
|
||||
use crate::messages::prelude::*;
|
||||
|
||||
@@ -25,5 +26,6 @@ pub enum PropertiesPanelMessage {
|
||||
ModifyTransform { value: f64, transform_op: TransformOp },
|
||||
ResendActiveProperties,
|
||||
SetActiveLayers { paths: Vec<Vec<LayerId>>, document: TargetDocument },
|
||||
SetPivot { new_position: PivotPosition },
|
||||
UpdateSelectedDocumentProperties,
|
||||
}
|
||||
|
||||
+7
@@ -101,6 +101,13 @@ impl<'a> MessageHandler<PropertiesPanelMessage, PropertiesPanelMessageHandlerDat
|
||||
let (path, _) = self.active_selection.clone().expect("Received update for properties panel with no active layer");
|
||||
responses.push_back(Operation::SetTextContent { path, new_text }.into())
|
||||
}
|
||||
SetPivot { new_position } => {
|
||||
let (layer_path, _) = self.active_selection.clone().expect("Received update for properties panel with no active layer");
|
||||
let position: Option<glam::DVec2> = new_position.into();
|
||||
let pivot = position.unwrap().into();
|
||||
|
||||
responses.push_back(Operation::SetPivot { layer_path, pivot }.into());
|
||||
}
|
||||
CheckSelectedWasUpdated { path } => {
|
||||
if self.matches_selected(&path) {
|
||||
responses.push_back(PropertiesPanelMessage::ResendActiveProperties.into())
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use super::utility_types::TransformOp;
|
||||
use crate::messages::layout::utility_types::layout_widget::{Layout, LayoutGroup, Widget, WidgetCallback, WidgetHolder, WidgetLayout};
|
||||
use crate::messages::layout::utility_types::misc::LayoutTarget;
|
||||
use crate::messages::layout::utility_types::widgets::assist_widgets::PivotAssist;
|
||||
use crate::messages::layout::utility_types::widgets::button_widgets::PopoverButton;
|
||||
use crate::messages::layout::utility_types::widgets::input_widgets::{ColorInput, FontInput, NumberInput, RadioEntryData, RadioInput, TextAreaInput, TextInput};
|
||||
use crate::messages::layout::utility_types::widgets::label_widgets::{IconLabel, IconStyle, Separator, SeparatorDirection, SeparatorType, TextLabel};
|
||||
@@ -80,6 +81,7 @@ pub fn register_artboard_layer_properties(layer: &Layer, responses: &mut VecDequ
|
||||
} else {
|
||||
panic!("Artboard must have a solid fill")
|
||||
};
|
||||
let pivot = layer.transform.transform_vector2(layer.layerspace_pivot(font_cache));
|
||||
|
||||
vec![LayoutGroup::Section {
|
||||
name: "Artboard".into(),
|
||||
@@ -95,12 +97,12 @@ pub fn register_artboard_layer_properties(layer: &Layer, responses: &mut VecDequ
|
||||
direction: SeparatorDirection::Horizontal,
|
||||
})),
|
||||
WidgetHolder::new(Widget::NumberInput(NumberInput {
|
||||
value: Some(layer.transform.x()),
|
||||
value: Some(layer.transform.x() + pivot.x),
|
||||
label: "X".into(),
|
||||
unit: " px".into(),
|
||||
on_update: WidgetCallback::new(|number_input: &NumberInput| {
|
||||
on_update: WidgetCallback::new(move |number_input: &NumberInput| {
|
||||
PropertiesPanelMessage::ModifyTransform {
|
||||
value: number_input.value.unwrap(),
|
||||
value: number_input.value.unwrap() - pivot.x,
|
||||
transform_op: TransformOp::X,
|
||||
}
|
||||
.into()
|
||||
@@ -112,12 +114,12 @@ pub fn register_artboard_layer_properties(layer: &Layer, responses: &mut VecDequ
|
||||
direction: SeparatorDirection::Horizontal,
|
||||
})),
|
||||
WidgetHolder::new(Widget::NumberInput(NumberInput {
|
||||
value: Some(layer.transform.y()),
|
||||
value: Some(layer.transform.y() + pivot.y),
|
||||
label: "Y".into(),
|
||||
unit: " px".into(),
|
||||
on_update: WidgetCallback::new(|number_input: &NumberInput| {
|
||||
on_update: WidgetCallback::new(move |number_input: &NumberInput| {
|
||||
PropertiesPanelMessage::ModifyTransform {
|
||||
value: number_input.value.unwrap(),
|
||||
value: number_input.value.unwrap() - pivot.y,
|
||||
transform_op: TransformOp::Y,
|
||||
}
|
||||
.into()
|
||||
@@ -308,6 +310,7 @@ pub fn register_artwork_layer_properties(layer: &Layer, responses: &mut VecDeque
|
||||
}
|
||||
|
||||
fn node_section_transform(layer: &Layer, font_cache: &FontCache) -> LayoutGroup {
|
||||
let pivot = layer.transform.transform_vector2(layer.layerspace_pivot(font_cache));
|
||||
LayoutGroup::Section {
|
||||
name: "Transform".into(),
|
||||
layout: vec![
|
||||
@@ -317,17 +320,25 @@ fn node_section_transform(layer: &Layer, font_cache: &FontCache) -> LayoutGroup
|
||||
value: "Location".into(),
|
||||
..TextLabel::default()
|
||||
})),
|
||||
WidgetHolder::new(Widget::Separator(Separator {
|
||||
separator_type: SeparatorType::Related,
|
||||
direction: SeparatorDirection::Horizontal,
|
||||
})),
|
||||
WidgetHolder::new(Widget::PivotAssist(PivotAssist {
|
||||
position: layer.pivot.into(),
|
||||
on_update: WidgetCallback::new(|pivot_assist: &PivotAssist| PropertiesPanelMessage::SetPivot { new_position: pivot_assist.position }.into()),
|
||||
})),
|
||||
WidgetHolder::new(Widget::Separator(Separator {
|
||||
separator_type: SeparatorType::Unrelated,
|
||||
direction: SeparatorDirection::Horizontal,
|
||||
})),
|
||||
WidgetHolder::new(Widget::NumberInput(NumberInput {
|
||||
value: Some(layer.transform.x()),
|
||||
value: Some(layer.transform.x() + pivot.x),
|
||||
label: "X".into(),
|
||||
unit: " px".into(),
|
||||
on_update: WidgetCallback::new(|number_input: &NumberInput| {
|
||||
on_update: WidgetCallback::new(move |number_input: &NumberInput| {
|
||||
PropertiesPanelMessage::ModifyTransform {
|
||||
value: number_input.value.unwrap(),
|
||||
value: number_input.value.unwrap() - pivot.x,
|
||||
transform_op: TransformOp::X,
|
||||
}
|
||||
.into()
|
||||
@@ -339,12 +350,12 @@ fn node_section_transform(layer: &Layer, font_cache: &FontCache) -> LayoutGroup
|
||||
direction: SeparatorDirection::Horizontal,
|
||||
})),
|
||||
WidgetHolder::new(Widget::NumberInput(NumberInput {
|
||||
value: Some(layer.transform.y()),
|
||||
value: Some(layer.transform.y() + pivot.y),
|
||||
label: "Y".into(),
|
||||
unit: " px".into(),
|
||||
on_update: WidgetCallback::new(|number_input: &NumberInput| {
|
||||
on_update: WidgetCallback::new(move |number_input: &NumberInput| {
|
||||
PropertiesPanelMessage::ModifyTransform {
|
||||
value: number_input.value.unwrap(),
|
||||
value: number_input.value.unwrap() - pivot.y,
|
||||
transform_op: TransformOp::Y,
|
||||
}
|
||||
.into()
|
||||
|
||||
Reference in New Issue
Block a user