diff --git a/material_maker/doc/user_interface_main_menu.rst b/material_maker/doc/user_interface_main_menu.rst index b0d6c2179..0f3e83cc3 100644 --- a/material_maker/doc/user_interface_main_menu.rst +++ b/material_maker/doc/user_interface_main_menu.rst @@ -80,7 +80,11 @@ Edit menu * *Select targets* selects all direct and indirect target nodes of the current selection -* *Align Start/Center/End* align selections horizontally +* *Align Top* align selections vertically by their top edge + +* *Align Start/End* align selections horizontally + +* *Straighten Connections* straighten connection lines between two or more connected nodes. * *Load Selection* Loads a graph selection previously saved into a file diff --git a/material_maker/doc/user_interface_shortcuts.rst b/material_maker/doc/user_interface_shortcuts.rst index b0ea0d3ec..158355edc 100644 --- a/material_maker/doc/user_interface_shortcuts.rst +++ b/material_maker/doc/user_interface_shortcuts.rst @@ -104,11 +104,14 @@ Graph Editor +-------------------------------------------------------+----------------------------------------------------+ | :kbd:`Ctrl/Cmd-Shift-L` | Select target nodes fom current selection | +-------------------------------------------------------+----------------------------------------------------+ -| :kbd:`Ctrl/Cmd-[` | Align node(s) horizontally (start) | +| :kbd:`Shift-A` | Align node(s) horizontally (start) | +-------------------------------------------------------+----------------------------------------------------+ -| :kbd:`Ctrl/Cmd-\\` | Align node(s) horizontally (center) | +| :kbd:`Shift-W` | Align node(s) by their top edge | +-------------------------------------------------------+----------------------------------------------------+ -| :kbd:`Ctrl/Cmd-]` | Align node(s) horizontally (end) | +| :kbd:`Shift-D` | Align node(s) horizontally (end) | ++-------------------------------------------------------+----------------------------------------------------+ +| :kbd:`Q` | straighten connection lines between two or more | +| | connected nodes. | +-------------------------------------------------------+----------------------------------------------------+ | :kbd:`Ctrl/Cmd-I` | Invert selection | +-------------------------------------------------------+----------------------------------------------------+ diff --git a/material_maker/main_window.gd b/material_maker/main_window.gd index 48db5a475..d497f17cb 100644 --- a/material_maker/main_window.gd +++ b/material_maker/main_window.gd @@ -85,9 +85,10 @@ const MENU : Array[Dictionary] = [ { menu="Edit/Select Sources", command="edit_select_sources", shortcut="Control+L" }, { menu="Edit/Select Targets", command="edit_select_targets", shortcut="Control+Shift+L" }, { menu="Edit/-" }, - { menu="Edit/Align Start", command="edit_align_start", shortcut="Control+BRACKETLEFT" }, - { menu="Edit/Align Center", command="edit_align_center", shortcut="Control+BACKSLASH" }, - { menu="Edit/Align End", command="edit_align_end", shortcut="Control+BRACKETRIGHT" }, + { menu="Edit/Align Top", command="edit_align_top", shortcut="Shift+W" }, + { menu="Edit/Align Start", command="edit_align_start", shortcut="Shift+A" }, + { menu="Edit/Align End", command="edit_align_end", shortcut="Shift+D" }, + { menu="Edit/Straighten Connections", command="edit_straighten_connections", shortcut="Q" }, { menu="Edit/-" }, { menu="Edit/Load Selection", command="edit_load_selection", not_in_ports=["HTML5"] }, { menu="Edit/Save Selection", command="edit_save_selection", not_in_ports=["HTML5"] }, @@ -1000,33 +1001,24 @@ func edit_preferences() -> void: dialog.edit_preferences(mm_globals.config) func edit_align_start() -> void: - var nodes : Array = get_current_graph_edit().get_selected_nodes() - var min_offset : float = INF - - for node : GraphElement in nodes: - min_offset = min(min_offset, node.position_offset.x) - for node : GraphElement in nodes: - node.position_offset.x = min_offset - -func edit_align_center() -> void: - var nodes : Array = get_current_graph_edit().get_selected_nodes() - var min_offset : float = INF - var max_offset : float = -INF - - for node : GraphElement in nodes: - max_offset = max(max_offset, node.position_offset.x + node.size.x) - min_offset = min(min_offset, node.position_offset.x) - for node : GraphElement in nodes: - node.position_offset.x = (max_offset + min_offset) * 0.5 - (node.size.x * 0.5) + var graph_edit : MMGraphEdit = get_current_graph_edit() + if graph_edit != null: + graph_edit.align_start() func edit_align_end() -> void: - var nodes : Array = get_current_graph_edit().get_selected_nodes() - var max_offset : float = -INF + var graph_edit : MMGraphEdit = get_current_graph_edit() + if graph_edit != null: + graph_edit.align_end() + +func edit_align_top() -> void: + var graph_edit : MMGraphEdit = get_current_graph_edit() + if graph_edit != null: + graph_edit.align_top() - for node : GraphElement in nodes: - max_offset = max(max_offset, node.position_offset.x + node.size.x) - for node : GraphElement in nodes: - node.position_offset.x = max_offset - node.size.x +func edit_straighten_connections() -> void: + var graph_edit : MMGraphEdit = get_current_graph_edit() + if graph_edit != null: + graph_edit.straighten_connections() func view_center() -> void: var graph_edit : MMGraphEdit = get_current_graph_edit() diff --git a/material_maker/panels/graph_edit/graph_align_menu.gd b/material_maker/panels/graph_edit/graph_align_menu.gd index a0918769b..321a8a677 100644 --- a/material_maker/panels/graph_edit/graph_align_menu.gd +++ b/material_maker/panels/graph_edit/graph_align_menu.gd @@ -5,9 +5,13 @@ func _on_align_start_pressed() -> void: mm_globals.main_window.edit_align_start() -func _on_align_center_pressed() -> void: - mm_globals.main_window.edit_align_center() - - func _on_align_end_pressed() -> void: mm_globals.main_window.edit_align_end() + + +func _on_align_top_pressed() -> void: + mm_globals.main_window.edit_align_top() + + +func _on_straighten_pressed() -> void: + mm_globals.main_window.edit_straighten_connections() diff --git a/material_maker/panels/graph_edit/graph_edit.gd b/material_maker/panels/graph_edit/graph_edit.gd index 4ee270890..5ce1c2be9 100644 --- a/material_maker/panels/graph_edit/graph_edit.gd +++ b/material_maker/panels/graph_edit/graph_edit.gd @@ -274,12 +274,6 @@ func _gui_input(event) -> void: minimize_selection() KEY_DELETE,KEY_BACKSPACE,KEY_X: remove_selection() - KEY_C: - if OS.get_name() == "macOS": - center_view() - KEY_MASK_ALT | KEY_S: - if OS.get_name() == "macOS": - swap_node_inputs() KEY_LEFT: scroll_offset.x -= 0.5*size.x accept_event() @@ -299,6 +293,26 @@ func _gui_input(event) -> void: has_grab = true KEY_ESCAPE: has_grab = false + + # macOS global menu does not support single-key accelerators + # and they also require Cmd/Ctrl to be present in them to work + # see https://github.com/godotengine/godot/issues/108622 + # As a workaround the menu items are invoked here + if OS.get_name() == "macOS": + match scancode_with_modifiers: + KEY_C: + center_view() + KEY_MASK_ALT | KEY_S: + swap_node_inputs() + KEY_Q: + straighten_connections() + KEY_MASK_SHIFT | KEY_W: + align_top() + KEY_MASK_SHIFT | KEY_A: + align_start() + KEY_MASK_SHIFT | KEY_D: + align_end() + match event.get_keycode(): KEY_SHIFT, KEY_CTRL, KEY_ALT: var found_tip : bool = false @@ -1924,3 +1938,53 @@ func _on_connection_drag_started(_from_node : StringName, _from_port : int, _is_ func _on_connection_drag_ended() -> void: is_dragging_connection = false + +func align_start() -> void: + var nodes : Array = get_selected_nodes() + var min_offset : float = INF + + for node : GraphElement in nodes: + min_offset = min(min_offset, node.position_offset.x) + for node : GraphElement in nodes: + node.position_offset.x = min_offset + +func align_end() -> void: + var nodes : Array = get_selected_nodes() + var max_offset : float = -INF + + for node : GraphElement in nodes: + max_offset = max(max_offset, node.position_offset.x + node.size.x) + for node : GraphElement in nodes: + node.position_offset.x = max_offset - node.size.x + +func align_top() -> void: + var nodes : Array = get_selected_nodes().filter(func(n): return n is GraphNode) + nodes.sort_custom(func(a: GraphNode, b: GraphNode): + return a.position_offset.x < b.position_offset.x) + for node in nodes: + node.position_offset.y = nodes[0].position_offset.y + +func straighten_connections() -> void: + # basic connection straightening + # expects selected nodes to be connected along a line + # and connections are made from left to right(in/out port position) + var nodes : Array = get_selected_nodes().filter(func(n): return n is GraphNode) + if nodes.size() < 2: + return + nodes.sort_custom(func(a, b) -> bool: + return a.position_offset.x < b.position_offset.x) + for i in nodes.size() - 1: + var from_node : MMGraphNodeMinimal = nodes[i] + var to_node : MMGraphNodeMinimal = nodes[i + 1] + var conns : Array[Dictionary] + for c in connections: + if c.to_node == to_node.name: + conns.append(c) + if conns.is_empty(): + return + for conn in conns: + if conn.from_node == from_node.name: + var from_pos_y = from_node.get_output_port_position(conn.from_port).y + from_node.position_offset.y + var to_pos_y = to_node.get_input_port_position(conn.to_port).y + to_node.position_offset.y + var y_diff = to_pos_y - from_pos_y + to_node.position_offset.y -= y_diff diff --git a/material_maker/projects_panel.tscn b/material_maker/projects_panel.tscn index 538bfa34d..a9c12d147 100644 --- a/material_maker/projects_panel.tscn +++ b/material_maker/projects_panel.tscn @@ -439,15 +439,15 @@ icon_alignment = 1 script = ExtResource("7_qnupl") icon_name = "align_start" -[node name="AlignCenter" type="Button" parent="MenuBar/HBox/AlignMenu/HBox"] +[node name="AlignTop" type="Button" parent="MenuBar/HBox/AlignMenu/HBox"] custom_minimum_size = Vector2(25, 25) layout_mode = 2 -tooltip_text = "Align Center" +tooltip_text = "Align Top" shortcut = SubResource("Shortcut_7tisq") shortcut_in_tooltip = false icon_alignment = 1 script = ExtResource("7_qnupl") -icon_name = "align_center" +icon_name = "align_top" [node name="AlignEnd" type="Button" parent="MenuBar/HBox/AlignMenu/HBox"] custom_minimum_size = Vector2(25, 25) @@ -459,6 +459,16 @@ icon_alignment = 1 script = ExtResource("7_qnupl") icon_name = "align_end" +[node name="Straighten" type="Button" parent="MenuBar/HBox/AlignMenu/HBox"] +custom_minimum_size = Vector2(25, 25) +layout_mode = 2 +tooltip_text = "Straighten Connections" +shortcut = SubResource("Shortcut_7tisq") +shortcut_in_tooltip = false +icon_alignment = 1 +script = ExtResource("7_qnupl") +icon_name = "straighten_connections" + [node name="PreviewsMenu" type="PanelContainer" parent="MenuBar/HBox"] unique_name_in_owner = true layout_mode = 2 @@ -523,8 +533,9 @@ Scroll to zoom the 3D Preview." [connection signal="value_changed" from="MenuBar/HBox/MainGraphMenuBar/HBox/ViewMenu/ViewMenuPanel/VBoxContainer/VBoxContainer2/Curvature/LineCurvature" to="MenuBar/HBox/MainGraphMenuBar/HBox/ViewMenu" method="_on_line_curvature_value_changed"] [connection signal="value_changed" from="MenuBar/HBox/MainGraphMenuBar/HBox/ViewMenu/ViewMenuPanel/VBoxContainer/VBoxContainer2/Curvature/LineCurvature" to="MenuBar/HBox/MainGraphMenuBar/HBox/ViewMenu/ViewMenuPanel" method="_on_line_curvature_value_changed"] [connection signal="pressed" from="MenuBar/HBox/AlignMenu/HBox/AlignStart" to="MenuBar/HBox/AlignMenu" method="_on_align_start_pressed"] -[connection signal="pressed" from="MenuBar/HBox/AlignMenu/HBox/AlignCenter" to="MenuBar/HBox/AlignMenu" method="_on_align_center_pressed"] +[connection signal="pressed" from="MenuBar/HBox/AlignMenu/HBox/AlignTop" to="MenuBar/HBox/AlignMenu" method="_on_align_top_pressed"] [connection signal="pressed" from="MenuBar/HBox/AlignMenu/HBox/AlignEnd" to="MenuBar/HBox/AlignMenu" method="_on_align_end_pressed"] +[connection signal="pressed" from="MenuBar/HBox/AlignMenu/HBox/Straighten" to="MenuBar/HBox/AlignMenu" method="_on_straighten_pressed"] [connection signal="toggled" from="MenuBar/HBox/PreviewsMenu/HBox/2DPreview" to="." method="show_background_preview_2d"] [connection signal="toggled" from="MenuBar/HBox/PreviewsMenu/HBox/3DPreview" to="." method="show_background_preview_3d"] [connection signal="gui_input" from="MenuBar/HBox/PreviewsMenu/HBox/ControlView" to="BackgroundPreviews/Preview3D" method="on_gui_input"] diff --git a/material_maker/theme/classic_base.tres b/material_maker/theme/classic_base.tres index 1541f9cb4..ccef66753 100644 --- a/material_maker/theme/classic_base.tres +++ b/material_maker/theme/classic_base.tres @@ -291,7 +291,7 @@ border_color = Color(1, 0.560784, 0.560784, 1) [sub_resource type="AtlasTexture" id="AtlasTexture_nmkov"] atlas = ExtResource("1_fw8f4") region = Rect2(16, 224, 16, 16) -metadata/recolor = false +metadata/recolor = true [sub_resource type="AtlasTexture" id="AtlasTexture_ppdpb"] atlas = ExtResource("1_fw8f4") @@ -301,7 +301,7 @@ metadata/recolor = true [sub_resource type="AtlasTexture" id="AtlasTexture_btb0w"] atlas = ExtResource("1_fw8f4") region = Rect2(96, 208, 16, 16) -metadata/recolor = false +metadata/recolor = true [sub_resource type="AtlasTexture" id="AtlasTexture_1207d"] atlas = ExtResource("1_fw8f4") @@ -315,7 +315,7 @@ metadata/recolor = true [sub_resource type="AtlasTexture" id="AtlasTexture_a74kv"] atlas = ExtResource("1_fw8f4") -region = Rect2(48, 208, 16, 16) +region = Rect2(32, 224, 16, 16) metadata/recolor = true [sub_resource type="AtlasTexture" id="AtlasTexture_wbe58"] diff --git a/material_maker/theme/default.tres b/material_maker/theme/default.tres index f19d6072b..4a2a496bd 100644 --- a/material_maker/theme/default.tres +++ b/material_maker/theme/default.tres @@ -365,9 +365,9 @@ atlas = ExtResource("1_s43fy") region = Rect2(64, 208, 16, 16) metadata/recolor = true -[sub_resource type="AtlasTexture" id="AtlasTexture_8xpdb"] +[sub_resource type="AtlasTexture" id="AtlasTexture_a74kv"] atlas = ExtResource("1_s43fy") -region = Rect2(48, 208, 16, 16) +region = Rect2(32, 224, 16, 16) metadata/recolor = true [sub_resource type="AtlasTexture" id="AtlasTexture_5aawx"] @@ -431,10 +431,6 @@ metadata/recolor = true atlas = ExtResource("1_s43fy") region = Rect2(32, 96, 16, 16) -[sub_resource type="AtlasTexture" id="AtlasTexture_khddu"] -atlas = ExtResource("1_s43fy") -region = Rect2(16, 208, 16, 16) - [sub_resource type="AtlasTexture" id="AtlasTexture_xbfay"] atlas = ExtResource("1_s43fy") region = Rect2(32, 208, 16, 16) @@ -443,6 +439,10 @@ region = Rect2(32, 208, 16, 16) atlas = ExtResource("1_s43fy") region = Rect2(0, 208, 16, 16) +[sub_resource type="AtlasTexture" id="AtlasTexture_khddu"] +atlas = ExtResource("1_s43fy") +region = Rect2(16, 208, 16, 16) + [sub_resource type="AtlasTexture" id="AtlasTexture_60g77"] atlas = ExtResource("1_s43fy") region = Rect2(96, 144, 16, 16) @@ -627,6 +627,10 @@ region = Rect2(96, 16, 16, 16) atlas = ExtResource("1_s43fy") region = Rect2(48, 16, 16, 16) +[sub_resource type="AtlasTexture" id="AtlasTexture_8xpdb"] +atlas = ExtResource("1_s43fy") +region = Rect2(48, 208, 16, 16) + [sub_resource type="AtlasTexture" id="AtlasTexture_en6gw"] atlas = ExtResource("1_s43fy") region = Rect2(0, 0, 16, 16) @@ -1309,7 +1313,7 @@ MM_CurveIcons/icons/bounce = SubResource("AtlasTexture_skutf") MM_CurveIcons/icons/easein = SubResource("AtlasTexture_tqdx4") MM_CurveIcons/icons/easeinout = SubResource("AtlasTexture_1okio") MM_CurveIcons/icons/easeout = SubResource("AtlasTexture_a1e3v") -MM_CurveIcons/icons/linear = SubResource("AtlasTexture_8xpdb") +MM_CurveIcons/icons/linear = SubResource("AtlasTexture_a74kv") MM_CurveIcons/icons/sawtooth = SubResource("AtlasTexture_5aawx") MM_FilterLineEdit/base_type = &"LineEdit" MM_FilterLineEdit/styles/focus = SubResource("StyleBoxFlat_dyhk7") @@ -1322,9 +1326,9 @@ MM_Icons/icons/2D_preview = SubResource("AtlasTexture_1yu4y") MM_Icons/icons/3D_preview = SubResource("AtlasTexture_ao7ds") MM_Icons/icons/3D_preview_control = SubResource("AtlasTexture_hht3q") MM_Icons/icons/add_image = SubResource("AtlasTexture_86qok") -MM_Icons/icons/align_center = SubResource("AtlasTexture_khddu") MM_Icons/icons/align_end = SubResource("AtlasTexture_xbfay") MM_Icons/icons/align_start = SubResource("AtlasTexture_nw6qx") +MM_Icons/icons/align_top = SubResource("AtlasTexture_khddu") MM_Icons/icons/arrange_nodes = SubResource("AtlasTexture_60g77") MM_Icons/icons/arrow_left = SubResource("AtlasTexture_q32qs") MM_Icons/icons/arrow_right = SubResource("AtlasTexture_r3xak") @@ -1369,6 +1373,7 @@ MM_Icons/icons/spline_link = SubResource("AtlasTexture_fs6qc") MM_Icons/icons/spline_progressive = SubResource("AtlasTexture_70aex") MM_Icons/icons/spline_reverse = SubResource("AtlasTexture_ahanl") MM_Icons/icons/spline_unlink = SubResource("AtlasTexture_iofl8") +MM_Icons/icons/straighten_connections = SubResource("AtlasTexture_8xpdb") MM_Icons/icons/view = SubResource("AtlasTexture_en6gw") MM_Icons/icons/zoom = SubResource("AtlasTexture_iyaen") MM_Icons/icons/zoom_in = SubResource("AtlasTexture_5k62t") diff --git a/material_maker/theme/default_theme_icons.svg b/material_maker/theme/default_theme_icons.svg index 1f2fe015f..721f97de9 100644 --- a/material_maker/theme/default_theme_icons.svg +++ b/material_maker/theme/default_theme_icons.svg @@ -8,7 +8,7 @@ version="1.1" id="svg1" inkscape:version="1.4.3 (0d15f75, 2025-12-25)" - sodipodi:docname="default_theme_icons.svg" + sodipodi:docname="default_theme_icggons.svg" inkscape:export-filename="new_theme_icons.png" inkscape:export-xdpi="96" inkscape:export-ydpi="96" @@ -28,15 +28,15 @@ inkscape:deskcolor="#d1d1d1" inkscape:document-units="mm" showgrid="true" - inkscape:zoom="8" - inkscape:cx="36.6875" - inkscape:cy="213.8125" + inkscape:zoom="16" + inkscape:cx="44.96875" + inkscape:cy="222.53125" inkscape:window-width="1152" inkscape:window-height="981" inkscape:window-x="0" inkscape:window-y="38" inkscape:window-maximized="0" - inkscape:current-layer="g46" + inkscape:current-layer="g44" showguides="false"> + style="display:inline"> - - - - - - - + + + + + + + + + + + + + + + + +