Skip to content

Commit 51ba5f1

Browse files
TrueDoctorKeavon
authored andcommitted
Differentiate between scale and dimensions (#570)
* Differentiate between scale and dimensions * Fix layout and naming of properties
1 parent aec23d1 commit 51ba5f1

File tree

6 files changed

+101
-39
lines changed

6 files changed

+101
-39
lines changed

editor/src/document/properties_panel_message.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ pub enum PropertiesPanelMessage {
2222
pub enum TransformOp {
2323
X,
2424
Y,
25+
ScaleX,
26+
ScaleY,
2527
Width,
2628
Height,
2729
Rotation,

editor/src/document/properties_panel_message_handler.rs

Lines changed: 82 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ use std::f64::consts::PI;
1818
use std::rc::Rc;
1919

2020
trait DAffine2Utils {
21-
fn width(&self) -> f64;
22-
fn update_width(self, new_width: f64) -> Self;
23-
fn height(&self) -> f64;
24-
fn update_height(self, new_height: f64) -> Self;
21+
fn scale_x(&self) -> f64;
22+
fn update_scale_x(self, new_width: f64) -> Self;
23+
fn scale_y(&self) -> f64;
24+
fn update_scale_y(self, new_height: f64) -> Self;
2525
fn x(&self) -> f64;
2626
fn update_x(self, new_x: f64) -> Self;
2727
fn y(&self) -> f64;
@@ -31,20 +31,20 @@ trait DAffine2Utils {
3131
}
3232

3333
impl DAffine2Utils for DAffine2 {
34-
fn width(&self) -> f64 {
34+
fn scale_x(&self) -> f64 {
3535
self.transform_vector2((1., 0.).into()).length()
3636
}
3737

38-
fn update_width(self, new_width: f64) -> Self {
39-
self * DAffine2::from_scale((new_width / self.width(), 1.).into())
38+
fn update_scale_x(self, new_width: f64) -> Self {
39+
self * DAffine2::from_scale((new_width / self.scale_x(), 1.).into())
4040
}
4141

42-
fn height(&self) -> f64 {
42+
fn scale_y(&self) -> f64 {
4343
self.transform_vector2((0., 1.).into()).length()
4444
}
4545

46-
fn update_height(self, new_height: f64) -> Self {
47-
self * DAffine2::from_scale((1., new_height / self.height()).into())
46+
fn update_scale_y(self, new_height: f64) -> Self {
47+
self * DAffine2::from_scale((1., new_height / self.scale_y()).into())
4848
}
4949

5050
fn x(&self) -> f64 {
@@ -66,14 +66,14 @@ impl DAffine2Utils for DAffine2 {
6666
}
6767

6868
fn rotation(&self) -> f64 {
69-
let cos = self.matrix2.col(0).x / self.width();
70-
let sin = self.matrix2.col(0).y / self.width();
69+
let cos = self.matrix2.col(0).x / self.scale_x();
70+
let sin = self.matrix2.col(0).y / self.scale_x();
7171
sin.atan2(cos)
7272
}
7373

7474
fn update_rotation(self, new_rotation: f64) -> Self {
75-
let width = self.width();
76-
let height = self.height();
75+
let width = self.scale_x();
76+
let height = self.scale_y();
7777
let half_width = width / 2.;
7878
let half_height = height / 2.;
7979

@@ -138,15 +138,21 @@ impl MessageHandler<PropertiesPanelMessage, &GrapheneDocument> for PropertiesPan
138138
let action = match transform_op {
139139
X => DAffine2::update_x,
140140
Y => DAffine2::update_y,
141-
Width => DAffine2::update_width,
142-
Height => DAffine2::update_height,
141+
ScaleX | Width => DAffine2::update_scale_x,
142+
ScaleY | Height => DAffine2::update_scale_y,
143143
Rotation => DAffine2::update_rotation,
144144
};
145145

146+
let scale = match transform_op {
147+
Width => layer.bounding_transform().scale_x() / layer.transform.scale_x(),
148+
Height => layer.bounding_transform().scale_y() / layer.transform.scale_y(),
149+
_ => 1.,
150+
};
151+
146152
responses.push_back(
147153
Operation::SetLayerTransform {
148154
path: path.clone(),
149-
transform: action(layer.transform, value).to_cols_array(),
155+
transform: action(layer.transform, value / scale).to_cols_array(),
150156
}
151157
.into(),
152158
);
@@ -297,7 +303,7 @@ fn node_section_transform(layer: &Layer) -> LayoutRow {
297303
name: "".into(),
298304
widgets: vec![
299305
WidgetHolder::new(Widget::TextLabel(TextLabel {
300-
value: "Position".into(),
306+
value: "Location".into(),
301307
..TextLabel::default()
302308
})),
303309
WidgetHolder::new(Widget::Separator(Separator {
@@ -340,21 +346,47 @@ fn node_section_transform(layer: &Layer) -> LayoutRow {
340346
name: "".into(),
341347
widgets: vec![
342348
WidgetHolder::new(Widget::TextLabel(TextLabel {
343-
value: "Dimensions".into(),
349+
value: "Rotation".into(),
344350
..TextLabel::default()
345351
})),
346352
WidgetHolder::new(Widget::Separator(Separator {
347353
separator_type: SeparatorType::Unrelated,
348354
direction: SeparatorDirection::Horizontal,
349355
})),
350356
WidgetHolder::new(Widget::NumberInput(NumberInput {
351-
value: layer.transform.width(),
352-
label: "W".into(),
353-
unit: " px".into(),
357+
value: layer.transform.rotation() * 180. / PI,
358+
label: "".into(),
359+
unit: "°".into(),
360+
on_update: WidgetCallback::new(|number_input: &NumberInput| {
361+
PropertiesPanelMessage::ModifyTransform {
362+
value: number_input.value / 180. * PI,
363+
transform_op: TransformOp::Rotation,
364+
}
365+
.into()
366+
}),
367+
..NumberInput::default()
368+
})),
369+
],
370+
},
371+
LayoutRow::Row {
372+
name: "".into(),
373+
widgets: vec![
374+
WidgetHolder::new(Widget::TextLabel(TextLabel {
375+
value: "Scale".into(),
376+
..TextLabel::default()
377+
})),
378+
WidgetHolder::new(Widget::Separator(Separator {
379+
separator_type: SeparatorType::Unrelated,
380+
direction: SeparatorDirection::Horizontal,
381+
})),
382+
WidgetHolder::new(Widget::NumberInput(NumberInput {
383+
value: layer.transform.scale_x(),
384+
label: "X".into(),
385+
unit: "".into(),
354386
on_update: WidgetCallback::new(|number_input: &NumberInput| {
355387
PropertiesPanelMessage::ModifyTransform {
356388
value: number_input.value,
357-
transform_op: TransformOp::Width,
389+
transform_op: TransformOp::ScaleX,
358390
}
359391
.into()
360392
}),
@@ -365,13 +397,13 @@ fn node_section_transform(layer: &Layer) -> LayoutRow {
365397
direction: SeparatorDirection::Horizontal,
366398
})),
367399
WidgetHolder::new(Widget::NumberInput(NumberInput {
368-
value: layer.transform.height(),
369-
label: "H".into(),
370-
unit: " px".into(),
400+
value: layer.transform.scale_y(),
401+
label: "Y".into(),
402+
unit: "".into(),
371403
on_update: WidgetCallback::new(|number_input: &NumberInput| {
372404
PropertiesPanelMessage::ModifyTransform {
373405
value: number_input.value,
374-
transform_op: TransformOp::Height,
406+
transform_op: TransformOp::ScaleY,
375407
}
376408
.into()
377409
}),
@@ -383,21 +415,38 @@ fn node_section_transform(layer: &Layer) -> LayoutRow {
383415
name: "".into(),
384416
widgets: vec![
385417
WidgetHolder::new(Widget::TextLabel(TextLabel {
386-
value: "Rotation".into(),
418+
value: "Dimensions".into(),
387419
..TextLabel::default()
388420
})),
389421
WidgetHolder::new(Widget::Separator(Separator {
390422
separator_type: SeparatorType::Unrelated,
391423
direction: SeparatorDirection::Horizontal,
392424
})),
393425
WidgetHolder::new(Widget::NumberInput(NumberInput {
394-
value: layer.transform.rotation() * 180. / PI,
395-
label: "R".into(),
396-
unit: "°".into(),
426+
value: layer.bounding_transform().scale_x(),
427+
label: "W".into(),
428+
unit: " px".into(),
397429
on_update: WidgetCallback::new(|number_input: &NumberInput| {
398430
PropertiesPanelMessage::ModifyTransform {
399-
value: number_input.value / 180. * PI,
400-
transform_op: TransformOp::Rotation,
431+
value: number_input.value,
432+
transform_op: TransformOp::Width,
433+
}
434+
.into()
435+
}),
436+
..NumberInput::default()
437+
})),
438+
WidgetHolder::new(Widget::Separator(Separator {
439+
separator_type: SeparatorType::Related,
440+
direction: SeparatorDirection::Horizontal,
441+
})),
442+
WidgetHolder::new(Widget::NumberInput(NumberInput {
443+
value: layer.bounding_transform().scale_y(),
444+
label: "H".into(),
445+
unit: " px".into(),
446+
on_update: WidgetCallback::new(|number_input: &NumberInput| {
447+
PropertiesPanelMessage::ModifyTransform {
448+
value: number_input.value,
449+
transform_op: TransformOp::Height,
401450
}
402451
.into()
403452
}),

editor/src/document/transformation.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ impl<'a> Selected<'a> {
221221
.document
222222
.layer(path)
223223
.unwrap()
224-
.current_bounding_box_with_transform(multiplied_transform)
224+
.aabounding_box_for_transform(multiplied_transform)
225225
.unwrap_or([multiplied_transform.translation; 2]);
226226

227227
(bounds[0] + bounds[1]) / 2.

editor/src/viewport_tools/tools/gradient_tool.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ impl Default for GradientToolFsmState {
8181

8282
/// Computes the transform from gradient space to layer space (where gradient space is 0..1 in layer space)
8383
fn gradient_space_transform(path: &[LayerId], layer: &Layer, document: &DocumentMessageHandler) -> DAffine2 {
84-
let bounds = layer.current_bounding_box().unwrap();
84+
let bounds = layer.aabounding_box().unwrap();
8585
let bound_transform = DAffine2::from_scale_angle_translation(bounds[1] - bounds[0], 0., bounds[0]);
8686

8787
document.graphene_document.multiply_transforms(&path[..path.len() - 1]).unwrap() * bound_transform

editor/src/viewport_tools/tools/text_tool.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ fn update_overlays(document: &DocumentMessageHandler, data: &mut TextToolData, r
166166
.graphene_document
167167
.layer(layer_path)
168168
.unwrap()
169-
.current_bounding_box_with_transform(document.graphene_document.multiply_transforms(layer_path).unwrap())
169+
.aabounding_box_for_transform(document.graphene_document.multiply_transforms(layer_path).unwrap())
170170
.unwrap();
171171

172172
let operation = Operation::SetLayerTransformInViewport {

graphene/src/layers/layer_info.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,12 +146,23 @@ impl Layer {
146146
self.data.intersects_quad(transformed_quad, path, intersections)
147147
}
148148

149-
pub fn current_bounding_box_with_transform(&self, transform: DAffine2) -> Option<[DVec2; 2]> {
149+
pub fn aabounding_box_for_transform(&self, transform: DAffine2) -> Option<[DVec2; 2]> {
150150
self.data.bounding_box(transform)
151151
}
152152

153-
pub fn current_bounding_box(&self) -> Option<[DVec2; 2]> {
154-
self.current_bounding_box_with_transform(self.transform)
153+
pub fn aabounding_box(&self) -> Option<[DVec2; 2]> {
154+
self.aabounding_box_for_transform(self.transform)
155+
}
156+
pub fn bounding_transform(&self) -> DAffine2 {
157+
let scale = match self.aabounding_box_for_transform(DAffine2::IDENTITY) {
158+
Some([a, b]) => {
159+
let dimensions = b - a;
160+
DAffine2::from_scale(dimensions)
161+
}
162+
_ => DAffine2::IDENTITY,
163+
};
164+
165+
self.transform * scale
155166
}
156167

157168
pub fn as_folder_mut(&mut self) -> Result<&mut FolderLayer, DocumentError> {

0 commit comments

Comments
 (0)