diff --git a/editor/src/messages/layout/layout_message_handler.rs b/editor/src/messages/layout/layout_message_handler.rs index adeae9d1..ab10a615 100644 --- a/editor/src/messages/layout/layout_message_handler.rs +++ b/editor/src/messages/layout/layout_message_handler.rs @@ -125,6 +125,12 @@ impl Vec> MessageHandler { + let update_value = value.as_str().expect("RadioInput update was not of type: u64"); + pivot_assist.position = update_value.into(); + let callback_message = (pivot_assist.on_update.callback)(pivot_assist); + responses.push_back(callback_message); + } Widget::PopoverButton(_) => {} Widget::RadioInput(radio_input) => { let update_value = value.as_u64().expect("RadioInput update was not of type: u64"); diff --git a/editor/src/messages/layout/utility_types/layout_widget.rs b/editor/src/messages/layout/utility_types/layout_widget.rs index 8fef627e..5371a8b0 100644 --- a/editor/src/messages/layout/utility_types/layout_widget.rs +++ b/editor/src/messages/layout/utility_types/layout_widget.rs @@ -1,3 +1,4 @@ +use super::widgets::assist_widgets::*; use super::widgets::button_widgets::*; use super::widgets::input_widgets::*; use super::widgets::label_widgets::*; @@ -278,6 +279,7 @@ pub enum Widget { InvisibleStandinInput(InvisibleStandinInput), NumberInput(NumberInput), OptionalInput(OptionalInput), + PivotAssist(PivotAssist), PopoverButton(PopoverButton), RadioInput(RadioInput), Separator(Separator), diff --git a/editor/src/messages/layout/utility_types/widgets/assist_widgets.rs b/editor/src/messages/layout/utility_types/widgets/assist_widgets.rs new file mode 100644 index 00000000..8535f993 --- /dev/null +++ b/editor/src/messages/layout/utility_types/widgets/assist_widgets.rs @@ -0,0 +1,48 @@ +use derivative::*; +use serde::{Deserialize, Serialize}; + +use crate::messages::layout::utility_types::layout_widget::WidgetCallback; + +#[derive(Clone, Default, Derivative, Serialize, Deserialize)] +#[derivative(Debug, PartialEq)] +pub struct PivotAssist { + pub position: PivotPosition, + + // Callbacks + #[serde(skip)] + #[derivative(Debug = "ignore", PartialEq = "ignore")] + pub on_update: WidgetCallback, +} + +#[derive(Clone, Serialize, Deserialize, Debug, Default, PartialEq, Eq)] +pub enum PivotPosition { + #[default] + None, + TopLeft, + TopCenter, + TopRight, + CenterLeft, + Center, + CenterRight, + BottomLeft, + BottomCenter, + BottomRight, +} + +impl From<&str> for PivotPosition { + fn from(input: &str) -> Self { + match input { + "None" => PivotPosition::None, + "TopLeft" => PivotPosition::TopLeft, + "TopCenter" => PivotPosition::TopCenter, + "TopRight" => PivotPosition::TopRight, + "CenterLeft" => PivotPosition::CenterLeft, + "Center" => PivotPosition::Center, + "CenterRight" => PivotPosition::CenterRight, + "BottomLeft" => PivotPosition::BottomLeft, + "BottomCenter" => PivotPosition::BottomCenter, + "BottomRight" => PivotPosition::BottomRight, + _ => panic!("Failed parsing unrecognized PivotPosition enum value '{}'", input), + } + } +} diff --git a/editor/src/messages/layout/utility_types/widgets/mod.rs b/editor/src/messages/layout/utility_types/widgets/mod.rs index 92202963..d388b080 100644 --- a/editor/src/messages/layout/utility_types/widgets/mod.rs +++ b/editor/src/messages/layout/utility_types/widgets/mod.rs @@ -1,3 +1,4 @@ +pub mod assist_widgets; pub mod button_widgets; pub mod input_widgets; pub mod label_widgets; diff --git a/editor/src/messages/portfolio/document/transform_layer/transform_layer_message_handler.rs b/editor/src/messages/portfolio/document/transform_layer/transform_layer_message_handler.rs index b9b03873..3776dad5 100644 --- a/editor/src/messages/portfolio/document/transform_layer/transform_layer_message_handler.rs +++ b/editor/src/messages/portfolio/document/transform_layer/transform_layer_message_handler.rs @@ -62,7 +62,7 @@ impl<'a> MessageHandler> for TransformL } // Don't allow grab with no selected layers - if selected_layers.len() == 0 { + if selected_layers.is_empty() { return; } @@ -78,7 +78,7 @@ impl<'a> MessageHandler> for TransformL } // Don't allow rotate with no selected layers - if selected_layers.len() == 0 { + if selected_layers.is_empty() { return; } @@ -94,7 +94,7 @@ impl<'a> MessageHandler> for TransformL } // Don't allow scale with no selected layers - if selected_layers.len() == 0 { + if selected_layers.is_empty() { return; } diff --git a/editor/src/messages/tool/common_functionality/transformation_cage.rs b/editor/src/messages/tool/common_functionality/transformation_cage.rs index 0b60413e..613dc41b 100644 --- a/editor/src/messages/tool/common_functionality/transformation_cage.rs +++ b/editor/src/messages/tool/common_functionality/transformation_cage.rs @@ -107,7 +107,7 @@ impl SelectedEdges { _ => size, }; let delta_size = new_size - size; - min = min - delta_size * min_pivot; + min -= delta_size * min_pivot; max = min + new_size; } diff --git a/editor/src/messages/tool/tool_messages/select_tool.rs b/editor/src/messages/tool/tool_messages/select_tool.rs index cc737e09..2371b3c7 100644 --- a/editor/src/messages/tool/tool_messages/select_tool.rs +++ b/editor/src/messages/tool/tool_messages/select_tool.rs @@ -4,6 +4,7 @@ use crate::messages::frontend::utility_types::MouseCursorIcon; use crate::messages::input_mapper::utility_types::input_keyboard::{Key, KeysGroup, MouseMotion}; use crate::messages::input_mapper::utility_types::input_mouse::ViewportPosition; use crate::messages::layout::utility_types::layout_widget::{Layout, LayoutGroup, PropertyHolder, Widget, WidgetCallback, WidgetHolder, WidgetLayout}; +use crate::messages::layout::utility_types::widgets::assist_widgets::{PivotAssist, PivotPosition}; use crate::messages::layout::utility_types::widgets::button_widgets::{IconButton, PopoverButton}; use crate::messages::layout::utility_types::widgets::label_widgets::{Separator, SeparatorDirection, SeparatorType}; use crate::messages::portfolio::document::utility_types::misc::{AlignAggregate, AlignAxis, FlipAxis}; @@ -245,6 +246,19 @@ impl PropertyHolder for SelectTool { text: "The contents of this popover menu are coming soon".into(), ..Default::default() })), + WidgetHolder::new(Widget::Separator(Separator { + direction: SeparatorDirection::Horizontal, + separator_type: SeparatorType::Section, + })), + // We'd like this widget to hide and show itself whenever the transformation cage is active or inactive (i.e. when no layers are selected) + WidgetHolder::new(Widget::PivotAssist(PivotAssist { + position: PivotPosition::Center, + on_update: WidgetCallback::new(|pivot_assist: &PivotAssist| { + // TODO: Make this actually do something + log::debug!("Changed pivot to {:?}", pivot_assist.position); + Message::NoOp + }), + })), ], }])) } diff --git a/frontend/src/components/widgets/WidgetRow.vue b/frontend/src/components/widgets/WidgetRow.vue index fdef6891..f72fc3f1 100644 --- a/frontend/src/components/widgets/WidgetRow.vue +++ b/frontend/src/components/widgets/WidgetRow.vue @@ -23,6 +23,7 @@ :incrementCallbackDecrease="() => updateLayout(component.widgetId, 'Decrement')" /> +

{{ (component.props as any).header }}

{{ (component.props as any).text }}

@@ -75,6 +76,7 @@ import { defineComponent, type PropType } from "vue"; import { isWidgetColumn, isWidgetRow, type WidgetColumn, type WidgetRow } from "@/wasm-communication/messages"; +import PivotAssist from "@/components/widgets/assists/PivotAssist.vue"; import IconButton from "@/components/widgets/buttons/IconButton.vue"; import PopoverButton from "@/components/widgets/buttons/PopoverButton.vue"; import TextButton from "@/components/widgets/buttons/TextButton.vue"; @@ -134,6 +136,7 @@ export default defineComponent({ IconLabel, NumberInput, OptionalInput, + PivotAssist, PopoverButton, RadioInput, Separator, diff --git a/frontend/src/components/widgets/assists/PivotAssist.vue b/frontend/src/components/widgets/assists/PivotAssist.vue new file mode 100644 index 00000000..2acc4681 --- /dev/null +++ b/frontend/src/components/widgets/assists/PivotAssist.vue @@ -0,0 +1,114 @@ + + + + + diff --git a/frontend/src/wasm-communication/messages.ts b/frontend/src/wasm-communication/messages.ts index aceb4aee..3057a763 100644 --- a/frontend/src/wasm-communication/messages.ts +++ b/frontend/src/wasm-communication/messages.ts @@ -612,6 +612,12 @@ export class TextLabel extends WidgetProps { multiline!: boolean; } +export type PivotPosition = "None" | "TopLeft" | "TopCenter" | "TopRight" | "CenterLeft" | "Center" | "CenterRight" | "BottomLeft" | "BottomCenter" | "BottomRight"; + +export class PivotAssist extends WidgetProps { + position!: PivotPosition; +} + // WIDGET const widgetSubTypes = [ @@ -631,6 +637,7 @@ const widgetSubTypes = [ { value: TextButton, name: "TextButton" }, { value: TextInput, name: "TextInput" }, { value: TextLabel, name: "TextLabel" }, + { value: PivotAssist, name: "PivotAssist" }, ]; export type WidgetPropsSet = InstanceType;