diff --git a/editor/src/communication/dispatcher.rs b/editor/src/communication/dispatcher.rs index 7752cfbc..185ebf48 100644 --- a/editor/src/communication/dispatcher.rs +++ b/editor/src/communication/dispatcher.rs @@ -4,6 +4,7 @@ use crate::input::{InputMapperMessageHandler, InputPreprocessorMessageHandler}; use crate::layout::layout_message_handler::LayoutMessageHandler; use crate::message_prelude::*; use crate::viewport_tools::tool_message_handler::ToolMessageHandler; +use crate::workspace::WorkspaceMessageHandler; use std::collections::VecDeque; @@ -27,6 +28,7 @@ struct DispatcherMessageHandlers { layout_message_handler: LayoutMessageHandler, portfolio_message_handler: PortfolioMessageHandler, tool_message_handler: ToolMessageHandler, + workspace_message_handler: WorkspaceMessageHandler, } /// For optimization, these are messages guaranteed to be redundant when repeated. @@ -40,7 +42,7 @@ const SIDE_EFFECT_FREE_MESSAGES: &[MessageDiscriminant] = &[ ))), MessageDiscriminant::Portfolio(PortfolioMessageDiscriminant::Document(DocumentMessageDiscriminant::FolderChanged)), MessageDiscriminant::Frontend(FrontendMessageDiscriminant::UpdateDocumentLayer), - MessageDiscriminant::Frontend(FrontendMessageDiscriminant::DisplayDocumentLayerTreeStructure), + MessageDiscriminant::Frontend(FrontendMessageDiscriminant::UpdateDocumentLayerTreeStructure), MessageDiscriminant::Frontend(FrontendMessageDiscriminant::UpdateOpenDocumentsList), MessageDiscriminant::Tool(ToolMessageDiscriminant::DocumentIsDirty), ]; @@ -113,6 +115,11 @@ impl Dispatcher { &mut self.message_queue, ); } + Workspace(message) => { + self.message_handlers + .workspace_message_handler + .process_action(message, &self.message_handlers.input_preprocessor_message_handler, &mut self.message_queue); + } #[remain::unsorted] PopulateBuildMetadata { new } => self.build_metadata = new, diff --git a/editor/src/communication/message.rs b/editor/src/communication/message.rs index cb575717..7be45c44 100644 --- a/editor/src/communication/message.rs +++ b/editor/src/communication/message.rs @@ -39,6 +39,8 @@ pub enum Message { Portfolio(PortfolioMessage), #[child] Tool(ToolMessage), + #[child] + Workspace(WorkspaceMessage), #[remain::unsorted] PopulateBuildMetadata { new: BuildMetadata }, diff --git a/editor/src/document/document_message_handler.rs b/editor/src/document/document_message_handler.rs index 2352a62e..c359b88f 100644 --- a/editor/src/document/document_message_handler.rs +++ b/editor/src/document/document_message_handler.rs @@ -846,7 +846,7 @@ impl MessageHandler for Docum DocumentHistoryForward => self.redo(responses).unwrap_or_else(|e| log::warn!("{}", e)), DocumentStructureChanged => { let data_buffer: RawBuffer = self.serialize_root().into(); - responses.push_back(FrontendMessage::DisplayDocumentLayerTreeStructure { data_buffer }.into()) + responses.push_back(FrontendMessage::UpdateDocumentLayerTreeStructure { data_buffer }.into()) } DuplicateSelectedLayers => { self.backup(responses); diff --git a/editor/src/frontend/frontend_message.rs b/editor/src/frontend/frontend_message.rs index 3143e255..b50502e4 100644 --- a/editor/src/frontend/frontend_message.rs +++ b/editor/src/frontend/frontend_message.rs @@ -16,7 +16,6 @@ pub enum FrontendMessage { DisplayDialog { icon: String }, DisplayDialogDismiss, DisplayDialogPanic { panic_info: String, title: String, description: String }, - DisplayDocumentLayerTreeStructure { data_buffer: RawBuffer }, DisplayEditableTextbox { text: String, line_width: Option, font_size: f64, color: Color }, DisplayRemoveEditableTextbox, @@ -43,12 +42,14 @@ pub enum FrontendMessage { UpdateDocumentArtwork { svg: String }, UpdateDocumentBarLayout { layout_target: LayoutTarget, layout: SubLayout }, UpdateDocumentLayer { data: LayerPanelEntry }, + UpdateDocumentLayerTreeStructure { data_buffer: RawBuffer }, UpdateDocumentOverlays { svg: String }, UpdateDocumentRulers { origin: (f64, f64), spacing: f64, interval: f64 }, UpdateDocumentScrollbars { position: (f64, f64), size: (f64, f64), multiplier: (f64, f64) }, UpdateImageData { image_data: Vec }, UpdateInputHints { hint_data: HintData }, UpdateMouseCursor { cursor: MouseCursorIcon }, + UpdateNodeGraphVisibility { visible: bool }, UpdateOpenDocumentsList { open_documents: Vec }, UpdatePropertyPanelOptionsLayout { layout_target: LayoutTarget, layout: SubLayout }, UpdatePropertyPanelSectionsLayout { layout_target: LayoutTarget, layout: SubLayout }, diff --git a/editor/src/lib.rs b/editor/src/lib.rs index 7981e64a..56958fd8 100644 --- a/editor/src/lib.rs +++ b/editor/src/lib.rs @@ -11,6 +11,7 @@ pub mod global; pub mod input; pub mod layout; pub mod viewport_tools; +pub mod workspace; #[doc(inline)] pub use graphene::color::Color; @@ -89,6 +90,7 @@ pub mod message_prelude { pub use crate::viewport_tools::tools::shape_tool::{ShapeToolMessage, ShapeToolMessageDiscriminant}; pub use crate::viewport_tools::tools::spline_tool::{SplineToolMessage, SplineToolMessageDiscriminant}; pub use crate::viewport_tools::tools::text_tool::{TextMessage, TextMessageDiscriminant}; + pub use crate::workspace::{WorkspaceMessage, WorkspaceMessageDiscriminant}; pub use graphite_proc_macros::*; pub use std::collections::VecDeque; diff --git a/editor/src/workspace/mod.rs b/editor/src/workspace/mod.rs new file mode 100644 index 00000000..891ac11f --- /dev/null +++ b/editor/src/workspace/mod.rs @@ -0,0 +1,7 @@ +mod workspace_message; +mod workspace_message_handler; + +#[doc(inline)] +pub use workspace_message::{WorkspaceMessage, WorkspaceMessageDiscriminant}; +#[doc(inline)] +pub use workspace_message_handler::WorkspaceMessageHandler; diff --git a/editor/src/workspace/workspace_message.rs b/editor/src/workspace/workspace_message.rs new file mode 100644 index 00000000..903b4da0 --- /dev/null +++ b/editor/src/workspace/workspace_message.rs @@ -0,0 +1,11 @@ +use crate::message_prelude::*; + +use serde::{Deserialize, Serialize}; + +#[remain::sorted] +#[impl_message(Message, Workspace)] +#[derive(PartialEq, Clone, Debug, Serialize, Deserialize)] +pub enum WorkspaceMessage { + // Messages + NodeGraphToggleVisibility, +} diff --git a/editor/src/workspace/workspace_message_handler.rs b/editor/src/workspace/workspace_message_handler.rs new file mode 100644 index 00000000..46a6025f --- /dev/null +++ b/editor/src/workspace/workspace_message_handler.rs @@ -0,0 +1,29 @@ +use crate::input::InputPreprocessorMessageHandler; +use crate::message_prelude::*; + +#[derive(Debug, Clone, Default)] +pub struct WorkspaceMessageHandler { + node_graph_visible: bool, +} + +impl MessageHandler for WorkspaceMessageHandler { + #[remain::check] + fn process_action(&mut self, message: WorkspaceMessage, _ipp: &InputPreprocessorMessageHandler, responses: &mut VecDeque) { + use WorkspaceMessage::*; + + #[remain::sorted] + match message { + // Messages + NodeGraphToggleVisibility => { + self.node_graph_visible = !self.node_graph_visible; + responses.push_back(FrontendMessage::UpdateNodeGraphVisibility { visible: self.node_graph_visible }.into()); + } + } + } + + fn actions(&self) -> ActionList { + actions!(WorkspaceMessageDiscriminant; + NodeGraphToggleVisibility, + ) + } +} diff --git a/frontend/assets/16px-solid/node-blur.svg b/frontend/assets/16px-solid/node-blur.svg new file mode 100644 index 00000000..bcdd2f0d --- /dev/null +++ b/frontend/assets/16px-solid/node-blur.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/assets/16px-solid/node-brushwork.svg b/frontend/assets/16px-solid/node-brushwork.svg new file mode 100644 index 00000000..d41a8c6e --- /dev/null +++ b/frontend/assets/16px-solid/node-brushwork.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/frontend/assets/16px-solid/node-color-correction.svg b/frontend/assets/16px-solid/node-color-correction.svg new file mode 100644 index 00000000..05e7ac1b --- /dev/null +++ b/frontend/assets/16px-solid/node-color-correction.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/assets/16px-solid/node-gradient.svg b/frontend/assets/16px-solid/node-gradient.svg new file mode 100644 index 00000000..f63d1c3b --- /dev/null +++ b/frontend/assets/16px-solid/node-gradient.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/assets/16px-solid/node-magic-wand.svg b/frontend/assets/16px-solid/node-magic-wand.svg new file mode 100644 index 00000000..2c5c5539 --- /dev/null +++ b/frontend/assets/16px-solid/node-magic-wand.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/frontend/assets/16px-solid/node-mask.svg b/frontend/assets/16px-solid/node-mask.svg new file mode 100644 index 00000000..75e45929 --- /dev/null +++ b/frontend/assets/16px-solid/node-mask.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/assets/16px-solid/node-motion-blur.svg b/frontend/assets/16px-solid/node-motion-blur.svg new file mode 100644 index 00000000..0fd73320 --- /dev/null +++ b/frontend/assets/16px-solid/node-motion-blur.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/frontend/assets/16px-solid/node-output.svg b/frontend/assets/16px-solid/node-output.svg new file mode 100644 index 00000000..bc5a6e2b --- /dev/null +++ b/frontend/assets/16px-solid/node-output.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/assets/16px-solid/node-transform.svg b/frontend/assets/16px-solid/node-transform.svg new file mode 100644 index 00000000..3e10e184 --- /dev/null +++ b/frontend/assets/16px-solid/node-transform.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 7c457fea..fd3d7eb4 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -70,8 +70,12 @@ --color-data-general-rgb: 197, 197, 197; --color-data-vector: #65bbe5; --color-data-vector-rgb: 101, 187, 229; + --color-data-vector-dim: #4b778c; + --color-data-vector-dim-rgb: 75, 119, 140; --color-data-raster: #e4bb72; --color-data-raster-rgb: 228, 187, 114; + --color-data-raster-dim: #8b7752; + --color-data-raster-dim-rgb: 139, 119, 82; --color-data-mask: #8d85c7; --color-data-mask-rgb: 141, 133, 199; --color-data-unused1: #d6536e; @@ -258,9 +262,10 @@ import { createAutoSaveManager } from "@/lifetime/auto-save"; import { initErrorHandling } from "@/lifetime/errors"; import { createInputManager, InputManager } from "@/lifetime/input"; import { createDialogState, DialogState } from "@/state/dialog"; -import { createDocumentsState, DocumentsState } from "@/state/documents"; import { createFullscreenState, FullscreenState } from "@/state/fullscreen"; +import { createPortfolioState, PortfolioState } from "@/state/portfolio"; import { createEditorState, EditorState } from "@/state/wasm-loader"; +import { createWorkspaceState, WorkspaceState } from "@/state/workspace"; import LayoutCol from "@/components/layout/LayoutCol.vue"; import LayoutRow from "@/components/layout/LayoutRow.vue"; @@ -270,7 +275,8 @@ import MainWindow from "@/components/window/MainWindow.vue"; declare module "@vue/runtime-core" { interface ComponentCustomProperties { dialog: DialogState; - documents: DocumentsState; + portfolio: PortfolioState; + workspace: WorkspaceState; fullscreen: FullscreenState; editor: EditorState; // This must be set to optional because there is a time in the lifecycle of the component where inputManager is undefined. @@ -284,7 +290,8 @@ export default defineComponent({ return { editor: this.editor, dialog: this.dialog, - documents: this.documents, + portfolio: this.portfolio, + workspace: this.workspace, fullscreen: this.fullscreen, inputManager: this.inputManager, }; @@ -295,15 +302,17 @@ export default defineComponent({ // Initialize other stateful Vue systems const dialog = createDialogState(editor); - const documents = createDocumentsState(editor); + const portfolio = createPortfolioState(editor); + const workspace = createWorkspaceState(editor); const fullscreen = createFullscreenState(); initErrorHandling(editor, dialog); - createAutoSaveManager(editor, documents); + createAutoSaveManager(editor, portfolio); return { editor, dialog, - documents, + portfolio, + workspace, fullscreen, showUnsupportedModal: !("BigInt64Array" in window), inputManager: undefined as undefined | InputManager, @@ -315,7 +324,7 @@ export default defineComponent({ }, }, mounted() { - this.inputManager = createInputManager(this.editor, this.$el.parentElement, this.dialog, this.documents, this.fullscreen); + this.inputManager = createInputManager(this.editor, this.$el.parentElement, this.dialog, this.portfolio, this.fullscreen); }, beforeUnmount() { this.inputManager?.removeListeners(); diff --git a/frontend/src/components/panels/LayerTree.vue b/frontend/src/components/panels/LayerTree.vue index bf8cfcb4..6c593024 100644 --- a/frontend/src/components/panels/LayerTree.vue +++ b/frontend/src/components/panels/LayerTree.vue @@ -1,5 +1,5 @@