diff --git a/material_maker/globals.gd b/material_maker/globals.gd index baf778c76..f65df2e30 100644 --- a/material_maker/globals.gd +++ b/material_maker/globals.gd @@ -58,6 +58,7 @@ const DEFAULT_CONFIG : Dictionary = { ui_use_native_file_dialogs = true, win_tablet_driver = 0, dialog_dim_background = true, + ui_warp_mouse_gestures = false, node_minimize_button = true, node_close_button = true, } @@ -176,11 +177,38 @@ func parse_paste_data(data : String): # Misc. UI functions +func warp_mouse(position : Vector2, node : Control) -> void: + if mm_globals.get_config("ui_warp_mouse_gestures"): + Input.mouse_mode = Input.MOUSE_MODE_HIDDEN + node.warp_mouse(position) + Input.mouse_mode = Input.MOUSE_MODE_VISIBLE + +func do_warp_mouse_y(node : Control, from_y : float, to_y : float, margin : int = 2) -> void: + var mouse_pos : Vector2 = node.get_local_mouse_position() + var mouse_pos_y_warpped : float = wrapf(mouse_pos.y, from_y + margin, to_y - margin) + if mouse_pos.y != mouse_pos_y_warpped: + warp_mouse(Vector2(mouse_pos.x, mouse_pos_y_warpped), node) + +func handle_drag_zoom_gesture(node : Control, zoom_func : Callable, + from_rect_y : float, to_rect_y : float) -> void: + node.accept_event() + zoom_func.call() + do_warp_mouse_y(node, from_rect_y, to_rect_y) + +func handle_vscroll_gesture(event : InputEvent, node : Control, vscroll : VScrollBar, + from_rect_y : float, to_rect_y : float, relative_offset_mult : float = 1.0) -> void: + if event is InputEventMouseMotion and (event.button_mask & MOUSE_BUTTON_MASK_MIDDLE) != 0: + node.mouse_default_cursor_shape = Control.CURSOR_DRAG + vscroll.value -= event.relative.y * relative_offset_mult + do_warp_mouse_y(node, from_rect_y, to_rect_y) + else: + node.mouse_default_cursor_shape = Control.CURSOR_ARROW + func popup_menu(menu : PopupMenu, parent : Control): - var zoom_fac = 1.0 + var zoom_fac : float = 1.0 if parent is GraphNode: - zoom_fac *= mm_globals.main_window.get_current_graph_edit().zoom - + zoom_fac *= main_window.get_current_graph_edit().zoom + var content_scale_factor = mm_globals.main_window.get_window().content_scale_factor menu.popup(Rect2(parent.get_local_mouse_position()*content_scale_factor*zoom_fac + parent.get_screen_position(), Vector2(0, 0))) diff --git a/material_maker/panels/graph_edit/graph_edit.gd b/material_maker/panels/graph_edit/graph_edit.gd index 739a37277..46478b885 100644 --- a/material_maker/panels/graph_edit/graph_edit.gd +++ b/material_maker/panels/graph_edit/graph_edit.gd @@ -337,6 +337,14 @@ func _gui_input(event) -> void: if rect.has_point(get_global_mouse_position()): mm_globals.set_tip_text("Space/#RMB: Nodes menu, Arrow keys: Pan, Mouse wheel: Zoom", 3) + if (event.button_mask & MOUSE_BUTTON_MASK_MIDDLE) != 0 and ( + event.ctrl_pressed or event.meta_pressed): + mm_globals.handle_drag_zoom_gesture(self, + (func(): + #force connection lines to redraw + set_connection_lines_curvature(connection_lines_curvature) + zoom -= event.relative.y / get_viewport_rect().size.y * 2.0), + get_viewport_rect().position.y, get_rect().size.y) if ((event.button_mask & MOUSE_BUTTON_MASK_RIGHT) != 0 and valid_drag_cut_entry and event.relative.length() > 1.0): if event.ctrl_pressed: @@ -361,6 +369,14 @@ func _gui_input(event) -> void: lasso_points.clear() queue_redraw() + if (event.button_mask & MOUSE_BUTTON_MASK_MIDDLE) != 0 and ( + event.ctrl_pressed or event.meta_pressed): + mm_globals.handle_drag_zoom_gesture(self, + (func() -> void: + #force connection lines to redraw + set_connection_lines_curvature(connection_lines_curvature) + zoom -= event.relative.y * 0.002), + get_viewport_rect().position.y,get_rect().size.y) func get_padded_node_rect(graph_node:GraphNode) -> Rect2: var rect : Rect2 = graph_node.get_global_rect() diff --git a/material_maker/panels/library/library.tscn b/material_maker/panels/library/library.tscn index 45adda47f..db7edddb2 100644 --- a/material_maker/panels/library/library.tscn +++ b/material_maker/panels/library/library.tscn @@ -92,6 +92,7 @@ item_5/id = 5 [connection signal="about_to_popup" from="Library/Filter/Libraries" to="." method="_on_Libraries_about_to_show"] [connection signal="item_collapsed" from="Library/Tree" to="." method="_on_Tree_item_collapsed"] [connection signal="item_mouse_selected" from="Library/Tree" to="." method="_on_tree_item_mouse_selected"] +[connection signal="ready" from="Library/Tree" to="Library/Tree" method="_on_ready"] [connection signal="pressed" from="Library/GetFromWebsite" to="." method="_on_GetFromWebsite_pressed"] [connection signal="about_to_popup" from="ItemMenu" to="Library" method="_on_PopupMenu_about_to_show"] [connection signal="index_pressed" from="ItemMenu" to="." method="_on_PopupMenu_index_pressed"] diff --git a/material_maker/panels/library/library_tree.gd b/material_maker/panels/library/library_tree.gd index 6cc8e5613..17f4f3070 100644 --- a/material_maker/panels/library/library_tree.gd +++ b/material_maker/panels/library/library_tree.gd @@ -4,6 +4,20 @@ extends Tree var scroll_position = 0.0 +var tree_scrollbar : VScrollBar + +func _on_ready() -> void: + for node in get_children(true): + if node is VScrollBar: + tree_scrollbar = node + +func _gui_input(event: InputEvent) -> void: + if event is InputEventMouseMotion: + auto_tooltip = false + mm_globals.handle_vscroll_gesture(event, self, tree_scrollbar, 0, get_rect().size.y) + else: + auto_tooltip = true + func get_last_item(parent : TreeItem): while true: if parent.collapsed: diff --git a/material_maker/panels/preview_2d/preview_2d_panel.gd b/material_maker/panels/preview_2d/preview_2d_panel.gd index d00f64453..3767c72cb 100644 --- a/material_maker/panels/preview_2d/preview_2d_panel.gd +++ b/material_maker/panels/preview_2d/preview_2d_panel.gd @@ -259,6 +259,7 @@ func on_resized() -> void: var dragging : bool = false var zooming : bool = false +var drag_zooming : bool = false func _input(event): if event.is_pressed(): @@ -288,17 +289,27 @@ func _on_gui_input(event): else: dragging = false zooming = false + drag_zooming = false elif event is InputEventMouseMotion: - if dragging: - new_center = center-event.relative*view_scale/multiplier - elif zooming: - new_scale = clamp(new_scale*(1.0+0.01*event.relative.y), 0.005, 5.0) + if (event.button_mask & MOUSE_BUTTON_MASK_MIDDLE) != 0 and ( + event.ctrl_pressed or event.meta_pressed): + drag_zooming = true + var sca : Array[float] = [new_scale] + mm_globals.handle_drag_zoom_gesture(self, + (func(): sca[0] *= 1.0 + 0.005 *event.relative.y), 0, get_rect().size.y) + new_scale = clamp(sca[0], 0.005, 5.0) + else: + if dragging: + new_center = center-event.relative*view_scale/multiplier + elif zooming: + new_scale = clamp(new_scale*(1.0+0.01*event.relative.y), 0.005, 5.0) elif event is InputEventPanGesture: new_center = center-event.delta*10.0*view_scale/multiplier elif event is InputEventMagnifyGesture: new_scale = clamp(new_scale/event.factor, 0.005, 5.0) if new_scale != view_scale: - new_center = center+offset_from_center*(view_scale-new_scale)/multiplier + if not drag_zooming: + new_center = center+offset_from_center*(view_scale-new_scale)/multiplier view_scale = new_scale need_update = true if new_center != center: diff --git a/material_maker/panels/reference/reference_panel.gd b/material_maker/panels/reference/reference_panel.gd index ce755ef82..91fdec84d 100644 --- a/material_maker/panels/reference/reference_panel.gd +++ b/material_maker/panels/reference/reference_panel.gd @@ -12,6 +12,7 @@ var current_image_index := 0 var is_picking := false var is_dragging := false var is_zooming := false +var is_drag_zooming := false var selected_slot: Button = null @@ -195,7 +196,7 @@ func handle_movement(event: InputEvent) -> void: is_dragging = event.pressed and event.shift_pressed is_zooming = event.pressed and event.is_command_or_control_pressed() and not is_dragging - + is_drag_zooming = false MOUSE_BUTTON_WHEEL_DOWN: new_scale = min(new_scale+0.05, 3) @@ -203,15 +204,24 @@ func handle_movement(event: InputEvent) -> void: new_scale = max(new_scale-0.05, 0.05) elif event is InputEventMouseMotion: - if is_dragging: - new_center = m.get_shader_parameter("center")-event.relative*image_scale/multiplier + if (event.button_mask & MOUSE_BUTTON_MASK_MIDDLE) != 0 and ( + event.ctrl_pressed or event.meta_pressed): + is_drag_zooming = true + var sca : Array[float] = [new_scale] + mm_globals.handle_drag_zoom_gesture(self, + (func(): sca[0] *= 1.0 + 0.005 * event.relative.y),0, get_rect().size.y) + new_scale = clamp(sca[0], 0.005, 3.0) + else: + if is_dragging: + new_center = m.get_shader_parameter("center")-event.relative*image_scale/multiplier - elif is_zooming: - new_scale = clamp(new_scale*(1.0+0.01*event.relative.y), 0.005, 3) + elif is_zooming: + new_scale = clamp(new_scale*(1.0+0.01*event.relative.y), 0.005, 3) if new_scale != image_scale: m.set_shader_parameter("scale", new_scale) - new_center = center+offset_from_center*(image_scale-new_scale)/multiplier + if not is_drag_zooming: + new_center = center+offset_from_center*(image_scale-new_scale)/multiplier opened_images[current_image_index].scale = new_scale if new_center != center: diff --git a/material_maker/projects_panel.tscn b/material_maker/projects_panel.tscn index 538bfa34d..4407ce373 100644 --- a/material_maker/projects_panel.tscn +++ b/material_maker/projects_panel.tscn @@ -498,7 +498,7 @@ layout_mode = 2 size_flags_vertical = 4 tooltip_text = "Middle-Mouse click and drag to turn the 3D preview. -Scroll to zoom the 3D Preview." +Scroll or Ctrl/Cmd+MMB drag to zoom the 3D Preview." [connection signal="resized" from="." to="." method="_on_projects_panel_resized"] [connection signal="no_more_tabs" from="Projects" to="." method="_on_projects_no_more_tabs"] diff --git a/material_maker/widgets/code_editor/code_editor.gd b/material_maker/widgets/code_editor/code_editor.gd index f7beca207..7fe1d45bb 100644 --- a/material_maker/widgets/code_editor/code_editor.gd +++ b/material_maker/widgets/code_editor/code_editor.gd @@ -62,6 +62,10 @@ func _on_gui_input(event): %ReplaceString.grab_focus() else: %FindString.grab_focus() + elif event is InputEventMouseMotion: + mm_globals.handle_vscroll_gesture(event, self, get_v_scroll_bar(), 0, + get_rect().size.y, 1.0 / get_line_height()) + func _on_close_pressed(): %Find.visible = false diff --git a/material_maker/windows/about/about.gd b/material_maker/windows/about/about.gd index 386628e5d..f077f1395 100644 --- a/material_maker/windows/about/about.gd +++ b/material_maker/windows/about/about.gd @@ -121,3 +121,17 @@ func _notification(what: int) -> void: for logo in $HBoxContainer/MarginContainer/SocialNetworks.get_children(): if logo.material: logo.material.set_shader_parameter("invert", is_light_theme) + %EpicLogo.material.set_shader_parameter("invert", + "light" in mm_globals.main_window.theme.resource_path) + +func _on_patrons_gui_input(event : InputEvent) -> void: + mm_globals.handle_vscroll_gesture(event, %Patrons, %Patrons.get_v_scroll_bar(), 0, + %Patrons.get_rect().size.y) + +func _on_authors_gui_input(event : InputEvent) -> void: + mm_globals.handle_vscroll_gesture(event, %Authors, %Authors.get_v_scroll_bar(), 0, + %Authors.get_rect().size.y) + +func _on_license_gui_input(event : InputEvent) -> void: + mm_globals.handle_vscroll_gesture(event, %License, %License.get_v_scroll_bar(), 0, + %License.get_rect().size.y, 1.0 / %License.get_line_height()) diff --git a/material_maker/windows/about/about.tscn b/material_maker/windows/about/about.tscn index 4c1b0632b..7628195ea 100644 --- a/material_maker/windows/about/about.tscn +++ b/material_maker/windows/about/about.tscn @@ -120,6 +120,7 @@ tab_alignment = 1 current_tab = 0 [node name="Authors" type="ScrollContainer" parent="HBoxContainer/VBoxContainer/VBoxContainer"] +unique_name_in_owner = true layout_mode = 2 metadata/_tab_index = 0 @@ -171,6 +172,7 @@ size_flags_horizontal = 4 text = "Sponsors" [node name="Patrons" type="ItemList" parent="HBoxContainer/VBoxContainer/VBoxContainer/Donors/VBoxContainer"] +unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 3 @@ -179,6 +181,7 @@ same_column_width = true fixed_column_width = 190 [node name="License" type="TextEdit" parent="HBoxContainer/VBoxContainer/VBoxContainer"] +unique_name_in_owner = true visible = false layout_mode = 2 size_flags_horizontal = 3 @@ -309,6 +312,10 @@ ignore_texture_size = true stretch_mode = 4 [connection signal="close_requested" from="." to="." method="queue_free"] +[connection signal="gui_input" from="HBoxContainer/VBoxContainer/VBoxContainer/Authors" to="." method="_on_authors_gui_input"] +[connection signal="gui_input" from="HBoxContainer/VBoxContainer/VBoxContainer/Donors" to="." method="_on_donors_gui_input"] +[connection signal="gui_input" from="HBoxContainer/VBoxContainer/VBoxContainer/Donors/VBoxContainer/Patrons" to="." method="_on_patrons_gui_input"] +[connection signal="gui_input" from="HBoxContainer/VBoxContainer/VBoxContainer/License" to="." method="_on_license_gui_input"] [connection signal="pressed" from="HBoxContainer/MarginContainer/SocialNetworks/Patreon" to="." method="open_url" binds= ["https://www.patreon.com/rodzlabs"]] [connection signal="pressed" from="HBoxContainer/MarginContainer/SocialNetworks/ItchIo" to="." method="open_url" binds= ["https://rodzilla.itch.io/material-maker"]] [connection signal="pressed" from="HBoxContainer/MarginContainer/SocialNetworks/Github" to="." method="open_url" binds= ["https://github.com/RodZill4/godot-procedural-textures"]] diff --git a/material_maker/windows/add_node_popup/add_node_popup.gd b/material_maker/windows/add_node_popup/add_node_popup.gd index 711cc6230..4c54932eb 100644 --- a/material_maker/windows/add_node_popup/add_node_popup.gd +++ b/material_maker/windows/add_node_popup/add_node_popup.gd @@ -13,7 +13,6 @@ var qc_is_output : bool @onready var library_manager = get_node("/root/MainWindow/NodeLibraryManager") - func get_current_graph(): return get_parent().get_current_graph_edit() @@ -215,7 +214,10 @@ func _on_list_gui_input(event: InputEvent) -> void: var idx: int = %List.get_item_at_position(%List.get_local_mouse_position(), true) if idx != -1: _on_list_item_activated(idx) - + elif event is InputEventMouseMotion: + var list_rect = %List.get_rect() + mm_globals.handle_vscroll_gesture(event, %List, %List.get_v_scroll_bar(), + 0, list_rect.size.y) func get_list_drag_data(m_position): var data = %List.get_item_metadata(%List.get_item_at_position(m_position)) diff --git a/material_maker/windows/environment_editor/camera_controller.gd b/material_maker/windows/environment_editor/camera_controller.gd index afe130e77..eee2fd201 100644 --- a/material_maker/windows/environment_editor/camera_controller.gd +++ b/material_maker/windows/environment_editor/camera_controller.gd @@ -26,6 +26,17 @@ func process_event(event : InputEvent, viewport : Viewport = null) -> bool: var factor = 0.0025*camera_position.position.z camera_target_position.translate(-factor*event.relative.x*camera_position.global_transform.basis.x) camera_target_position.translate(factor*event.relative.y*camera_position.global_transform.basis.y) + elif event.ctrl_pressed or event.meta_pressed: + if get_parent().name == "Preview3d": + var preview_3d : SubViewportContainer = get_parent().owner + + mm_globals.handle_drag_zoom_gesture(preview_3d, + (func() -> void: + var amount : float = 1.0 + event.relative.y * 0.002 + camera_position.position.z = clamp( + camera_position.position.z * amount, + preview_3d.CAMERA_DISTANCE_MIN, preview_3d.CAMERA_DISTANCE_MAX) + ), 0, preview_3d.get_rect().size.y) else: camera_rotation2.rotate_x(-0.01*event.relative.y) camera_rotation1.rotate_y(-0.01*event.relative.x) diff --git a/material_maker/windows/environment_editor/environment_editor.gd b/material_maker/windows/environment_editor/environment_editor.gd index d6056d471..2be19d57a 100644 --- a/material_maker/windows/environment_editor/environment_editor.gd +++ b/material_maker/windows/environment_editor/environment_editor.gd @@ -136,14 +136,21 @@ func _on_Environments_item_selected(index): environment_list.select(index) set_current_environment(index) + func _on_Environments_gui_input(event): - if ! (event is InputEventMouseButton) or event.button_index != MOUSE_BUTTON_RIGHT: + if event is InputEventMouseMotion: + var rect : Rect2 = environment_list.get_rect() + mm_globals.handle_vscroll_gesture(event, environment_list, + environment_list.get_v_scroll_bar(), rect.position.y, rect.size.y) + + elif ! (event is InputEventMouseButton) or event.button_index != MOUSE_BUTTON_RIGHT: return var context_menu : PopupMenu = $Main/HSplitContainer/Environments/ContextMenu var index = environment_list.get_item_at_position(event.position) if environment_list.is_selected(index) and ! environment_manager.is_read_only(index): mm_globals.popup_menu(context_menu, $Main/HSplitContainer/Environments) + func _on_ContextMenu_id_pressed(id): var index = environment_list.get_selected_items()[0] environment_manager.delete_environment(index) diff --git a/material_maker/windows/load_from_website/load_from_website.gd b/material_maker/windows/load_from_website/load_from_website.gd index 35738798c..b124d8a59 100644 --- a/material_maker/windows/load_from_website/load_from_website.gd +++ b/material_maker/windows/load_from_website/load_from_website.gd @@ -157,3 +157,7 @@ func _on_VBoxContainer_minimum_size_changed(): func _on_Filter_changed(new_text): fill_list(new_text) + +func _on_item_list_gui_input(event: InputEvent) -> void: + mm_globals.handle_vscroll_gesture(event, item_list, item_list.get_v_scroll_bar(), 0, + item_list.get_rect().size.y) diff --git a/material_maker/windows/load_from_website/load_from_website.tscn b/material_maker/windows/load_from_website/load_from_website.tscn index 92faf71f4..2b7e514ff 100644 --- a/material_maker/windows/load_from_website/load_from_website.tscn +++ b/material_maker/windows/load_from_website/load_from_website.tscn @@ -60,6 +60,7 @@ text = "Cancel" [connection signal="close_requested" from="." to="." method="_on_Cancel_pressed"] [connection signal="minimum_size_changed" from="VBoxContainer" to="." method="_on_VBoxContainer_minimum_size_changed"] [connection signal="text_changed" from="VBoxContainer/Filter/LineEdit" to="." method="_on_Filter_changed"] +[connection signal="gui_input" from="VBoxContainer/ItemList" to="." method="_on_item_list_gui_input"] [connection signal="item_activated" from="VBoxContainer/ItemList" to="." method="_on_ItemList_item_activated"] [connection signal="item_selected" from="VBoxContainer/ItemList" to="." method="_on_ItemList_item_selected"] [connection signal="pressed" from="VBoxContainer/Buttons/OK" to="." method="_on_OK_pressed"] diff --git a/material_maker/windows/preferences/preferences.gd b/material_maker/windows/preferences/preferences.gd index 6105f2e72..ab47bdd4a 100644 --- a/material_maker/windows/preferences/preferences.gd +++ b/material_maker/windows/preferences/preferences.gd @@ -71,3 +71,9 @@ func _on_DownloadLanguage_closed(): func _on_ready() -> void: %WinTabletDriver.visible = OS.get_name() == "Windows" %WinTabletDriverSpacer.visible = OS.get_name() == "Windows" + setup_scroll_gestures() + +func setup_scroll_gestures() -> void: + for tab : ScrollContainer in %TabContainer.get_children(): + tab.gui_input.connect(func(e : InputEvent) -> void: + mm_globals.handle_vscroll_gesture(e, tab, tab.get_v_scroll_bar(), 0.0, tab.get_rect().size.y)) diff --git a/material_maker/windows/preferences/preferences.tscn b/material_maker/windows/preferences/preferences.tscn index 5e33751ba..f8bef11aa 100644 --- a/material_maker/windows/preferences/preferences.tscn +++ b/material_maker/windows/preferences/preferences.tscn @@ -4,9 +4,9 @@ [ext_resource type="Script" uid="uid://cwom8loyqsvf2" path="res://material_maker/windows/preferences/preferences.gd" id="2"] [ext_resource type="FontFile" uid="uid://bn648prik7soq" path="res://material_maker/theme/font_rubik/Rubik-416.ttf" id="2_vp06c"] [ext_resource type="PackedScene" uid="uid://3lo2jh781ten" path="res://material_maker/windows/preferences/float_option.tscn" id="3"] -[ext_resource type="Script" path="res://material_maker/windows/preferences/preferences_tree.gd" id="3_mlqij"] +[ext_resource type="Script" uid="uid://b6irr1ykhui6l" path="res://material_maker/windows/preferences/preferences_tree.gd" id="3_mlqij"] [ext_resource type="Script" uid="uid://gmystrme5ayw" path="res://material_maker/windows/preferences/lang_option.gd" id="4"] -[ext_resource type="Script" path="res://material_maker/windows/preferences/enum_option.gd" id="5_vp06c"] +[ext_resource type="Script" uid="uid://d3h4xmek7b2vq" path="res://material_maker/windows/preferences/enum_option.gd" id="5_vp06c"] [node name="Preferences" type="Window"] oversampling_override = 1.0 @@ -191,6 +191,27 @@ text = "On" flat = false config_variable = "dialog_dim_background" +[node name="GuiWarpMouseGestures" type="HBoxContainer" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/General/VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/General/VBoxContainer/GuiWarpMouseGestures"] +layout_mode = 2 +mouse_filter = 1 +text = "Warp mouse gestures" + +[node name="GuiWarpMouseGestures" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/General/VBoxContainer/GuiWarpMouseGestures" instance=ExtResource("1")] +custom_minimum_size = Vector2(200, 0) +layout_mode = 2 +size_flags_horizontal = 10 +tooltip_text = "Drag zoom/scroll via Ctrl/Cmd + MMB / MMB + +This makes it possible to move over a large area without +exiting and having to adjust mouse position, but may cause +issues with some OSes and/or pen input devices." +text = "On" +flat = false +config_variable = "ui_warp_mouse_gestures" + [node name="Spacer5" type="Control" parent="HSplitContainer/PreferencesPanel/VBoxContainer/TabContainer/General/VBoxContainer"] custom_minimum_size = Vector2(0, 10) layout_mode = 2