Split out viewport handling into its own message handler (#3331)

* extract viewport handeling

* fix web overlays

* some cleanup

* remove some physical conversions

* fix resize snapping

* fixup

* apply some review feedback

* make viewport api more ergonomic

* fix

* fix web overlay canvas clear size

* clear workaround for canvas

* rename trigger message

---------

Co-authored-by: Dennis Kobert <dennis@kobert.dev>
This commit is contained in:
Timon
2025-11-08 08:59:38 +00:00
committed by GitHub
co-authored by Dennis Kobert
parent 3490111b96
commit 881ec0b193
60 changed files with 1326 additions and 607 deletions
@@ -1,14 +1,11 @@
use super::new_document_dialog::NewDocumentDialogMessageContext;
use super::simple_dialogs::{self, AboutGraphiteDialog, ComingSoonDialog, DemoArtworkDialog, LicensesDialog};
use crate::messages::dialog::simple_dialogs::LicensesThirdPartyDialog;
use crate::messages::input_mapper::utility_types::input_mouse::ViewportBounds;
use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::prelude::*;
#[derive(ExtractField)]
pub struct DialogMessageContext<'a> {
pub portfolio: &'a PortfolioMessageHandler,
pub viewport_bounds: &'a ViewportBounds,
pub preferences: &'a PreferencesMessageHandler,
}
@@ -23,15 +20,11 @@ pub struct DialogMessageHandler {
#[message_handler_data]
impl MessageHandler<DialogMessage, DialogMessageContext<'_>> for DialogMessageHandler {
fn process_message(&mut self, message: DialogMessage, responses: &mut VecDeque<Message>, context: DialogMessageContext) {
let DialogMessageContext {
portfolio,
preferences,
viewport_bounds,
} = context;
let DialogMessageContext { portfolio, preferences } = context;
match message {
DialogMessage::ExportDialog(message) => self.export_dialog.process_message(message, responses, ExportDialogMessageContext { portfolio }),
DialogMessage::NewDocumentDialog(message) => self.new_document_dialog.process_message(message, responses, NewDocumentDialogMessageContext { viewport_bounds }),
DialogMessage::NewDocumentDialog(message) => self.new_document_dialog.process_message(message, responses, ()),
DialogMessage::PreferencesDialog(message) => self.preferences_dialog.process_message(message, responses, PreferencesDialogMessageContext { preferences }),
DialogMessage::CloseAllDocumentsWithConfirmation => {
@@ -4,4 +4,4 @@ mod new_document_dialog_message_handler;
#[doc(inline)]
pub use new_document_dialog_message::{NewDocumentDialogMessage, NewDocumentDialogMessageDiscriminant};
#[doc(inline)]
pub use new_document_dialog_message_handler::{NewDocumentDialogMessageContext, NewDocumentDialogMessageHandler};
pub use new_document_dialog_message_handler::NewDocumentDialogMessageHandler;
@@ -1,13 +1,8 @@
use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::prelude::*;
use crate::messages::{input_mapper::utility_types::input_mouse::ViewportBounds, layout::utility_types::widget_prelude::*};
use glam::{IVec2, UVec2};
use graph_craft::document::NodeId;
#[derive(ExtractField)]
pub struct NewDocumentDialogMessageContext<'a> {
pub viewport_bounds: &'a ViewportBounds,
}
/// A dialog to allow users to set some initial options about a new document.
#[derive(Debug, Clone, Default, ExtractField)]
pub struct NewDocumentDialogMessageHandler {
@@ -17,8 +12,8 @@ pub struct NewDocumentDialogMessageHandler {
}
#[message_handler_data]
impl<'a> MessageHandler<NewDocumentDialogMessage, NewDocumentDialogMessageContext<'a>> for NewDocumentDialogMessageHandler {
fn process_message(&mut self, message: NewDocumentDialogMessage, responses: &mut VecDeque<Message>, context: NewDocumentDialogMessageContext<'a>) {
impl<'a> MessageHandler<NewDocumentDialogMessage, ()> for NewDocumentDialogMessageHandler {
fn process_message(&mut self, message: NewDocumentDialogMessage, responses: &mut VecDeque<Message>, _: ()) {
match message {
NewDocumentDialogMessage::Name { name } => self.name = name,
NewDocumentDialogMessage::Infinite { infinite } => self.infinite = infinite,
@@ -35,12 +30,9 @@ impl<'a> MessageHandler<NewDocumentDialogMessage, NewDocumentDialogMessageContex
});
responses.add(NavigationMessage::CanvasPan { delta: self.dimensions.as_dvec2() });
responses.add(NodeGraphMessage::RunDocumentGraph);
// If we already have bounds, we won't receive a viewport bounds update so we just fabricate one ourselves
if *context.viewport_bounds != ViewportBounds::default() {
responses.add(InputPreprocessorMessage::BoundsOfViewports {
bounds_of_viewports: vec![context.viewport_bounds.clone()],
});
}
responses.add(ViewportMessage::RepropagateUpdate);
responses.add(DeferMessage::AfterNavigationReady {
messages: vec![DocumentMessage::ZoomCanvasToFitAll.into(), DocumentMessage::DeselectAllLayers.into()],
});