Improve document tilt and reset

This commit is contained in:
Keavon Chambers 2024-01-15 04:05:36 -08:00
parent d602603d46
commit 8eef96511e
5 changed files with 82 additions and 50 deletions

View File

@ -826,7 +826,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
} }
ZoomCanvasToFitAll => { ZoomCanvasToFitAll => {
if let Some(bounds) = self.metadata().document_bounds_document_space(true) { if let Some(bounds) = self.metadata().document_bounds_document_space(true) {
responses.add(NavigationMessage::SetCanvasRotation { angle_radians: 0. }); responses.add(NavigationMessage::SetCanvasTilt { angle_radians: 0. });
responses.add(NavigationMessage::FitViewportToBounds { bounds, prevent_zoom_past_100: true }); responses.add(NavigationMessage::FitViewportToBounds { bounds, prevent_zoom_past_100: true });
} }
} }
@ -1104,7 +1104,37 @@ impl DocumentMessageHandler {
} }
pub fn update_document_widgets(&self, responses: &mut VecDeque<Message>) { pub fn update_document_widgets(&self, responses: &mut VecDeque<Message>) {
// Document mode (dropdown menu at the left of the bar above the viewport, before the tool options)
let document_mode_layout = WidgetLayout::new(vec![LayoutGroup::Row {
widgets: vec![
DropdownInput::new(
vec![vec![
MenuListEntry::new(DocumentMode::DesignMode.to_string()).icon(DocumentMode::DesignMode.icon_name()),
MenuListEntry::new(DocumentMode::SelectMode.to_string())
.icon(DocumentMode::SelectMode.icon_name())
.on_update(|_| DialogMessage::RequestComingSoonDialog { issue: Some(330) }.into()),
MenuListEntry::new(DocumentMode::GuideMode.to_string())
.icon(DocumentMode::GuideMode.icon_name())
.on_update(|_| DialogMessage::RequestComingSoonDialog { issue: Some(331) }.into()),
]])
.selected_index(Some(self.document_mode as u32))
.draw_icon( true)
.interactive( false) // TODO: set to true when dialogs are not spawned
.widget_holder(),
Separator::new(SeparatorType::Section).widget_holder(),
],
}]);
responses.add(LayoutMessage::SendLayout {
layout: Layout::WidgetLayout(document_mode_layout),
layout_target: LayoutTarget::DocumentMode,
});
// Document bar (right portion of the bar above the viewport)
let snapping_state = self.snapping_state.clone(); let snapping_state = self.snapping_state.clone();
let mut widgets = vec![ let mut widgets = vec![
CheckboxInput::new(self.overlays_visible) CheckboxInput::new(self.overlays_visible)
.icon("Overlays") .icon("Overlays")
@ -1211,13 +1241,27 @@ impl DocumentMessageHandler {
.on_update(|_| NavigationMessage::DecreaseCanvasZoom { center_on_mouse: false }.into()) .on_update(|_| NavigationMessage::DecreaseCanvasZoom { center_on_mouse: false }.into())
.widget_holder(), .widget_holder(),
IconButton::new("ZoomReset", 24) IconButton::new("ZoomReset", 24)
.tooltip("Zoom to 100%") .tooltip("Reset Tilt and Zoom to 100%")
.tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::ZoomCanvasTo100Percent)) .tooltip_shortcut(action_keys!(NavigationMessageDiscriminant::ResetCanvasTiltAndZoomTo100Percent))
.on_update(|_| NavigationMessage::SetCanvasZoom { zoom_factor: 1. }.into()) .on_update(|_| NavigationMessage::ResetCanvasTiltAndZoomTo100Percent.into())
.widget_holder(), .widget_holder(),
PopoverButton::new( PopoverButton::new(
"Canvas Navigation", "Canvas Navigation",
"Interactive controls in this\nmenu are coming soon.\n\nPan:\n• Middle Click Drag\n\nTilt:\n• Alt + Middle Click Drag\n\nZoom:\n• Shift + Middle Click Drag\n• Ctrl + Scroll Wheel Roll", "
Interactive controls in this\n\
menu are coming soon.\n\
\n\
Pan:\n\
Middle Click Drag\n\
\n\
Tilt:\n\
Alt + Middle Click Drag\n\
\n\
Zoom:\n\
Shift + Middle Click Drag\n\
Ctrl + Scroll Wheel Roll
"
.trim(),
) )
.widget_holder(), .widget_holder(),
Separator::new(SeparatorType::Related).widget_holder(), Separator::new(SeparatorType::Related).widget_holder(),
@ -1225,7 +1269,7 @@ impl DocumentMessageHandler {
.unit("%") .unit("%")
.min(0.000001) .min(0.000001)
.max(1000000.) .max(1000000.)
.mode_increment() .tooltip("Document zoom within the viewport")
.on_update(|number_input: &NumberInput| { .on_update(|number_input: &NumberInput| {
NavigationMessage::SetCanvasZoom { NavigationMessage::SetCanvasZoom {
zoom_factor: number_input.value.unwrap() / 100., zoom_factor: number_input.value.unwrap() / 100.,
@ -1236,23 +1280,18 @@ impl DocumentMessageHandler {
.increment_callback_decrease(|_| NavigationMessage::DecreaseCanvasZoom { center_on_mouse: false }.into()) .increment_callback_decrease(|_| NavigationMessage::DecreaseCanvasZoom { center_on_mouse: false }.into())
.increment_callback_increase(|_| NavigationMessage::IncreaseCanvasZoom { center_on_mouse: false }.into()) .increment_callback_increase(|_| NavigationMessage::IncreaseCanvasZoom { center_on_mouse: false }.into())
.widget_holder(), .widget_holder(),
Separator::new(SeparatorType::Unrelated).widget_holder(),
TextButton::new("Node Graph")
.icon(Some(if self.graph_view_overlay_open { "GraphViewOpen".into() } else { "GraphViewClosed".into() }))
.tooltip(if self.graph_view_overlay_open { "Hide Node Graph" } else { "Show Node Graph" })
.tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::GraphViewOverlayToggle))
.on_update(move |_| DocumentMessage::GraphViewOverlayToggle.into())
.widget_holder(),
]; ];
let rotation_value = self.navigation_handler.snapped_angle(self.navigation.tilt) / (std::f64::consts::PI / 180.);
if rotation_value.abs() > 0.00001 { let tilt_value = self.navigation_handler.snapped_angle(self.navigation.tilt) / (std::f64::consts::PI / 180.);
if tilt_value.abs() > 0.00001 {
widgets.extend([ widgets.extend([
Separator::new(SeparatorType::Related).widget_holder(), Separator::new(SeparatorType::Related).widget_holder(),
NumberInput::new(Some(rotation_value)) NumberInput::new(Some(tilt_value))
.unit("°") .unit("°")
.step(15.) .step(15.)
.tooltip("Document tilt within the viewport")
.on_update(|number_input: &NumberInput| { .on_update(|number_input: &NumberInput| {
NavigationMessage::SetCanvasRotation { NavigationMessage::SetCanvasTilt {
angle_radians: number_input.value.unwrap() * (std::f64::consts::PI / 180.), angle_radians: number_input.value.unwrap() * (std::f64::consts::PI / 180.),
} }
.into() .into()
@ -1260,37 +1299,23 @@ impl DocumentMessageHandler {
.widget_holder(), .widget_holder(),
]); ]);
} }
let document_bar_layout = WidgetLayout::new(vec![LayoutGroup::Row { widgets }]);
let document_mode_layout = WidgetLayout::new(vec![LayoutGroup::Row { widgets.extend([
widgets: vec![ Separator::new(SeparatorType::Unrelated).widget_holder(),
DropdownInput::new( TextButton::new("Node Graph")
vec![vec![ .icon(Some(if self.graph_view_overlay_open { "GraphViewOpen".into() } else { "GraphViewClosed".into() }))
MenuListEntry::new(DocumentMode::DesignMode.to_string()).icon(DocumentMode::DesignMode.icon_name()), .tooltip(if self.graph_view_overlay_open { "Hide Node Graph" } else { "Show Node Graph" })
MenuListEntry::new(DocumentMode::SelectMode.to_string()) .tooltip_shortcut(action_keys!(DocumentMessageDiscriminant::GraphViewOverlayToggle))
.icon(DocumentMode::SelectMode.icon_name()) .on_update(move |_| DocumentMessage::GraphViewOverlayToggle.into())
.on_update(|_| DialogMessage::RequestComingSoonDialog { issue: Some(330) }.into()), .widget_holder(),
MenuListEntry::new(DocumentMode::GuideMode.to_string()) ]);
.icon(DocumentMode::GuideMode.icon_name())
.on_update(|_| DialogMessage::RequestComingSoonDialog { issue: Some(331) }.into()), let document_bar_layout = WidgetLayout::new(vec![LayoutGroup::Row { widgets }]);
]])
.selected_index(Some(self.document_mode as u32))
.draw_icon( true)
.interactive( false) // TODO: set to true when dialogs are not spawned
.widget_holder(),
Separator::new(SeparatorType::Section).widget_holder(),
],
}]);
responses.add(LayoutMessage::SendLayout { responses.add(LayoutMessage::SendLayout {
layout: Layout::WidgetLayout(document_bar_layout), layout: Layout::WidgetLayout(document_bar_layout),
layout_target: LayoutTarget::DocumentBar, layout_target: LayoutTarget::DocumentBar,
}); });
responses.add(LayoutMessage::SendLayout {
layout: Layout::WidgetLayout(document_mode_layout),
layout_target: LayoutTarget::DocumentMode,
});
} }
pub fn update_layers_panel_options_bar_widgets(&self, responses: &mut VecDeque<Message>) { pub fn update_layers_panel_options_bar_widgets(&self, responses: &mut VecDeque<Message>) {

View File

@ -26,10 +26,11 @@ pub enum NavigationMessage {
snap_zoom: Key, snap_zoom: Key,
zoom_from_viewport: Option<DVec2>, zoom_from_viewport: Option<DVec2>,
}, },
ResetCanvasTiltAndZoomTo100Percent,
RotateCanvasBegin { RotateCanvasBegin {
was_dispatched_from_menu: bool, was_dispatched_from_menu: bool,
}, },
SetCanvasRotation { SetCanvasTilt {
angle_radians: f64, angle_radians: f64,
}, },
SetCanvasZoom { SetCanvasZoom {

View File

@ -147,7 +147,7 @@ impl MessageHandler<NavigationMessage, (&DocumentMetadata, Option<[DVec2; 2]>, &
start_offset.angle_between(end_offset) start_offset.angle_between(end_offset)
}; };
responses.add(SetCanvasRotation { angle_radians: ptz.tilt + rotation }); responses.add(SetCanvasTilt { angle_radians: ptz.tilt + rotation });
} }
TransformOperation::Zoom { snap_zoom_enabled, pre_commit_zoom } => { TransformOperation::Zoom { snap_zoom_enabled, pre_commit_zoom } => {
let zoom_start = self.snapped_scale(ptz.zoom); let zoom_start = self.snapped_scale(ptz.zoom);
@ -184,6 +184,12 @@ impl MessageHandler<NavigationMessage, (&DocumentMetadata, Option<[DVec2; 2]>, &
self.mouse_position = ipp.mouse.position; self.mouse_position = ipp.mouse.position;
} }
ResetCanvasTiltAndZoomTo100Percent => {
ptz.tilt = 0.;
ptz.zoom = 1.;
responses.add(PortfolioMessage::UpdateDocumentWidgets);
self.create_document_transform(ipp.viewport_bounds.center(), &ptz, responses);
}
RotateCanvasBegin { was_dispatched_from_menu } => { RotateCanvasBegin { was_dispatched_from_menu } => {
responses.add(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::Default }); responses.add(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::Default });
responses.add(FrontendMessage::UpdateInputHints { responses.add(FrontendMessage::UpdateInputHints {
@ -210,7 +216,7 @@ impl MessageHandler<NavigationMessage, (&DocumentMetadata, Option<[DVec2; 2]>, &
self.mouse_position = ipp.mouse.position; self.mouse_position = ipp.mouse.position;
self.finish_operation_with_click = was_dispatched_from_menu; self.finish_operation_with_click = was_dispatched_from_menu;
} }
SetCanvasRotation { angle_radians } => { SetCanvasTilt { angle_radians } => {
ptz.tilt = angle_radians; ptz.tilt = angle_radians;
self.create_document_transform(ipp.viewport_bounds.center(), &ptz, responses); self.create_document_transform(ipp.viewport_bounds.center(), &ptz, responses);
responses.add(PortfolioMessage::UpdateDocumentWidgets); responses.add(PortfolioMessage::UpdateDocumentWidgets);
@ -226,7 +232,7 @@ impl MessageHandler<NavigationMessage, (&DocumentMetadata, Option<[DVec2; 2]>, &
match self.transform_operation { match self.transform_operation {
TransformOperation::None => {} TransformOperation::None => {}
TransformOperation::Rotate { pre_commit_tilt, .. } => { TransformOperation::Rotate { pre_commit_tilt, .. } => {
responses.add(SetCanvasRotation { angle_radians: pre_commit_tilt }); responses.add(SetCanvasTilt { angle_radians: pre_commit_tilt });
} }
TransformOperation::Pan { pre_commit_pan, .. } => { TransformOperation::Pan { pre_commit_pan, .. } => {
ptz.pan = pre_commit_pan; ptz.pan = pre_commit_pan;
@ -323,7 +329,7 @@ impl MessageHandler<NavigationMessage, (&DocumentMetadata, Option<[DVec2; 2]>, &
TranslateCanvasBegin, TranslateCanvasBegin,
RotateCanvasBegin, RotateCanvasBegin,
ZoomCanvasBegin, ZoomCanvasBegin,
SetCanvasRotation, SetCanvasTilt,
WheelCanvasZoom, WheelCanvasZoom,
IncreaseCanvasZoom, IncreaseCanvasZoom,
DecreaseCanvasZoom, DecreaseCanvasZoom,

View File

@ -1303,7 +1303,7 @@ pub fn quantize_properties(document_node: &DocumentNode, node_id: NodeId, _conte
pub fn exposure_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> { pub fn exposure_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
let exposure = number_widget(document_node, node_id, 1, "Exposure", NumberInput::default().min(-20.).max(20.), true); let exposure = number_widget(document_node, node_id, 1, "Exposure", NumberInput::default().min(-20.).max(20.), true);
let offset = number_widget(document_node, node_id, 2, "Offset", NumberInput::default().min(-0.5).max(0.5), true); let offset = number_widget(document_node, node_id, 2, "Offset", NumberInput::default().min(-0.5).max(0.5), true);
let gamma_input = NumberInput::default().min(0.01).max(9.99).mode_increment().increment_step(0.1); let gamma_input = NumberInput::default().min(0.01).max(9.99).increment_step(0.1);
let gamma_correction = number_widget(document_node, node_id, 3, "Gamma Correction", gamma_input, true); let gamma_correction = number_widget(document_node, node_id, 3, "Gamma Correction", gamma_input, true);
vec![ vec![

View File

@ -273,8 +273,8 @@ impl LayoutHolder for MenuBarMessageHandler {
}, },
MenuBarEntry { MenuBarEntry {
label: "Reset Tilt".into(), label: "Reset Tilt".into(),
shortcut: action_keys!(NavigationMessageDiscriminant::SetCanvasRotation), shortcut: action_keys!(NavigationMessageDiscriminant::SetCanvasTilt),
action: MenuBarEntry::create_action(|_| NavigationMessage::SetCanvasRotation { angle_radians: 0.into() }.into()), action: MenuBarEntry::create_action(|_| NavigationMessage::SetCanvasTilt { angle_radians: 0.into() }.into()),
disabled: no_active_document, disabled: no_active_document,
..MenuBarEntry::default() ..MenuBarEntry::default()
}, },