diff --git a/desktop/src/app.rs b/desktop/src/app.rs index 803a2f0a3..da055ff5b 100644 --- a/desktop/src/app.rs +++ b/desktop/src/app.rs @@ -61,8 +61,8 @@ impl WinitApp { } fn send_messages_to_editor(&mut self, mut responses: Vec) { - for message in responses.extract_if(.., |m| matches!(m, FrontendMessage::RenderOverlays(_))) { - let FrontendMessage::RenderOverlays(overlay_context) = message else { unreachable!() }; + for message in responses.extract_if(.., |m| matches!(m, FrontendMessage::RenderOverlays { .. })) { + let FrontendMessage::RenderOverlays { context: overlay_context } = message else { unreachable!() }; if let Some(graphics_state) = &mut self.graphics_state { let scene = overlay_context.take_scene(); graphics_state.set_overlays_scene(scene); diff --git a/editor/src/dispatcher.rs b/editor/src/dispatcher.rs index a80c94045..44bea9ff4 100644 --- a/editor/src/dispatcher.rs +++ b/editor/src/dispatcher.rs @@ -52,7 +52,7 @@ const SIDE_EFFECT_FREE_MESSAGES: &[MessageDiscriminant] = &[ MessageDiscriminant::Frontend(FrontendMessageDiscriminant::TriggerFontLoad), ]; const DEBUG_MESSAGE_BLOCK_LIST: &[MessageDiscriminant] = &[ - MessageDiscriminant::Broadcast(BroadcastMessageDiscriminant::TriggerEvent(BroadcastEventDiscriminant::AnimationFrame)), + MessageDiscriminant::Broadcast(BroadcastMessageDiscriminant::TriggerEvent(EventMessageDiscriminant::AnimationFrame)), MessageDiscriminant::Animation(AnimationMessageDiscriminant::IncrementFrameCounter), ]; // TODO: Find a way to combine these with the list above. We use strings for now since these are the standard variant names used by multiple messages. But having these also type-checked would be best. diff --git a/editor/src/messages/animation/animation_message.rs b/editor/src/messages/animation/animation_message.rs index 128cc70ea..4b5aea386 100644 --- a/editor/src/messages/animation/animation_message.rs +++ b/editor/src/messages/animation/animation_message.rs @@ -1,6 +1,5 @@ -use crate::messages::prelude::*; - use super::animation_message_handler::AnimationTimeMode; +use crate::messages::prelude::*; #[impl_message(Message, Animation)] #[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)] diff --git a/editor/src/messages/broadcast/broadcast_message.rs b/editor/src/messages/broadcast/broadcast_message.rs index 984d4e56a..35e49981a 100644 --- a/editor/src/messages/broadcast/broadcast_message.rs +++ b/editor/src/messages/broadcast/broadcast_message.rs @@ -5,15 +5,15 @@ use crate::messages::prelude::*; pub enum BroadcastMessage { // Sub-messages #[child] - TriggerEvent(BroadcastEvent), + TriggerEvent(EventMessage), // Messages SubscribeEvent { - on: BroadcastEvent, + on: EventMessage, send: Box, }, UnsubscribeEvent { - on: BroadcastEvent, - message: Box, + on: EventMessage, + send: Box, }, } diff --git a/editor/src/messages/broadcast/broadcast_message_handler.rs b/editor/src/messages/broadcast/broadcast_message_handler.rs index 29d75f5cb..2d6bbb006 100644 --- a/editor/src/messages/broadcast/broadcast_message_handler.rs +++ b/editor/src/messages/broadcast/broadcast_message_handler.rs @@ -2,7 +2,8 @@ use crate::messages::prelude::*; #[derive(Debug, Clone, Default, ExtractField)] pub struct BroadcastMessageHandler { - listeners: HashMap>, + event: EventMessageHandler, + listeners: HashMap>, } #[message_handler_data] @@ -10,19 +11,15 @@ impl MessageHandler for BroadcastMessageHandler { fn process_message(&mut self, message: BroadcastMessage, responses: &mut VecDeque, _: ()) { match message { // Sub-messages - BroadcastMessage::TriggerEvent(event) => { - for message in self.listeners.entry(event).or_default() { - responses.add_front(message.clone()) - } - } + BroadcastMessage::TriggerEvent(message) => self.event.process_message(message, responses, EventMessageContext { listeners: &mut self.listeners }), // Messages BroadcastMessage::SubscribeEvent { on, send } => self.listeners.entry(on).or_default().push(*send), - BroadcastMessage::UnsubscribeEvent { on, message } => self.listeners.entry(on).or_default().retain(|msg| *msg != *message), + BroadcastMessage::UnsubscribeEvent { on, send } => self.listeners.entry(on).or_default().retain(|msg| *msg != *send), } } fn actions(&self) -> ActionList { - actions!(BroadcastEventDiscriminant;) + actions!(EventMessageDiscriminant;) } } diff --git a/editor/src/messages/broadcast/broadcast_event.rs b/editor/src/messages/broadcast/event/event_message.rs similarity index 92% rename from editor/src/messages/broadcast/broadcast_event.rs rename to editor/src/messages/broadcast/event/event_message.rs index ebe2318aa..b2c77111d 100644 --- a/editor/src/messages/broadcast/broadcast_event.rs +++ b/editor/src/messages/broadcast/event/event_message.rs @@ -1,8 +1,8 @@ use crate::messages::prelude::*; -#[derive(PartialEq, Eq, Clone, Debug, serde::Serialize, serde::Deserialize, Hash)] #[impl_message(Message, BroadcastMessage, TriggerEvent)] -pub enum BroadcastEvent { +#[derive(PartialEq, Eq, Clone, Debug, serde::Serialize, serde::Deserialize, Hash)] +pub enum EventMessage { /// Triggered by requestAnimationFrame in JS AnimationFrame, CanvasTransformed, diff --git a/editor/src/messages/broadcast/event/event_message_handler.rs b/editor/src/messages/broadcast/event/event_message_handler.rs new file mode 100644 index 000000000..c8d0170d0 --- /dev/null +++ b/editor/src/messages/broadcast/event/event_message_handler.rs @@ -0,0 +1,22 @@ +use crate::messages::prelude::*; + +#[derive(ExtractField)] +pub struct EventMessageContext<'a> { + pub listeners: &'a mut HashMap>, +} + +#[derive(Debug, Clone, Default, ExtractField)] +pub struct EventMessageHandler {} + +#[message_handler_data] +impl MessageHandler> for EventMessageHandler { + fn process_message(&mut self, message: EventMessage, responses: &mut VecDeque, context: EventMessageContext) { + for message in context.listeners.entry(message).or_default() { + responses.add_front(message.clone()) + } + } + + fn actions(&self) -> ActionList { + actions!(EventMessageDiscriminant;) + } +} diff --git a/editor/src/messages/broadcast/event/mod.rs b/editor/src/messages/broadcast/event/mod.rs new file mode 100644 index 000000000..36913e5ad --- /dev/null +++ b/editor/src/messages/broadcast/event/mod.rs @@ -0,0 +1,7 @@ +mod event_message; +mod event_message_handler; + +#[doc(inline)] +pub use event_message::{EventMessage, EventMessageDiscriminant}; +#[doc(inline)] +pub use event_message_handler::{EventMessageContext, EventMessageHandler}; diff --git a/editor/src/messages/broadcast/mod.rs b/editor/src/messages/broadcast/mod.rs index a6ecb8897..e95de4a79 100644 --- a/editor/src/messages/broadcast/mod.rs +++ b/editor/src/messages/broadcast/mod.rs @@ -1,7 +1,7 @@ mod broadcast_message; mod broadcast_message_handler; -pub mod broadcast_event; +pub mod event; #[doc(inline)] pub use broadcast_message::{BroadcastMessage, BroadcastMessageDiscriminant}; diff --git a/editor/src/messages/defer/defer_message.rs b/editor/src/messages/defer/defer_message.rs index 66db0ff78..c1b699a70 100644 --- a/editor/src/messages/defer/defer_message.rs +++ b/editor/src/messages/defer/defer_message.rs @@ -3,8 +3,8 @@ use crate::messages::prelude::*; #[impl_message(Message, Defer)] #[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)] pub enum DeferMessage { - SetGraphSubmissionIndex(u64), - TriggerGraphRun(u64, DocumentId), + SetGraphSubmissionIndex { execution_id: u64 }, + TriggerGraphRun { execution_id: u64, document_id: DocumentId }, AfterGraphRun { messages: Vec }, TriggerNavigationReady, AfterNavigationReady { messages: Vec }, diff --git a/editor/src/messages/defer/defer_message_handler.rs b/editor/src/messages/defer/defer_message_handler.rs index d4775ded2..a1c4907ec 100644 --- a/editor/src/messages/defer/defer_message_handler.rs +++ b/editor/src/messages/defer/defer_message_handler.rs @@ -24,10 +24,10 @@ impl MessageHandler> for DeferMessageHandl DeferMessage::AfterNavigationReady { messages } => { self.after_viewport_resize.extend_from_slice(&messages); } - DeferMessage::SetGraphSubmissionIndex(execution_id) => { + DeferMessage::SetGraphSubmissionIndex { execution_id } => { self.current_graph_submission_id = execution_id + 1; } - DeferMessage::TriggerGraphRun(execution_id, document_id) => { + DeferMessage::TriggerGraphRun { execution_id, document_id } => { let after_graph_run = self.after_graph_run.entry(document_id).or_default(); if after_graph_run.is_empty() { return; diff --git a/editor/src/messages/dialog/export_dialog/export_dialog_message.rs b/editor/src/messages/dialog/export_dialog/export_dialog_message.rs index 20b0f8486..c33d94f36 100644 --- a/editor/src/messages/dialog/export_dialog/export_dialog_message.rs +++ b/editor/src/messages/dialog/export_dialog/export_dialog_message.rs @@ -4,10 +4,10 @@ use crate::messages::prelude::*; #[impl_message(Message, DialogMessage, ExportDialog)] #[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)] pub enum ExportDialogMessage { - FileType(FileType), - ScaleFactor(f64), - TransparentBackground(bool), - ExportBounds(ExportBounds), + FileType { file_type: FileType }, + ScaleFactor { factor: f64 }, + TransparentBackground { transparent: bool }, + ExportBounds { bounds: ExportBounds }, Submit, } diff --git a/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs b/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs index 0fa126917..684a240fe 100644 --- a/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs +++ b/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs @@ -38,10 +38,10 @@ impl MessageHandler> for Exp let ExportDialogMessageContext { portfolio } = context; match message { - ExportDialogMessage::FileType(export_type) => self.file_type = export_type, - ExportDialogMessage::ScaleFactor(factor) => self.scale_factor = factor, - ExportDialogMessage::TransparentBackground(transparent_background) => self.transparent_background = transparent_background, - ExportDialogMessage::ExportBounds(export_area) => self.bounds = export_area, + ExportDialogMessage::FileType { file_type } => self.file_type = file_type, + ExportDialogMessage::ScaleFactor { factor } => self.scale_factor = factor, + ExportDialogMessage::TransparentBackground { transparent } => self.transparent_background = transparent, + ExportDialogMessage::ExportBounds { bounds } => self.bounds = bounds, ExportDialogMessage::Submit => responses.add_front(PortfolioMessage::SubmitDocumentExport { file_name: portfolio.active_document().map(|document| document.name.clone()).unwrap_or_default(), @@ -84,7 +84,11 @@ impl LayoutHolder for ExportDialogMessageHandler { fn layout(&self) -> Layout { let entries = [(FileType::Png, "PNG"), (FileType::Jpg, "JPG"), (FileType::Svg, "SVG")] .into_iter() - .map(|(val, name)| RadioEntryData::new(format!("{val:?}")).label(name).on_update(move |_| ExportDialogMessage::FileType(val).into())) + .map(|(file_type, name)| { + RadioEntryData::new(format!("{file_type:?}")) + .label(name) + .on_update(move |_| ExportDialogMessage::FileType { file_type }.into()) + }) .collect(); let export_type = vec![ @@ -101,7 +105,7 @@ impl LayoutHolder for ExportDialogMessageHandler { .min(0.) .max((1_u64 << f64::MANTISSA_DIGITS) as f64) .disabled(self.file_type == FileType::Svg) - .on_update(|number_input: &NumberInput| ExportDialogMessage::ScaleFactor(number_input.value.unwrap()).into()) + .on_update(|number_input: &NumberInput| ExportDialogMessage::ScaleFactor { factor: number_input.value.unwrap() }.into()) .min_width(200) .widget_holder(), ]; @@ -125,10 +129,10 @@ impl LayoutHolder for ExportDialogMessageHandler { .map(|choice| { choice .into_iter() - .map(|(val, name, disabled)| { - MenuListEntry::new(format!("{val:?}")) + .map(|(bounds, name, disabled)| { + MenuListEntry::new(format!("{bounds:?}")) .label(name) - .on_commit(move |_| ExportDialogMessage::ExportBounds(val).into()) + .on_commit(move |_| ExportDialogMessage::ExportBounds { bounds }.into()) .disabled(disabled) }) .collect::>() @@ -151,7 +155,7 @@ impl LayoutHolder for ExportDialogMessageHandler { Separator::new(SeparatorType::Unrelated).widget_holder(), CheckboxInput::new(self.transparent_background) .disabled(self.file_type == FileType::Jpg) - .on_update(move |value: &CheckboxInput| ExportDialogMessage::TransparentBackground(value.checked).into()) + .on_update(move |value: &CheckboxInput| ExportDialogMessage::TransparentBackground { transparent: value.checked }.into()) .for_label(checkbox_id) .widget_holder(), ]; diff --git a/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message.rs b/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message.rs index 26502196c..21774de33 100644 --- a/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message.rs +++ b/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message.rs @@ -3,10 +3,10 @@ use crate::messages::prelude::*; #[impl_message(Message, DialogMessage, NewDocumentDialog)] #[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)] pub enum NewDocumentDialogMessage { - Name(String), - Infinite(bool), - DimensionsX(f64), - DimensionsY(f64), + Name { name: String }, + Infinite { infinite: bool }, + DimensionsX { width: f64 }, + DimensionsY { height: f64 }, Submit, } diff --git a/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message_handler.rs b/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message_handler.rs index 51cf61518..a91330249 100644 --- a/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message_handler.rs +++ b/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message_handler.rs @@ -20,10 +20,10 @@ pub struct NewDocumentDialogMessageHandler { impl<'a> MessageHandler> for NewDocumentDialogMessageHandler { fn process_message(&mut self, message: NewDocumentDialogMessage, responses: &mut VecDeque, context: NewDocumentDialogMessageContext<'a>) { match message { - NewDocumentDialogMessage::Name(name) => self.name = name, - NewDocumentDialogMessage::Infinite(infinite) => self.infinite = infinite, - NewDocumentDialogMessage::DimensionsX(x) => self.dimensions.x = x as u32, - NewDocumentDialogMessage::DimensionsY(y) => self.dimensions.y = y as u32, + NewDocumentDialogMessage::Name { name } => self.name = name, + NewDocumentDialogMessage::Infinite { infinite } => self.infinite = infinite, + NewDocumentDialogMessage::DimensionsX { width } => self.dimensions.x = width as u32, + NewDocumentDialogMessage::DimensionsY { height } => self.dimensions.y = height as u32, NewDocumentDialogMessage::Submit => { responses.add(PortfolioMessage::NewDocumentWithName { name: self.name.clone() }); @@ -82,7 +82,7 @@ impl LayoutHolder for NewDocumentDialogMessageHandler { TextLabel::new("Name").table_align(true).min_width(90).widget_holder(), Separator::new(SeparatorType::Unrelated).widget_holder(), TextInput::new(&self.name) - .on_update(|text_input: &TextInput| NewDocumentDialogMessage::Name(text_input.value.clone()).into()) + .on_update(|text_input: &TextInput| NewDocumentDialogMessage::Name { name: text_input.value.clone() }.into()) .min_width(204) // Matches the 100px of both NumberInputs below + the 4px of the Unrelated-type separator .widget_holder(), ]; @@ -92,7 +92,7 @@ impl LayoutHolder for NewDocumentDialogMessageHandler { TextLabel::new("Infinite Canvas").table_align(true).min_width(90).for_checkbox(checkbox_id).widget_holder(), Separator::new(SeparatorType::Unrelated).widget_holder(), CheckboxInput::new(self.infinite) - .on_update(|checkbox_input: &CheckboxInput| NewDocumentDialogMessage::Infinite(checkbox_input.checked).into()) + .on_update(|checkbox_input: &CheckboxInput| NewDocumentDialogMessage::Infinite { infinite: checkbox_input.checked }.into()) .for_label(checkbox_id) .widget_holder(), ]; @@ -108,7 +108,7 @@ impl LayoutHolder for NewDocumentDialogMessageHandler { .is_integer(true) .disabled(self.infinite) .min_width(100) - .on_update(|number_input: &NumberInput| NewDocumentDialogMessage::DimensionsX(number_input.value.unwrap()).into()) + .on_update(|number_input: &NumberInput| NewDocumentDialogMessage::DimensionsX { width: number_input.value.unwrap() }.into()) .widget_holder(), Separator::new(SeparatorType::Related).widget_holder(), NumberInput::new(Some(self.dimensions.y as f64)) @@ -119,7 +119,7 @@ impl LayoutHolder for NewDocumentDialogMessageHandler { .is_integer(true) .disabled(self.infinite) .min_width(100) - .on_update(|number_input: &NumberInput| NewDocumentDialogMessage::DimensionsY(number_input.value.unwrap()).into()) + .on_update(|number_input: &NumberInput| NewDocumentDialogMessage::DimensionsY { height: number_input.value.unwrap() }.into()) .widget_holder(), ]; diff --git a/editor/src/messages/dialog/simple_dialogs/close_document_dialog.rs b/editor/src/messages/dialog/simple_dialogs/close_document_dialog.rs index d370b2fde..90c43bf9e 100644 --- a/editor/src/messages/dialog/simple_dialogs/close_document_dialog.rs +++ b/editor/src/messages/dialog/simple_dialogs/close_document_dialog.rs @@ -1,4 +1,4 @@ -use crate::messages::broadcast::broadcast_event::BroadcastEvent; +use crate::messages::broadcast::event::EventMessage; use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::prelude::*; @@ -27,7 +27,7 @@ impl DialogLayoutHolder for CloseDocumentDialog { TextButton::new("Discard") .on_update(move |_| { DialogMessage::CloseDialogAndThen { - followups: vec![BroadcastEvent::ToolAbort.into(), PortfolioMessage::CloseDocument { document_id }.into()], + followups: vec![EventMessage::ToolAbort.into(), PortfolioMessage::CloseDocument { document_id }.into()], } .into() }) diff --git a/editor/src/messages/frontend/frontend_message.rs b/editor/src/messages/frontend/frontend_message.rs index 6d6ddd720..1289fc4db 100644 --- a/editor/src/messages/frontend/frontend_message.rs +++ b/editor/src/messages/frontend/frontend_message.rs @@ -335,9 +335,9 @@ pub enum FrontendMessage { active: bool, }, #[cfg(not(target_family = "wasm"))] - RenderOverlays( + RenderOverlays { #[serde(skip, default = "OverlayContext::default")] #[derivative(Debug = "ignore", PartialEq = "ignore")] - OverlayContext, - ), + context: OverlayContext, + }, } diff --git a/editor/src/messages/input_mapper/input_mappings.rs b/editor/src/messages/input_mapper/input_mappings.rs index 255193a43..71f68acc9 100644 --- a/editor/src/messages/input_mapper/input_mappings.rs +++ b/editor/src/messages/input_mapper/input_mappings.rs @@ -96,7 +96,7 @@ pub fn input_mappings() -> Mapping { entry!(PointerMove; refresh_keys=[Control, Shift], action_dispatch=TransformLayerMessage::PointerMove { slow_key: Shift, increments_key: Control }), // // SelectToolMessage - entry!(PointerMove; refresh_keys=[Control, Alt, Shift], action_dispatch=SelectToolMessage::PointerMove(SelectToolPointerKeys { axis_align: Shift, snap_angle: Shift, center: Alt, duplicate: Alt })), + entry!(PointerMove; refresh_keys=[Control, Alt, Shift], action_dispatch=SelectToolMessage::PointerMove { modifier_keys: SelectToolPointerKeys { axis_align: Shift, snap_angle: Shift, center: Alt, duplicate: Alt } }), entry!(KeyDown(MouseLeft); action_dispatch=SelectToolMessage::DragStart { extend_selection: Shift, remove_from_selection: Alt, select_deepest: Accel, lasso_select: Control, skew: Control }), entry!(KeyUp(MouseLeft); action_dispatch=SelectToolMessage::DragStop { remove_from_selection: Alt }), entry!(KeyDown(Enter); action_dispatch=SelectToolMessage::Enter), @@ -178,7 +178,7 @@ pub fn input_mappings() -> Mapping { entry!(KeyDown(Escape); action_dispatch=ShapeToolMessage::Abort), entry!(KeyDown(BracketLeft); action_dispatch=ShapeToolMessage::DecreaseSides), entry!(KeyDown(BracketRight); action_dispatch=ShapeToolMessage::IncreaseSides), - entry!(PointerMove; refresh_keys=[Alt, Shift, Control], action_dispatch=ShapeToolMessage::PointerMove([Alt, Shift, Control])), + entry!(PointerMove; refresh_keys=[Alt, Shift, Control], action_dispatch=ShapeToolMessage::PointerMove { modifier: [Alt, Shift, Control] }), entry!(KeyDown(ArrowUp); modifiers=[Shift, ArrowLeft], action_dispatch=ShapeToolMessage::NudgeSelectedLayers { delta_x: -BIG_NUDGE_AMOUNT, delta_y: -BIG_NUDGE_AMOUNT, resize: Alt, resize_opposite_corner: Control }), entry!(KeyDown(ArrowUp); modifiers=[Shift, ArrowRight], action_dispatch=ShapeToolMessage::NudgeSelectedLayers { delta_x: BIG_NUDGE_AMOUNT, delta_y: -BIG_NUDGE_AMOUNT, resize: Alt, resize_opposite_corner: Control }), entry!(KeyDown(ArrowUp); modifiers=[Shift], action_dispatch=ShapeToolMessage::NudgeSelectedLayers { delta_x: 0., delta_y: -BIG_NUDGE_AMOUNT, resize: Alt, resize_opposite_corner: Control }), @@ -297,8 +297,8 @@ pub fn input_mappings() -> Mapping { entry!(PointerMove; action_dispatch=BrushToolMessage::PointerMove), entry!(KeyDown(MouseLeft); action_dispatch=BrushToolMessage::DragStart), entry!(KeyUp(MouseLeft); action_dispatch=BrushToolMessage::DragStop), - entry!(KeyDown(BracketLeft); action_dispatch=BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::ChangeDiameter(-BRUSH_SIZE_CHANGE_KEYBOARD))), - entry!(KeyDown(BracketRight); action_dispatch=BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::ChangeDiameter(BRUSH_SIZE_CHANGE_KEYBOARD))), + entry!(KeyDown(BracketLeft); action_dispatch=BrushToolMessage::UpdateOptions { options: BrushToolMessageOptionsUpdate::ChangeDiameter(-BRUSH_SIZE_CHANGE_KEYBOARD) }), + entry!(KeyDown(BracketRight); action_dispatch=BrushToolMessage::UpdateOptions { options: BrushToolMessageOptionsUpdate::ChangeDiameter(BRUSH_SIZE_CHANGE_KEYBOARD) }), entry!(KeyDown(MouseRight); action_dispatch=BrushToolMessage::Abort), entry!(KeyDown(Escape); action_dispatch=BrushToolMessage::Abort), // diff --git a/editor/src/messages/input_mapper/key_mapping/key_mapping_message.rs b/editor/src/messages/input_mapper/key_mapping/key_mapping_message.rs index 95cb5cc57..3214864da 100644 --- a/editor/src/messages/input_mapper/key_mapping/key_mapping_message.rs +++ b/editor/src/messages/input_mapper/key_mapping/key_mapping_message.rs @@ -3,13 +3,16 @@ use crate::messages::prelude::*; #[impl_message(Message, KeyMapping)] #[derive(PartialEq, Eq, Clone, Debug, Hash, serde::Serialize, serde::Deserialize)] pub enum KeyMappingMessage { + // Sub-messages #[child] Lookup(InputMapperMessage), - #[child] - ModifyMapping(MappingVariant), + + // Messages + ModifyMapping { + mapping: MappingVariant, + }, } -#[impl_message(Message, KeyMappingMessage, ModifyMapping)] #[derive(PartialEq, Eq, Clone, Debug, Default, Hash, serde::Serialize, serde::Deserialize)] pub enum MappingVariant { #[default] diff --git a/editor/src/messages/input_mapper/key_mapping/key_mapping_message_handler.rs b/editor/src/messages/input_mapper/key_mapping/key_mapping_message_handler.rs index 605f2587f..4d40a9ebb 100644 --- a/editor/src/messages/input_mapper/key_mapping/key_mapping_message_handler.rs +++ b/editor/src/messages/input_mapper/key_mapping/key_mapping_message_handler.rs @@ -19,8 +19,11 @@ impl MessageHandler> for KeyMapp let KeyMappingMessageContext { input, actions } = context; match message { + // Sub-messages KeyMappingMessage::Lookup(input_message) => self.mapping_handler.process_message(input_message, responses, InputMapperMessageContext { input, actions }), - KeyMappingMessage::ModifyMapping(new_layout) => self.mapping_handler.set_mapping(new_layout.into()), + + // Messages + KeyMappingMessage::ModifyMapping { mapping } => self.mapping_handler.set_mapping(mapping.into()), } } advertise_actions!(); diff --git a/editor/src/messages/input_mapper/key_mapping/mod.rs b/editor/src/messages/input_mapper/key_mapping/mod.rs index 064b58509..255b00cdd 100644 --- a/editor/src/messages/input_mapper/key_mapping/mod.rs +++ b/editor/src/messages/input_mapper/key_mapping/mod.rs @@ -2,6 +2,6 @@ mod key_mapping_message; mod key_mapping_message_handler; #[doc(inline)] -pub use key_mapping_message::{KeyMappingMessage, KeyMappingMessageDiscriminant, MappingVariant, MappingVariantDiscriminant}; +pub use key_mapping_message::{KeyMappingMessage, KeyMappingMessageDiscriminant, MappingVariant}; #[doc(inline)] pub use key_mapping_message_handler::{KeyMappingMessageContext, KeyMappingMessageHandler}; diff --git a/editor/src/messages/message.rs b/editor/src/messages/message.rs index b654eb884..a60ca681d 100644 --- a/editor/src/messages/message.rs +++ b/editor/src/messages/message.rs @@ -35,10 +35,10 @@ pub enum Message { Tool(ToolMessage), // Messages - NoOp, Batched { messages: Box<[Message]>, }, + NoOp, } /// Provides an impl of `specta::Type` for `MessageDiscriminant`, the struct created by `impl_message`. @@ -94,6 +94,17 @@ mod test { } } + // Print message field if any + if let Some(fields) = tree.fields() { + let len = fields.len(); + for (i, field) in fields.iter().enumerate() { + let is_last_field = i == len - 1; + let branch = if is_last_field { "└── " } else { "├── " }; + + file.write_all(format!("{}{}{}\n", child_prefix, branch, field).as_bytes()).unwrap(); + } + } + // Print handler field if any if let Some(data) = tree.message_handler_fields() { let len = data.fields().len(); @@ -102,16 +113,19 @@ mod test { } else { ("└── ", format!("{} ", prefix)) }; - if data.path().is_empty() { - file.write_all(format!("{}{}{}\n", prefix, branch, data.name()).as_bytes()).unwrap(); - } else { - file.write_all(format!("{}{}{} `{}`\n", prefix, branch, data.name(), data.path()).as_bytes()).unwrap(); - } - for (i, field) in data.fields().iter().enumerate() { - let is_last_field = i == len - 1; - let branch = if is_last_field { "└── " } else { "├── " }; - file.write_all(format!("{}{}{}\n", child_prefix, branch, field.0).as_bytes()).unwrap(); + const FRONTEND_MESSAGE_STR: &str = "FrontendMessage"; + if data.name().is_empty() && tree.name() != FRONTEND_MESSAGE_STR { + panic!("{}'s MessageHandler is missing #[message_handler_data]", tree.name()); + } else if tree.name() != FRONTEND_MESSAGE_STR { + file.write_all(format!("{}{}{} `{}`\n", prefix, branch, data.name(), data.path()).as_bytes()).unwrap(); + + for (i, field) in data.fields().iter().enumerate() { + let is_last_field = i == len - 1; + let branch = if is_last_field { "└── " } else { "├── " }; + + file.write_all(format!("{}{}{}\n", child_prefix, branch, field.0).as_bytes()).unwrap(); + } } } diff --git a/editor/src/messages/portfolio/document/document_message.rs b/editor/src/messages/portfolio/document/document_message.rs index 9a1952617..17e131f5f 100644 --- a/editor/src/messages/portfolio/document/document_message.rs +++ b/editor/src/messages/portfolio/document/document_message.rs @@ -53,7 +53,9 @@ pub enum DocumentMessage { DocumentHistoryBackward, DocumentHistoryForward, DocumentStructureChanged, - DrawArtboardOverlays(OverlayContext), + DrawArtboardOverlays { + context: OverlayContext, + }, DuplicateSelectedLayers, EnterNestedNetwork { node_id: NodeId, @@ -72,9 +74,15 @@ pub enum DocumentMessage { open: bool, }, GraphViewOverlayToggle, - GridOptions(GridSnapping), - GridOverlays(OverlayContext), - GridVisibility(bool), + GridOptions { + options: GridSnapping, + }, + GridOverlays { + context: OverlayContext, + }, + GridVisibility { + visible: bool, + }, GroupSelectedLayers { group_folder_type: GroupFolderType, }, diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index d647f5ba7..91135299a 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -391,7 +391,7 @@ impl MessageHandler> for DocumentMes responses.add(FrontendMessage::UpdateDocumentLayerStructure { data_buffer }); } } - DocumentMessage::DrawArtboardOverlays(overlay_context) => { + DocumentMessage::DrawArtboardOverlays { context: overlay_context } => { if !overlay_context.visibility_settings.artboard_name() { return; } @@ -588,19 +588,19 @@ impl MessageHandler> for DocumentMes DocumentMessage::GraphViewOverlayToggle => { responses.add(DocumentMessage::GraphViewOverlay { open: !self.graph_view_overlay_open }); } - DocumentMessage::GridOptions(grid) => { - self.snapping_state.grid = grid; + DocumentMessage::GridOptions { options } => { + self.snapping_state.grid = options; self.snapping_state.grid_snapping = true; responses.add(OverlaysMessage::Draw); responses.add(PortfolioMessage::UpdateDocumentWidgets); } - DocumentMessage::GridOverlays(mut overlay_context) => { + DocumentMessage::GridOverlays { context: mut overlay_context } => { if self.snapping_state.grid_snapping { grid_overlay(self, &mut overlay_context) } } - DocumentMessage::GridVisibility(enabled) => { - self.snapping_state.grid_snapping = enabled; + DocumentMessage::GridVisibility { visible } => { + self.snapping_state.grid_snapping = visible; responses.add(OverlaysMessage::Draw); } DocumentMessage::GroupSelectedLayers { group_folder_type } => { @@ -1062,7 +1062,7 @@ impl MessageHandler> for DocumentMes if !parent_layers.is_empty() { let nodes = parent_layers.into_iter().collect(); responses.add(NodeGraphMessage::SelectedNodesSet { nodes }); - responses.add(BroadcastEvent::SelectionChanged); + responses.add(EventMessage::SelectionChanged); } } DocumentMessage::SelectAllLayers => { @@ -1137,7 +1137,7 @@ impl MessageHandler> for DocumentMes } else { responses.add_front(NodeGraphMessage::SelectedNodesAdd { nodes: vec![id] }); } - responses.add(BroadcastEvent::SelectionChanged); + responses.add(EventMessage::SelectionChanged); } else { nodes.push(id); } @@ -1206,7 +1206,7 @@ impl MessageHandler> for DocumentMes Some(overlays_type) => overlays_type, None => { visibility_settings.all = visible; - responses.add(BroadcastEvent::ToolAbort); + responses.add(EventMessage::ToolAbort); responses.add(OverlaysMessage::Draw); return; } @@ -1229,7 +1229,7 @@ impl MessageHandler> for DocumentMes OverlaysType::Handles => visibility_settings.handles = visible, } - responses.add(BroadcastEvent::ToolAbort); + responses.add(EventMessage::ToolAbort); responses.add(OverlaysMessage::Draw); } DocumentMessage::SetRangeSelectionLayer { new_layer } => { @@ -1443,12 +1443,14 @@ impl MessageHandler> for DocumentMes let transform = self.navigation_handler.calculate_offset_transform(ipp.viewport_bounds.center(), &self.document_ptz); self.network_interface.set_document_to_viewport_transform(transform); // Ensure selection box is kept in sync with the pointer when the PTZ changes - responses.add(SelectToolMessage::PointerMove(SelectToolPointerKeys { - axis_align: Key::Shift, - snap_angle: Key::Shift, - center: Key::Alt, - duplicate: Key::Alt, - })); + responses.add(SelectToolMessage::PointerMove { + modifier_keys: SelectToolPointerKeys { + axis_align: Key::Shift, + snap_angle: Key::Shift, + center: Key::Alt, + duplicate: Key::Alt, + }, + }); responses.add(NodeGraphMessage::RunDocumentGraph); } else { let Some(network_metadata) = self.network_interface.network_metadata(&self.breadcrumb_network_path) else { @@ -1477,11 +1479,11 @@ impl MessageHandler> for DocumentMes } DocumentMessage::SelectionStepBack => { self.network_interface.selection_step_back(&self.selection_network_path); - responses.add(BroadcastEvent::SelectionChanged); + responses.add(EventMessage::SelectionChanged); } DocumentMessage::SelectionStepForward => { self.network_interface.selection_step_forward(&self.selection_network_path); - responses.add(BroadcastEvent::SelectionChanged); + responses.add(EventMessage::SelectionChanged); } DocumentMessage::WrapContentInArtboard { place_artboard_at_origin } => { // Get bounding box of all layers @@ -2484,7 +2486,7 @@ impl DocumentMessageHandler { .icon("Grid") .tooltip("Grid") .tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::ToggleGridVisibility)) - .on_update(|optional_input: &CheckboxInput| DocumentMessage::GridVisibility(optional_input.checked).into()) + .on_update(|optional_input: &CheckboxInput| DocumentMessage::GridVisibility { visible: optional_input.checked }.into()) .widget_holder(), PopoverButton::new() .popover_layout(overlay_options(&self.snapping_state.grid)) diff --git a/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs b/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs index e01e1195e..259b60e99 100644 --- a/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs +++ b/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs @@ -139,7 +139,7 @@ impl MessageHandler> for Navigat let transformed_delta = document_to_viewport.inverse().transform_vector2(delta); ptz.pan += transformed_delta; - responses.add(BroadcastEvent::CanvasTransformed); + responses.add(EventMessage::CanvasTransformed); responses.add(DocumentMessage::PTZUpdate); } NavigationMessage::CanvasPanAbortPrepare { x_not_y_axis } => { @@ -286,7 +286,7 @@ impl MessageHandler> for Navigat ptz.flip = !ptz.flip; responses.add(DocumentMessage::PTZUpdate); - responses.add(BroadcastEvent::CanvasTransformed); + responses.add(EventMessage::CanvasTransformed); responses.add(MenuBarMessage::SendLayout); responses.add(PortfolioMessage::UpdateDocumentWidgets); } @@ -325,7 +325,7 @@ impl MessageHandler> for Navigat self.navigation_operation = NavigationOperation::None; // Send the final messages to close out the operation - responses.add(BroadcastEvent::CanvasTransformed); + responses.add(EventMessage::CanvasTransformed); responses.add(ToolMessage::UpdateCursor); responses.add(ToolMessage::UpdateHints); responses.add(NavigateToolMessage::End); diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs index 40e39a558..6f1898336 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs @@ -129,7 +129,7 @@ impl<'a> MessageHandler> for NodeG NodeGraphMessage::AddPathNode => { if let Some(layer) = make_path_editable_is_allowed(network_interface, network_interface.document_metadata()) { responses.add(NodeGraphMessage::CreateNodeInLayerWithTransaction { node_type: "Path".to_string(), layer }); - responses.add(BroadcastEvent::SelectionChanged); + responses.add(EventMessage::SelectionChanged); } } NodeGraphMessage::AddImport => { @@ -142,7 +142,7 @@ impl<'a> MessageHandler> for NodeG } NodeGraphMessage::Init => { responses.add(BroadcastMessage::SubscribeEvent { - on: BroadcastEvent::SelectionChanged, + on: EventMessage::SelectionChanged, send: Box::new(NodeGraphMessage::SelectedNodesUpdated.into()), }); network_interface.load_structure(); @@ -1472,7 +1472,7 @@ impl<'a> MessageHandler> for NodeG return; }; selected_nodes.add_selected_nodes(nodes); - responses.add(BroadcastEvent::SelectionChanged); + responses.add(EventMessage::SelectionChanged); } NodeGraphMessage::SelectedNodesRemove { nodes } => { let Some(selected_nodes) = network_interface.selected_nodes_mut(selection_network_path) else { @@ -1480,7 +1480,7 @@ impl<'a> MessageHandler> for NodeG return; }; selected_nodes.retain_selected_nodes(|node| !nodes.contains(node)); - responses.add(BroadcastEvent::SelectionChanged); + responses.add(EventMessage::SelectionChanged); } NodeGraphMessage::SelectedNodesSet { nodes } => { let Some(selected_nodes) = network_interface.selected_nodes_mut(selection_network_path) else { @@ -1488,7 +1488,7 @@ impl<'a> MessageHandler> for NodeG return; }; selected_nodes.set_selected_nodes(nodes); - responses.add(BroadcastEvent::SelectionChanged); + responses.add(EventMessage::SelectionChanged); } NodeGraphMessage::SendClickTargets => responses.add(FrontendMessage::UpdateClickTargets { click_targets: Some(network_interface.collect_frontend_click_targets(breadcrumb_network_path)), @@ -1888,7 +1888,7 @@ impl<'a> MessageHandler> for NodeG return; }; selected_nodes.clear_selected_nodes(); - responses.add(BroadcastEvent::SelectionChanged); + responses.add(EventMessage::SelectionChanged); responses.add(NodeGraphMessage::SendGraph); } diff --git a/editor/src/messages/portfolio/document/overlays/grid_overlays.rs b/editor/src/messages/portfolio/document/overlays/grid_overlays.rs index 97cf2fdf7..9155e7bce 100644 --- a/editor/src/messages/portfolio/document/overlays/grid_overlays.rs +++ b/editor/src/messages/portfolio/document/overlays/grid_overlays.rs @@ -200,7 +200,7 @@ pub fn overlay_options(grid: &GridSnapping) -> Vec { move |input: &I| { let mut grid = grid.clone(); update(&mut grid, input); - DocumentMessage::GridOptions(grid).into() + DocumentMessage::GridOptions { options: grid }.into() } } let update_origin = |grid, update: fn(&mut GridSnapping) -> Option<&mut f64>| { diff --git a/editor/src/messages/portfolio/document/overlays/overlays_message.rs b/editor/src/messages/portfolio/document/overlays/overlays_message.rs index 5ab1e7773..8610e2505 100644 --- a/editor/src/messages/portfolio/document/overlays/overlays_message.rs +++ b/editor/src/messages/portfolio/document/overlays/overlays_message.rs @@ -7,14 +7,14 @@ use crate::messages::prelude::*; pub enum OverlaysMessage { Draw, // Serde functionality isn't used but is required by the message system macros - AddProvider( + AddProvider { #[serde(skip, default = "empty_provider")] #[derivative(Debug = "ignore", PartialEq = "ignore")] - OverlayProvider, - ), - RemoveProvider( + provider: OverlayProvider, + }, + RemoveProvider { #[serde(skip, default = "empty_provider")] #[derivative(Debug = "ignore", PartialEq = "ignore")] - OverlayProvider, - ), + provider: OverlayProvider, + }, } diff --git a/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs b/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs index e5896f350..e6da0a9bc 100644 --- a/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs +++ b/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs @@ -56,12 +56,14 @@ impl MessageHandler> for OverlaysMes let _ = canvas_context.reset_transform(); if visibility_settings.all() { - responses.add(DocumentMessage::GridOverlays(OverlayContext { - render_context: canvas_context.clone(), - size: size.as_dvec2(), - device_pixel_ratio, - visibility_settings: visibility_settings.clone(), - })); + responses.add(DocumentMessage::GridOverlays { + context: OverlayContext { + render_context: canvas_context.clone(), + size: size.as_dvec2(), + device_pixel_ratio, + visibility_settings: visibility_settings.clone(), + }, + }); for provider in &self.overlay_providers { responses.add(provider(OverlayContext { render_context: canvas_context.clone(), @@ -81,22 +83,22 @@ impl MessageHandler> for OverlaysMes let overlay_context = OverlayContext::new(size, device_pixel_ratio, visibility_settings); if visibility_settings.all() { - responses.add(DocumentMessage::GridOverlays(overlay_context.clone())); + responses.add(DocumentMessage::GridOverlays { context: overlay_context.clone() }); for provider in &self.overlay_providers { responses.add(provider(overlay_context.clone())); } } - responses.add(FrontendMessage::RenderOverlays(overlay_context)); + responses.add(FrontendMessage::RenderOverlays { context: overlay_context }); } #[cfg(all(not(target_family = "wasm"), test))] OverlaysMessage::Draw => { let _ = (responses, visibility_settings, ipp, device_pixel_ratio); } - OverlaysMessage::AddProvider(message) => { + OverlaysMessage::AddProvider { provider: message } => { self.overlay_providers.insert(message); } - OverlaysMessage::RemoveProvider(message) => { + OverlaysMessage::RemoveProvider { provider: message } => { self.overlay_providers.remove(&message); } } diff --git a/editor/src/messages/portfolio/portfolio_message_handler.rs b/editor/src/messages/portfolio/portfolio_message_handler.rs index 94c4371c0..b299f64bc 100644 --- a/editor/src/messages/portfolio/portfolio_message_handler.rs +++ b/editor/src/messages/portfolio/portfolio_message_handler.rs @@ -204,7 +204,7 @@ impl MessageHandler> for Portfolio } PortfolioMessage::CloseAllDocuments => { if self.active_document_id.is_some() { - responses.add(BroadcastEvent::ToolAbort); + responses.add(EventMessage::ToolAbort); responses.add(ToolMessage::DeactivateTools); // Clear relevant UI layouts if there are no documents @@ -250,7 +250,7 @@ impl MessageHandler> for Portfolio PortfolioMessage::CloseDocumentWithConfirmation { document_id } => { let target_document = self.documents.get(&document_id).unwrap(); if target_document.is_saved() { - responses.add(BroadcastEvent::ToolAbort); + responses.add(EventMessage::ToolAbort); responses.add(PortfolioMessage::CloseDocument { document_id }); } else { let dialog = simple_dialogs::CloseDocumentDialog { @@ -395,7 +395,7 @@ impl MessageHandler> for Portfolio let document_id = DocumentId(generate_uuid()); if self.active_document().is_some() { - new_responses.add(BroadcastEvent::ToolAbort); + new_responses.add(EventMessage::ToolAbort); new_responses.add(NavigationMessage::CanvasPan { delta: (0., 0.).into() }); } @@ -874,8 +874,8 @@ impl MessageHandler> for Portfolio responses.add(ToolMessage::InitTools); responses.add(NodeGraphMessage::Init); responses.add(OverlaysMessage::Draw); - responses.add(BroadcastEvent::ToolAbort); - responses.add(BroadcastEvent::SelectionChanged); + responses.add(EventMessage::ToolAbort); + responses.add(EventMessage::SelectionChanged); responses.add(NavigationMessage::CanvasPan { delta: (0., 0.).into() }); responses.add(NodeGraphMessage::RunDocumentGraph); responses.add(DocumentMessage::GraphViewOverlay { open: node_graph_open }); @@ -1132,7 +1132,7 @@ impl PortfolioMessageHandler { self.documents.insert(document_id, new_document); if self.active_document().is_some() { - responses.add(BroadcastEvent::ToolAbort); + responses.add(EventMessage::ToolAbort); responses.add(ToolMessage::DeactivateTools); } else { // Load the default font upon creating the first document diff --git a/editor/src/messages/preferences/preferences_message_handler.rs b/editor/src/messages/preferences/preferences_message_handler.rs index a79ad379b..214903b9b 100644 --- a/editor/src/messages/preferences/preferences_message_handler.rs +++ b/editor/src/messages/preferences/preferences_message_handler.rs @@ -62,7 +62,7 @@ impl MessageHandler for PreferencesMessageHandler { } PreferencesMessage::ResetToDefaults => { refresh_dialog(responses); - responses.add(KeyMappingMessage::ModifyMapping(MappingVariant::Default)); + responses.add(KeyMappingMessage::ModifyMapping { mapping: MappingVariant::Default }); *self = Self::default() } @@ -80,7 +80,7 @@ impl MessageHandler for PreferencesMessageHandler { self.zoom_with_scroll = zoom_with_scroll; let variant = if zoom_with_scroll { MappingVariant::ZoomWithScroll } else { MappingVariant::Default }; - responses.add(KeyMappingMessage::ModifyMapping(variant)); + responses.add(KeyMappingMessage::ModifyMapping { mapping: variant }); } PreferencesMessage::SelectionMode { selection_mode } => { self.selection_mode = selection_mode; diff --git a/editor/src/messages/prelude.rs b/editor/src/messages/prelude.rs index 8df632f91..7a696f9ed 100644 --- a/editor/src/messages/prelude.rs +++ b/editor/src/messages/prelude.rs @@ -1,9 +1,11 @@ -// Root -pub use crate::utility_traits::{ActionList, AsMessage, HierarchicalTree, MessageHandler, ToDiscriminant, TransitiveChild}; +// Message-related +pub use crate::utility_traits::{ActionList, AsMessage, ExtractField, HierarchicalTree, MessageHandler, ToDiscriminant, TransitiveChild}; pub use crate::utility_types::{DebugMessageTree, MessageData}; + // Message, MessageData, MessageDiscriminant, MessageHandler pub use crate::messages::animation::{AnimationMessage, AnimationMessageDiscriminant, AnimationMessageHandler}; pub use crate::messages::app_window::{AppWindowMessage, AppWindowMessageDiscriminant, AppWindowMessageHandler}; +pub use crate::messages::broadcast::event::{EventMessage, EventMessageContext, EventMessageDiscriminant, EventMessageHandler}; pub use crate::messages::broadcast::{BroadcastMessage, BroadcastMessageDiscriminant, BroadcastMessageHandler}; pub use crate::messages::debug::{DebugMessage, DebugMessageDiscriminant, DebugMessageHandler}; pub use crate::messages::defer::{DeferMessage, DeferMessageDiscriminant, DeferMessageHandler}; @@ -31,7 +33,6 @@ pub use crate::messages::tool::transform_layer::{TransformLayerMessage, Transfor pub use crate::messages::tool::{ToolMessage, ToolMessageContext, ToolMessageDiscriminant, ToolMessageHandler}; // Message, MessageDiscriminant -pub use crate::messages::broadcast::broadcast_event::{BroadcastEvent, BroadcastEventDiscriminant}; pub use crate::messages::message::{Message, MessageDiscriminant}; pub use crate::messages::tool::tool_messages::artboard_tool::{ArtboardToolMessage, ArtboardToolMessageDiscriminant}; pub use crate::messages::tool::tool_messages::brush_tool::{BrushToolMessage, BrushToolMessageDiscriminant}; @@ -47,7 +48,7 @@ pub use crate::messages::tool::tool_messages::shape_tool::{ShapeToolMessage, Sha pub use crate::messages::tool::tool_messages::spline_tool::{SplineToolMessage, SplineToolMessageDiscriminant}; pub use crate::messages::tool::tool_messages::text_tool::{TextToolMessage, TextToolMessageDiscriminant}; -// Helper +// Helper/miscellaneous pub use crate::messages::globals::global_variables::*; pub use crate::messages::portfolio::document::utility_types::misc::DocumentId; pub use graphite_proc_macros::*; diff --git a/editor/src/messages/tool/common_functionality/auto_panning.rs b/editor/src/messages/tool/common_functionality/auto_panning.rs index a13f6706e..0ba5346c8 100644 --- a/editor/src/messages/tool/common_functionality/auto_panning.rs +++ b/editor/src/messages/tool/common_functionality/auto_panning.rs @@ -14,7 +14,7 @@ impl AutoPanning { for message in messages { responses.add(BroadcastMessage::SubscribeEvent { - on: BroadcastEvent::AnimationFrame, + on: EventMessage::AnimationFrame, send: Box::new(message.clone()), }); } @@ -27,8 +27,8 @@ impl AutoPanning { for message in messages { responses.add(BroadcastMessage::UnsubscribeEvent { - on: BroadcastEvent::AnimationFrame, - message: Box::new(message.clone()), + on: EventMessage::AnimationFrame, + send: Box::new(message.clone()), }); } } diff --git a/editor/src/messages/tool/common_functionality/pivot.rs b/editor/src/messages/tool/common_functionality/pivot.rs index 1950b7a5b..cd6ad63bb 100644 --- a/editor/src/messages/tool/common_functionality/pivot.rs +++ b/editor/src/messages/tool/common_functionality/pivot.rs @@ -17,8 +17,14 @@ pub fn pin_pivot_widget(active: bool, enabled: bool, source: PivotToolSource) -> .tooltip(String::from(if active { "Unpin Custom Pivot" } else { "Pin Custom Pivot" }) + "\n\nUnless pinned, the pivot will return to its prior reference point when a new selection is made.") .disabled(!enabled) .on_update(move |_| match source { - PivotToolSource::Select => SelectToolMessage::SelectOptions(SelectOptionsUpdate::TogglePivotPinned).into(), - PivotToolSource::Path => PathToolMessage::UpdateOptions(PathOptionsUpdate::TogglePivotPinned).into(), + PivotToolSource::Select => SelectToolMessage::SelectOptions { + options: SelectOptionsUpdate::TogglePivotPinned, + } + .into(), + PivotToolSource::Path => PathToolMessage::UpdateOptions { + options: PathOptionsUpdate::TogglePivotPinned, + } + .into(), }) .widget_holder() } @@ -41,8 +47,14 @@ pub fn pivot_gizmo_type_widget(state: PivotGizmoState, source: PivotToolSource) MenuListEntry::new(format!("{gizmo_type:?}")).label(gizmo_type.to_string()).on_commit({ let value = source.clone(); move |_| match value { - PivotToolSource::Select => SelectToolMessage::SelectOptions(SelectOptionsUpdate::PivotGizmoType(*gizmo_type)).into(), - PivotToolSource::Path => PathToolMessage::UpdateOptions(PathOptionsUpdate::PivotGizmoType(*gizmo_type)).into(), + PivotToolSource::Select => SelectToolMessage::SelectOptions { + options: SelectOptionsUpdate::PivotGizmoType(*gizmo_type), + } + .into(), + PivotToolSource::Path => PathToolMessage::UpdateOptions { + options: PathOptionsUpdate::PivotGizmoType(*gizmo_type), + } + .into(), } }) }) @@ -57,8 +69,14 @@ pub fn pivot_gizmo_type_widget(state: PivotGizmoState, source: PivotToolSource) Disabled: rotation and scaling occurs about the center of the selection bounds.", ) .on_update(move |optional_input: &CheckboxInput| match source { - PivotToolSource::Select => SelectToolMessage::SelectOptions(SelectOptionsUpdate::TogglePivotGizmoType(optional_input.checked)).into(), - PivotToolSource::Path => PathToolMessage::UpdateOptions(PathOptionsUpdate::TogglePivotGizmoType(optional_input.checked)).into(), + PivotToolSource::Select => SelectToolMessage::SelectOptions { + options: SelectOptionsUpdate::TogglePivotGizmoType(optional_input.checked), + } + .into(), + PivotToolSource::Path => PathToolMessage::UpdateOptions { + options: PathOptionsUpdate::TogglePivotGizmoType(optional_input.checked), + } + .into(), }) .widget_holder(), Separator::new(SeparatorType::Related).widget_holder(), diff --git a/editor/src/messages/tool/tool_message_handler.rs b/editor/src/messages/tool/tool_message_handler.rs index 937ded595..c3dc27846 100644 --- a/editor/src/messages/tool/tool_message_handler.rs +++ b/editor/src/messages/tool/tool_message_handler.rs @@ -11,7 +11,7 @@ use crate::messages::tool::utility_types::ToolType; use crate::node_graph_executor::NodeGraphExecutor; use graphene_std::raster::color::Color; -const ARTBOARD_OVERLAY_PROVIDER: OverlayProvider = |overlay_context| DocumentMessage::DrawArtboardOverlays(overlay_context).into(); +const ARTBOARD_OVERLAY_PROVIDER: OverlayProvider = |context| DocumentMessage::DrawArtboardOverlays { context }.into(); #[derive(ExtractField)] pub struct ToolMessageContext<'a> { @@ -75,8 +75,8 @@ impl MessageHandler> for ToolMessageHandler self.tool_state.tool_data.active_tool_type = ToolType::Shape; } responses.add_front(ToolMessage::ActivateTool { tool_type: ToolType::Shape }); - responses.add(ShapeToolMessage::SetShape(ShapeType::Polygon)); - responses.add(ShapeToolMessage::HideShapeTypeWidget(false)) + responses.add(ShapeToolMessage::SetShape { shape: ShapeType::Polygon }); + responses.add(ShapeToolMessage::HideShapeTypeWidget { hide: false }) } ToolMessage::ActivateToolBrush => responses.add_front(ToolMessage::ActivateTool { tool_type: ToolType::Brush }), ToolMessage::ActivateToolShapeLine | ToolMessage::ActivateToolShapeRectangle | ToolMessage::ActivateToolShapeEllipse => { @@ -89,8 +89,8 @@ impl MessageHandler> for ToolMessageHandler self.tool_state.tool_data.active_shape_type = Some(shape.tool_type()); responses.add_front(ToolMessage::ActivateTool { tool_type: ToolType::Shape }); - responses.add(ShapeToolMessage::HideShapeTypeWidget(true)); - responses.add(ShapeToolMessage::SetShape(shape)); + responses.add(ShapeToolMessage::HideShapeTypeWidget { hide: true }); + responses.add(ShapeToolMessage::SetShape { shape }); } ToolMessage::ActivateTool { tool_type } => { let tool_data = &mut self.tool_state.tool_data; @@ -157,13 +157,13 @@ impl MessageHandler> for ToolMessageHandler tool_data.tools.get(&tool_type).unwrap().activate(responses); // Re-add the artboard overlay provider when tools are reactivated - responses.add(OverlaysMessage::AddProvider(ARTBOARD_OVERLAY_PROVIDER)); + responses.add(OverlaysMessage::AddProvider { provider: ARTBOARD_OVERLAY_PROVIDER }); // Send the SelectionChanged message to the active tool, this will ensure the selection is updated - responses.add(BroadcastEvent::SelectionChanged); + responses.add(EventMessage::SelectionChanged); // Update the working colors for the active tool - responses.add(BroadcastEvent::WorkingColorChanged); + responses.add(EventMessage::WorkingColorChanged); // Send tool options to the frontend responses.add(ToolMessage::RefreshToolOptions); @@ -176,11 +176,12 @@ impl MessageHandler> for ToolMessageHandler tool_data.tools.get(&tool_data.active_tool_type).unwrap().deactivate(responses); // Unsubscribe the transform layer to selection change events - let message = Box::new(TransformLayerMessage::SelectionChanged.into()); - let on = BroadcastEvent::SelectionChanged; - responses.add(BroadcastMessage::UnsubscribeEvent { message, on }); + responses.add(BroadcastMessage::UnsubscribeEvent { + on: EventMessage::SelectionChanged, + send: Box::new(TransformLayerMessage::SelectionChanged.into()), + }); - responses.add(OverlaysMessage::RemoveProvider(ARTBOARD_OVERLAY_PROVIDER)); + responses.add(OverlaysMessage::RemoveProvider { provider: ARTBOARD_OVERLAY_PROVIDER }); responses.add(FrontendMessage::UpdateInputHints { hint_data: Default::default() }); responses.add(FrontendMessage::UpdateMouseCursor { cursor: Default::default() }); @@ -190,12 +191,12 @@ impl MessageHandler> for ToolMessageHandler ToolMessage::InitTools => { // Subscribe the transform layer to selection change events responses.add(BroadcastMessage::SubscribeEvent { - on: BroadcastEvent::SelectionChanged, + on: EventMessage::SelectionChanged, send: Box::new(TransformLayerMessage::SelectionChanged.into()), }); responses.add(BroadcastMessage::SubscribeEvent { - on: BroadcastEvent::SelectionChanged, + on: EventMessage::SelectionChanged, send: Box::new(SelectToolMessage::SyncHistory.into()), }); @@ -232,12 +233,12 @@ impl MessageHandler> for ToolMessageHandler tool_data.active_tool_mut().process_message(ToolMessage::UpdateHints, responses, &mut data); tool_data.active_tool_mut().process_message(ToolMessage::UpdateCursor, responses, &mut data); - responses.add(OverlaysMessage::AddProvider(ARTBOARD_OVERLAY_PROVIDER)); + responses.add(OverlaysMessage::AddProvider { provider: ARTBOARD_OVERLAY_PROVIDER }); } ToolMessage::PreUndo => { let tool_data = &mut self.tool_state.tool_data; if tool_data.active_tool_type != ToolType::Pen { - responses.add(BroadcastEvent::ToolAbort); + responses.add(EventMessage::ToolAbort); } } ToolMessage::Redo => { diff --git a/editor/src/messages/tool/tool_messages/artboard_tool.rs b/editor/src/messages/tool/tool_messages/artboard_tool.rs index aafc86923..63404b458 100644 --- a/editor/src/messages/tool/tool_messages/artboard_tool.rs +++ b/editor/src/messages/tool/tool_messages/artboard_tool.rs @@ -26,7 +26,7 @@ pub struct ArtboardTool { pub enum ArtboardToolMessage { // Standard messages Abort, - Overlays(OverlayContext), + Overlays { context: OverlayContext }, // Tool-specific messages UpdateSelectedArtboard, @@ -83,7 +83,7 @@ impl ToolTransition for ArtboardTool { fn event_to_message_map(&self) -> EventToMessageMap { EventToMessageMap { tool_abort: Some(ArtboardToolMessage::Abort.into()), - overlay_provider: Some(|overlay_context| ArtboardToolMessage::Overlays(overlay_context).into()), + overlay_provider: Some(|context| ArtboardToolMessage::Overlays { context }.into()), ..Default::default() } } @@ -227,7 +227,7 @@ impl Fsm for ArtboardToolFsmState { let ToolMessage::Artboard(event) = event else { return self }; match (self, event) { - (state, ArtboardToolMessage::Overlays(mut overlay_context)) => { + (state, ArtboardToolMessage::Overlays { context: mut overlay_context }) => { let display_transform_cage = overlay_context.visibility_settings.transform_cage(); if display_transform_cage && state != ArtboardToolFsmState::Drawing { if let Some(bounds) = tool_data.selected_artboard.and_then(|layer| document.metadata().bounding_box_document(layer)) { diff --git a/editor/src/messages/tool/tool_messages/brush_tool.rs b/editor/src/messages/tool/tool_messages/brush_tool.rs index 4fba66f7c..650031acc 100644 --- a/editor/src/messages/tool/tool_messages/brush_tool.rs +++ b/editor/src/messages/tool/tool_messages/brush_tool.rs @@ -62,7 +62,7 @@ pub enum BrushToolMessage { DragStart, DragStop, PointerMove, - UpdateOptions(BrushToolMessageOptionsUpdate), + UpdateOptions { options: BrushToolMessageOptionsUpdate }, } #[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize, specta::Type)] @@ -106,7 +106,7 @@ impl LayoutHolder for BrushTool { .min(1.) .max(BRUSH_MAX_SIZE) /* Anything bigger would cause the application to be unresponsive and eventually die */ .unit(" px") - .on_update(|number_input: &NumberInput| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::Diameter(number_input.value.unwrap())).into()) + .on_update(|number_input: &NumberInput| BrushToolMessage::UpdateOptions { options: BrushToolMessageOptionsUpdate::Diameter(number_input.value.unwrap()) }.into()) .widget_holder(), Separator::new(SeparatorType::Related).widget_holder(), NumberInput::new(Some(self.options.hardness)) @@ -115,7 +115,12 @@ impl LayoutHolder for BrushTool { .max(100.) .mode_range() .unit("%") - .on_update(|number_input: &NumberInput| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::Hardness(number_input.value.unwrap())).into()) + .on_update(|number_input: &NumberInput| { + BrushToolMessage::UpdateOptions { + options: BrushToolMessageOptionsUpdate::Hardness(number_input.value.unwrap()), + } + .into() + }) .widget_holder(), Separator::new(SeparatorType::Related).widget_holder(), NumberInput::new(Some(self.options.flow)) @@ -124,7 +129,12 @@ impl LayoutHolder for BrushTool { .max(100.) .mode_range() .unit("%") - .on_update(|number_input: &NumberInput| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::Flow(number_input.value.unwrap())).into()) + .on_update(|number_input: &NumberInput| { + BrushToolMessage::UpdateOptions { + options: BrushToolMessageOptionsUpdate::Flow(number_input.value.unwrap()), + } + .into() + }) .widget_holder(), Separator::new(SeparatorType::Related).widget_holder(), NumberInput::new(Some(self.options.spacing)) @@ -133,7 +143,12 @@ impl LayoutHolder for BrushTool { .max(100.) .mode_range() .unit("%") - .on_update(|number_input: &NumberInput| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::Spacing(number_input.value.unwrap())).into()) + .on_update(|number_input: &NumberInput| { + BrushToolMessage::UpdateOptions { + options: BrushToolMessageOptionsUpdate::Spacing(number_input.value.unwrap()), + } + .into() + }) .widget_holder(), ]; @@ -142,9 +157,12 @@ impl LayoutHolder for BrushTool { let draw_mode_entries: Vec<_> = [DrawMode::Draw, DrawMode::Erase, DrawMode::Restore] .into_iter() .map(|draw_mode| { - RadioEntryData::new(format!("{draw_mode:?}")) - .label(format!("{draw_mode:?}")) - .on_update(move |_| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::DrawMode(draw_mode)).into()) + RadioEntryData::new(format!("{draw_mode:?}")).label(format!("{draw_mode:?}")).on_update(move |_| { + BrushToolMessage::UpdateOptions { + options: BrushToolMessageOptionsUpdate::DrawMode(draw_mode), + } + .into() + }) }) .collect(); widgets.push(RadioInput::new(draw_mode_entries).selected_index(Some(self.options.draw_mode as u32)).widget_holder()); @@ -154,9 +172,26 @@ impl LayoutHolder for BrushTool { widgets.append(&mut self.options.color.create_widgets( "Color", false, - |_| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::Color(None)).into(), - |color_type: ToolColorType| WidgetCallback::new(move |_| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::ColorType(color_type.clone())).into()), - |color: &ColorInput| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::Color(color.value.as_solid().map(|color| color.to_linear_srgb()))).into(), + |_| { + BrushToolMessage::UpdateOptions { + options: BrushToolMessageOptionsUpdate::Color(None), + } + .into() + }, + |color_type: ToolColorType| { + WidgetCallback::new(move |_| { + BrushToolMessage::UpdateOptions { + options: BrushToolMessageOptionsUpdate::ColorType(color_type.clone()), + } + .into() + }) + }, + |color: &ColorInput| { + BrushToolMessage::UpdateOptions { + options: BrushToolMessageOptionsUpdate::Color(color.value.as_solid().map(|color| color.to_linear_srgb())), + } + .into() + }, )); widgets.push(Separator::new(SeparatorType::Related).widget_holder()); @@ -167,9 +202,12 @@ impl LayoutHolder for BrushTool { section .iter() .map(|blend_mode| { - MenuListEntry::new(format!("{blend_mode:?}")) - .label(blend_mode.to_string()) - .on_commit(|_| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::BlendMode(*blend_mode)).into()) + MenuListEntry::new(format!("{blend_mode:?}")).label(blend_mode.to_string()).on_commit(|_| { + BrushToolMessage::UpdateOptions { + options: BrushToolMessageOptionsUpdate::BlendMode(*blend_mode), + } + .into() + }) }) .collect() }) @@ -189,11 +227,11 @@ impl LayoutHolder for BrushTool { #[message_handler_data] impl<'a> MessageHandler> for BrushTool { fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque, context: &mut ToolActionMessageContext<'a>) { - let ToolMessage::Brush(BrushToolMessage::UpdateOptions(action)) = message else { + let ToolMessage::Brush(BrushToolMessage::UpdateOptions { options }) = message else { self.fsm_state.process_event(message, &mut self.data, context, &self.options, responses, true); return; }; - match action { + match options { BrushToolMessageOptionsUpdate::BlendMode(blend_mode) => self.options.blend_mode = blend_mode, BrushToolMessageOptionsUpdate::ChangeDiameter(change) => { let needs_rounding = ((self.options.diameter + change.abs() / 2.) % change.abs() - change.abs() / 2.).abs() > 0.5; @@ -408,10 +446,9 @@ impl Fsm for BrushToolFsmState { BrushToolFsmState::Ready } (_, BrushToolMessage::WorkingColorChanged) => { - responses.add(BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::WorkingColors( - Some(global_tool_data.primary_color), - Some(global_tool_data.secondary_color), - ))); + responses.add(BrushToolMessage::UpdateOptions { + options: BrushToolMessageOptionsUpdate::WorkingColors(Some(global_tool_data.primary_color), Some(global_tool_data.secondary_color)), + }); self } _ => self, diff --git a/editor/src/messages/tool/tool_messages/fill_tool.rs b/editor/src/messages/tool/tool_messages/fill_tool.rs index 6a9429e3e..228ab5a5f 100644 --- a/editor/src/messages/tool/tool_messages/fill_tool.rs +++ b/editor/src/messages/tool/tool_messages/fill_tool.rs @@ -14,7 +14,7 @@ pub enum FillToolMessage { // Standard messages Abort, WorkingColorChanged, - Overlays(OverlayContext), + Overlays { context: OverlayContext }, // Tool-specific messages PointerMove, @@ -67,7 +67,7 @@ impl ToolTransition for FillTool { EventToMessageMap { tool_abort: Some(FillToolMessage::Abort.into()), working_color_changed: Some(FillToolMessage::WorkingColorChanged.into()), - overlay_provider: Some(|overlay_context| FillToolMessage::Overlays(overlay_context).into()), + overlay_provider: Some(|context| FillToolMessage::Overlays { context }.into()), ..Default::default() } } @@ -99,7 +99,7 @@ impl Fsm for FillToolFsmState { let ToolMessage::Fill(event) = event else { return self }; match (self, event) { - (_, FillToolMessage::Overlays(mut overlay_context)) => { + (_, FillToolMessage::Overlays { context: mut overlay_context }) => { // Choose the working color to preview let use_secondary = input.keyboard.get(Key::Shift as usize); let preview_color = if use_secondary { global_tool_data.secondary_color } else { global_tool_data.primary_color }; diff --git a/editor/src/messages/tool/tool_messages/freehand_tool.rs b/editor/src/messages/tool/tool_messages/freehand_tool.rs index eb862b7fe..b22ca6761 100644 --- a/editor/src/messages/tool/tool_messages/freehand_tool.rs +++ b/editor/src/messages/tool/tool_messages/freehand_tool.rs @@ -40,7 +40,7 @@ impl Default for FreehandOptions { #[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize, specta::Type)] pub enum FreehandToolMessage { // Standard messages - Overlays(OverlayContext), + Overlays { context: OverlayContext }, Abort, WorkingColorChanged, @@ -48,7 +48,7 @@ pub enum FreehandToolMessage { DragStart { append_to_selected: Key }, DragStop, PointerMove, - UpdateOptions(FreehandOptionsUpdate), + UpdateOptions { options: FreehandOptionsUpdate }, } #[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize, specta::Type)] @@ -86,7 +86,12 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder { .label("Weight") .min(1.) .max((1_u64 << f64::MANTISSA_DIGITS) as f64) - .on_update(|number_input: &NumberInput| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::LineWeight(number_input.value.unwrap())).into()) + .on_update(|number_input: &NumberInput| { + FreehandToolMessage::UpdateOptions { + options: FreehandOptionsUpdate::LineWeight(number_input.value.unwrap()), + } + .into() + }) .widget_holder() } @@ -95,9 +100,26 @@ impl LayoutHolder for FreehandTool { let mut widgets = self.options.fill.create_widgets( "Fill", true, - |_| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::FillColor(None)).into(), - |color_type: ToolColorType| WidgetCallback::new(move |_| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::FillColorType(color_type.clone())).into()), - |color: &ColorInput| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::FillColor(color.value.as_solid().map(|color| color.to_linear_srgb()))).into(), + |_| { + FreehandToolMessage::UpdateOptions { + options: FreehandOptionsUpdate::FillColor(None), + } + .into() + }, + |color_type: ToolColorType| { + WidgetCallback::new(move |_| { + FreehandToolMessage::UpdateOptions { + options: FreehandOptionsUpdate::FillColorType(color_type.clone()), + } + .into() + }) + }, + |color: &ColorInput| { + FreehandToolMessage::UpdateOptions { + options: FreehandOptionsUpdate::FillColor(color.value.as_solid().map(|color| color.to_linear_srgb())), + } + .into() + }, ); widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder()); @@ -105,9 +127,26 @@ impl LayoutHolder for FreehandTool { widgets.append(&mut self.options.stroke.create_widgets( "Stroke", true, - |_| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::StrokeColor(None)).into(), - |color_type: ToolColorType| WidgetCallback::new(move |_| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::StrokeColorType(color_type.clone())).into()), - |color: &ColorInput| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::StrokeColor(color.value.as_solid().map(|color| color.to_linear_srgb()))).into(), + |_| { + FreehandToolMessage::UpdateOptions { + options: FreehandOptionsUpdate::StrokeColor(None), + } + .into() + }, + |color_type: ToolColorType| { + WidgetCallback::new(move |_| { + FreehandToolMessage::UpdateOptions { + options: FreehandOptionsUpdate::StrokeColorType(color_type.clone()), + } + .into() + }) + }, + |color: &ColorInput| { + FreehandToolMessage::UpdateOptions { + options: FreehandOptionsUpdate::StrokeColor(color.value.as_solid().map(|color| color.to_linear_srgb())), + } + .into() + }, )); widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder()); widgets.push(create_weight_widget(self.options.line_weight)); @@ -119,11 +158,11 @@ impl LayoutHolder for FreehandTool { #[message_handler_data] impl<'a> MessageHandler> for FreehandTool { fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque, context: &mut ToolActionMessageContext<'a>) { - let ToolMessage::Freehand(FreehandToolMessage::UpdateOptions(action)) = message else { + let ToolMessage::Freehand(FreehandToolMessage::UpdateOptions { options }) = message else { self.fsm_state.process_event(message, &mut self.data, context, &self.options, responses, true); return; }; - match action { + match options { FreehandOptionsUpdate::FillColor(color) => { self.options.fill.custom_color = color; self.options.fill.color_type = ToolColorType::Custom; @@ -164,7 +203,7 @@ impl<'a> MessageHandler> for Free impl ToolTransition for FreehandTool { fn event_to_message_map(&self) -> EventToMessageMap { EventToMessageMap { - overlay_provider: Some(|overlay_context: OverlayContext| FreehandToolMessage::Overlays(overlay_context).into()), + overlay_provider: Some(|context: OverlayContext| FreehandToolMessage::Overlays { context }.into()), tool_abort: Some(FreehandToolMessage::Abort.into()), working_color_changed: Some(FreehandToolMessage::WorkingColorChanged.into()), ..Default::default() @@ -203,7 +242,7 @@ impl Fsm for FreehandToolFsmState { let ToolMessage::Freehand(event) = event else { return self }; match (self, event) { - (_, FreehandToolMessage::Overlays(mut overlay_context)) => { + (_, FreehandToolMessage::Overlays { context: mut overlay_context }) => { path_endpoint_overlays(document, shape_editor, &mut overlay_context, tool_action_data.preferences); self @@ -287,10 +326,9 @@ impl Fsm for FreehandToolFsmState { FreehandToolFsmState::Ready } (_, FreehandToolMessage::WorkingColorChanged) => { - responses.add(FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::WorkingColors( - Some(global_tool_data.primary_color), - Some(global_tool_data.secondary_color), - ))); + responses.add(FreehandToolMessage::UpdateOptions { + options: FreehandOptionsUpdate::WorkingColors(Some(global_tool_data.primary_color), Some(global_tool_data.secondary_color)), + }); self } _ => self, @@ -679,7 +717,9 @@ mod test_freehand { let custom_line_weight = 5.; editor - .handle_message(ToolMessage::Freehand(FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::LineWeight(custom_line_weight)))) + .handle_message(ToolMessage::Freehand(FreehandToolMessage::UpdateOptions { + options: FreehandOptionsUpdate::LineWeight(custom_line_weight), + })) .await; let points = [DVec2::new(100., 100.), DVec2::new(200., 200.), DVec2::new(300., 100.)]; diff --git a/editor/src/messages/tool/tool_messages/gradient_tool.rs b/editor/src/messages/tool/tool_messages/gradient_tool.rs index 7ad1573cd..0b12abe62 100644 --- a/editor/src/messages/tool/tool_messages/gradient_tool.rs +++ b/editor/src/messages/tool/tool_messages/gradient_tool.rs @@ -24,7 +24,7 @@ pub struct GradientOptions { pub enum GradientToolMessage { // Standard messages Abort, - Overlays(OverlayContext), + Overlays { context: OverlayContext }, // Tool-specific messages DeleteStop, @@ -33,7 +33,7 @@ pub enum GradientToolMessage { PointerMove { constrain_axis: Key }, PointerOutsideViewport { constrain_axis: Key }, PointerUp, - UpdateOptions(GradientOptionsUpdate), + UpdateOptions { options: GradientOptionsUpdate }, } #[derive(PartialEq, Eq, Clone, Debug, Hash, serde::Serialize, serde::Deserialize, specta::Type)] @@ -56,11 +56,11 @@ impl ToolMetadata for GradientTool { #[message_handler_data] impl<'a> MessageHandler> for GradientTool { fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque, context: &mut ToolActionMessageContext<'a>) { - let ToolMessage::Gradient(GradientToolMessage::UpdateOptions(action)) = message else { + let ToolMessage::Gradient(GradientToolMessage::UpdateOptions { options }) = message else { self.fsm_state.process_event(message, &mut self.data, context, &self.options, responses, false); return; }; - match action { + match options { GradientOptionsUpdate::Type(gradient_type) => { self.options.gradient_type = gradient_type; // Update the selected gradient if it exists @@ -91,14 +91,18 @@ impl<'a> MessageHandler> for Grad impl LayoutHolder for GradientTool { fn layout(&self) -> Layout { let gradient_type = RadioInput::new(vec![ - RadioEntryData::new("Linear") - .label("Linear") - .tooltip("Linear gradient") - .on_update(move |_| GradientToolMessage::UpdateOptions(GradientOptionsUpdate::Type(GradientType::Linear)).into()), - RadioEntryData::new("Radial") - .label("Radial") - .tooltip("Radial gradient") - .on_update(move |_| GradientToolMessage::UpdateOptions(GradientOptionsUpdate::Type(GradientType::Radial)).into()), + RadioEntryData::new("Linear").label("Linear").tooltip("Linear gradient").on_update(move |_| { + GradientToolMessage::UpdateOptions { + options: GradientOptionsUpdate::Type(GradientType::Linear), + } + .into() + }), + RadioEntryData::new("Radial").label("Radial").tooltip("Radial gradient").on_update(move |_| { + GradientToolMessage::UpdateOptions { + options: GradientOptionsUpdate::Type(GradientType::Radial), + } + .into() + }), ]) .selected_index(Some((self.selected_gradient().unwrap_or(self.options.gradient_type) == GradientType::Radial) as u32)) .widget_holder(); @@ -224,7 +228,7 @@ impl ToolTransition for GradientTool { fn event_to_message_map(&self) -> EventToMessageMap { EventToMessageMap { tool_abort: Some(GradientToolMessage::Abort.into()), - overlay_provider: Some(|overlay_context| GradientToolMessage::Overlays(overlay_context).into()), + overlay_provider: Some(|context| GradientToolMessage::Overlays { context }.into()), ..Default::default() } } @@ -256,7 +260,7 @@ impl Fsm for GradientToolFsmState { let ToolMessage::Gradient(event) = event else { return self }; match (self, event) { - (_, GradientToolMessage::Overlays(mut overlay_context)) => { + (_, GradientToolMessage::Overlays { context: mut overlay_context }) => { let selected = tool_data.selected_gradient.as_ref(); for layer in document.network_interface.selected_nodes().selected_visible_layers(&document.network_interface) { diff --git a/editor/src/messages/tool/tool_messages/path_tool.rs b/editor/src/messages/tool/tool_messages/path_tool.rs index e913af50c..aad53ae4f 100644 --- a/editor/src/messages/tool/tool_messages/path_tool.rs +++ b/editor/src/messages/tool/tool_messages/path_tool.rs @@ -51,8 +51,10 @@ pub struct PathToolOptions { pub enum PathToolMessage { // Standard messages Abort, - Overlays(OverlayContext), SelectionChanged, + Overlays { + context: OverlayContext, + }, // Tool-specific messages BreakPath, @@ -123,7 +125,9 @@ pub enum PathToolMessage { position: ReferencePoint, }, SwapSelectedHandles, - UpdateOptions(PathOptionsUpdate), + UpdateOptions { + options: PathOptionsUpdate, + }, UpdateSelectedPointsStatus { overlay_context: OverlayContext, }, @@ -275,15 +279,30 @@ impl LayoutHolder for PathTool { RadioEntryData::new("all") .icon("HandleVisibilityAll") .tooltip("Show all handles regardless of selection") - .on_update(move |_| PathToolMessage::UpdateOptions(PathOptionsUpdate::OverlayModeType(PathOverlayMode::AllHandles)).into()), + .on_update(move |_| { + PathToolMessage::UpdateOptions { + options: PathOptionsUpdate::OverlayModeType(PathOverlayMode::AllHandles), + } + .into() + }), RadioEntryData::new("selected") .icon("HandleVisibilitySelected") .tooltip("Show only handles of the segments connected to selected points") - .on_update(move |_| PathToolMessage::UpdateOptions(PathOptionsUpdate::OverlayModeType(PathOverlayMode::SelectedPointHandles)).into()), + .on_update(move |_| { + PathToolMessage::UpdateOptions { + options: PathOptionsUpdate::OverlayModeType(PathOverlayMode::SelectedPointHandles), + } + .into() + }), RadioEntryData::new("frontier") .icon("HandleVisibilityFrontier") .tooltip("Show only handles at the frontiers of the segments connected to selected points") - .on_update(move |_| PathToolMessage::UpdateOptions(PathOptionsUpdate::OverlayModeType(PathOverlayMode::FrontierHandles)).into()), + .on_update(move |_| { + PathToolMessage::UpdateOptions { + options: PathOptionsUpdate::OverlayModeType(PathOverlayMode::FrontierHandles), + } + .into() + }), ]) .selected_index(Some(self.options.path_overlay_mode as u32)) .widget_holder(); @@ -345,7 +364,7 @@ impl<'a> MessageHandler> for Path let updating_point = message == ToolMessage::Path(PathToolMessage::SelectedPointUpdated); match message { - ToolMessage::Path(PathToolMessage::UpdateOptions(action)) => match action { + ToolMessage::Path(PathToolMessage::UpdateOptions { options }) => match options { PathOptionsUpdate::OverlayModeType(overlay_mode_type) => { self.options.path_overlay_mode = overlay_mode_type; responses.add(OverlaysMessage::Draw); @@ -478,7 +497,7 @@ impl ToolTransition for PathTool { EventToMessageMap { tool_abort: Some(PathToolMessage::Abort.into()), selection_changed: Some(PathToolMessage::SelectionChanged.into()), - overlay_provider: Some(|overlay_context| PathToolMessage::Overlays(overlay_context).into()), + overlay_provider: Some(|context| PathToolMessage::Overlays { context }.into()), ..Default::default() } } @@ -1557,14 +1576,22 @@ impl Fsm for PathToolFsmState { match (multiple_toggle, point_edit) { (true, true) => { - responses.add(PathToolMessage::UpdateOptions(PathOptionsUpdate::PointEditingMode { enabled: false })); + responses.add(PathToolMessage::UpdateOptions { + options: PathOptionsUpdate::PointEditingMode { enabled: false }, + }); } (true, false) => { - responses.add(PathToolMessage::UpdateOptions(PathOptionsUpdate::PointEditingMode { enabled: true })); + responses.add(PathToolMessage::UpdateOptions { + options: PathOptionsUpdate::PointEditingMode { enabled: true }, + }); } (_, _) => { - responses.add(PathToolMessage::UpdateOptions(PathOptionsUpdate::PointEditingMode { enabled: true })); - responses.add(PathToolMessage::UpdateOptions(PathOptionsUpdate::SegmentEditingMode { enabled: false })); + responses.add(PathToolMessage::UpdateOptions { + options: PathOptionsUpdate::PointEditingMode { enabled: true }, + }); + responses.add(PathToolMessage::UpdateOptions { + options: PathOptionsUpdate::SegmentEditingMode { enabled: false }, + }); // Select all of the end points of selected segments let selected_layers = shape_editor.selected_layers().cloned().collect::>(); @@ -1602,14 +1629,22 @@ impl Fsm for PathToolFsmState { match (multiple_toggle, segment_edit) { (true, true) => { - responses.add(PathToolMessage::UpdateOptions(PathOptionsUpdate::SegmentEditingMode { enabled: false })); + responses.add(PathToolMessage::UpdateOptions { + options: PathOptionsUpdate::SegmentEditingMode { enabled: false }, + }); } (true, false) => { - responses.add(PathToolMessage::UpdateOptions(PathOptionsUpdate::SegmentEditingMode { enabled: true })); + responses.add(PathToolMessage::UpdateOptions { + options: PathOptionsUpdate::SegmentEditingMode { enabled: true }, + }); } (_, _) => { - responses.add(PathToolMessage::UpdateOptions(PathOptionsUpdate::PointEditingMode { enabled: false })); - responses.add(PathToolMessage::UpdateOptions(PathOptionsUpdate::SegmentEditingMode { enabled: true })); + responses.add(PathToolMessage::UpdateOptions { + options: PathOptionsUpdate::PointEditingMode { enabled: false }, + }); + responses.add(PathToolMessage::UpdateOptions { + options: PathOptionsUpdate::SegmentEditingMode { enabled: true }, + }); // Select all the segments which have both of the ends selected let selected_layers = shape_editor.selected_layers().cloned().collect::>(); @@ -1632,7 +1667,7 @@ impl Fsm for PathToolFsmState { self } - (_, PathToolMessage::Overlays(mut overlay_context)) => { + (_, PathToolMessage::Overlays { context: mut overlay_context }) => { // Set this to show ghost line only if drag actually happened if matches!(self, Self::Dragging(_)) && tool_data.drag_start_pos.distance(input.mouse.position) > DRAG_THRESHOLD { for (outline, layer) in &tool_data.ghost_outline { diff --git a/editor/src/messages/tool/tool_messages/pen_tool.rs b/editor/src/messages/tool/tool_messages/pen_tool.rs index a1b6d332e..547f638fa 100644 --- a/editor/src/messages/tool/tool_messages/pen_tool.rs +++ b/editor/src/messages/tool/tool_messages/pen_tool.rs @@ -50,7 +50,9 @@ pub enum PenToolMessage { Abort, SelectionChanged, WorkingColorChanged, - Overlays(OverlayContext), + Overlays { + context: OverlayContext, + }, // Tool-specific messages @@ -80,7 +82,9 @@ pub enum PenToolMessage { }, Redo, Undo, - UpdateOptions(PenOptionsUpdate), + UpdateOptions { + options: PenOptionsUpdate, + }, RecalculateLatestPointsPosition, RemovePreviousHandle, GRS { @@ -138,7 +142,12 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder { .label("Weight") .min(0.) .max((1_u64 << f64::MANTISSA_DIGITS) as f64) - .on_update(|number_input: &NumberInput| PenToolMessage::UpdateOptions(PenOptionsUpdate::LineWeight(number_input.value.unwrap())).into()) + .on_update(|number_input: &NumberInput| { + PenToolMessage::UpdateOptions { + options: PenOptionsUpdate::LineWeight(number_input.value.unwrap()), + } + .into() + }) .widget_holder() } @@ -147,9 +156,26 @@ impl LayoutHolder for PenTool { let mut widgets = self.options.fill.create_widgets( "Fill", true, - |_| PenToolMessage::UpdateOptions(PenOptionsUpdate::FillColor(None)).into(), - |color_type: ToolColorType| WidgetCallback::new(move |_| PenToolMessage::UpdateOptions(PenOptionsUpdate::FillColorType(color_type.clone())).into()), - |color: &ColorInput| PenToolMessage::UpdateOptions(PenOptionsUpdate::FillColor(color.value.as_solid().map(|color| color.to_linear_srgb()))).into(), + |_| { + PenToolMessage::UpdateOptions { + options: PenOptionsUpdate::FillColor(None), + } + .into() + }, + |color_type: ToolColorType| { + WidgetCallback::new(move |_| { + PenToolMessage::UpdateOptions { + options: PenOptionsUpdate::FillColorType(color_type.clone()), + } + .into() + }) + }, + |color: &ColorInput| { + PenToolMessage::UpdateOptions { + options: PenOptionsUpdate::FillColor(color.value.as_solid().map(|color| color.to_linear_srgb())), + } + .into() + }, ); widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder()); @@ -157,9 +183,26 @@ impl LayoutHolder for PenTool { widgets.append(&mut self.options.stroke.create_widgets( "Stroke", true, - |_| PenToolMessage::UpdateOptions(PenOptionsUpdate::StrokeColor(None)).into(), - |color_type: ToolColorType| WidgetCallback::new(move |_| PenToolMessage::UpdateOptions(PenOptionsUpdate::StrokeColorType(color_type.clone())).into()), - |color: &ColorInput| PenToolMessage::UpdateOptions(PenOptionsUpdate::StrokeColor(color.value.as_solid().map(|color| color.to_linear_srgb()))).into(), + |_| { + PenToolMessage::UpdateOptions { + options: PenOptionsUpdate::StrokeColor(None), + } + .into() + }, + |color_type: ToolColorType| { + WidgetCallback::new(move |_| { + PenToolMessage::UpdateOptions { + options: PenOptionsUpdate::StrokeColorType(color_type.clone()), + } + .into() + }) + }, + |color: &ColorInput| { + PenToolMessage::UpdateOptions { + options: PenOptionsUpdate::StrokeColor(color.value.as_solid().map(|color| color.to_linear_srgb())), + } + .into() + }, )); widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder()); @@ -173,11 +216,21 @@ impl LayoutHolder for PenTool { RadioEntryData::new("all") .icon("HandleVisibilityAll") .tooltip("Show all handles regardless of selection") - .on_update(move |_| PenToolMessage::UpdateOptions(PenOptionsUpdate::OverlayModeType(PenOverlayMode::AllHandles)).into()), + .on_update(move |_| { + PenToolMessage::UpdateOptions { + options: PenOptionsUpdate::OverlayModeType(PenOverlayMode::AllHandles), + } + .into() + }), RadioEntryData::new("frontier") .icon("HandleVisibilityFrontier") .tooltip("Show only handles at the frontiers of the segments connected to selected points") - .on_update(move |_| PenToolMessage::UpdateOptions(PenOptionsUpdate::OverlayModeType(PenOverlayMode::FrontierHandles)).into()), + .on_update(move |_| { + PenToolMessage::UpdateOptions { + options: PenOptionsUpdate::OverlayModeType(PenOverlayMode::FrontierHandles), + } + .into() + }), ]) .selected_index(Some(self.options.pen_overlay_mode as u32)) .widget_holder(), @@ -190,12 +243,12 @@ impl LayoutHolder for PenTool { #[message_handler_data] impl<'a> MessageHandler> for PenTool { fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque, context: &mut ToolActionMessageContext<'a>) { - let ToolMessage::Pen(PenToolMessage::UpdateOptions(action)) = message else { + let ToolMessage::Pen(PenToolMessage::UpdateOptions { options }) = message else { self.fsm_state.process_event(message, &mut self.tool_data, context, &self.options, responses, true); return; }; - match action { + match options { PenOptionsUpdate::OverlayModeType(overlay_mode_type) => { self.options.pen_overlay_mode = overlay_mode_type; responses.add(OverlaysMessage::Draw); @@ -253,7 +306,7 @@ impl ToolTransition for PenTool { tool_abort: Some(PenToolMessage::Abort.into()), selection_changed: Some(PenToolMessage::SelectionChanged.into()), working_color_changed: Some(PenToolMessage::WorkingColorChanged.into()), - overlay_provider: Some(|overlay_context| PenToolMessage::Overlays(overlay_context).into()), + overlay_provider: Some(|context| PenToolMessage::Overlays { context }.into()), ..Default::default() } } @@ -1547,7 +1600,7 @@ impl Fsm for PenToolFsmState { responses.add(OverlaysMessage::Draw); self } - (PenToolFsmState::Ready, PenToolMessage::Overlays(mut overlay_context)) => { + (PenToolFsmState::Ready, PenToolMessage::Overlays { context: mut overlay_context }) => { match tool_options.pen_overlay_mode { PenOverlayMode::AllHandles => { path_overlays(document, DrawHandles::All, shape_editor, &mut overlay_context); @@ -1575,7 +1628,7 @@ impl Fsm for PenToolFsmState { tool_data.snap_manager.draw_overlays(SnapData::new(document, input), &mut overlay_context); self } - (_, PenToolMessage::Overlays(mut overlay_context)) => { + (_, PenToolMessage::Overlays { context: mut overlay_context }) => { let display_anchors = overlay_context.visibility_settings.anchors(); let display_handles = overlay_context.visibility_settings.handles(); @@ -1753,10 +1806,9 @@ impl Fsm for PenToolFsmState { self } (_, PenToolMessage::WorkingColorChanged) => { - responses.add(PenToolMessage::UpdateOptions(PenOptionsUpdate::WorkingColors( - Some(global_tool_data.primary_color), - Some(global_tool_data.secondary_color), - ))); + responses.add(PenToolMessage::UpdateOptions { + options: PenOptionsUpdate::WorkingColors(Some(global_tool_data.primary_color), Some(global_tool_data.secondary_color)), + }); self } (PenToolFsmState::Ready, PenToolMessage::DragStart { append_to_selected }) => { diff --git a/editor/src/messages/tool/tool_messages/select_tool.rs b/editor/src/messages/tool/tool_messages/select_tool.rs index 629357482..8f8e13445 100644 --- a/editor/src/messages/tool/tool_messages/select_tool.rs +++ b/editor/src/messages/tool/tool_messages/select_tool.rs @@ -78,7 +78,9 @@ pub struct SelectToolPointerKeys { pub enum SelectToolMessage { // Standard messages Abort, - Overlays(OverlayContext), + Overlays { + context: OverlayContext, + }, // Tool-specific messages DragStart { @@ -94,9 +96,15 @@ pub enum SelectToolMessage { EditLayer, EditLayerExec, Enter, - PointerMove(SelectToolPointerKeys), - PointerOutsideViewport(SelectToolPointerKeys), - SelectOptions(SelectOptionsUpdate), + PointerMove { + modifier_keys: SelectToolPointerKeys, + }, + PointerOutsideViewport { + modifier_keys: SelectToolPointerKeys, + }, + SelectOptions { + options: SelectOptionsUpdate, + }, SetPivot { position: ReferencePoint, }, @@ -127,9 +135,12 @@ impl SelectTool { let layer_selection_behavior_entries = [NestedSelectionBehavior::Shallowest, NestedSelectionBehavior::Deepest] .iter() .map(|mode| { - MenuListEntry::new(format!("{mode:?}")) - .label(mode.to_string()) - .on_commit(move |_| SelectToolMessage::SelectOptions(SelectOptionsUpdate::NestedSelectionBehavior(*mode)).into()) + MenuListEntry::new(format!("{mode:?}")).label(mode.to_string()).on_commit(move |_| { + SelectToolMessage::SelectOptions { + options: SelectOptionsUpdate::NestedSelectionBehavior(*mode), + } + .into() + }) }) .collect(); @@ -278,7 +289,7 @@ impl<'a> MessageHandler> for Sele fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque, context: &mut ToolActionMessageContext<'a>) { let mut redraw_reference_pivot = false; - if let ToolMessage::Select(SelectToolMessage::SelectOptions(ref option_update)) = message { + if let ToolMessage::Select(SelectToolMessage::SelectOptions { options: ref option_update }) = message { match option_update { SelectOptionsUpdate::NestedSelectionBehavior(nested_selection_behavior) => { self.tool_data.nested_selection_behavior = *nested_selection_behavior; @@ -342,7 +353,7 @@ impl ToolTransition for SelectTool { fn event_to_message_map(&self) -> EventToMessageMap { EventToMessageMap { tool_abort: Some(SelectToolMessage::Abort.into()), - overlay_provider: Some(|overlay_context| SelectToolMessage::Overlays(overlay_context).into()), + overlay_provider: Some(|context| SelectToolMessage::Overlays { context }.into()), ..Default::default() } } @@ -591,7 +602,7 @@ impl Fsm for SelectToolFsmState { let ToolMessage::Select(event) = event else { return self }; match (self, event) { - (_, SelectToolMessage::Overlays(mut overlay_context)) => { + (_, SelectToolMessage::Overlays { context: mut overlay_context }) => { tool_data.snap_manager.draw_overlays(SnapData::new(document, input), &mut overlay_context); let selected_layers_count = document.network_interface.selected_nodes().selected_unlocked_layers(&document.network_interface).count(); @@ -1142,7 +1153,7 @@ impl Fsm for SelectToolFsmState { deepest, remove, }, - SelectToolMessage::PointerMove(modifier_keys), + SelectToolMessage::PointerMove { modifier_keys }, ) => { if !has_dragged { responses.add(ToolMessage::UpdateHints); @@ -1187,8 +1198,8 @@ impl Fsm for SelectToolFsmState { // Auto-panning let messages = [ - SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(), - SelectToolMessage::PointerMove(modifier_keys).into(), + SelectToolMessage::PointerOutsideViewport { modifier_keys: modifier_keys.clone() }.into(), + SelectToolMessage::PointerMove { modifier_keys }.into(), ]; tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses); @@ -1200,7 +1211,7 @@ impl Fsm for SelectToolFsmState { remove, } } - (SelectToolFsmState::ResizingBounds, SelectToolMessage::PointerMove(modifier_keys)) => { + (SelectToolFsmState::ResizingBounds, SelectToolMessage::PointerMove { modifier_keys }) => { if let Some(bounds) = &mut tool_data.bounding_box_manager { resize_bounds( document, @@ -1215,14 +1226,14 @@ impl Fsm for SelectToolFsmState { ToolType::Select, ); let messages = [ - SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(), - SelectToolMessage::PointerMove(modifier_keys).into(), + SelectToolMessage::PointerOutsideViewport { modifier_keys: modifier_keys.clone() }.into(), + SelectToolMessage::PointerMove { modifier_keys }.into(), ]; tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses); } SelectToolFsmState::ResizingBounds } - (SelectToolFsmState::SkewingBounds { skew }, SelectToolMessage::PointerMove(_)) => { + (SelectToolFsmState::SkewingBounds { skew }, SelectToolMessage::PointerMove { .. }) => { if let Some(bounds) = &mut tool_data.bounding_box_manager { skew_bounds( document, @@ -1236,7 +1247,7 @@ impl Fsm for SelectToolFsmState { } SelectToolFsmState::SkewingBounds { skew } } - (SelectToolFsmState::RotatingBounds, SelectToolMessage::PointerMove(_)) => { + (SelectToolFsmState::RotatingBounds, SelectToolMessage::PointerMove { .. }) => { if let Some(bounds) = &mut tool_data.bounding_box_manager { rotate_bounds( document, @@ -1252,7 +1263,7 @@ impl Fsm for SelectToolFsmState { SelectToolFsmState::RotatingBounds } - (SelectToolFsmState::DraggingPivot, SelectToolMessage::PointerMove(modifier_keys)) => { + (SelectToolFsmState::DraggingPivot, SelectToolMessage::PointerMove { modifier_keys }) => { let mouse_position = input.mouse.position; let snapped_mouse_position = mouse_position; @@ -1262,14 +1273,14 @@ impl Fsm for SelectToolFsmState { // Auto-panning let messages = [ - SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(), - SelectToolMessage::PointerMove(modifier_keys).into(), + SelectToolMessage::PointerOutsideViewport { modifier_keys: modifier_keys.clone() }.into(), + SelectToolMessage::PointerMove { modifier_keys }.into(), ]; tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses); SelectToolFsmState::DraggingPivot } - (SelectToolFsmState::Drawing { selection_shape, has_drawn }, SelectToolMessage::PointerMove(modifier_keys)) => { + (SelectToolFsmState::Drawing { selection_shape, has_drawn }, SelectToolMessage::PointerMove { modifier_keys }) => { if !has_drawn { responses.add(ToolMessage::UpdateHints); } @@ -1283,14 +1294,14 @@ impl Fsm for SelectToolFsmState { // Auto-panning let messages = [ - SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(), - SelectToolMessage::PointerMove(modifier_keys).into(), + SelectToolMessage::PointerOutsideViewport { modifier_keys: modifier_keys.clone() }.into(), + SelectToolMessage::PointerMove { modifier_keys }.into(), ]; tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses); SelectToolFsmState::Drawing { selection_shape, has_drawn: true } } - (SelectToolFsmState::Ready { .. }, SelectToolMessage::PointerMove(_)) => { + (SelectToolFsmState::Ready { .. }, SelectToolMessage::PointerMove { .. }) => { let dragging_bounds = tool_data .bounding_box_manager .as_mut() @@ -1326,7 +1337,7 @@ impl Fsm for SelectToolFsmState { deepest, remove, }, - SelectToolMessage::PointerOutsideViewport(_), + SelectToolMessage::PointerOutsideViewport { .. }, ) => { // Auto-panning if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) { @@ -1342,7 +1353,7 @@ impl Fsm for SelectToolFsmState { remove, } } - (SelectToolFsmState::ResizingBounds | SelectToolFsmState::SkewingBounds { .. }, SelectToolMessage::PointerOutsideViewport(_)) => { + (SelectToolFsmState::ResizingBounds | SelectToolFsmState::SkewingBounds { .. }, SelectToolMessage::PointerOutsideViewport { .. }) => { // Auto-panning if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) { if let Some(bounds) = &mut tool_data.bounding_box_manager { @@ -1353,13 +1364,13 @@ impl Fsm for SelectToolFsmState { self } - (SelectToolFsmState::DraggingPivot, SelectToolMessage::PointerOutsideViewport(_)) => { + (SelectToolFsmState::DraggingPivot, SelectToolMessage::PointerOutsideViewport { .. }) => { // Auto-panning let _ = tool_data.auto_panning.shift_viewport(input, responses); self } - (SelectToolFsmState::Drawing { .. }, SelectToolMessage::PointerOutsideViewport(_)) => { + (SelectToolFsmState::Drawing { .. }, SelectToolMessage::PointerOutsideViewport { .. }) => { // Auto-panning if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) { tool_data.drag_start += shift; @@ -1367,11 +1378,11 @@ impl Fsm for SelectToolFsmState { self } - (state, SelectToolMessage::PointerOutsideViewport(modifier_keys)) => { + (state, SelectToolMessage::PointerOutsideViewport { modifier_keys }) => { // Auto-panning let messages = [ - SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(), - SelectToolMessage::PointerMove(modifier_keys).into(), + SelectToolMessage::PointerOutsideViewport { modifier_keys: modifier_keys.clone() }.into(), + SelectToolMessage::PointerMove { modifier_keys }.into(), ]; tool_data.auto_panning.stop(&messages, responses); diff --git a/editor/src/messages/tool/tool_messages/shape_tool.rs b/editor/src/messages/tool/tool_messages/shape_tool.rs index c6e6911a6..2c6eea957 100644 --- a/editor/src/messages/tool/tool_messages/shape_tool.rs +++ b/editor/src/messages/tool/tool_messages/shape_tool.rs @@ -27,7 +27,7 @@ use graphene_std::renderer::Quad; use graphene_std::vector::misc::ArcType; use std::vec; -#[derive(Default)] +#[derive(Default, ExtractField)] pub struct ShapeTool { fsm_state: ShapeToolFsmState, tool_data: ShapeToolData, @@ -73,18 +73,18 @@ pub enum ShapeOptionsUpdate { #[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize, specta::Type)] pub enum ShapeToolMessage { // Standard messages - Overlays(OverlayContext), + Overlays { context: OverlayContext }, Abort, WorkingColorChanged, // Tool-specific messages DragStart, DragStop, - HideShapeTypeWidget(bool), - PointerMove(ShapeToolModifierKey), - PointerOutsideViewport(ShapeToolModifierKey), - UpdateOptions(ShapeOptionsUpdate), - SetShape(ShapeType), + HideShapeTypeWidget { hide: bool }, + PointerMove { modifier: ShapeToolModifierKey }, + PointerOutsideViewport { modifier: ShapeToolModifierKey }, + UpdateOptions { options: ShapeOptionsUpdate }, + SetShape { shape: ShapeType }, IncreaseSides, DecreaseSides, @@ -99,39 +99,65 @@ fn create_sides_widget(vertices: u32) -> WidgetHolder { .min(3.) .max(1000.) .mode(NumberInputMode::Increment) - .on_update(|number_input: &NumberInput| ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::Vertices(number_input.value.unwrap() as u32)).into()) + .on_update(|number_input: &NumberInput| { + ShapeToolMessage::UpdateOptions { + options: ShapeOptionsUpdate::Vertices(number_input.value.unwrap() as u32), + } + .into() + }) .widget_holder() } fn create_shape_option_widget(shape_type: ShapeType) -> WidgetHolder { let entries = vec![vec![ - MenuListEntry::new("Polygon") - .label("Polygon") - .on_commit(move |_| ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::ShapeType(ShapeType::Polygon)).into()), - MenuListEntry::new("Star") - .label("Star") - .on_commit(move |_| ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::ShapeType(ShapeType::Star)).into()), - MenuListEntry::new("Circle") - .label("Circle") - .on_commit(move |_| ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::ShapeType(ShapeType::Circle)).into()), - MenuListEntry::new("Arc") - .label("Arc") - .on_commit(move |_| ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::ShapeType(ShapeType::Arc)).into()), + MenuListEntry::new("Polygon").label("Polygon").on_commit(move |_| { + ShapeToolMessage::UpdateOptions { + options: ShapeOptionsUpdate::ShapeType(ShapeType::Polygon), + } + .into() + }), + MenuListEntry::new("Star").label("Star").on_commit(move |_| { + ShapeToolMessage::UpdateOptions { + options: ShapeOptionsUpdate::ShapeType(ShapeType::Star), + } + .into() + }), + MenuListEntry::new("Circle").label("Circle").on_commit(move |_| { + ShapeToolMessage::UpdateOptions { + options: ShapeOptionsUpdate::ShapeType(ShapeType::Circle), + } + .into() + }), + MenuListEntry::new("Arc").label("Arc").on_commit(move |_| { + ShapeToolMessage::UpdateOptions { + options: ShapeOptionsUpdate::ShapeType(ShapeType::Arc), + } + .into() + }), ]]; DropdownInput::new(entries).selected_index(Some(shape_type as u32)).widget_holder() } fn create_arc_type_widget(arc_type: ArcType) -> WidgetHolder { let entries = vec![ - RadioEntryData::new("Open") - .label("Open") - .on_update(move |_| ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::ArcType(ArcType::Open)).into()), - RadioEntryData::new("Closed") - .label("Closed") - .on_update(move |_| ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::ArcType(ArcType::Closed)).into()), - RadioEntryData::new("Pie") - .label("Pie") - .on_update(move |_| ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::ArcType(ArcType::PieSlice)).into()), + RadioEntryData::new("Open").label("Open").on_update(move |_| { + ShapeToolMessage::UpdateOptions { + options: ShapeOptionsUpdate::ArcType(ArcType::Open), + } + .into() + }), + RadioEntryData::new("Closed").label("Closed").on_update(move |_| { + ShapeToolMessage::UpdateOptions { + options: ShapeOptionsUpdate::ArcType(ArcType::Closed), + } + .into() + }), + RadioEntryData::new("Pie").label("Pie").on_update(move |_| { + ShapeToolMessage::UpdateOptions { + options: ShapeOptionsUpdate::ArcType(ArcType::PieSlice), + } + .into() + }), ]; RadioInput::new(entries).selected_index(Some(arc_type as u32)).widget_holder() } @@ -142,7 +168,12 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder { .label("Weight") .min(0.) .max((1_u64 << f64::MANTISSA_DIGITS) as f64) - .on_update(|number_input: &NumberInput| ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::LineWeight(number_input.value.unwrap())).into()) + .on_update(|number_input: &NumberInput| { + ShapeToolMessage::UpdateOptions { + options: ShapeOptionsUpdate::LineWeight(number_input.value.unwrap()), + } + .into() + }) .widget_holder() } @@ -169,9 +200,26 @@ impl LayoutHolder for ShapeTool { widgets.append(&mut self.options.fill.create_widgets( "Fill", true, - |_| ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::FillColor(None)).into(), - |color_type: ToolColorType| WidgetCallback::new(move |_| ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::FillColorType(color_type.clone())).into()), - |color: &ColorInput| ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::FillColor(color.value.as_solid().map(|color| color.to_linear_srgb()))).into(), + |_| { + ShapeToolMessage::UpdateOptions { + options: ShapeOptionsUpdate::FillColor(None), + } + .into() + }, + |color_type: ToolColorType| { + WidgetCallback::new(move |_| { + ShapeToolMessage::UpdateOptions { + options: ShapeOptionsUpdate::FillColorType(color_type.clone()), + } + .into() + }) + }, + |color: &ColorInput| { + ShapeToolMessage::UpdateOptions { + options: ShapeOptionsUpdate::FillColor(color.value.as_solid().map(|color| color.to_linear_srgb())), + } + .into() + }, )); widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder()); @@ -180,9 +228,26 @@ impl LayoutHolder for ShapeTool { widgets.append(&mut self.options.stroke.create_widgets( "Stroke", true, - |_| ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::StrokeColor(None)).into(), - |color_type: ToolColorType| WidgetCallback::new(move |_| ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::StrokeColorType(color_type.clone())).into()), - |color: &ColorInput| ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::StrokeColor(color.value.as_solid().map(|color| color.to_linear_srgb()))).into(), + |_| { + ShapeToolMessage::UpdateOptions { + options: ShapeOptionsUpdate::StrokeColor(None), + } + .into() + }, + |color_type: ToolColorType| { + WidgetCallback::new(move |_| { + ShapeToolMessage::UpdateOptions { + options: ShapeOptionsUpdate::StrokeColorType(color_type.clone()), + } + .into() + }) + }, + |color: &ColorInput| { + ShapeToolMessage::UpdateOptions { + options: ShapeOptionsUpdate::StrokeColor(color.value.as_solid().map(|color| color.to_linear_srgb())), + } + .into() + }, )); widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder()); widgets.push(create_weight_widget(self.options.line_weight)); @@ -191,13 +256,14 @@ impl LayoutHolder for ShapeTool { } } +#[message_handler_data] impl<'a> MessageHandler> for ShapeTool { fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque, context: &mut ToolActionMessageContext<'a>) { - let ToolMessage::Shape(ShapeToolMessage::UpdateOptions(action)) = message else { + let ToolMessage::Shape(ShapeToolMessage::UpdateOptions { options }) = message else { self.fsm_state.process_event(message, &mut self.tool_data, context, &self.options, responses, true); return; }; - match action { + match options { ShapeOptionsUpdate::FillColor(color) => { self.options.fill.custom_color = color; self.options.fill.color_type = ToolColorType::Custom; @@ -285,7 +351,7 @@ impl ToolMetadata for ShapeTool { impl ToolTransition for ShapeTool { fn event_to_message_map(&self) -> EventToMessageMap { EventToMessageMap { - overlay_provider: Some(|overlay_context| ShapeToolMessage::Overlays(overlay_context).into()), + overlay_provider: Some(|context| ShapeToolMessage::Overlays { context }.into()), tool_abort: Some(ShapeToolMessage::Abort.into()), working_color_changed: Some(ShapeToolMessage::WorkingColorChanged.into()), ..Default::default() @@ -402,7 +468,7 @@ impl Fsm for ShapeToolFsmState { let ToolMessage::Shape(event) = event else { return self }; match (self, event) { - (_, ShapeToolMessage::Overlays(mut overlay_context)) => { + (_, ShapeToolMessage::Overlays { context: mut overlay_context }) => { let mouse_position = tool_data .data .snap_manager @@ -484,11 +550,15 @@ impl Fsm for ShapeToolFsmState { self } (ShapeToolFsmState::Ready(_), ShapeToolMessage::IncreaseSides) => { - responses.add(ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::Vertices(tool_options.vertices + 1))); + responses.add(ShapeToolMessage::UpdateOptions { + options: ShapeOptionsUpdate::Vertices(tool_options.vertices + 1), + }); self } (ShapeToolFsmState::Ready(_), ShapeToolMessage::DecreaseSides) => { - responses.add(ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::Vertices((tool_options.vertices - 1).max(3)))); + responses.add(ShapeToolMessage::UpdateOptions { + options: ShapeOptionsUpdate::Vertices((tool_options.vertices - 1).max(3)), + }); self } ( @@ -542,7 +612,9 @@ impl Fsm for ShapeToolFsmState { return self; }; - responses.add(ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::Vertices(n + 1))); + responses.add(ShapeToolMessage::UpdateOptions { + options: ShapeOptionsUpdate::Vertices(n + 1), + }); responses.add(NodeGraphMessage::SetInput { input_connector: InputConnector::node(node_id, 1), @@ -571,7 +643,9 @@ impl Fsm for ShapeToolFsmState { return self; }; - responses.add(ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::Vertices((n - 1).max(3)))); + responses.add(ShapeToolMessage::UpdateOptions { + options: ShapeOptionsUpdate::Vertices((n - 1).max(3)), + }); responses.add(NodeGraphMessage::SetInput { input_connector: InputConnector::node(node_id, 1), @@ -603,7 +677,9 @@ impl Fsm for ShapeToolFsmState { tool_data.cursor = cursor; responses.add(FrontendMessage::UpdateMouseCursor { cursor }); // Send a PointerMove message to refresh the cursor icon - responses.add(ShapeToolMessage::PointerMove(ShapeToolData::shape_tool_modifier_keys())); + responses.add(ShapeToolMessage::PointerMove { + modifier: ShapeToolData::shape_tool_modifier_keys(), + }); return ShapeToolFsmState::ModifyingGizmo; } @@ -630,7 +706,9 @@ impl Fsm for ShapeToolFsmState { let cursor = tool_data.transform_cage_mouse_icon(input); tool_data.cursor = cursor; responses.add(FrontendMessage::UpdateMouseCursor { cursor }); - responses.add(ShapeToolMessage::PointerMove(ShapeToolData::shape_tool_modifier_keys())); + responses.add(ShapeToolMessage::PointerMove { + modifier: ShapeToolData::shape_tool_modifier_keys(), + }); }; match (resize, rotate, skew) { @@ -710,7 +788,7 @@ impl Fsm for ShapeToolFsmState { ShapeToolFsmState::Drawing(tool_data.current_shape) } - (ShapeToolFsmState::Drawing(shape), ShapeToolMessage::PointerMove(modifier)) => { + (ShapeToolFsmState::Drawing(shape), ShapeToolMessage::PointerMove { modifier }) => { let Some(layer) = tool_data.data.layer else { return ShapeToolFsmState::Ready(shape); }; @@ -726,33 +804,33 @@ impl Fsm for ShapeToolFsmState { } // Auto-panning - let messages = [ShapeToolMessage::PointerOutsideViewport(modifier).into(), ShapeToolMessage::PointerMove(modifier).into()]; + let messages = [ShapeToolMessage::PointerOutsideViewport { modifier }.into(), ShapeToolMessage::PointerMove { modifier }.into()]; tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses); self } - (ShapeToolFsmState::DraggingLineEndpoints, ShapeToolMessage::PointerMove(modifier)) => { + (ShapeToolFsmState::DraggingLineEndpoints, ShapeToolMessage::PointerMove { modifier }) => { let Some(layer) = tool_data.line_data.editing_layer else { return ShapeToolFsmState::Ready(tool_data.current_shape); }; Line::update_shape(document, input, layer, tool_data, modifier, responses); // Auto-panning - let messages = [ShapeToolMessage::PointerOutsideViewport(modifier).into(), ShapeToolMessage::PointerMove(modifier).into()]; + let messages = [ShapeToolMessage::PointerOutsideViewport { modifier }.into(), ShapeToolMessage::PointerMove { modifier }.into()]; tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses); self } - (ShapeToolFsmState::ModifyingGizmo, ShapeToolMessage::PointerMove(..)) => { + (ShapeToolFsmState::ModifyingGizmo, ShapeToolMessage::PointerMove { .. }) => { tool_data.gizmo_manager.handle_update(tool_data.data.viewport_drag_start(document), document, input, responses); responses.add(OverlaysMessage::Draw); ShapeToolFsmState::ModifyingGizmo } - (ShapeToolFsmState::ResizingBounds, ShapeToolMessage::PointerMove(modifier)) => { + (ShapeToolFsmState::ResizingBounds, ShapeToolMessage::PointerMove { modifier }) => { if let Some(bounds) = &mut tool_data.bounding_box_manager { - let messages = [ShapeToolMessage::PointerOutsideViewport(modifier).into(), ShapeToolMessage::PointerMove(modifier).into()]; + let messages = [ShapeToolMessage::PointerOutsideViewport { modifier }.into(), ShapeToolMessage::PointerMove { modifier }.into()]; resize_bounds( document, responses, @@ -771,7 +849,7 @@ impl Fsm for ShapeToolFsmState { responses.add(OverlaysMessage::Draw); ShapeToolFsmState::ResizingBounds } - (ShapeToolFsmState::RotatingBounds, ShapeToolMessage::PointerMove(modifier)) => { + (ShapeToolFsmState::RotatingBounds, ShapeToolMessage::PointerMove { modifier }) => { if let Some(bounds) = &mut tool_data.bounding_box_manager { rotate_bounds( document, @@ -787,7 +865,7 @@ impl Fsm for ShapeToolFsmState { ShapeToolFsmState::RotatingBounds } - (ShapeToolFsmState::SkewingBounds { skew }, ShapeToolMessage::PointerMove(_)) => { + (ShapeToolFsmState::SkewingBounds { skew }, ShapeToolMessage::PointerMove { .. }) => { if let Some(bounds) = &mut tool_data.bounding_box_manager { skew_bounds( document, @@ -803,7 +881,7 @@ impl Fsm for ShapeToolFsmState { ShapeToolFsmState::SkewingBounds { skew } } - (_, ShapeToolMessage::PointerMove(_)) => { + (_, ShapeToolMessage::PointerMove { .. }) => { let dragging_bounds = tool_data .bounding_box_manager .as_mut() @@ -825,7 +903,7 @@ impl Fsm for ShapeToolFsmState { responses.add(OverlaysMessage::Draw); self } - (ShapeToolFsmState::ResizingBounds | ShapeToolFsmState::SkewingBounds { .. }, ShapeToolMessage::PointerOutsideViewport(_)) => { + (ShapeToolFsmState::ResizingBounds | ShapeToolFsmState::SkewingBounds { .. }, ShapeToolMessage::PointerOutsideViewport { .. }) => { // Auto-panning if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) { if let Some(bounds) = &mut tool_data.bounding_box_manager { @@ -836,7 +914,7 @@ impl Fsm for ShapeToolFsmState { self } - (ShapeToolFsmState::Ready(_), ShapeToolMessage::PointerOutsideViewport(..)) => self, + (ShapeToolFsmState::Ready(_), ShapeToolMessage::PointerOutsideViewport { .. }) => self, (_, ShapeToolMessage::PointerOutsideViewport { .. }) => { // Auto-panning let _ = tool_data.auto_panning.shift_viewport(input, responses); @@ -891,21 +969,22 @@ impl Fsm for ShapeToolFsmState { ShapeToolFsmState::Ready(tool_data.current_shape) } (_, ShapeToolMessage::WorkingColorChanged) => { - responses.add(ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::WorkingColors( - Some(global_tool_data.primary_color), - Some(global_tool_data.secondary_color), - ))); + responses.add(ShapeToolMessage::UpdateOptions { + options: ShapeOptionsUpdate::WorkingColors(Some(global_tool_data.primary_color), Some(global_tool_data.secondary_color)), + }); self } - (_, ShapeToolMessage::SetShape(shape)) => { + (_, ShapeToolMessage::SetShape { shape }) => { responses.add(DocumentMessage::AbortTransaction); tool_data.data.cleanup(responses); tool_data.current_shape = shape; - responses.add(ShapeToolMessage::UpdateOptions(ShapeOptionsUpdate::ShapeType(shape))); + responses.add(ShapeToolMessage::UpdateOptions { + options: ShapeOptionsUpdate::ShapeType(shape), + }); ShapeToolFsmState::Ready(shape) } - (_, ShapeToolMessage::HideShapeTypeWidget(hide)) => { + (_, ShapeToolMessage::HideShapeTypeWidget { hide }) => { tool_data.hide_shape_option_widget = hide; responses.add(ToolMessage::RefreshToolOptions); self diff --git a/editor/src/messages/tool/tool_messages/spline_tool.rs b/editor/src/messages/tool/tool_messages/spline_tool.rs index 6e455b293..268890f5b 100644 --- a/editor/src/messages/tool/tool_messages/spline_tool.rs +++ b/editor/src/messages/tool/tool_messages/spline_tool.rs @@ -41,7 +41,7 @@ impl Default for SplineOptions { #[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize, specta::Type)] pub enum SplineToolMessage { // Standard messages - Overlays(OverlayContext), + Overlays { context: OverlayContext }, CanvasTransformed, Abort, WorkingColorChanged, @@ -54,7 +54,7 @@ pub enum SplineToolMessage { PointerMove, PointerOutsideViewport, Undo, - UpdateOptions(SplineOptionsUpdate), + UpdateOptions { options: SplineOptionsUpdate }, } #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] @@ -93,7 +93,12 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder { .label("Weight") .min(0.) .max((1_u64 << f64::MANTISSA_DIGITS) as f64) - .on_update(|number_input: &NumberInput| SplineToolMessage::UpdateOptions(SplineOptionsUpdate::LineWeight(number_input.value.unwrap())).into()) + .on_update(|number_input: &NumberInput| { + SplineToolMessage::UpdateOptions { + options: SplineOptionsUpdate::LineWeight(number_input.value.unwrap()), + } + .into() + }) .widget_holder() } @@ -102,9 +107,26 @@ impl LayoutHolder for SplineTool { let mut widgets = self.options.fill.create_widgets( "Fill", true, - |_| SplineToolMessage::UpdateOptions(SplineOptionsUpdate::FillColor(None)).into(), - |color_type: ToolColorType| WidgetCallback::new(move |_| SplineToolMessage::UpdateOptions(SplineOptionsUpdate::FillColorType(color_type.clone())).into()), - |color: &ColorInput| SplineToolMessage::UpdateOptions(SplineOptionsUpdate::FillColor(color.value.as_solid().map(|color| color.to_linear_srgb()))).into(), + |_| { + SplineToolMessage::UpdateOptions { + options: SplineOptionsUpdate::FillColor(None), + } + .into() + }, + |color_type: ToolColorType| { + WidgetCallback::new(move |_| { + SplineToolMessage::UpdateOptions { + options: SplineOptionsUpdate::FillColorType(color_type.clone()), + } + .into() + }) + }, + |color: &ColorInput| { + SplineToolMessage::UpdateOptions { + options: SplineOptionsUpdate::FillColor(color.value.as_solid().map(|color| color.to_linear_srgb())), + } + .into() + }, ); widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder()); @@ -112,9 +134,26 @@ impl LayoutHolder for SplineTool { widgets.append(&mut self.options.stroke.create_widgets( "Stroke", true, - |_| SplineToolMessage::UpdateOptions(SplineOptionsUpdate::StrokeColor(None)).into(), - |color_type: ToolColorType| WidgetCallback::new(move |_| SplineToolMessage::UpdateOptions(SplineOptionsUpdate::StrokeColorType(color_type.clone())).into()), - |color: &ColorInput| SplineToolMessage::UpdateOptions(SplineOptionsUpdate::StrokeColor(color.value.as_solid().map(|color| color.to_linear_srgb()))).into(), + |_| { + SplineToolMessage::UpdateOptions { + options: SplineOptionsUpdate::StrokeColor(None), + } + .into() + }, + |color_type: ToolColorType| { + WidgetCallback::new(move |_| { + SplineToolMessage::UpdateOptions { + options: SplineOptionsUpdate::StrokeColorType(color_type.clone()), + } + .into() + }) + }, + |color: &ColorInput| { + SplineToolMessage::UpdateOptions { + options: SplineOptionsUpdate::StrokeColor(color.value.as_solid().map(|color| color.to_linear_srgb())), + } + .into() + }, )); widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder()); widgets.push(create_weight_widget(self.options.line_weight)); @@ -126,11 +165,11 @@ impl LayoutHolder for SplineTool { #[message_handler_data] impl<'a> MessageHandler> for SplineTool { fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque, context: &mut ToolActionMessageContext<'a>) { - let ToolMessage::Spline(SplineToolMessage::UpdateOptions(action)) = message else { + let ToolMessage::Spline(SplineToolMessage::UpdateOptions { options }) = message else { self.fsm_state.process_event(message, &mut self.tool_data, context, &self.options, responses, true); return; }; - match action { + match options { SplineOptionsUpdate::LineWeight(line_weight) => self.options.line_weight = line_weight, SplineOptionsUpdate::FillColor(color) => { self.options.fill.custom_color = color; @@ -179,7 +218,7 @@ impl<'a> MessageHandler> for Spli impl ToolTransition for SplineTool { fn event_to_message_map(&self) -> EventToMessageMap { EventToMessageMap { - overlay_provider: Some(|overlay_context: OverlayContext| SplineToolMessage::Overlays(overlay_context).into()), + overlay_provider: Some(|context: OverlayContext| SplineToolMessage::Overlays { context }.into()), canvas_transformed: Some(SplineToolMessage::CanvasTransformed.into()), tool_abort: Some(SplineToolMessage::Abort.into()), working_color_changed: Some(SplineToolMessage::WorkingColorChanged.into()), @@ -262,7 +301,7 @@ impl Fsm for SplineToolFsmState { let ToolMessage::Spline(event) = event else { return self }; match (self, event) { (_, SplineToolMessage::CanvasTransformed) => self, - (_, SplineToolMessage::Overlays(mut overlay_context)) => { + (_, SplineToolMessage::Overlays { context: mut overlay_context }) => { path_endpoint_overlays(document, shape_editor, &mut overlay_context, preferences); tool_data.snap_manager.draw_overlays(SnapData::new(document, input), &mut overlay_context); self @@ -440,10 +479,9 @@ impl Fsm for SplineToolFsmState { SplineToolFsmState::Ready } (_, SplineToolMessage::WorkingColorChanged) => { - responses.add(SplineToolMessage::UpdateOptions(SplineOptionsUpdate::WorkingColors( - Some(global_tool_data.primary_color), - Some(global_tool_data.secondary_color), - ))); + responses.add(SplineToolMessage::UpdateOptions { + options: SplineOptionsUpdate::WorkingColors(Some(global_tool_data.primary_color), Some(global_tool_data.secondary_color)), + }); self } _ => self, diff --git a/editor/src/messages/tool/tool_messages/text_tool.rs b/editor/src/messages/tool/tool_messages/text_tool.rs index 1e2cc3f6a..3187c98ee 100644 --- a/editor/src/messages/tool/tool_messages/text_tool.rs +++ b/editor/src/messages/tool/tool_messages/text_tool.rs @@ -59,7 +59,7 @@ pub enum TextToolMessage { // Standard messages Abort, WorkingColorChanged, - Overlays(OverlayContext), + Overlays { context: OverlayContext }, // Tool-specific messages DragStart, @@ -70,7 +70,7 @@ pub enum TextToolMessage { PointerOutsideViewport { center: Key, lock_ratio: Key }, TextChange { new_text: String, is_left_or_right_click: bool }, UpdateBounds { new_text: String }, - UpdateOptions(TextOptionsUpdate), + UpdateOptions { options: TextOptionsUpdate }, } #[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize, specta::Type)] @@ -100,20 +100,24 @@ fn create_text_widgets(tool: &TextTool) -> Vec { let font = FontInput::new(&tool.options.font_name, &tool.options.font_style) .is_style_picker(false) .on_update(|font_input: &FontInput| { - TextToolMessage::UpdateOptions(TextOptionsUpdate::Font { - family: font_input.font_family.clone(), - style: font_input.font_style.clone(), - }) + TextToolMessage::UpdateOptions { + options: TextOptionsUpdate::Font { + family: font_input.font_family.clone(), + style: font_input.font_style.clone(), + }, + } .into() }) .widget_holder(); let style = FontInput::new(&tool.options.font_name, &tool.options.font_style) .is_style_picker(true) .on_update(|font_input: &FontInput| { - TextToolMessage::UpdateOptions(TextOptionsUpdate::Font { - family: font_input.font_family.clone(), - style: font_input.font_style.clone(), - }) + TextToolMessage::UpdateOptions { + options: TextOptionsUpdate::Font { + family: font_input.font_family.clone(), + style: font_input.font_style.clone(), + }, + } .into() }) .widget_holder(); @@ -123,7 +127,12 @@ fn create_text_widgets(tool: &TextTool) -> Vec { .int() .min(1.) .max((1_u64 << f64::MANTISSA_DIGITS) as f64) - .on_update(|number_input: &NumberInput| TextToolMessage::UpdateOptions(TextOptionsUpdate::FontSize(number_input.value.unwrap())).into()) + .on_update(|number_input: &NumberInput| { + TextToolMessage::UpdateOptions { + options: TextOptionsUpdate::FontSize(number_input.value.unwrap()), + } + .into() + }) .widget_holder(); let line_height_ratio = NumberInput::new(Some(tool.options.line_height_ratio)) .label("Line Height") @@ -131,14 +140,22 @@ fn create_text_widgets(tool: &TextTool) -> Vec { .min(0.) .max((1_u64 << f64::MANTISSA_DIGITS) as f64) .step(0.1) - .on_update(|number_input: &NumberInput| TextToolMessage::UpdateOptions(TextOptionsUpdate::LineHeightRatio(number_input.value.unwrap())).into()) + .on_update(|number_input: &NumberInput| { + TextToolMessage::UpdateOptions { + options: TextOptionsUpdate::LineHeightRatio(number_input.value.unwrap()), + } + .into() + }) .widget_holder(); let align_entries: Vec<_> = [TextAlign::Left, TextAlign::Center, TextAlign::Right, TextAlign::JustifyLeft] .into_iter() .map(|align| { - RadioEntryData::new(format!("{align:?}")) - .label(align.to_string()) - .on_update(move |_| TextToolMessage::UpdateOptions(TextOptionsUpdate::Align(align)).into()) + RadioEntryData::new(format!("{align:?}")).label(align.to_string()).on_update(move |_| { + TextToolMessage::UpdateOptions { + options: TextOptionsUpdate::Align(align), + } + .into() + }) }) .collect(); let align = RadioInput::new(align_entries).selected_index(Some(tool.options.align as u32)).widget_holder(); @@ -164,9 +181,26 @@ impl LayoutHolder for TextTool { widgets.append(&mut self.options.fill.create_widgets( "Fill", true, - |_| TextToolMessage::UpdateOptions(TextOptionsUpdate::FillColor(None)).into(), - |color_type: ToolColorType| WidgetCallback::new(move |_| TextToolMessage::UpdateOptions(TextOptionsUpdate::FillColorType(color_type.clone())).into()), - |color: &ColorInput| TextToolMessage::UpdateOptions(TextOptionsUpdate::FillColor(color.value.as_solid().map(|color| color.to_linear_srgb()))).into(), + |_| { + TextToolMessage::UpdateOptions { + options: TextOptionsUpdate::FillColor(None), + } + .into() + }, + |color_type: ToolColorType| { + WidgetCallback::new(move |_| { + TextToolMessage::UpdateOptions { + options: TextOptionsUpdate::FillColorType(color_type.clone()), + } + .into() + }) + }, + |color: &ColorInput| { + TextToolMessage::UpdateOptions { + options: TextOptionsUpdate::FillColor(color.value.as_solid().map(|color| color.to_linear_srgb())), + } + .into() + }, )); Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row { widgets }])) @@ -176,11 +210,11 @@ impl LayoutHolder for TextTool { #[message_handler_data] impl<'a> MessageHandler> for TextTool { fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque, context: &mut ToolActionMessageContext<'a>) { - let ToolMessage::Text(TextToolMessage::UpdateOptions(action)) = message else { + let ToolMessage::Text(TextToolMessage::UpdateOptions { options }) = message else { self.fsm_state.process_event(message, &mut self.tool_data, context, &self.options, responses, true); return; }; - match action { + match options { TextOptionsUpdate::Font { family, style } => { self.options.font_name = family; self.options.font_style = style; @@ -237,7 +271,7 @@ impl ToolTransition for TextTool { canvas_transformed: None, tool_abort: Some(TextToolMessage::Abort.into()), working_color_changed: Some(TextToolMessage::WorkingColorChanged.into()), - overlay_provider: Some(|overlay_context| TextToolMessage::Overlays(overlay_context).into()), + overlay_provider: Some(|context| TextToolMessage::Overlays { context }.into()), ..Default::default() } } @@ -474,7 +508,7 @@ impl Fsm for TextToolFsmState { let ToolMessage::Text(event) = event else { return self }; match (self, event) { - (TextToolFsmState::Editing, TextToolMessage::Overlays(mut overlay_context)) => { + (TextToolFsmState::Editing, TextToolMessage::Overlays { context: mut overlay_context }) => { responses.add(FrontendMessage::DisplayEditableTextboxTransform { transform: document.metadata().transform_to_viewport(tool_data.layer).to_cols_array(), }); @@ -490,7 +524,7 @@ impl Fsm for TextToolFsmState { TextToolFsmState::Editing } - (_, TextToolMessage::Overlays(mut overlay_context)) => { + (_, TextToolMessage::Overlays { context: mut overlay_context }) => { if matches!(self, Self::Placing) { // Get the updated selection box bounds let quad = Quad::from_box(tool_data.cached_resize_bounds); @@ -852,10 +886,9 @@ impl Fsm for TextToolFsmState { TextToolFsmState::Editing } (_, TextToolMessage::WorkingColorChanged) => { - responses.add(TextToolMessage::UpdateOptions(TextOptionsUpdate::WorkingColors( - Some(global_tool_data.primary_color), - Some(global_tool_data.secondary_color), - ))); + responses.add(TextToolMessage::UpdateOptions { + options: TextOptionsUpdate::WorkingColors(Some(global_tool_data.primary_color), Some(global_tool_data.secondary_color)), + }); self } (TextToolFsmState::Editing, TextToolMessage::Abort) => { diff --git a/editor/src/messages/tool/transform_layer/transform_layer_message.rs b/editor/src/messages/tool/transform_layer/transform_layer_message.rs index c819260e5..4922db713 100644 --- a/editor/src/messages/tool/transform_layer/transform_layer_message.rs +++ b/editor/src/messages/tool/transform_layer/transform_layer_message.rs @@ -8,10 +8,8 @@ use glam::DVec2; #[impl_message(Message, ToolMessage, TransformLayer)] #[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)] pub enum TransformLayerMessage { - // Overlays - Overlays(OverlayContext), - // Messages + Overlays { context: OverlayContext }, ApplyTransformOperation { final_transform: bool }, BeginTransformOperation { operation: TransformType }, BeginGrab, diff --git a/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs b/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs index 6fb8bccb5..d07cc31dd 100644 --- a/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs +++ b/editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs @@ -16,7 +16,7 @@ use graphene_std::vector::misc::ManipulatorPointId; use graphene_std::vector::{Vector, VectorModificationType}; use std::f64::consts::{PI, TAU}; -const TRANSFORM_GRS_OVERLAY_PROVIDER: OverlayProvider = |context| TransformLayerMessage::Overlays(context).into(); +const TRANSFORM_GRS_OVERLAY_PROVIDER: OverlayProvider = |context| TransformLayerMessage::Overlays { context }.into(); // TODO: Get these from the input mapper const SLOW_KEY: Key = Key::Shift; @@ -69,6 +69,7 @@ pub struct TransformLayerMessageHandler { was_grabbing: bool, } +#[message_handler_data] impl MessageHandler> for TransformLayerMessageHandler { fn process_message(&mut self, message: TransformLayerMessage, responses: &mut VecDeque, context: TransformLayerMessageContext) { let TransformLayerMessageContext { @@ -172,7 +173,7 @@ impl MessageHandler> for match message { // Overlays - TransformLayerMessage::Overlays(mut overlay_context) => { + TransformLayerMessage::Overlays { context: mut overlay_context } => { if !overlay_context.visibility_settings.transform_measurement() { return; } @@ -304,7 +305,9 @@ impl MessageHandler> for if final_transform { self.was_grabbing = false; - responses.add(OverlaysMessage::RemoveProvider(TRANSFORM_GRS_OVERLAY_PROVIDER)); + responses.add(OverlaysMessage::RemoveProvider { + provider: TRANSFORM_GRS_OVERLAY_PROVIDER, + }); } } TransformLayerMessage::BeginTransformOperation { operation } => { @@ -343,7 +346,9 @@ impl MessageHandler> for _ => unreachable!(), // Safe because the match arms are exhaustive }; - responses.add(OverlaysMessage::AddProvider(TRANSFORM_GRS_OVERLAY_PROVIDER)); + responses.add(OverlaysMessage::AddProvider { + provider: TRANSFORM_GRS_OVERLAY_PROVIDER, + }); // Find a way better than this hack responses.add(TransformLayerMessage::PointerMove { slow_key: SLOW_KEY, @@ -428,7 +433,9 @@ impl MessageHandler> for if chain_operation { responses.add(TransformLayerMessage::ApplyTransformOperation { final_transform: false }); } else { - responses.add(OverlaysMessage::AddProvider(TRANSFORM_GRS_OVERLAY_PROVIDER)); + responses.add(OverlaysMessage::AddProvider { + provider: TRANSFORM_GRS_OVERLAY_PROVIDER, + }); } responses.add(TransformLayerMessage::BeginTransformOperation { operation: transform_type }); responses.add(TransformLayerMessage::PointerMove { @@ -465,7 +472,9 @@ impl MessageHandler> for } responses.add(SelectToolMessage::PivotShift { offset: None, flush: false }); - responses.add(OverlaysMessage::RemoveProvider(TRANSFORM_GRS_OVERLAY_PROVIDER)); + responses.add(OverlaysMessage::RemoveProvider { + provider: TRANSFORM_GRS_OVERLAY_PROVIDER, + }); } TransformLayerMessage::ConstrainX => { let pivot = document_to_viewport.transform_point2(self.local_pivot); diff --git a/editor/src/messages/tool/utility_types.rs b/editor/src/messages/tool/utility_types.rs index 740b09c97..b26e14d62 100644 --- a/editor/src/messages/tool/utility_types.rs +++ b/editor/src/messages/tool/utility_types.rs @@ -3,7 +3,7 @@ use super::common_functionality::shape_editor::ShapeState; use super::tool_messages::*; use crate::messages::broadcast::BroadcastMessage; -use crate::messages::broadcast::broadcast_event::BroadcastEvent; +use crate::messages::broadcast::event::EventMessage; use crate::messages::input_mapper::utility_types::input_keyboard::{Key, KeysGroup, LayoutKeysGroup, MouseMotion}; use crate::messages::input_mapper::utility_types::macros::action_keys; use crate::messages::input_mapper::utility_types::misc::ActionKeys; @@ -141,7 +141,7 @@ impl DocumentToolData { layout_target: LayoutTarget::WorkingColors, }); - responses.add(BroadcastMessage::TriggerEvent(BroadcastEvent::WorkingColorChanged)); + responses.add(BroadcastMessage::TriggerEvent(EventMessage::WorkingColorChanged)); } } @@ -158,7 +158,7 @@ pub trait ToolTransition { fn event_to_message_map(&self) -> EventToMessageMap; fn activate(&self, responses: &mut VecDeque) { - let mut subscribe_message = |broadcast_to_tool_mapping: Option, event: BroadcastEvent| { + let mut subscribe_message = |broadcast_to_tool_mapping: Option, event: EventMessage| { if let Some(mapping) = broadcast_to_tool_mapping { responses.add(BroadcastMessage::SubscribeEvent { on: event, @@ -168,32 +168,32 @@ pub trait ToolTransition { }; let event_to_tool_map = self.event_to_message_map(); - subscribe_message(event_to_tool_map.canvas_transformed, BroadcastEvent::CanvasTransformed); - subscribe_message(event_to_tool_map.tool_abort, BroadcastEvent::ToolAbort); - subscribe_message(event_to_tool_map.selection_changed, BroadcastEvent::SelectionChanged); - subscribe_message(event_to_tool_map.working_color_changed, BroadcastEvent::WorkingColorChanged); + subscribe_message(event_to_tool_map.canvas_transformed, EventMessage::CanvasTransformed); + subscribe_message(event_to_tool_map.tool_abort, EventMessage::ToolAbort); + subscribe_message(event_to_tool_map.selection_changed, EventMessage::SelectionChanged); + subscribe_message(event_to_tool_map.working_color_changed, EventMessage::WorkingColorChanged); if let Some(overlay_provider) = event_to_tool_map.overlay_provider { - responses.add(OverlaysMessage::AddProvider(overlay_provider)); + responses.add(OverlaysMessage::AddProvider { provider: overlay_provider }); } } fn deactivate(&self, responses: &mut VecDeque) { - let mut unsubscribe_message = |broadcast_to_tool_mapping: Option, event: BroadcastEvent| { + let mut unsubscribe_message = |broadcast_to_tool_mapping: Option, event: EventMessage| { if let Some(mapping) = broadcast_to_tool_mapping { responses.add(BroadcastMessage::UnsubscribeEvent { on: event, - message: Box::new(mapping.into()), + send: Box::new(mapping.into()), }); } }; let event_to_tool_map = self.event_to_message_map(); - unsubscribe_message(event_to_tool_map.canvas_transformed, BroadcastEvent::CanvasTransformed); - unsubscribe_message(event_to_tool_map.tool_abort, BroadcastEvent::ToolAbort); - unsubscribe_message(event_to_tool_map.selection_changed, BroadcastEvent::SelectionChanged); - unsubscribe_message(event_to_tool_map.working_color_changed, BroadcastEvent::WorkingColorChanged); + unsubscribe_message(event_to_tool_map.canvas_transformed, EventMessage::CanvasTransformed); + unsubscribe_message(event_to_tool_map.tool_abort, EventMessage::ToolAbort); + unsubscribe_message(event_to_tool_map.selection_changed, EventMessage::SelectionChanged); + unsubscribe_message(event_to_tool_map.working_color_changed, EventMessage::WorkingColorChanged); if let Some(overlay_provider) = event_to_tool_map.overlay_provider { - responses.add(OverlaysMessage::RemoveProvider(overlay_provider)); + responses.add(OverlaysMessage::RemoveProvider { provider: overlay_provider }); } } } diff --git a/editor/src/node_graph_executor.rs b/editor/src/node_graph_executor.rs index c127ed734..36d01c6dc 100644 --- a/editor/src/node_graph_executor.rs +++ b/editor/src/node_graph_executor.rs @@ -160,7 +160,7 @@ impl NodeGraphExecutor { self.futures.insert(execution_id, ExecutionContext { export_config: None, document_id }); - Ok(DeferMessage::SetGraphSubmissionIndex(execution_id).into()) + Ok(DeferMessage::SetGraphSubmissionIndex { execution_id }.into()) } /// Evaluates a node graph, computing the entire graph @@ -288,7 +288,10 @@ impl NodeGraphExecutor { } else { self.process_node_graph_output(node_graph_output, responses)?; } - responses.add(DeferMessage::TriggerGraphRun(execution_id, execution_context.document_id)); + responses.add(DeferMessage::TriggerGraphRun { + execution_id, + document_id: execution_context.document_id, + }); // Update the Data panel on the frontend using the value of the inspect result. if let Some(inspect_result) = (self.previous_node_to_inspect.is_some()).then_some(inspect_result).flatten() { diff --git a/editor/src/utility_traits.rs b/editor/src/utility_traits.rs index aaf977d1d..386d6fda6 100644 --- a/editor/src/utility_traits.rs +++ b/editor/src/utility_traits.rs @@ -60,3 +60,9 @@ pub trait HierarchicalTree { "" } } + +pub trait ExtractField { + fn field_types() -> Vec<(String, usize)>; + fn path() -> &'static str; + fn print_field_types(); +} diff --git a/editor/src/utility_types.rs b/editor/src/utility_types.rs index fcc3c459a..c27ce5c12 100644 --- a/editor/src/utility_types.rs +++ b/editor/src/utility_types.rs @@ -26,6 +26,7 @@ impl MessageData { #[derive(Debug)] pub struct DebugMessageTree { name: String, + fields: Option>, variants: Option>, message_handler: Option, message_handler_data: Option, @@ -36,6 +37,7 @@ impl DebugMessageTree { pub fn new(name: &str) -> DebugMessageTree { DebugMessageTree { name: name.to_string(), + fields: None, variants: None, message_handler: None, message_handler_data: None, @@ -43,6 +45,10 @@ impl DebugMessageTree { } } + pub fn add_fields(&mut self, fields: Vec) { + self.fields = Some(fields); + } + pub fn set_path(&mut self, path: &'static str) { self.path = path; } @@ -67,6 +73,10 @@ impl DebugMessageTree { &self.name } + pub fn fields(&self) -> Option<&Vec> { + self.fields.as_ref() + } + pub fn path(&self) -> &'static str { self.path } diff --git a/frontend/wasm/src/editor_api.rs b/frontend/wasm/src/editor_api.rs index 80490c8b8..ddc4bc28d 100644 --- a/frontend/wasm/src/editor_api.rs +++ b/frontend/wasm/src/editor_api.rs @@ -277,7 +277,7 @@ impl EditorHandle { // Used by auto-panning, but this could possibly be refactored in the future, see: // - handle.dispatch(BroadcastMessage::TriggerEvent(BroadcastEvent::AnimationFrame)); + handle.dispatch(BroadcastMessage::TriggerEvent(EventMessage::AnimationFrame)); }); } diff --git a/proc-macros/src/extract_fields.rs b/proc-macros/src/extract_fields.rs index 606b3b8a3..949ff3f50 100644 --- a/proc-macros/src/extract_fields.rs +++ b/proc-macros/src/extract_fields.rs @@ -31,23 +31,23 @@ pub fn derive_extract_field_impl(input: TokenStream) -> syn::Result }) .collect::>(); - let field_str = field_info.into_iter().map(|(name, ty)| (format!("{}: {}", name, ty))); + let field_str = field_info.into_iter().map(|(name, ty)| (format!("{name}: {ty}"))); let res = quote! { - impl #impl_generics #struct_name #ty_generics #where_clause { - pub fn field_types() -> Vec<(String, usize)> { + impl #impl_generics ExtractField for #struct_name #ty_generics #where_clause { + fn field_types() -> Vec<(String, usize)> { vec![ #((String::from(#field_str), #field_line)),* ] } - pub fn print_field_types() { + fn print_field_types() { for (field, line) in Self::field_types() { println!("{} at line {}", field, line); } } - pub fn path() -> &'static str { + fn path() -> &'static str { file!() } } diff --git a/proc-macros/src/hierarchical_tree.rs b/proc-macros/src/hierarchical_tree.rs index e0d6fb6a7..fb7ae34f5 100644 --- a/proc-macros/src/hierarchical_tree.rs +++ b/proc-macros/src/hierarchical_tree.rs @@ -1,3 +1,4 @@ +use crate::helpers::clean_rust_type_syntax; use proc_macro2::{Span, TokenStream}; use quote::{ToTokens, quote}; use syn::{Data, DeriveInput, Fields, Type, parse2}; @@ -11,51 +12,89 @@ pub fn generate_hierarchical_tree(input: TokenStream) -> syn::Result return Err(syn::Error::new(Span::call_site(), "Tried to derive HierarchicalTree for non-enum")), }; - let build_message_tree = data.variants.iter().map(|variant| { - let variant_type = &variant.ident; + let build_message_tree: Result, syn::Error> = data + .variants + .iter() + .map(|variant| { + let variant_type = &variant.ident; - let has_child = variant - .attrs - .iter() - .any(|attr| attr.path().get_ident().is_some_and(|ident| ident == "sub_discriminant" || ident == "child")); + let has_child = variant + .attrs + .iter() + .any(|attr| attr.path().get_ident().is_some_and(|ident| ident == "sub_discriminant" || ident == "child")); - if has_child { - if let Fields::Unnamed(fields) = &variant.fields { - let field_type = &fields.unnamed.first().unwrap().ty; - quote! { - { - let mut variant_tree = DebugMessageTree::new(stringify!(#variant_type)); - let field_name = stringify!(#field_type); - const message_string: &str = "Message"; - if message_string == &field_name[field_name.len().saturating_sub(message_string.len())..] { - // The field is a Message type, recursively build its tree - let sub_tree = #field_type::build_message_tree(); - variant_tree.add_variant(sub_tree); - } - message_tree.add_variant(variant_tree); + match &variant.fields { + Fields::Unit => Ok(quote! { + message_tree.add_variant(DebugMessageTree::new(stringify!(#variant_type))); + }), + Fields::Unnamed(fields) => { + if has_child { + let field_type = &fields.unnamed.first().unwrap().ty; + Ok(quote! { + { + let mut variant_tree = DebugMessageTree::new(stringify!(#variant_type)); + let field_name = stringify!(#field_type); + const MESSAGE_SUFFIX: &str = "Message"; + if MESSAGE_SUFFIX == &field_name[field_name.len().saturating_sub(MESSAGE_SUFFIX.len())..] { + // The field is a Message type, recursively build its tree + let sub_tree = #field_type::build_message_tree(); + variant_tree.add_variant(sub_tree); + } else { + variant_tree.add_fields(vec![format!("{field_name}")]); + } + message_tree.add_variant(variant_tree); + } + }) + } else { + let error_msg = match fields.unnamed.len() { + 0 => format!("Remove the unnecessary `()` from the `{}` message enum variant.", variant_type), + 1 => { + let field_type = &fields.unnamed.first().unwrap().ty; + format!( + "The `{}` message should be defined as a struct-style (not tuple-style) enum variant to maintain consistent formatting across all editor messages.\n\ + Replace `{}` with a named field using {{curly braces}} instead of a positional field using (parentheses).", + variant_type, + field_type.to_token_stream() + ) + } + _ => { + let field_types = fields.unnamed.iter().map(|f| f.ty.to_token_stream().to_string()).collect::>().join(", "); + format!( + "The `{}` message should be defined as a struct-style (not tuple-style) enum variant to maintain consistent formatting across all editor messages.\n\ + Replace `{}` with named fields using {{curly braces}} instead of positional fields using (parentheses).", + variant_type, field_types + ) + } + }; + Err(syn::Error::new(Span::call_site(), error_msg)) } } - } else { - quote! { - message_tree.add_variant(DebugMessageTree::new(stringify!(#variant_type))); + Fields::Named(fields) => { + let names = fields.named.iter().map(|f| f.ident.as_ref().unwrap()); + let ty = fields.named.iter().map(|f| clean_rust_type_syntax(f.ty.to_token_stream().to_string())); + Ok(quote! { + { + let mut field_names = Vec::new(); + #(field_names.push(format!("{}: {}",stringify!(#names), #ty));)* + let mut variant_tree = DebugMessageTree::new(stringify!(#variant_type)); + variant_tree.add_fields(field_names); + message_tree.add_variant(variant_tree); + } + }) } } - } else { - quote! { - message_tree.add_variant(DebugMessageTree::new(stringify!(#variant_type))); - } - } - }); + }) + .collect(); + let build_message_tree = build_message_tree?; let res = quote! { impl HierarchicalTree for #input_type { fn build_message_tree() -> DebugMessageTree { let mut message_tree = DebugMessageTree::new(stringify!(#input_type)); #(#build_message_tree)* + let message_handler_str = #input_type::message_handler_str(); - if message_handler_str.fields().len() > 0 { - message_tree.add_message_handler_field(message_handler_str); - } + message_tree.add_message_handler_field(message_handler_str); let message_handler_data_str = #input_type::message_handler_data_str(); if message_handler_data_str.fields().len() > 0 { diff --git a/proc-macros/src/message_handler_data_attr.rs b/proc-macros/src/message_handler_data_attr.rs index 6c1c88b88..2459ac5a6 100644 --- a/proc-macros/src/message_handler_data_attr.rs +++ b/proc-macros/src/message_handler_data_attr.rs @@ -43,10 +43,8 @@ pub fn message_handler_data_attr_impl(attr: TokenStream, input_item: TokenStream quote! { #input_item impl #message_type { - pub fn message_handler_data_str() -> MessageData - { + pub fn message_handler_data_str() -> MessageData { MessageData::new(format!("{}", stringify!(#type_name)), #type_name::field_types(), #type_name::path()) - } pub fn message_handler_str() -> MessageData { MessageData::new(format!("{}", stringify!(#input_type)), #input_type::field_types(), #input_type::path()) diff --git a/proc-macros/src/widget_builder.rs b/proc-macros/src/widget_builder.rs index f5c6d0a54..5705d4b25 100644 --- a/proc-macros/src/widget_builder.rs +++ b/proc-macros/src/widget_builder.rs @@ -110,7 +110,7 @@ pub fn derive_widget_builder_impl(input_item: TokenStream2) -> syn::Result crate::messages::layout::utility_types::layout_widget::WidgetHolder{ + pub fn widget_holder(self) -> crate::messages::layout::utility_types::layout_widget::WidgetHolder { crate::messages::layout::utility_types::layout_widget::WidgetHolder::new( crate::messages::layout::utility_types::layout_widget::Widget::#struct_name_ident(self)) } } diff --git a/website/build-scripts/generate-editor-structure.js b/website/build-scripts/generate-editor-structure.js index 02db735a5..a2d9d2ef4 100644 --- a/website/build-scripts/generate-editor-structure.js +++ b/website/build-scripts/generate-editor-structure.js @@ -57,31 +57,37 @@ function buildHtmlList(nodes, currentIndex, currentLevel) { continue; } - const hasChildren = (i + 1 < nodes.length) && (nodes[i + 1].level > node.level); + const hasDirectChildren = i + 1 < nodes.length && nodes[i + 1].level > node.level; + const hasDeeperChildren = hasDirectChildren && i + 2 < nodes.length && nodes[i + 2].level > nodes[i + 1].level; + const linkHtml = node.link ? `${path.basename(node.link)}` : ""; const fieldPieces = node.text.match(/([^:]*):(.*)/); - const partOfMessageFromNamingConvention = ["Message", "MessageHandler", "MessageContext"].some((suffix) => node.text.replace(/(.*)<.*>/g, "$1").endsWith(suffix)); - const partOfMessageViolatesNamingConvention = node.link && !partOfMessageFromNamingConvention; - const partOfMessage = node.link ? "subsystem" : ""; - const messageParent = (hasChildren && !node.link) ? " submessage": ""; - const violatesNamingConvention = partOfMessageViolatesNamingConvention ? "(violates naming convention — should end with 'Message', 'MessageHandler', or 'MessageContext')" : ""; let escapedText; if (fieldPieces && fieldPieces.length === 3) { escapedText = [escapeHtml(fieldPieces[1].trim()), escapeHtml(fieldPieces[2].trim())]; } else { escapedText = [escapeHtml(node.text)]; } + + let role = "message"; + if (node.link) role = "subsystem"; + else if (hasDeeperChildren) role = "submessage"; + else if (escapedText.length === 2) role = "field"; - if (hasChildren) { - html += `
  • ${escapedText}${linkHtml}${violatesNamingConvention}`; + const partOfMessageFromNamingConvention = ["Message", "MessageHandler", "MessageContext"].some((suffix) => node.text.replace(/(.*)<.*>/g, "$1").endsWith(suffix)); + const partOfMessageViolatesNamingConvention = node.link && !partOfMessageFromNamingConvention; + const violatesNamingConvention = partOfMessageViolatesNamingConvention ? "(violates naming convention — should end with 'Message', 'MessageHandler', or 'MessageContext')" : ""; + + if (hasDirectChildren) { + html += `
  • ${escapedText}${linkHtml}${violatesNamingConvention}`; const childResult = buildHtmlList(nodes, i + 1, node.level + 1); html += `
    ${childResult.html}
  • \n`; i = childResult.nextIndex; - } else if (escapedText.length === 2) { - html += `
  • ${escapedText[0]}: ${escapedText[1]}${linkHtml}
  • \n`; + } else if (role === "field") { + html += `
  • ${escapedText[0]}: ${escapedText[1]}${linkHtml}
  • \n`; i++; } else { - html += `
  • ${escapedText[0]}${linkHtml}${violatesNamingConvention}
  • \n`; + html += `
  • ${escapedText[0]}${linkHtml}${violatesNamingConvention}
  • \n`; i++; } } diff --git a/website/sass/page/developer-guide-editor-structure.scss b/website/sass/page/developer-guide-editor-structure.scss index 3e649aa69..7d145f207 100644 --- a/website/sass/page/developer-guide-editor-structure.scss +++ b/website/sass/page/developer-guide-editor-structure.scss @@ -30,10 +30,8 @@ \ '); position: absolute; - margin: auto; - top: 0; - bottom: 0; left: 0; + margin: calc((1.5em - 10px) / 2) auto; width: 10px; height: 10px; } @@ -41,34 +39,10 @@ &.expanded::before { transform: rotate(90deg); } - - a { - margin-left: 12px; - color: var(--color-crimson); - font-size: 12px; - font-family: Arial, sans-serif; - position: relative; - - &:hover::after { - content: "↗"; - margin-left: 4px; - position: absolute; - } - } } .tree-leaf { margin-left: calc(10px + 8px); - - &.field { - padding-left: 4px; - color: var(--color-storm); - } - - &:not(.field) { - padding: 0 4px; - background: var(--color-fog); - } } .nested { @@ -80,6 +54,7 @@ } .warn { + display: inline; margin-left: 12px; color: var(--color-flamingo); font-family: Arial, sans-serif; @@ -87,6 +62,20 @@ text-decoration: none; font-style: italic; } + + a { + margin-left: 12px; + color: var(--color-crimson); + font-size: 12px; + font-family: Arial, sans-serif; + position: relative; + + &:hover::after { + content: "↗"; + margin-left: 4px; + position: absolute; + } + } } .subsystem, @@ -94,13 +83,27 @@ font-family: monospace; line-height: 1.5; padding: 0 4px; + + &.subsystem { + color: #ffffff; + background: var(--color-crimson); + } + + &.submessage { + background: var(--color-mustard); + } } -.subsystem { - color: #ffffff; - background: var(--color-storm); +.message { + padding: 0 4px; + background: var(--color-fog); } -.submessage { - background: var(--color-lilac); +.field { + padding-left: 4px; + color: #8887c0; + + + span { + color: #457297; + } }