From c7bf5cc66f170ccea4f262a68a939fcd1d81488e Mon Sep 17 00:00:00 2001 From: LMW Date: Sun, 18 Jan 2026 10:20:32 +0800 Subject: [PATCH 01/27] Added top-level bookmark menu --- material_maker/main_window.gd | 2 +- material_maker/main_window.tscn | 12 +- .../panels/graph_edit/graph_bookmark_menu.gd | 146 ++++++++++++++++++ .../graph_edit/graph_bookmark_menu.gd.uid | 1 + .../panels/graph_edit/graph_edit.gd | 12 +- material_maker/projects_panel.tscn | 60 ++++++- material_maker/theme/default.tres | 7 +- material_maker/theme/default_theme_icons.svg | 25 ++- .../bookmark_manager/bookmark_manager.gd | 48 ++++++ .../bookmark_manager/bookmark_manager.gd.uid | 1 + 10 files changed, 299 insertions(+), 15 deletions(-) create mode 100644 material_maker/panels/graph_edit/graph_bookmark_menu.gd create mode 100644 material_maker/panels/graph_edit/graph_bookmark_menu.gd.uid create mode 100644 material_maker/tools/bookmark_manager/bookmark_manager.gd create mode 100644 material_maker/tools/bookmark_manager/bookmark_manager.gd.uid diff --git a/material_maker/main_window.gd b/material_maker/main_window.gd index 9ce8c96af..d20fcf25d 100644 --- a/material_maker/main_window.gd +++ b/material_maker/main_window.gd @@ -22,7 +22,7 @@ var preview_tesselation_detail : int = 256 @onready var node_library_manager = $NodeLibraryManager @onready var brush_library_manager = $BrushLibraryManager - +@onready var bookmark_manager = $BookmarkManager @onready var projects_panel = $VBoxContainer/Layout/FlexibleLayout/Main diff --git a/material_maker/main_window.tscn b/material_maker/main_window.tscn index 975f9a438..c4ce59ebc 100644 --- a/material_maker/main_window.tscn +++ b/material_maker/main_window.tscn @@ -1,8 +1,9 @@ -[gd_scene load_steps=21 format=3 uid="uid://cgfeik04a5qqs"] +[gd_scene load_steps=22 format=3 uid="uid://cgfeik04a5qqs"] [ext_resource type="Script" uid="uid://cbfcjtm6e4t8h" path="res://material_maker/main_window.gd" id="1"] [ext_resource type="Theme" uid="uid://b628lwfk6ig2c" path="res://material_maker/theme/default.tres" id="1_2qcba"] [ext_resource type="Script" uid="uid://csdtiyrrw4pxg" path="res://material_maker/main_window_layout.gd" id="2"] +[ext_resource type="Script" uid="uid://dbvsf3qyuyrq6" path="res://material_maker/tools/bookmark_manager/bookmark_manager.gd" id="5_jxedr"] [ext_resource type="PackedScene" uid="uid://eiq3i53x72m2" path="res://addons/flexible_layout/flexible_layout.tscn" id="6_ygla4"] [ext_resource type="PackedScene" uid="uid://clw8sb0p8webl" path="res://material_maker/windows/add_node_popup/add_node_popup.tscn" id="7"] [ext_resource type="PackedScene" uid="uid://bnqq3vhwmudkw" path="res://material_maker/projects_panel.tscn" id="7_ih0ps"] @@ -140,6 +141,9 @@ config_section = "brush_lib" [node name="EnvironmentManager" parent="." instance=ExtResource("13")] +[node name="BookmarkManager" type="Node" parent="."] +script = ExtResource("5_jxedr") + [node name="VBoxContainer" type="VBoxContainer" parent="."] layout_mode = 2 size_flags_horizontal = 3 @@ -163,12 +167,16 @@ size_flags_horizontal = 3 allow_undock = true [node name="Main" parent="VBoxContainer/Layout/FlexibleLayout" instance=ExtResource("7_ih0ps")] -layout_mode = 2 +layout_mode = 0 anchors_preset = 0 +anchor_right = 0.0 +anchor_bottom = 0.0 offset_left = 18.0 offset_top = 4.0 offset_right = 263.0 offset_bottom = 32.0 +grow_horizontal = 1 +grow_vertical = 1 [node name="ConsoleResizer" type="Control" parent="VBoxContainer"] unique_name_in_owner = true diff --git a/material_maker/panels/graph_edit/graph_bookmark_menu.gd b/material_maker/panels/graph_edit/graph_bookmark_menu.gd new file mode 100644 index 000000000..ddef359ce --- /dev/null +++ b/material_maker/panels/graph_edit/graph_bookmark_menu.gd @@ -0,0 +1,146 @@ +extends PanelContainer + +var bookmark_manager : BookmarkManager + +@onready var tree := $Tree + +const MENU_RENAME := 0 +const MENU_DELETE := 1 + +func _ready() -> void: + if not mm_globals.main_window.is_node_ready(): + await mm_globals.main_window.ready + + # Workaround for godot issue #111756 + for p in tree.get_children(true): + if p is Popup: + p.about_to_popup.connect(fix_tree_line_editor_size.bind(p)) + break + + bookmark_manager = mm_globals.main_window.bookmark_manager + bookmark_manager.bookmark_added.connect(update_bookmarks) + + %Projects.tab_changed.connect(connect_graph_view_update_signal.unbind(1)) + +func connect_graph_view_update_signal(): + var graph : MMGraphEdit = mm_globals.main_window.get_current_graph_edit() + if not graph.view_updated.is_connected(update_bookmarks): + graph.view_updated.connect(update_bookmarks) + +func fix_tree_line_editor_size(p : Popup): + var vbox : VBoxContainer = p.get_child(0) + vbox.minimum_size_changed.connect( + func(): + await get_tree().process_frame + var contents_min_size = vbox.get_window().get_contents_minimum_size().y + @warning_ignore("narrowing_conversion") + vbox.get_window().max_size.y = contents_min_size + get_theme_constant("v_separation", "Tree")) + +func _open() -> void: + update_bookmarks() + +func update_bookmarks(with_updated_view : MMGenGraph = null) -> void: + validate_bookmarks(with_updated_view) + rebuild_bookmark_tree() + +func validate_bookmarks(current_subgraph : MMGenGraph) -> void: + var graph : MMGraphEdit = mm_globals.main_window.get_current_graph_edit() + + if tree.get_root(): + for item : TreeItem in tree.get_root().get_children(): + var bookmark : Dictionary = item.get_metadata(0) + var node_name : String = bookmark.node_name + + if node_name == "node_Material": + continue + + # Top-level graph + if graph.generator == graph.top_generator: + # Remove invalid reference + if not graph.has_node(NodePath(node_name)): + bookmark_manager.remove_bookmark(node_name) + # Inside subgraph + else: + # Update bookmark to reference new subgraph(at top-level) + if current_subgraph != null and current_subgraph.get_children().has(bookmark.generator): + var top_subgraph : MMGenGraph = current_subgraph + while top_subgraph.get_parent().get_parent() is not MMGraphEdit: + top_subgraph = top_subgraph.get_parent() + + bookmark_manager.set_generator(bookmark, top_subgraph) + var new_node_name := "node_" + top_subgraph.name + bookmark["node_name"] = new_node_name + bookmark_manager.remove_bookmark(node_name) + bookmark_manager.bookmarks[new_node_name] = { + "node_name": new_node_name, + "label": top_subgraph.name, + "generator": top_subgraph + } + +func rebuild_bookmark_tree() -> void: + await get_tree().process_frame + tree.clear() + var root : TreeItem = tree.create_item() + + var bookmarks : Dictionary[String, Dictionary] = bookmark_manager.get_bookmarks() + for bookmark_key : String in bookmarks: + var new_item : TreeItem = tree.create_item(root) + var bookmark = bookmarks[bookmark_key] + new_item.set_metadata(0, bookmark) + new_item.set_text(0, bookmark["label"]) + + # Show placeholder/hint if bookmarks are empty + tree.visible = tree.get_root().get_child_count() != 0 + $MarginContainer.visible = tree.get_root().get_child_count() == 0 + +func _on_tree_item_lmb_selected() -> void: + var selected_item : TreeItem = tree.get_selected() + var bookmark : Dictionary = selected_item.get_metadata(0) + var node_path := NodePath(bookmark.node_name) + var graph : MMGraphEdit = mm_globals.main_window.get_current_graph_edit() + + # Jump back to top-level graph + if graph.generator != graph.top_generator: + graph.update_view(graph.top_generator) + + # Center view on bookmarked node + if graph.has_node(node_path): + var node : GraphElement = graph.get_node(node_path) + if node != null: + graph.select_none() + node.selected = true + var tween := get_tree().create_tween() + var center := node.position_offset + 0.5 * node.size + var target_offset := center * graph.zoom - 0.5 * graph.size + tween.tween_property(graph, "scroll_offset", target_offset, 0.5).set_ease( + Tween.EASE_IN_OUT).set_trans(Tween.TRANS_CUBIC) + +func _on_tree_item_rmb_selected(_mouse_position : Vector2i): + mm_globals.popup_menu($ContextMenu, self) + +func _on_tree_gui_input(event: InputEvent) -> void: + if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT: + if event.double_click: + _on_context_menu_id_pressed(MENU_RENAME) + accept_event() + +func _on_tree_item_mouse_selected(mouse_position: Vector2, mouse_button_index: int) -> void: + if mouse_button_index == MOUSE_BUTTON_RIGHT: + _on_tree_item_rmb_selected(mouse_position) + elif mouse_button_index == MOUSE_BUTTON_LEFT: + _on_tree_item_lmb_selected() + +func _on_context_menu_id_pressed(id: int) -> void: + var item : TreeItem = tree.get_selected() + match id: + MENU_RENAME: + item.set_editable(0, true) + tree.edit_selected() + MENU_DELETE: + bookmark_manager.remove_bookmark(item.get_metadata(0).node_name) + rebuild_bookmark_tree() + +func _on_tree_item_edited() -> void: + var item : TreeItem = tree.get_selected() + item.set_editable(0, false) + bookmark_manager.edit_bookmark(item.get_metadata(0), item.get_text(0)) diff --git a/material_maker/panels/graph_edit/graph_bookmark_menu.gd.uid b/material_maker/panels/graph_edit/graph_bookmark_menu.gd.uid new file mode 100644 index 000000000..18570c75d --- /dev/null +++ b/material_maker/panels/graph_edit/graph_bookmark_menu.gd.uid @@ -0,0 +1 @@ +uid://dxreq1nitp4as diff --git a/material_maker/panels/graph_edit/graph_edit.gd b/material_maker/panels/graph_edit/graph_edit.gd index 00ab9f201..e94c05b26 100644 --- a/material_maker/panels/graph_edit/graph_edit.gd +++ b/material_maker/panels/graph_edit/graph_edit.gd @@ -251,6 +251,8 @@ func _gui_input(event) -> void: accept_event() KEY_F: color_comment_nodes() + KEY_B: + bookmark_node() match event.get_keycode(): KEY_SHIFT, KEY_CTRL, KEY_ALT: var found_tip : bool = false @@ -1005,7 +1007,6 @@ func create_subgraph() -> void: if subgraph != null: update_view(subgraph) - func _on_ButtonShowTree_pressed() -> void: var graph_tree : Popup = preload("res://material_maker/widgets/graph_tree/graph_tree.tscn").instantiate() add_child(graph_tree) @@ -1757,3 +1758,12 @@ func color_comment_nodes() -> void: picker.popup_hide.connect(picker.queue_free) picker.popup_hide.connect(undoredo.end_group) picker.popup() + +func bookmark_node() -> void: + var bookmark_manager : BookmarkManager = mm_globals.main_window.bookmark_manager + var selected_nodes := get_selected_nodes() + if selected_nodes.size() != 1: + return + var selected_node : GraphElement = selected_nodes[0] + var is_in_subgraph : bool = selected_node.generator.get_parent() != top_generator + bookmark_manager.add_bookmark(selected_node, is_in_subgraph) diff --git a/material_maker/projects_panel.tscn b/material_maker/projects_panel.tscn index 2517148fa..c1f6aecc1 100644 --- a/material_maker/projects_panel.tscn +++ b/material_maker/projects_panel.tscn @@ -1,16 +1,17 @@ -[gd_scene load_steps=16 format=3 uid="uid://bnqq3vhwmudkw"] +[gd_scene load_steps=17 format=3 uid="uid://bnqq3vhwmudkw"] [ext_resource type="Script" uid="uid://cryayuomvuwbo" path="res://material_maker/main_window_projects_panel.gd" id="1_m3usq"] [ext_resource type="PackedScene" uid="uid://bb6iar0tbj2qt" path="res://material_maker/panels/preview_2d/preview_2d.tscn" id="2_oiaqi"] [ext_resource type="PackedScene" uid="uid://dpaxvlnn2u1f6" path="res://material_maker/panels/preview_3d/preview_3d.tscn" id="3_qvj7k"] [ext_resource type="Script" uid="uid://bl15iwn2k8qm" path="res://material_maker/widgets/tabs/tabs.gd" id="4_mpinq"] [ext_resource type="Script" uid="uid://c37lcka7r53wk" path="res://material_maker/panels/common/menu_bar_button_with_panel.gd" id="6_r5hxx"] -[ext_resource type="Script" uid="uid://jvurydhtpvc2" path="res://material_maker/panels/graph_edit/graph_zoom_menu.gd" id="7_lbgjg"] +[ext_resource type="Script" path="res://material_maker/panels/graph_edit/graph_zoom_menu.gd" id="7_lbgjg"] [ext_resource type="Script" uid="uid://bos2fu0tsood3" path="res://material_maker/panels/preview_2d/simple_button.gd" id="7_qnupl"] [ext_resource type="PackedScene" uid="uid://rflulhsuy3ax" path="res://material_maker/widgets/float_edit/float_edit.tscn" id="8_1w3oe"] [ext_resource type="Script" uid="uid://bxwor0k6svci8" path="res://material_maker/panels/graph_edit/graph_view_menu.gd" id="8_nl2qi"] [ext_resource type="Script" uid="uid://pqxjwlcff5ko" path="res://material_maker/panels/graph_edit/graph_align_menu.gd" id="8_r5hxx"] [ext_resource type="ButtonGroup" uid="uid://biv6we3po8wbb" path="res://material_maker/line_style_btn_group.tres" id="10_lbgjg"] +[ext_resource type="Script" uid="uid://dxreq1nitp4as" path="res://material_maker/panels/graph_edit/graph_bookmark_menu.gd" id="11_qnupl"] [sub_resource type="Shader" id="1"] resource_local_to_scene = true @@ -157,7 +158,7 @@ layout_mode = 0 offset_left = 283.0 offset_top = -56.0 offset_right = 391.0 -offset_bottom = -32.0 +offset_bottom = -31.0 theme_type_variation = &"MM_PanelMenuSubPanel" script = ExtResource("7_lbgjg") @@ -392,6 +393,54 @@ max_value = 2.0 step = 0.01 float_only = true +[node name="BookmarkMenu" type="Button" parent="MenuBar/HBox/MainGraphMenuBar/HBox"] +custom_minimum_size = Vector2(40, 25) +layout_mode = 2 +tooltip_text = "Bookmarks" +theme_type_variation = &"MM_PanelMenuButton" +toggle_mode = true +button_mask = 3 +script = ExtResource("6_r5hxx") +icon_name = "bookmark" + +[node name="BookmarkMenuPanel" type="PanelContainer" parent="MenuBar/HBox/MainGraphMenuBar/HBox/BookmarkMenu"] +top_level = true +custom_minimum_size = Vector2(180, 200) +layout_mode = 0 +theme_type_variation = &"MM_PanelMenuSubPanel" +script = ExtResource("11_qnupl") + +[node name="MarginContainer" type="MarginContainer" parent="MenuBar/HBox/MainGraphMenuBar/HBox/BookmarkMenu/BookmarkMenuPanel"] +visible = false +layout_mode = 2 +theme_override_constants/margin_left = 4 +theme_override_constants/margin_top = 4 +theme_override_constants/margin_right = 4 +theme_override_constants/margin_bottom = 4 + +[node name="EmptyLabel" type="Label" parent="MenuBar/HBox/MainGraphMenuBar/HBox/BookmarkMenu/BookmarkMenuPanel/MarginContainer"] +modulate = Color(1, 1, 1, 0.51900005) +layout_mode = 2 +text = "No Bookmarks" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="Tree" type="Tree" parent="MenuBar/HBox/MainGraphMenuBar/HBox/BookmarkMenu/BookmarkMenuPanel"] +layout_mode = 2 +theme_override_constants/item_margin = 4 +allow_reselect = true +allow_rmb_select = true +hide_root = true +auto_tooltip = false + +[node name="ContextMenu" type="PopupMenu" parent="MenuBar/HBox/MainGraphMenuBar/HBox/BookmarkMenu/BookmarkMenuPanel"] +allow_search = false +item_count = 2 +item_0/text = "Rename" +item_0/id = 0 +item_1/text = "Delete" +item_1/id = 1 + [node name="ArrangeNodes" type="Button" parent="MenuBar/HBox/MainGraphMenuBar/HBox"] visible = false custom_minimum_size = Vector2(25, 25) @@ -507,6 +556,11 @@ Scroll to zoom the 3D Preview." [connection signal="value_changed" from="MenuBar/HBox/MainGraphMenuBar/HBox/ViewMenu/ViewMenuPanel/VBoxContainer/VBoxContainer2/Thickness/LineThickness" to="MenuBar/HBox/MainGraphMenuBar/HBox/ViewMenu/ViewMenuPanel" method="_on_line_thickness_value_changed"] [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="minimum_size_changed" from="MenuBar/HBox/MainGraphMenuBar/HBox/BookmarkMenu/BookmarkMenuPanel" to="MenuBar/HBox/MainGraphMenuBar/HBox/BookmarkMenu/BookmarkMenuPanel" method="_on_minimum_size_changed"] +[connection signal="gui_input" from="MenuBar/HBox/MainGraphMenuBar/HBox/BookmarkMenu/BookmarkMenuPanel/Tree" to="MenuBar/HBox/MainGraphMenuBar/HBox/BookmarkMenu/BookmarkMenuPanel" method="_on_tree_gui_input"] +[connection signal="item_edited" from="MenuBar/HBox/MainGraphMenuBar/HBox/BookmarkMenu/BookmarkMenuPanel/Tree" to="MenuBar/HBox/MainGraphMenuBar/HBox/BookmarkMenu/BookmarkMenuPanel" method="_on_tree_item_edited"] +[connection signal="item_mouse_selected" from="MenuBar/HBox/MainGraphMenuBar/HBox/BookmarkMenu/BookmarkMenuPanel/Tree" to="MenuBar/HBox/MainGraphMenuBar/HBox/BookmarkMenu/BookmarkMenuPanel" method="_on_tree_item_mouse_selected"] +[connection signal="id_pressed" from="MenuBar/HBox/MainGraphMenuBar/HBox/BookmarkMenu/BookmarkMenuPanel/ContextMenu" to="MenuBar/HBox/MainGraphMenuBar/HBox/BookmarkMenu/BookmarkMenuPanel" method="_on_context_menu_id_pressed"] [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/AlignEnd" to="MenuBar/HBox/AlignMenu" method="_on_align_end_pressed"] diff --git a/material_maker/theme/default.tres b/material_maker/theme/default.tres index 5dfefa461..9e5a5e4e3 100644 --- a/material_maker/theme/default.tres +++ b/material_maker/theme/default.tres @@ -1,4 +1,4 @@ -[gd_resource type="Theme" load_steps=165 format=3 uid="uid://b628lwfk6ig2c"] +[gd_resource type="Theme" load_steps=166 format=3 uid="uid://b628lwfk6ig2c"] [ext_resource type="FontFile" uid="uid://lro0qdrhfytt" path="res://material_maker/theme/font_rubik/Rubik-Light.ttf" id="1_5tfb1"] [ext_resource type="Texture2D" uid="uid://1s0c37uoj4rf" path="res://material_maker/theme/default_theme_icons.svg" id="1_s43fy"] @@ -425,6 +425,10 @@ region = Rect2(48, 48, 16, 16) atlas = ExtResource("1_s43fy") region = Rect2(112, 176, 16, 16) +[sub_resource type="AtlasTexture" id="AtlasTexture_0jwmb"] +atlas = ExtResource("1_s43fy") +region = Rect2(48, 208, 16, 16) + [sub_resource type="AtlasTexture" id="AtlasTexture_cscp3"] atlas = ExtResource("1_s43fy") region = Rect2(80, 192, 16, 16) @@ -1229,6 +1233,7 @@ MM_Icons/icons/arrange_nodes = SubResource("AtlasTexture_60g77") MM_Icons/icons/arrow_left = SubResource("AtlasTexture_q32qs") MM_Icons/icons/arrow_right = SubResource("AtlasTexture_r3xak") MM_Icons/icons/arrow_updown = SubResource("AtlasTexture_ovvp6") +MM_Icons/icons/bookmark = SubResource("AtlasTexture_0jwmb") MM_Icons/icons/camera = SubResource("AtlasTexture_cscp3") MM_Icons/icons/color_picker = SubResource("AtlasTexture_j13i3") MM_Icons/icons/connection_bezier = SubResource("AtlasTexture_rqjp3") diff --git a/material_maker/theme/default_theme_icons.svg b/material_maker/theme/default_theme_icons.svg index bd0af37d3..0f493143e 100644 --- a/material_maker/theme/default_theme_icons.svg +++ b/material_maker/theme/default_theme_icons.svg @@ -28,15 +28,15 @@ inkscape:deskcolor="#d1d1d1" inkscape:document-units="mm" showgrid="true" - inkscape:zoom="16" - inkscape:cx="113.5" - inkscape:cy="206.84375" + inkscape:zoom="32" + inkscape:cx="53.625" + inkscape:cy="214.0625" inkscape:window-width="1152" inkscape:window-height="981" inkscape:window-x="0" inkscape:window-y="38" inkscape:window-maximized="0" - inkscape:current-layer="g11-3" + inkscape:current-layer="g34" showguides="false"> + style="display:inline"> + id="g196" + inkscape:label="align_center"> + + + void: + var new_bookmark := {} + + new_bookmark.node_name = node.name + new_bookmark.label = node.name.trim_prefix("node_") + + # temporary reference(unsaved to .ptex) to track subgraph inclusion + new_bookmark.generator = node.generator + + # Not part of top-level graph + if is_in_subgraph: + return + + if not bookmarks.has(node.name): + bookmarks[node.name] = new_bookmark + mm_globals.set_tip_text("Added bookmark for %s" % node.name.trim_prefix("node_"), 1.0, 1) + bookmark_added.emit() + +func remove_bookmark(node_name : String) -> void: + bookmarks.erase(node_name) + +func set_generator(bookmark : Dictionary, subgraph_gen : MMGenGraph) -> void: + bookmark.generator = subgraph_gen + +func set_node(bookmark : Dictionary, node_name : String) -> void: + bookmark.node_name = node_name + +func edit_bookmark(bookmark : Dictionary, new_label : String) -> void: + bookmark.label = new_label + +func get_bookmarks() -> Dictionary[String, Dictionary]: + return bookmarks + +func _enter_tree() -> void: + pass + +func _exit_tree() -> void: + pass diff --git a/material_maker/tools/bookmark_manager/bookmark_manager.gd.uid b/material_maker/tools/bookmark_manager/bookmark_manager.gd.uid new file mode 100644 index 000000000..61843aeb3 --- /dev/null +++ b/material_maker/tools/bookmark_manager/bookmark_manager.gd.uid @@ -0,0 +1 @@ +uid://dbvsf3qyuyrq6 From 5e139897e9e87a3b7d3fc3c8315607e8e4c62369 Mon Sep 17 00:00:00 2001 From: LMW Date: Tue, 20 Jan 2026 00:42:34 +0800 Subject: [PATCH 02/27] simplify subgraph check --- material_maker/panels/graph_edit/graph_edit.gd | 5 +++-- material_maker/tools/bookmark_manager/bookmark_manager.gd | 6 +----- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/material_maker/panels/graph_edit/graph_edit.gd b/material_maker/panels/graph_edit/graph_edit.gd index e94c05b26..7d35c029c 100644 --- a/material_maker/panels/graph_edit/graph_edit.gd +++ b/material_maker/panels/graph_edit/graph_edit.gd @@ -1760,10 +1760,11 @@ func color_comment_nodes() -> void: picker.popup() func bookmark_node() -> void: + if generator != top_generator: + return var bookmark_manager : BookmarkManager = mm_globals.main_window.bookmark_manager var selected_nodes := get_selected_nodes() if selected_nodes.size() != 1: return var selected_node : GraphElement = selected_nodes[0] - var is_in_subgraph : bool = selected_node.generator.get_parent() != top_generator - bookmark_manager.add_bookmark(selected_node, is_in_subgraph) + bookmark_manager.add_bookmark(selected_node) diff --git a/material_maker/tools/bookmark_manager/bookmark_manager.gd b/material_maker/tools/bookmark_manager/bookmark_manager.gd index 13dcb8314..c457f820f 100644 --- a/material_maker/tools/bookmark_manager/bookmark_manager.gd +++ b/material_maker/tools/bookmark_manager/bookmark_manager.gd @@ -8,7 +8,7 @@ var bookmarks : Dictionary[String, Dictionary] signal bookmark_added -func add_bookmark(node : GraphElement, is_in_subgraph : bool) -> void: +func add_bookmark(node : GraphElement) -> void: var new_bookmark := {} new_bookmark.node_name = node.name @@ -17,10 +17,6 @@ func add_bookmark(node : GraphElement, is_in_subgraph : bool) -> void: # temporary reference(unsaved to .ptex) to track subgraph inclusion new_bookmark.generator = node.generator - # Not part of top-level graph - if is_in_subgraph: - return - if not bookmarks.has(node.name): bookmarks[node.name] = new_bookmark mm_globals.set_tip_text("Added bookmark for %s" % node.name.trim_prefix("node_"), 1.0, 1) From fdc06fae1342148029d89f9bd972cc98e775361b Mon Sep 17 00:00:00 2001 From: LMW Date: Tue, 20 Jan 2026 11:21:46 +0800 Subject: [PATCH 03/27] fix doubleclick editing in unpinned panel, add null check --- .../common/menu_bar_button_with_panel.gd | 2 + .../panels/graph_edit/graph_bookmark_menu.gd | 51 ++++++++++++++----- material_maker/projects_panel.tscn | 6 ++- .../bookmark_manager/bookmark_manager.gd | 18 ++++--- 4 files changed, 54 insertions(+), 23 deletions(-) diff --git a/material_maker/panels/common/menu_bar_button_with_panel.gd b/material_maker/panels/common/menu_bar_button_with_panel.gd index 8fed42568..231c12413 100644 --- a/material_maker/panels/common/menu_bar_button_with_panel.gd +++ b/material_maker/panels/common/menu_bar_button_with_panel.gd @@ -70,6 +70,8 @@ func _input(event : InputEvent) -> void: if event is InputEventMouseButton: var node := get_viewport().gui_get_hovered_control() + if node == null: + return if node != self and not is_ancestor_of(node) and (not pinned or (node and node.script == self.script) and node.owner == owner): button_pressed = false diff --git a/material_maker/panels/graph_edit/graph_bookmark_menu.gd b/material_maker/panels/graph_edit/graph_bookmark_menu.gd index ddef359ce..4401eb966 100644 --- a/material_maker/panels/graph_edit/graph_bookmark_menu.gd +++ b/material_maker/panels/graph_edit/graph_bookmark_menu.gd @@ -4,17 +4,21 @@ var bookmark_manager : BookmarkManager @onready var tree := $Tree -const MENU_RENAME := 0 -const MENU_DELETE := 1 +var is_unpinned_double_click_edited := false + +enum ContextMenu { + RENAME, + DELETE, +} func _ready() -> void: if not mm_globals.main_window.is_node_ready(): await mm_globals.main_window.ready - # Workaround for godot issue #111756 + # Workaround for godot issue #111756 (fixed in 4.6) for p in tree.get_children(true): if p is Popup: - p.about_to_popup.connect(fix_tree_line_editor_size.bind(p)) + p.about_to_popup.connect(fix_tree_line_edit_size.bind(p)) break bookmark_manager = mm_globals.main_window.bookmark_manager @@ -22,12 +26,14 @@ func _ready() -> void: %Projects.tab_changed.connect(connect_graph_view_update_signal.unbind(1)) + func connect_graph_view_update_signal(): var graph : MMGraphEdit = mm_globals.main_window.get_current_graph_edit() if not graph.view_updated.is_connected(update_bookmarks): graph.view_updated.connect(update_bookmarks) -func fix_tree_line_editor_size(p : Popup): + +func fix_tree_line_edit_size(p : Popup): var vbox : VBoxContainer = p.get_child(0) vbox.minimum_size_changed.connect( func(): @@ -36,13 +42,16 @@ func fix_tree_line_editor_size(p : Popup): @warning_ignore("narrowing_conversion") vbox.get_window().max_size.y = contents_min_size + get_theme_constant("v_separation", "Tree")) + func _open() -> void: update_bookmarks() + func update_bookmarks(with_updated_view : MMGenGraph = null) -> void: validate_bookmarks(with_updated_view) rebuild_bookmark_tree() + func validate_bookmarks(current_subgraph : MMGenGraph) -> void: var graph : MMGraphEdit = mm_globals.main_window.get_current_graph_edit() @@ -51,7 +60,7 @@ func validate_bookmarks(current_subgraph : MMGenGraph) -> void: var bookmark : Dictionary = item.get_metadata(0) var node_name : String = bookmark.node_name - if node_name == "node_Material": + if node_name in ["node_Material", "node_Brush"]: continue # Top-level graph @@ -61,21 +70,23 @@ func validate_bookmarks(current_subgraph : MMGenGraph) -> void: bookmark_manager.remove_bookmark(node_name) # Inside subgraph else: - # Update bookmark to reference new subgraph(at top-level) + # Update bookmark to reference new subgraph node(at top-level) + if not is_instance_valid(bookmark.generator): + continue if current_subgraph != null and current_subgraph.get_children().has(bookmark.generator): var top_subgraph : MMGenGraph = current_subgraph while top_subgraph.get_parent().get_parent() is not MMGraphEdit: top_subgraph = top_subgraph.get_parent() - bookmark_manager.set_generator(bookmark, top_subgraph) var new_node_name := "node_" + top_subgraph.name - bookmark["node_name"] = new_node_name bookmark_manager.remove_bookmark(node_name) - bookmark_manager.bookmarks[new_node_name] = { + bookmark_manager.add_bookmark_entry({ "node_name": new_node_name, "label": top_subgraph.name, "generator": top_subgraph - } + }) + + func rebuild_bookmark_tree() -> void: await get_tree().process_frame @@ -93,6 +104,7 @@ func rebuild_bookmark_tree() -> void: tree.visible = tree.get_root().get_child_count() != 0 $MarginContainer.visible = tree.get_root().get_child_count() == 0 + func _on_tree_item_lmb_selected() -> void: var selected_item : TreeItem = tree.get_selected() var bookmark : Dictionary = selected_item.get_metadata(0) @@ -115,14 +127,21 @@ func _on_tree_item_lmb_selected() -> void: tween.tween_property(graph, "scroll_offset", target_offset, 0.5).set_ease( Tween.EASE_IN_OUT).set_trans(Tween.TRANS_CUBIC) + func _on_tree_item_rmb_selected(_mouse_position : Vector2i): mm_globals.popup_menu($ContextMenu, self) + func _on_tree_gui_input(event: InputEvent) -> void: if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT: if event.double_click: - _on_context_menu_id_pressed(MENU_RENAME) accept_event() + if tree.get_selected(): + _on_context_menu_id_pressed(ContextMenu.RENAME) + # keep panel pinned while editing + is_unpinned_double_click_edited = not get_parent().pinned + get_parent().pinned = true + func _on_tree_item_mouse_selected(mouse_position: Vector2, mouse_button_index: int) -> void: if mouse_button_index == MOUSE_BUTTON_RIGHT: @@ -130,17 +149,21 @@ func _on_tree_item_mouse_selected(mouse_position: Vector2, mouse_button_index: i elif mouse_button_index == MOUSE_BUTTON_LEFT: _on_tree_item_lmb_selected() + func _on_context_menu_id_pressed(id: int) -> void: var item : TreeItem = tree.get_selected() match id: - MENU_RENAME: + ContextMenu.RENAME: item.set_editable(0, true) tree.edit_selected() - MENU_DELETE: + ContextMenu.DELETE: bookmark_manager.remove_bookmark(item.get_metadata(0).node_name) rebuild_bookmark_tree() + func _on_tree_item_edited() -> void: var item : TreeItem = tree.get_selected() item.set_editable(0, false) bookmark_manager.edit_bookmark(item.get_metadata(0), item.get_text(0)) + if is_unpinned_double_click_edited: + get_parent().pinned = false diff --git a/material_maker/projects_panel.tscn b/material_maker/projects_panel.tscn index c1f6aecc1..60ae09067 100644 --- a/material_maker/projects_panel.tscn +++ b/material_maker/projects_panel.tscn @@ -405,8 +405,10 @@ icon_name = "bookmark" [node name="BookmarkMenuPanel" type="PanelContainer" parent="MenuBar/HBox/MainGraphMenuBar/HBox/BookmarkMenu"] top_level = true -custom_minimum_size = Vector2(180, 200) +custom_minimum_size = Vector2(200, 200) layout_mode = 0 +offset_right = 200.0 +offset_bottom = 200.0 theme_type_variation = &"MM_PanelMenuSubPanel" script = ExtResource("11_qnupl") @@ -427,7 +429,7 @@ vertical_alignment = 1 [node name="Tree" type="Tree" parent="MenuBar/HBox/MainGraphMenuBar/HBox/BookmarkMenu/BookmarkMenuPanel"] layout_mode = 2 -theme_override_constants/item_margin = 4 +theme_override_constants/item_margin = 0 allow_reselect = true allow_rmb_select = true hide_root = true diff --git a/material_maker/tools/bookmark_manager/bookmark_manager.gd b/material_maker/tools/bookmark_manager/bookmark_manager.gd index c457f820f..9582c5ab3 100644 --- a/material_maker/tools/bookmark_manager/bookmark_manager.gd +++ b/material_maker/tools/bookmark_manager/bookmark_manager.gd @@ -8,6 +8,7 @@ var bookmarks : Dictionary[String, Dictionary] signal bookmark_added + func add_bookmark(node : GraphElement) -> void: var new_bookmark := {} @@ -22,23 +23,26 @@ func add_bookmark(node : GraphElement) -> void: mm_globals.set_tip_text("Added bookmark for %s" % node.name.trim_prefix("node_"), 1.0, 1) bookmark_added.emit() -func remove_bookmark(node_name : String) -> void: - bookmarks.erase(node_name) -func set_generator(bookmark : Dictionary, subgraph_gen : MMGenGraph) -> void: - bookmark.generator = subgraph_gen +func add_bookmark_entry(bookmark : Dictionary) -> void: + bookmarks[bookmark.node_name] = bookmark + + +func remove_bookmark(node_name: String) -> void: + bookmarks.erase(node_name) -func set_node(bookmark : Dictionary, node_name : String) -> void: - bookmark.node_name = node_name -func edit_bookmark(bookmark : Dictionary, new_label : String) -> void: +func edit_bookmark(bookmark: Dictionary, new_label: String) -> void: bookmark.label = new_label + func get_bookmarks() -> Dictionary[String, Dictionary]: return bookmarks + func _enter_tree() -> void: pass + func _exit_tree() -> void: pass From d33dd53d2116a4cbdf172241365545db1712e39d Mon Sep 17 00:00:00 2001 From: LMW Date: Wed, 21 Jan 2026 16:58:43 +0800 Subject: [PATCH 04/27] Support subgraph bookmarks --- .../panels/graph_edit/graph_bookmark_menu.gd | 114 ++++++++++-------- .../panels/graph_edit/graph_edit.gd | 10 +- .../panels/hierarchy/hierarchy_panel.gd | 1 + .../bookmark_manager/bookmark_manager.gd | 40 +++--- 4 files changed, 95 insertions(+), 70 deletions(-) diff --git a/material_maker/panels/graph_edit/graph_bookmark_menu.gd b/material_maker/panels/graph_edit/graph_bookmark_menu.gd index 4401eb966..4a152981a 100644 --- a/material_maker/panels/graph_edit/graph_bookmark_menu.gd +++ b/material_maker/panels/graph_edit/graph_bookmark_menu.gd @@ -24,10 +24,9 @@ func _ready() -> void: bookmark_manager = mm_globals.main_window.bookmark_manager bookmark_manager.bookmark_added.connect(update_bookmarks) - %Projects.tab_changed.connect(connect_graph_view_update_signal.unbind(1)) + %Projects.tab_changed.connect(projects_panel_tab_changed.unbind(1)) - -func connect_graph_view_update_signal(): +func projects_panel_tab_changed(): var graph : MMGraphEdit = mm_globals.main_window.get_current_graph_edit() if not graph.view_updated.is_connected(update_bookmarks): graph.view_updated.connect(update_bookmarks) @@ -47,45 +46,40 @@ func _open() -> void: update_bookmarks() -func update_bookmarks(with_updated_view : MMGenGraph = null) -> void: - validate_bookmarks(with_updated_view) +func update_bookmarks(updated_view : MMGenGraph = null) -> void: + validate_bookmarks(updated_view) rebuild_bookmark_tree() -func validate_bookmarks(current_subgraph : MMGenGraph) -> void: +func validate_bookmarks(updated_view : MMGenGraph = null) -> void: + # Update and remove invalid references var graph : MMGraphEdit = mm_globals.main_window.get_current_graph_edit() - if tree.get_root(): - for item : TreeItem in tree.get_root().get_children(): - var bookmark : Dictionary = item.get_metadata(0) - var node_name : String = bookmark.node_name - - if node_name in ["node_Material", "node_Brush"]: - continue - - # Top-level graph - if graph.generator == graph.top_generator: - # Remove invalid reference - if not graph.has_node(NodePath(node_name)): - bookmark_manager.remove_bookmark(node_name) - # Inside subgraph - else: - # Update bookmark to reference new subgraph node(at top-level) - if not is_instance_valid(bookmark.generator): - continue - if current_subgraph != null and current_subgraph.get_children().has(bookmark.generator): - var top_subgraph : MMGenGraph = current_subgraph - while top_subgraph.get_parent().get_parent() is not MMGraphEdit: - top_subgraph = top_subgraph.get_parent() - - var new_node_name := "node_" + top_subgraph.name - bookmark_manager.remove_bookmark(node_name) - bookmark_manager.add_bookmark_entry({ - "node_name": new_node_name, - "label": top_subgraph.name, - "generator": top_subgraph - }) - + if tree.get_root() == null: + return + + for item : TreeItem in tree.get_root().get_children(): + var bookmark_path : String = item.get_metadata(0) + if bookmark_path in ["./Material", "./Brush"]: + continue + + # Path does not point to anything + if not graph.top_generator.has_node(bookmark_path): + var target_node : String = bookmark_path.split("/")[-1] + + # Check if the node is part of the updated graph view + # i.e. from grouping the currently bookmarked node + + # Remove invalid reference + bookmark_manager.remove_bookmark(bookmark_path) + + # Add bookmark + if updated_view != null: + var node_path := "node_" + target_node + if graph.has_node(node_path): + var gen : MMGenBase = graph.get_node(node_path).generator + var new_path := BookmarkManager.get_path_from_gen(gen, graph.top_generator) + bookmark_manager.add_bookmark_from_path(new_path, target_node) func rebuild_bookmark_tree() -> void: @@ -93,12 +87,11 @@ func rebuild_bookmark_tree() -> void: tree.clear() var root : TreeItem = tree.create_item() - var bookmarks : Dictionary[String, Dictionary] = bookmark_manager.get_bookmarks() - for bookmark_key : String in bookmarks: + var bookmarks : Dictionary[String, String] = bookmark_manager.get_bookmarks() + for path : String in bookmarks: var new_item : TreeItem = tree.create_item(root) - var bookmark = bookmarks[bookmark_key] - new_item.set_metadata(0, bookmark) - new_item.set_text(0, bookmark["label"]) + new_item.set_metadata(0, path) + new_item.set_text(0, bookmarks[path]) # Show placeholder/hint if bookmarks are empty tree.visible = tree.get_root().get_child_count() != 0 @@ -107,22 +100,43 @@ func rebuild_bookmark_tree() -> void: func _on_tree_item_lmb_selected() -> void: var selected_item : TreeItem = tree.get_selected() - var bookmark : Dictionary = selected_item.get_metadata(0) - var node_path := NodePath(bookmark.node_name) + var path : String = selected_item.get_metadata(0) + path = path.get_slice("./", 1) var graph : MMGraphEdit = mm_globals.main_window.get_current_graph_edit() - # Jump back to top-level graph - if graph.generator != graph.top_generator: - graph.update_view(graph.top_generator) + var target_gen : MMGenBase + + # Top-level bookmark + if "/" not in path: + # Jump back to top if we are in a subgraph + if graph.generator != graph.top_generator: + graph.update_view(graph.top_generator) + # Get target node from current graph + var node_path := NodePath("node_" + path) + if graph.has_node(node_path): + target_gen = graph.get_node(node_path).generator + else: + # Subgraph bookmark + target_gen = graph.top_generator.get_node(NodePath(path)) + + if target_gen == null: + # bookmark no longer exists + return + + if target_gen.get_parent() is MMGenGraph and target_gen.get_parent() != graph.top_generator: + # Jump to node's subgraph if we are not already in it + if graph.generator != target_gen.get_parent(): + graph.update_view(target_gen.get_parent()) # Center view on bookmarked node - if graph.has_node(node_path): - var node : GraphElement = graph.get_node(node_path) + var bookmark_node_path : NodePath = "node_" + target_gen.name + if graph.has_node(bookmark_node_path): + var node : GraphElement = graph.get_node(bookmark_node_path) if node != null: graph.select_none() node.selected = true - var tween := get_tree().create_tween() var center := node.position_offset + 0.5 * node.size + var tween := get_tree().create_tween() var target_offset := center * graph.zoom - 0.5 * graph.size tween.tween_property(graph, "scroll_offset", target_offset, 0.5).set_ease( Tween.EASE_IN_OUT).set_trans(Tween.TRANS_CUBIC) diff --git a/material_maker/panels/graph_edit/graph_edit.gd b/material_maker/panels/graph_edit/graph_edit.gd index 7d35c029c..782a8f99a 100644 --- a/material_maker/panels/graph_edit/graph_edit.gd +++ b/material_maker/panels/graph_edit/graph_edit.gd @@ -1760,11 +1760,15 @@ func color_comment_nodes() -> void: picker.popup() func bookmark_node() -> void: - if generator != top_generator: - return var bookmark_manager : BookmarkManager = mm_globals.main_window.bookmark_manager var selected_nodes := get_selected_nodes() if selected_nodes.size() != 1: return var selected_node : GraphElement = selected_nodes[0] - bookmark_manager.add_bookmark(selected_node) + var generator_path : String + + if generator == top_generator: + generator_path = "./" + selected_node.generator.name + else: + generator_path = BookmarkManager.get_path_from_gen(selected_node.generator, top_generator) + bookmark_manager.add_bookmark(selected_node, generator_path) diff --git a/material_maker/panels/hierarchy/hierarchy_panel.gd b/material_maker/panels/hierarchy/hierarchy_panel.gd index ef6d63ad8..bb6c3ff70 100644 --- a/material_maker/panels/hierarchy/hierarchy_panel.gd +++ b/material_maker/panels/hierarchy/hierarchy_panel.gd @@ -96,6 +96,7 @@ func fill_item(item : TreeItem, generator : MMGenGraph, selected : MMGenGraph, i func _on_Hierarchy_item_double_clicked() -> void: if tree.get_selected() != null: + print(tree.get_selected().get_metadata(0).get_tree_string()) emit_signal("group_selected", tree.get_selected().get_metadata(0)) func on_view_updated(generator) -> void: diff --git a/material_maker/tools/bookmark_manager/bookmark_manager.gd b/material_maker/tools/bookmark_manager/bookmark_manager.gd index 9582c5ab3..4ce513719 100644 --- a/material_maker/tools/bookmark_manager/bookmark_manager.gd +++ b/material_maker/tools/bookmark_manager/bookmark_manager.gd @@ -4,42 +4,48 @@ class_name BookmarkManager ## Top-level graph bookmarks to revisit them later -var bookmarks : Dictionary[String, Dictionary] +var bookmarks : Dictionary[String, String] signal bookmark_added -func add_bookmark(node : GraphElement) -> void: - var new_bookmark := {} - - new_bookmark.node_name = node.name - new_bookmark.label = node.name.trim_prefix("node_") - - # temporary reference(unsaved to .ptex) to track subgraph inclusion - new_bookmark.generator = node.generator - - if not bookmarks.has(node.name): - bookmarks[node.name] = new_bookmark +func add_bookmark(node: GraphElement, gen_path: String) -> void: + if not bookmarks.has(gen_path): + bookmarks[gen_path] = node.name.trim_prefix("node_") mm_globals.set_tip_text("Added bookmark for %s" % node.name.trim_prefix("node_"), 1.0, 1) bookmark_added.emit() -func add_bookmark_entry(bookmark : Dictionary) -> void: - bookmarks[bookmark.node_name] = bookmark +func add_bookmark_from_path(path: String, label: String) -> void: + bookmarks[path] = label -func remove_bookmark(node_name: String) -> void: - bookmarks.erase(node_name) +func remove_bookmark(path: String) -> void: + bookmarks.erase(path) func edit_bookmark(bookmark: Dictionary, new_label: String) -> void: bookmark.label = new_label -func get_bookmarks() -> Dictionary[String, Dictionary]: +func get_bookmarks() -> Dictionary[String, String]: return bookmarks +static func get_path_from_gen(generator: MMGenBase, top_generator: MMGenGraph) -> String: + var parent_gen = generator.get_parent() + var node_path : PackedStringArray + var current_gen : MMGenGraph = parent_gen + node_path.append(current_gen.name) + while current_gen.get_parent() != top_generator: + current_gen = current_gen.get_parent() + node_path.append(current_gen.name) + node_path.append(".") + node_path.reverse() + node_path.append(generator.name) + return "/".join(node_path) + + func _enter_tree() -> void: pass From bdd219bdaea53e577d40d75c82c8b2669f68530b Mon Sep 17 00:00:00 2001 From: LMW Date: Wed, 21 Jan 2026 17:03:47 +0800 Subject: [PATCH 05/27] comments --- .../panels/graph_edit/graph_bookmark_menu.gd | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/material_maker/panels/graph_edit/graph_bookmark_menu.gd b/material_maker/panels/graph_edit/graph_bookmark_menu.gd index 4a152981a..06c6f8709 100644 --- a/material_maker/panels/graph_edit/graph_bookmark_menu.gd +++ b/material_maker/panels/graph_edit/graph_bookmark_menu.gd @@ -60,20 +60,22 @@ func validate_bookmarks(updated_view : MMGenGraph = null) -> void: for item : TreeItem in tree.get_root().get_children(): var bookmark_path : String = item.get_metadata(0) + + # Material & Brush nodes are always in top level graph if bookmark_path in ["./Material", "./Brush"]: continue - # Path does not point to anything + # Bookmarked path does not point to anything if not graph.top_generator.has_node(bookmark_path): var target_node : String = bookmark_path.split("/")[-1] - # Check if the node is part of the updated graph view - # i.e. from grouping the currently bookmarked node - # Remove invalid reference bookmark_manager.remove_bookmark(bookmark_path) - # Add bookmark + # Check if the node is part of the updated graph view + # i.e. from grouping the currently bookmarked node + + # Add bookmark if it's in the updated view if updated_view != null: var node_path := "node_" + target_node if graph.has_node(node_path): From e93baa8911015b346025666ee86b72429a73ef75 Mon Sep 17 00:00:00 2001 From: LMW Date: Wed, 21 Jan 2026 22:00:35 +0800 Subject: [PATCH 06/27] remove unused signal --- material_maker/panels/graph_edit/graph_bookmark_menu.gd | 2 +- material_maker/projects_panel.tscn | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/material_maker/panels/graph_edit/graph_bookmark_menu.gd b/material_maker/panels/graph_edit/graph_bookmark_menu.gd index 06c6f8709..601e36367 100644 --- a/material_maker/panels/graph_edit/graph_bookmark_menu.gd +++ b/material_maker/panels/graph_edit/graph_bookmark_menu.gd @@ -113,7 +113,7 @@ func _on_tree_item_lmb_selected() -> void: # Jump back to top if we are in a subgraph if graph.generator != graph.top_generator: graph.update_view(graph.top_generator) - # Get target node from current graph + # Get bookmarked node from current graph var node_path := NodePath("node_" + path) if graph.has_node(node_path): target_gen = graph.get_node(node_path).generator diff --git a/material_maker/projects_panel.tscn b/material_maker/projects_panel.tscn index 60ae09067..50662611e 100644 --- a/material_maker/projects_panel.tscn +++ b/material_maker/projects_panel.tscn @@ -558,7 +558,6 @@ Scroll to zoom the 3D Preview." [connection signal="value_changed" from="MenuBar/HBox/MainGraphMenuBar/HBox/ViewMenu/ViewMenuPanel/VBoxContainer/VBoxContainer2/Thickness/LineThickness" to="MenuBar/HBox/MainGraphMenuBar/HBox/ViewMenu/ViewMenuPanel" method="_on_line_thickness_value_changed"] [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="minimum_size_changed" from="MenuBar/HBox/MainGraphMenuBar/HBox/BookmarkMenu/BookmarkMenuPanel" to="MenuBar/HBox/MainGraphMenuBar/HBox/BookmarkMenu/BookmarkMenuPanel" method="_on_minimum_size_changed"] [connection signal="gui_input" from="MenuBar/HBox/MainGraphMenuBar/HBox/BookmarkMenu/BookmarkMenuPanel/Tree" to="MenuBar/HBox/MainGraphMenuBar/HBox/BookmarkMenu/BookmarkMenuPanel" method="_on_tree_gui_input"] [connection signal="item_edited" from="MenuBar/HBox/MainGraphMenuBar/HBox/BookmarkMenu/BookmarkMenuPanel/Tree" to="MenuBar/HBox/MainGraphMenuBar/HBox/BookmarkMenu/BookmarkMenuPanel" method="_on_tree_item_edited"] [connection signal="item_mouse_selected" from="MenuBar/HBox/MainGraphMenuBar/HBox/BookmarkMenu/BookmarkMenuPanel/Tree" to="MenuBar/HBox/MainGraphMenuBar/HBox/BookmarkMenu/BookmarkMenuPanel" method="_on_tree_item_mouse_selected"] From 101bd4246937a238300b371a2836c557e2e78f8d Mon Sep 17 00:00:00 2001 From: LMW Date: Thu, 22 Jan 2026 00:06:54 +0800 Subject: [PATCH 07/27] added class name for reroute --- material_maker/nodes/reroute/reroute.gd | 1 + 1 file changed, 1 insertion(+) diff --git a/material_maker/nodes/reroute/reroute.gd b/material_maker/nodes/reroute/reroute.gd index cb890ca7b..db6f097ac 100644 --- a/material_maker/nodes/reroute/reroute.gd +++ b/material_maker/nodes/reroute/reroute.gd @@ -1,5 +1,6 @@ extends MMGraphNodeMinimal +class_name MMGraphReroute const PREVIEW_SIZES : Array[int] = [ 0, 64, 128, 192] From e3b7a9e5ced3325f7438720346b5a13edb8a96f9 Mon Sep 17 00:00:00 2001 From: LMW Date: Thu, 22 Jan 2026 00:12:25 +0800 Subject: [PATCH 08/27] Bookmark new reroute/comment nodes --- .../panels/graph_edit/graph_bookmark_menu.gd | 2 +- material_maker/panels/graph_edit/graph_edit.gd | 10 ++++++++++ .../tools/bookmark_manager/bookmark_manager.gd | 16 ++++++++++------ 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/material_maker/panels/graph_edit/graph_bookmark_menu.gd b/material_maker/panels/graph_edit/graph_bookmark_menu.gd index 601e36367..44bb914c4 100644 --- a/material_maker/panels/graph_edit/graph_bookmark_menu.gd +++ b/material_maker/panels/graph_edit/graph_bookmark_menu.gd @@ -22,7 +22,7 @@ func _ready() -> void: break bookmark_manager = mm_globals.main_window.bookmark_manager - bookmark_manager.bookmark_added.connect(update_bookmarks) + bookmark_manager.should_refresh_bookmarks.connect(update_bookmarks) %Projects.tab_changed.connect(projects_panel_tab_changed.unbind(1)) diff --git a/material_maker/panels/graph_edit/graph_edit.gd b/material_maker/panels/graph_edit/graph_edit.gd index 782a8f99a..c6eac9587 100644 --- a/material_maker/panels/graph_edit/graph_edit.gd +++ b/material_maker/panels/graph_edit/graph_edit.gd @@ -326,6 +326,7 @@ func add_node(node) -> void: add_child(node) move_child(node, 0) node.connect("delete_request", Callable(self, "remove_node").bind(node)) + add_default_bookmark(node) func swap_node_inputs() -> void: var selected_nodes : Array = get_selected_nodes() @@ -486,6 +487,7 @@ func do_remove_node(node) -> void: remove_child(node) node.queue_free() send_changed_signal() + get_node("/root/MainWindow/BookmarkManager").should_refresh_bookmarks.emit() # Global operations on graph @@ -1772,3 +1774,11 @@ func bookmark_node() -> void: else: generator_path = BookmarkManager.get_path_from_gen(selected_node.generator, top_generator) bookmark_manager.add_bookmark(selected_node, generator_path) + +func add_default_bookmark(node : GraphElement) -> void: + print(node.generator.name) + if node.get_script() in [MMGraphReroute, MMGraphComment]: + await get_tree().process_frame + var node_path = BookmarkManager.get_path_from_gen(node.generator, top_generator) + var bookmark_manager : BookmarkManager = mm_globals.main_window.bookmark_manager + bookmark_manager.add_bookmark_from_path(node_path, node.generator.name) diff --git a/material_maker/tools/bookmark_manager/bookmark_manager.gd b/material_maker/tools/bookmark_manager/bookmark_manager.gd index 4ce513719..409e2f8d3 100644 --- a/material_maker/tools/bookmark_manager/bookmark_manager.gd +++ b/material_maker/tools/bookmark_manager/bookmark_manager.gd @@ -6,18 +6,19 @@ class_name BookmarkManager var bookmarks : Dictionary[String, String] -signal bookmark_added +signal should_refresh_bookmarks func add_bookmark(node: GraphElement, gen_path: String) -> void: if not bookmarks.has(gen_path): bookmarks[gen_path] = node.name.trim_prefix("node_") mm_globals.set_tip_text("Added bookmark for %s" % node.name.trim_prefix("node_"), 1.0, 1) - bookmark_added.emit() + should_refresh_bookmarks.emit() func add_bookmark_from_path(path: String, label: String) -> void: bookmarks[path] = label + should_refresh_bookmarks.emit() func remove_bookmark(path: String) -> void: @@ -35,11 +36,14 @@ func get_bookmarks() -> Dictionary[String, String]: static func get_path_from_gen(generator: MMGenBase, top_generator: MMGenGraph) -> String: var parent_gen = generator.get_parent() var node_path : PackedStringArray - var current_gen : MMGenGraph = parent_gen + var current_gen = parent_gen node_path.append(current_gen.name) - while current_gen.get_parent() != top_generator: - current_gen = current_gen.get_parent() - node_path.append(current_gen.name) + if current_gen != top_generator: + while current_gen.get_parent() != top_generator: + current_gen = current_gen.get_parent() + node_path.append(current_gen.name) + else: + return "./" + generator.name node_path.append(".") node_path.reverse() node_path.append(generator.name) From 75b3dc3d01f93badb2b88a5aedb603d7e07ebff7 Mon Sep 17 00:00:00 2001 From: LMW Date: Thu, 22 Jan 2026 00:16:39 +0800 Subject: [PATCH 09/27] Add material node as a default bookmark --- material_maker/panels/graph_edit/graph_edit.gd | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/material_maker/panels/graph_edit/graph_edit.gd b/material_maker/panels/graph_edit/graph_edit.gd index c6eac9587..71ebee3fd 100644 --- a/material_maker/panels/graph_edit/graph_edit.gd +++ b/material_maker/panels/graph_edit/graph_edit.gd @@ -1776,8 +1776,7 @@ func bookmark_node() -> void: bookmark_manager.add_bookmark(selected_node, generator_path) func add_default_bookmark(node : GraphElement) -> void: - print(node.generator.name) - if node.get_script() in [MMGraphReroute, MMGraphComment]: + if node.get_script() in [MMGraphReroute, MMGraphComment] or node.name == "node_Material": await get_tree().process_frame var node_path = BookmarkManager.get_path_from_gen(node.generator, top_generator) var bookmark_manager : BookmarkManager = mm_globals.main_window.bookmark_manager From 4f72e9816e3f9acc085e1dc54a76ac213e552899 Mon Sep 17 00:00:00 2001 From: LMW Date: Thu, 22 Jan 2026 00:17:48 +0800 Subject: [PATCH 10/27] minor comment update --- material_maker/tools/bookmark_manager/bookmark_manager.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/material_maker/tools/bookmark_manager/bookmark_manager.gd b/material_maker/tools/bookmark_manager/bookmark_manager.gd index 409e2f8d3..a376c8dbc 100644 --- a/material_maker/tools/bookmark_manager/bookmark_manager.gd +++ b/material_maker/tools/bookmark_manager/bookmark_manager.gd @@ -2,7 +2,7 @@ extends Node class_name BookmarkManager -## Top-level graph bookmarks to revisit them later +## Graph bookmarks to revisit them later var bookmarks : Dictionary[String, String] From c4fd78de7af83c3136573d3e092ea4da11cc69d8 Mon Sep 17 00:00:00 2001 From: LMW Date: Thu, 22 Jan 2026 00:31:55 +0800 Subject: [PATCH 11/27] bookmark comment line nodes automatically --- material_maker/panels/graph_edit/graph_edit.gd | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/material_maker/panels/graph_edit/graph_edit.gd b/material_maker/panels/graph_edit/graph_edit.gd index 71ebee3fd..e8ef3cd80 100644 --- a/material_maker/panels/graph_edit/graph_edit.gd +++ b/material_maker/panels/graph_edit/graph_edit.gd @@ -1776,7 +1776,8 @@ func bookmark_node() -> void: bookmark_manager.add_bookmark(selected_node, generator_path) func add_default_bookmark(node : GraphElement) -> void: - if node.get_script() in [MMGraphReroute, MMGraphComment] or node.name == "node_Material": + if (node.get_script() in [MMGraphReroute, MMGraphComment, MMGraphCommentLine] + or node.name == "node_Material"): await get_tree().process_frame var node_path = BookmarkManager.get_path_from_gen(node.generator, top_generator) var bookmark_manager : BookmarkManager = mm_globals.main_window.bookmark_manager From 7c1f1978a99910dbbaa68731dcffae7121ff7958 Mon Sep 17 00:00:00 2001 From: LMW Date: Thu, 22 Jan 2026 12:05:14 +0800 Subject: [PATCH 12/27] simplify getting node path --- .../panels/graph_edit/graph_bookmark_menu.gd | 2 +- material_maker/panels/graph_edit/graph_edit.gd | 9 ++------- .../tools/bookmark_manager/bookmark_manager.gd | 18 ------------------ 3 files changed, 3 insertions(+), 26 deletions(-) diff --git a/material_maker/panels/graph_edit/graph_bookmark_menu.gd b/material_maker/panels/graph_edit/graph_bookmark_menu.gd index 44bb914c4..2a0b458fc 100644 --- a/material_maker/panels/graph_edit/graph_bookmark_menu.gd +++ b/material_maker/panels/graph_edit/graph_bookmark_menu.gd @@ -80,7 +80,7 @@ func validate_bookmarks(updated_view : MMGenGraph = null) -> void: var node_path := "node_" + target_node if graph.has_node(node_path): var gen : MMGenBase = graph.get_node(node_path).generator - var new_path := BookmarkManager.get_path_from_gen(gen, graph.top_generator) + var new_path : String = "./" + str(graph.top_generator.get_path_to(gen)) bookmark_manager.add_bookmark_from_path(new_path, target_node) diff --git a/material_maker/panels/graph_edit/graph_edit.gd b/material_maker/panels/graph_edit/graph_edit.gd index e8ef3cd80..dc4dd2e48 100644 --- a/material_maker/panels/graph_edit/graph_edit.gd +++ b/material_maker/panels/graph_edit/graph_edit.gd @@ -1767,18 +1767,13 @@ func bookmark_node() -> void: if selected_nodes.size() != 1: return var selected_node : GraphElement = selected_nodes[0] - var generator_path : String - - if generator == top_generator: - generator_path = "./" + selected_node.generator.name - else: - generator_path = BookmarkManager.get_path_from_gen(selected_node.generator, top_generator) + var generator_path : String = "./" + str(top_generator.get_path_to(selected_node.generator)) bookmark_manager.add_bookmark(selected_node, generator_path) func add_default_bookmark(node : GraphElement) -> void: if (node.get_script() in [MMGraphReroute, MMGraphComment, MMGraphCommentLine] or node.name == "node_Material"): await get_tree().process_frame - var node_path = BookmarkManager.get_path_from_gen(node.generator, top_generator) + var node_path = "./" + str(top_generator.get_path_to(node.generator)) var bookmark_manager : BookmarkManager = mm_globals.main_window.bookmark_manager bookmark_manager.add_bookmark_from_path(node_path, node.generator.name) diff --git a/material_maker/tools/bookmark_manager/bookmark_manager.gd b/material_maker/tools/bookmark_manager/bookmark_manager.gd index a376c8dbc..b024ef3f7 100644 --- a/material_maker/tools/bookmark_manager/bookmark_manager.gd +++ b/material_maker/tools/bookmark_manager/bookmark_manager.gd @@ -32,24 +32,6 @@ func edit_bookmark(bookmark: Dictionary, new_label: String) -> void: func get_bookmarks() -> Dictionary[String, String]: return bookmarks - -static func get_path_from_gen(generator: MMGenBase, top_generator: MMGenGraph) -> String: - var parent_gen = generator.get_parent() - var node_path : PackedStringArray - var current_gen = parent_gen - node_path.append(current_gen.name) - if current_gen != top_generator: - while current_gen.get_parent() != top_generator: - current_gen = current_gen.get_parent() - node_path.append(current_gen.name) - else: - return "./" + generator.name - node_path.append(".") - node_path.reverse() - node_path.append(generator.name) - return "/".join(node_path) - - func _enter_tree() -> void: pass From 813ca38d756b7618cd3311c5ad6c38c1b61e4e1a Mon Sep 17 00:00:00 2001 From: LMW Date: Thu, 22 Jan 2026 12:37:42 +0800 Subject: [PATCH 13/27] fix editing bookmarks --- material_maker/tools/bookmark_manager/bookmark_manager.gd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/material_maker/tools/bookmark_manager/bookmark_manager.gd b/material_maker/tools/bookmark_manager/bookmark_manager.gd index b024ef3f7..961f294f8 100644 --- a/material_maker/tools/bookmark_manager/bookmark_manager.gd +++ b/material_maker/tools/bookmark_manager/bookmark_manager.gd @@ -25,8 +25,8 @@ func remove_bookmark(path: String) -> void: bookmarks.erase(path) -func edit_bookmark(bookmark: Dictionary, new_label: String) -> void: - bookmark.label = new_label +func edit_bookmark(path: String, new_label: String) -> void: + bookmarks[path] = new_label func get_bookmarks() -> Dictionary[String, String]: From 0b599608e0a813af00d3e9072e7743be41a263f4 Mon Sep 17 00:00:00 2001 From: LMW Date: Thu, 22 Jan 2026 15:32:54 +0800 Subject: [PATCH 14/27] simplify getting graphedit from panel --- addons/material_maker/engine/nodes/gen_graph.gd | 15 +++++++++++++-- .../panels/graph_edit/graph_bookmark_menu.gd | 13 +++++++++---- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/addons/material_maker/engine/nodes/gen_graph.gd b/addons/material_maker/engine/nodes/gen_graph.gd index 8ab629bce..a10593ff6 100644 --- a/addons/material_maker/engine/nodes/gen_graph.gd +++ b/addons/material_maker/engine/nodes/gen_graph.gd @@ -13,6 +13,8 @@ var transmits_seed : bool = true var current_mesh : Mesh = null +var bookmarks = null + signal graph_changed() signal connections_changed(removed_connections, added_connections) @@ -22,11 +24,14 @@ signal hierarchy_changed() func _ready() -> void: super._ready() -func emit_hierarchy_changed(): +func get_top() -> MMGenGraph: var top = self while top.get_parent() != null and top.get_parent().get_script() == get_script(): top = top.get_parent() - top.emit_signal("hierarchy_changed") + return top + +func emit_hierarchy_changed(): + get_top().emit_signal("hierarchy_changed") func fix_remotes() -> void: for c in get_children(): @@ -534,6 +539,9 @@ func _serialize(data: Dictionary) -> Dictionary: data.nodes.append(c.serialize()) #data.connections = connections_to_compact(connections) data.connections = connections + if self == get_top(): + # save bookmarks + pass return data func _deserialize(data : Dictionary) -> void: @@ -551,6 +559,9 @@ func _deserialize(data : Dictionary) -> void: elif data.connections is Dictionary: connection_array = connections_from_compact(data.connections) var new_stuff = await mm_loader.add_to_gen_graph(self, nodes, connection_array) + if self == get_top(): + # load bookmarks + pass #region Node Graph Diff func apply_diff_from(graph : MMGenGraph) -> void: diff --git a/material_maker/panels/graph_edit/graph_bookmark_menu.gd b/material_maker/panels/graph_edit/graph_bookmark_menu.gd index 2a0b458fc..8508c29c2 100644 --- a/material_maker/panels/graph_edit/graph_bookmark_menu.gd +++ b/material_maker/panels/graph_edit/graph_bookmark_menu.gd @@ -1,9 +1,10 @@ extends PanelContainer -var bookmark_manager : BookmarkManager @onready var tree := $Tree +var bookmark_manager : BookmarkManager + var is_unpinned_double_click_edited := false enum ContextMenu { @@ -27,7 +28,7 @@ func _ready() -> void: %Projects.tab_changed.connect(projects_panel_tab_changed.unbind(1)) func projects_panel_tab_changed(): - var graph : MMGraphEdit = mm_globals.main_window.get_current_graph_edit() + var graph : MMGraphEdit = owner.current_graph_edit if not graph.view_updated.is_connected(update_bookmarks): graph.view_updated.connect(update_bookmarks) @@ -53,7 +54,11 @@ func update_bookmarks(updated_view : MMGenGraph = null) -> void: func validate_bookmarks(updated_view : MMGenGraph = null) -> void: # Update and remove invalid references - var graph : MMGraphEdit = mm_globals.main_window.get_current_graph_edit() + var graph : MMGraphEdit = owner.current_graph_edit + if updated_view != null and updated_view == graph.top_generator: + if updated_view.bookmarks != null: + # load bookmarks from gen, skpping material and brush + pass if tree.get_root() == null: return @@ -104,7 +109,7 @@ func _on_tree_item_lmb_selected() -> void: var selected_item : TreeItem = tree.get_selected() var path : String = selected_item.get_metadata(0) path = path.get_slice("./", 1) - var graph : MMGraphEdit = mm_globals.main_window.get_current_graph_edit() + var graph : MMGraphEdit = owner.current_graph_edit var target_gen : MMGenBase From 91814393581bc5d21131d3334ed32d755d269456 Mon Sep 17 00:00:00 2001 From: LMW Date: Thu, 22 Jan 2026 17:05:05 +0800 Subject: [PATCH 15/27] implement bookmarks save/load from file --- .../material_maker/engine/nodes/gen_graph.gd | 10 ++--- .../panels/graph_edit/graph_bookmark_menu.gd | 38 ++++++++++++------- .../panels/graph_edit/graph_edit.gd | 6 +-- .../bookmark_manager/bookmark_manager.gd | 18 +++------ 4 files changed, 37 insertions(+), 35 deletions(-) diff --git a/addons/material_maker/engine/nodes/gen_graph.gd b/addons/material_maker/engine/nodes/gen_graph.gd index a10593ff6..29c428192 100644 --- a/addons/material_maker/engine/nodes/gen_graph.gd +++ b/addons/material_maker/engine/nodes/gen_graph.gd @@ -539,9 +539,8 @@ func _serialize(data: Dictionary) -> Dictionary: data.nodes.append(c.serialize()) #data.connections = connections_to_compact(connections) data.connections = connections - if self == get_top(): - # save bookmarks - pass + if self == get_top() and bookmarks != null: + data.bookmarks = bookmarks return data func _deserialize(data : Dictionary) -> void: @@ -559,9 +558,8 @@ func _deserialize(data : Dictionary) -> void: elif data.connections is Dictionary: connection_array = connections_from_compact(data.connections) var new_stuff = await mm_loader.add_to_gen_graph(self, nodes, connection_array) - if self == get_top(): - # load bookmarks - pass + if self == get_top() and data.has("bookmarks"): + bookmarks = data.bookmarks #region Node Graph Diff func apply_diff_from(graph : MMGenGraph) -> void: diff --git a/material_maker/panels/graph_edit/graph_bookmark_menu.gd b/material_maker/panels/graph_edit/graph_bookmark_menu.gd index 8508c29c2..7199efc85 100644 --- a/material_maker/panels/graph_edit/graph_bookmark_menu.gd +++ b/material_maker/panels/graph_edit/graph_bookmark_menu.gd @@ -12,6 +12,11 @@ enum ContextMenu { DELETE, } + +func _open() -> void: + update_bookmarks() + + func _ready() -> void: if not mm_globals.main_window.is_node_ready(): await mm_globals.main_window.ready @@ -27,13 +32,14 @@ func _ready() -> void: %Projects.tab_changed.connect(projects_panel_tab_changed.unbind(1)) -func projects_panel_tab_changed(): + +func projects_panel_tab_changed() -> void: var graph : MMGraphEdit = owner.current_graph_edit if not graph.view_updated.is_connected(update_bookmarks): graph.view_updated.connect(update_bookmarks) -func fix_tree_line_edit_size(p : Popup): +func fix_tree_line_edit_size(p : Popup) -> void: var vbox : VBoxContainer = p.get_child(0) vbox.minimum_size_changed.connect( func(): @@ -43,22 +49,29 @@ func fix_tree_line_edit_size(p : Popup): vbox.get_window().max_size.y = contents_min_size + get_theme_constant("v_separation", "Tree")) -func _open() -> void: - update_bookmarks() - - func update_bookmarks(updated_view : MMGenGraph = null) -> void: validate_bookmarks(updated_view) + save_bookmarks() rebuild_bookmark_tree() +func save_bookmarks() -> void: + var graph : MMGraphEdit = owner.current_graph_edit + if graph.top_generator != null: + var current_bookmarks = bookmark_manager.bookmarks.duplicate() + current_bookmarks.erase("./Material") + if current_bookmarks.is_empty(): + graph.top_generator.bookmarks = null + else: + graph.top_generator.bookmarks = current_bookmarks + + func validate_bookmarks(updated_view : MMGenGraph = null) -> void: # Update and remove invalid references var graph : MMGraphEdit = owner.current_graph_edit if updated_view != null and updated_view == graph.top_generator: if updated_view.bookmarks != null: - # load bookmarks from gen, skpping material and brush - pass + bookmark_manager.bookmarks = updated_view.bookmarks if tree.get_root() == null: return @@ -67,7 +80,7 @@ func validate_bookmarks(updated_view : MMGenGraph = null) -> void: var bookmark_path : String = item.get_metadata(0) # Material & Brush nodes are always in top level graph - if bookmark_path in ["./Material", "./Brush"]: + if bookmark_path in ["./Material"]: continue # Bookmarked path does not point to anything @@ -79,8 +92,6 @@ func validate_bookmarks(updated_view : MMGenGraph = null) -> void: # Check if the node is part of the updated graph view # i.e. from grouping the currently bookmarked node - - # Add bookmark if it's in the updated view if updated_view != null: var node_path := "node_" + target_node if graph.has_node(node_path): @@ -88,13 +99,12 @@ func validate_bookmarks(updated_view : MMGenGraph = null) -> void: var new_path : String = "./" + str(graph.top_generator.get_path_to(gen)) bookmark_manager.add_bookmark_from_path(new_path, target_node) - func rebuild_bookmark_tree() -> void: await get_tree().process_frame tree.clear() var root : TreeItem = tree.create_item() - var bookmarks : Dictionary[String, String] = bookmark_manager.get_bookmarks() + var bookmarks := bookmark_manager.bookmarks for path : String in bookmarks: var new_item : TreeItem = tree.create_item(root) new_item.set_metadata(0, path) @@ -149,7 +159,7 @@ func _on_tree_item_lmb_selected() -> void: Tween.EASE_IN_OUT).set_trans(Tween.TRANS_CUBIC) -func _on_tree_item_rmb_selected(_mouse_position : Vector2i): +func _on_tree_item_rmb_selected(_mouse_position : Vector2i) -> void: mm_globals.popup_menu($ContextMenu, self) diff --git a/material_maker/panels/graph_edit/graph_edit.gd b/material_maker/panels/graph_edit/graph_edit.gd index dc4dd2e48..c13e10c0d 100644 --- a/material_maker/panels/graph_edit/graph_edit.gd +++ b/material_maker/panels/graph_edit/graph_edit.gd @@ -1771,9 +1771,9 @@ func bookmark_node() -> void: bookmark_manager.add_bookmark(selected_node, generator_path) func add_default_bookmark(node : GraphElement) -> void: - if (node.get_script() in [MMGraphReroute, MMGraphComment, MMGraphCommentLine] - or node.name == "node_Material"): - await get_tree().process_frame + if BookmarkManager.is_default_bookmark_node(node): + if not node.generator: + await get_tree().process_frame var node_path = "./" + str(top_generator.get_path_to(node.generator)) var bookmark_manager : BookmarkManager = mm_globals.main_window.bookmark_manager bookmark_manager.add_bookmark_from_path(node_path, node.generator.name) diff --git a/material_maker/tools/bookmark_manager/bookmark_manager.gd b/material_maker/tools/bookmark_manager/bookmark_manager.gd index 961f294f8..d8e8e49db 100644 --- a/material_maker/tools/bookmark_manager/bookmark_manager.gd +++ b/material_maker/tools/bookmark_manager/bookmark_manager.gd @@ -4,11 +4,16 @@ class_name BookmarkManager ## Graph bookmarks to revisit them later -var bookmarks : Dictionary[String, String] +var bookmarks: Dictionary[String, String] signal should_refresh_bookmarks +static func is_default_bookmark_node(node: GraphElement) -> bool: + return (node.get_script() in [MMGraphReroute, MMGraphComment, MMGraphCommentLine] + or node.name in ["node_Material"]) + + func add_bookmark(node: GraphElement, gen_path: String) -> void: if not bookmarks.has(gen_path): bookmarks[gen_path] = node.name.trim_prefix("node_") @@ -27,14 +32,3 @@ func remove_bookmark(path: String) -> void: func edit_bookmark(path: String, new_label: String) -> void: bookmarks[path] = new_label - - -func get_bookmarks() -> Dictionary[String, String]: - return bookmarks - -func _enter_tree() -> void: - pass - - -func _exit_tree() -> void: - pass From a8fab280ad324a16ab8ea818e67b8de58250fd9e Mon Sep 17 00:00:00 2001 From: LMW Date: Thu, 22 Jan 2026 17:22:48 +0800 Subject: [PATCH 16/27] implement bookmark save/load when switching project tab --- .../panels/graph_edit/graph_bookmark_menu.gd | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/material_maker/panels/graph_edit/graph_bookmark_menu.gd b/material_maker/panels/graph_edit/graph_bookmark_menu.gd index 7199efc85..0da729618 100644 --- a/material_maker/panels/graph_edit/graph_bookmark_menu.gd +++ b/material_maker/panels/graph_edit/graph_bookmark_menu.gd @@ -37,9 +37,12 @@ func projects_panel_tab_changed() -> void: var graph : MMGraphEdit = owner.current_graph_edit if not graph.view_updated.is_connected(update_bookmarks): graph.view_updated.connect(update_bookmarks) + if graph.top_generator == null: + await get_tree().process_frame + update_bookmarks(graph.top_generator) -func fix_tree_line_edit_size(p : Popup) -> void: +func fix_tree_line_edit_size(p: Popup) -> void: var vbox : VBoxContainer = p.get_child(0) vbox.minimum_size_changed.connect( func(): @@ -49,7 +52,7 @@ func fix_tree_line_edit_size(p : Popup) -> void: vbox.get_window().max_size.y = contents_min_size + get_theme_constant("v_separation", "Tree")) -func update_bookmarks(updated_view : MMGenGraph = null) -> void: +func update_bookmarks(updated_view: MMGenGraph = null) -> void: validate_bookmarks(updated_view) save_bookmarks() rebuild_bookmark_tree() @@ -59,14 +62,10 @@ func save_bookmarks() -> void: var graph : MMGraphEdit = owner.current_graph_edit if graph.top_generator != null: var current_bookmarks = bookmark_manager.bookmarks.duplicate() - current_bookmarks.erase("./Material") - if current_bookmarks.is_empty(): - graph.top_generator.bookmarks = null - else: - graph.top_generator.bookmarks = current_bookmarks + graph.top_generator.bookmarks = current_bookmarks -func validate_bookmarks(updated_view : MMGenGraph = null) -> void: +func validate_bookmarks(updated_view: MMGenGraph = null) -> void: # Update and remove invalid references var graph : MMGraphEdit = owner.current_graph_edit if updated_view != null and updated_view == graph.top_generator: @@ -159,7 +158,7 @@ func _on_tree_item_lmb_selected() -> void: Tween.EASE_IN_OUT).set_trans(Tween.TRANS_CUBIC) -func _on_tree_item_rmb_selected(_mouse_position : Vector2i) -> void: +func _on_tree_item_rmb_selected(_mouse_position: Vector2i) -> void: mm_globals.popup_menu($ContextMenu, self) From 7ce8ba9dd07f1f0f82c2b0a36faf3ed7aa244e1b Mon Sep 17 00:00:00 2001 From: LMW Date: Thu, 22 Jan 2026 17:25:33 +0800 Subject: [PATCH 17/27] fix bookmark context menu actions --- material_maker/panels/graph_edit/graph_bookmark_menu.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/material_maker/panels/graph_edit/graph_bookmark_menu.gd b/material_maker/panels/graph_edit/graph_bookmark_menu.gd index 0da729618..d30cc7a05 100644 --- a/material_maker/panels/graph_edit/graph_bookmark_menu.gd +++ b/material_maker/panels/graph_edit/graph_bookmark_menu.gd @@ -187,7 +187,7 @@ func _on_context_menu_id_pressed(id: int) -> void: item.set_editable(0, true) tree.edit_selected() ContextMenu.DELETE: - bookmark_manager.remove_bookmark(item.get_metadata(0).node_name) + bookmark_manager.remove_bookmark(item.get_metadata(0)) rebuild_bookmark_tree() From 3c1769ff58e8abc1b60ba1e5b37fd41699f0226a Mon Sep 17 00:00:00 2001 From: LMW Date: Thu, 22 Jan 2026 18:05:20 +0800 Subject: [PATCH 18/27] fix loading bookmarks from crash state --- material_maker/panels/graph_edit/graph_bookmark_menu.gd | 1 + 1 file changed, 1 insertion(+) diff --git a/material_maker/panels/graph_edit/graph_bookmark_menu.gd b/material_maker/panels/graph_edit/graph_bookmark_menu.gd index d30cc7a05..d7069c69f 100644 --- a/material_maker/panels/graph_edit/graph_bookmark_menu.gd +++ b/material_maker/panels/graph_edit/graph_bookmark_menu.gd @@ -70,6 +70,7 @@ func validate_bookmarks(updated_view: MMGenGraph = null) -> void: var graph : MMGraphEdit = owner.current_graph_edit if updated_view != null and updated_view == graph.top_generator: if updated_view.bookmarks != null: + await get_tree().process_frame bookmark_manager.bookmarks = updated_view.bookmarks if tree.get_root() == null: From e2c8b16e936d2dae948086309fadff9b86299a63 Mon Sep 17 00:00:00 2001 From: LMW Date: Thu, 22 Jan 2026 19:20:52 +0800 Subject: [PATCH 19/27] fix loading bookmarks during rescue --- material_maker/panels/graph_edit/graph_bookmark_menu.gd | 1 - material_maker/tools/bookmark_manager/bookmark_manager.gd | 7 ++++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/material_maker/panels/graph_edit/graph_bookmark_menu.gd b/material_maker/panels/graph_edit/graph_bookmark_menu.gd index d7069c69f..d30cc7a05 100644 --- a/material_maker/panels/graph_edit/graph_bookmark_menu.gd +++ b/material_maker/panels/graph_edit/graph_bookmark_menu.gd @@ -70,7 +70,6 @@ func validate_bookmarks(updated_view: MMGenGraph = null) -> void: var graph : MMGraphEdit = owner.current_graph_edit if updated_view != null and updated_view == graph.top_generator: if updated_view.bookmarks != null: - await get_tree().process_frame bookmark_manager.bookmarks = updated_view.bookmarks if tree.get_root() == null: diff --git a/material_maker/tools/bookmark_manager/bookmark_manager.gd b/material_maker/tools/bookmark_manager/bookmark_manager.gd index d8e8e49db..3e8619818 100644 --- a/material_maker/tools/bookmark_manager/bookmark_manager.gd +++ b/material_maker/tools/bookmark_manager/bookmark_manager.gd @@ -4,11 +4,16 @@ class_name BookmarkManager ## Graph bookmarks to revisit them later -var bookmarks: Dictionary[String, String] +var bookmarks : Dictionary signal should_refresh_bookmarks + +func set_bookmarks(new_bookmarks: Dictionary) -> void: + bookmarks = new_bookmarks + + static func is_default_bookmark_node(node: GraphElement) -> bool: return (node.get_script() in [MMGraphReroute, MMGraphComment, MMGraphCommentLine] or node.name in ["node_Material"]) From 93d9e381ea7fb8d6b6ad284082014be58c28b0d5 Mon Sep 17 00:00:00 2001 From: LMW Date: Thu, 22 Jan 2026 19:25:57 +0800 Subject: [PATCH 20/27] use node title as bookmark label --- material_maker/tools/bookmark_manager/bookmark_manager.gd | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/material_maker/tools/bookmark_manager/bookmark_manager.gd b/material_maker/tools/bookmark_manager/bookmark_manager.gd index 3e8619818..a6e1bb648 100644 --- a/material_maker/tools/bookmark_manager/bookmark_manager.gd +++ b/material_maker/tools/bookmark_manager/bookmark_manager.gd @@ -21,8 +21,11 @@ static func is_default_bookmark_node(node: GraphElement) -> bool: func add_bookmark(node: GraphElement, gen_path: String) -> void: if not bookmarks.has(gen_path): - bookmarks[gen_path] = node.name.trim_prefix("node_") - mm_globals.set_tip_text("Added bookmark for %s" % node.name.trim_prefix("node_"), 1.0, 1) + var label : String = node.title + if label == "": + label = node.name.trim_prefix("node_") + bookmarks[gen_path] = label + mm_globals.set_tip_text("Added bookmark for %s" % label, 1.0, 1) should_refresh_bookmarks.emit() From 0bb6ef76163f7cc54416acb747502b50e2f95aa5 Mon Sep 17 00:00:00 2001 From: LMW Date: Thu, 22 Jan 2026 22:09:00 +0800 Subject: [PATCH 21/27] Added X/Delete key to remove bookmarks --- .../panels/graph_edit/graph_bookmark_menu.gd | 8 +++++++- material_maker/panels/graph_edit/graph_edit.gd | 2 +- .../tools/bookmark_manager/bookmark_manager.gd | 12 ++++++++---- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/material_maker/panels/graph_edit/graph_bookmark_menu.gd b/material_maker/panels/graph_edit/graph_bookmark_menu.gd index d30cc7a05..e189c95c1 100644 --- a/material_maker/panels/graph_edit/graph_bookmark_menu.gd +++ b/material_maker/panels/graph_edit/graph_bookmark_menu.gd @@ -28,7 +28,9 @@ func _ready() -> void: break bookmark_manager = mm_globals.main_window.bookmark_manager - bookmark_manager.should_refresh_bookmarks.connect(update_bookmarks) + bookmark_manager.bookmarks_added.connect(update_bookmarks) + bookmark_manager.updated_from_graph.connect(update_bookmarks) + bookmark_manager.bookmarks_edit_removed.connect(save_bookmarks) %Projects.tab_changed.connect(projects_panel_tab_changed.unbind(1)) @@ -171,6 +173,10 @@ func _on_tree_gui_input(event: InputEvent) -> void: # keep panel pinned while editing is_unpinned_double_click_edited = not get_parent().pinned get_parent().pinned = true + elif event is InputEventKey and event.pressed: + match event.get_keycode_with_modifiers(): + KEY_X, KEY_DELETE: + _on_context_menu_id_pressed(ContextMenu.DELETE) func _on_tree_item_mouse_selected(mouse_position: Vector2, mouse_button_index: int) -> void: diff --git a/material_maker/panels/graph_edit/graph_edit.gd b/material_maker/panels/graph_edit/graph_edit.gd index c13e10c0d..b926ae765 100644 --- a/material_maker/panels/graph_edit/graph_edit.gd +++ b/material_maker/panels/graph_edit/graph_edit.gd @@ -487,7 +487,7 @@ func do_remove_node(node) -> void: remove_child(node) node.queue_free() send_changed_signal() - get_node("/root/MainWindow/BookmarkManager").should_refresh_bookmarks.emit() + get_node("/root/MainWindow/BookmarkManager").updated_from_graph.emit() # Global operations on graph diff --git a/material_maker/tools/bookmark_manager/bookmark_manager.gd b/material_maker/tools/bookmark_manager/bookmark_manager.gd index a6e1bb648..faadf5a0c 100644 --- a/material_maker/tools/bookmark_manager/bookmark_manager.gd +++ b/material_maker/tools/bookmark_manager/bookmark_manager.gd @@ -6,9 +6,11 @@ class_name BookmarkManager var bookmarks : Dictionary -signal should_refresh_bookmarks - +signal bookmarks_added +signal bookmarks_edit_removed +@warning_ignore("unused_signal") +signal updated_from_graph func set_bookmarks(new_bookmarks: Dictionary) -> void: bookmarks = new_bookmarks @@ -26,17 +28,19 @@ func add_bookmark(node: GraphElement, gen_path: String) -> void: label = node.name.trim_prefix("node_") bookmarks[gen_path] = label mm_globals.set_tip_text("Added bookmark for %s" % label, 1.0, 1) - should_refresh_bookmarks.emit() + bookmarks_added.emit() func add_bookmark_from_path(path: String, label: String) -> void: bookmarks[path] = label - should_refresh_bookmarks.emit() + bookmarks_added.emit() func remove_bookmark(path: String) -> void: bookmarks.erase(path) + bookmarks_edit_removed.emit() func edit_bookmark(path: String, new_label: String) -> void: bookmarks[path] = new_label + bookmarks_edit_removed.emit() From 99edc201ba8c3675ee461a11aadf0220f64f3a90 Mon Sep 17 00:00:00 2001 From: LMW Date: Thu, 22 Jan 2026 22:11:58 +0800 Subject: [PATCH 22/27] Check for selection in tree before deletion --- material_maker/panels/graph_edit/graph_bookmark_menu.gd | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/material_maker/panels/graph_edit/graph_bookmark_menu.gd b/material_maker/panels/graph_edit/graph_bookmark_menu.gd index e189c95c1..0fbf8ea40 100644 --- a/material_maker/panels/graph_edit/graph_bookmark_menu.gd +++ b/material_maker/panels/graph_edit/graph_bookmark_menu.gd @@ -193,8 +193,9 @@ func _on_context_menu_id_pressed(id: int) -> void: item.set_editable(0, true) tree.edit_selected() ContextMenu.DELETE: - bookmark_manager.remove_bookmark(item.get_metadata(0)) - rebuild_bookmark_tree() + if item != null: + bookmark_manager.remove_bookmark(item.get_metadata(0)) + rebuild_bookmark_tree() func _on_tree_item_edited() -> void: From caec3c3baf1a89d6d0ee28610218fd962f7b3091 Mon Sep 17 00:00:00 2001 From: LMW Date: Fri, 23 Jan 2026 00:29:10 +0800 Subject: [PATCH 23/27] add visual inidication --- material_maker/panels/graph_edit/graph_edit.gd | 6 +++++- material_maker/projects_panel.tscn | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/material_maker/panels/graph_edit/graph_edit.gd b/material_maker/panels/graph_edit/graph_edit.gd index b926ae765..3a570a5bd 100644 --- a/material_maker/panels/graph_edit/graph_edit.gd +++ b/material_maker/panels/graph_edit/graph_edit.gd @@ -1768,7 +1768,11 @@ func bookmark_node() -> void: return var selected_node : GraphElement = selected_nodes[0] var generator_path : String = "./" + str(top_generator.get_path_to(selected_node.generator)) - bookmark_manager.add_bookmark(selected_node, generator_path) + if not bookmark_manager.bookmarks.has(generator_path): + var tween := get_tree().create_tween() + tween.tween_property(selected_node, "modulate", Color.DIM_GRAY, 0.1) + tween.parallel().tween_property(selected_node, "modulate", Color.WHITE, 0.15).set_delay(0.15) + bookmark_manager.add_bookmark(selected_node, generator_path) func add_default_bookmark(node : GraphElement) -> void: if BookmarkManager.is_default_bookmark_node(node): diff --git a/material_maker/projects_panel.tscn b/material_maker/projects_panel.tscn index 50662611e..65c5551b5 100644 --- a/material_maker/projects_panel.tscn +++ b/material_maker/projects_panel.tscn @@ -11,7 +11,7 @@ [ext_resource type="Script" uid="uid://bxwor0k6svci8" path="res://material_maker/panels/graph_edit/graph_view_menu.gd" id="8_nl2qi"] [ext_resource type="Script" uid="uid://pqxjwlcff5ko" path="res://material_maker/panels/graph_edit/graph_align_menu.gd" id="8_r5hxx"] [ext_resource type="ButtonGroup" uid="uid://biv6we3po8wbb" path="res://material_maker/line_style_btn_group.tres" id="10_lbgjg"] -[ext_resource type="Script" uid="uid://dxreq1nitp4as" path="res://material_maker/panels/graph_edit/graph_bookmark_menu.gd" id="11_qnupl"] +[ext_resource type="Script" path="res://material_maker/panels/graph_edit/graph_bookmark_menu.gd" id="11_qnupl"] [sub_resource type="Shader" id="1"] resource_local_to_scene = true From 9631a4765be7c24981b087a604ea737b4514126e Mon Sep 17 00:00:00 2001 From: LMW Date: Fri, 23 Jan 2026 12:17:15 +0800 Subject: [PATCH 24/27] bookmark title from node/generator --- material_maker/nodes/reroute/reroute.gd | 2 -- .../panels/graph_edit/graph_bookmark_menu.gd | 1 + .../panels/graph_edit/graph_edit.gd | 3 ++- material_maker/projects_panel.tscn | 2 +- .../bookmark_manager/bookmark_manager.gd | 19 +++++++++++++++---- 5 files changed, 19 insertions(+), 8 deletions(-) diff --git a/material_maker/nodes/reroute/reroute.gd b/material_maker/nodes/reroute/reroute.gd index db6f097ac..eadeb6db5 100644 --- a/material_maker/nodes/reroute/reroute.gd +++ b/material_maker/nodes/reroute/reroute.gd @@ -1,7 +1,5 @@ extends MMGraphNodeMinimal -class_name MMGraphReroute - const PREVIEW_SIZES : Array[int] = [ 0, 64, 128, 192] diff --git a/material_maker/panels/graph_edit/graph_bookmark_menu.gd b/material_maker/panels/graph_edit/graph_bookmark_menu.gd index 0fbf8ea40..2517cfe4b 100644 --- a/material_maker/panels/graph_edit/graph_bookmark_menu.gd +++ b/material_maker/panels/graph_edit/graph_bookmark_menu.gd @@ -146,6 +146,7 @@ func _on_tree_item_lmb_selected() -> void: if graph.generator != target_gen.get_parent(): graph.update_view(target_gen.get_parent()) + # Center view on bookmarked node var bookmark_node_path : NodePath = "node_" + target_gen.name if graph.has_node(bookmark_node_path): diff --git a/material_maker/panels/graph_edit/graph_edit.gd b/material_maker/panels/graph_edit/graph_edit.gd index 3a570a5bd..5dc7ad4f3 100644 --- a/material_maker/panels/graph_edit/graph_edit.gd +++ b/material_maker/panels/graph_edit/graph_edit.gd @@ -1780,4 +1780,5 @@ func add_default_bookmark(node : GraphElement) -> void: await get_tree().process_frame var node_path = "./" + str(top_generator.get_path_to(node.generator)) var bookmark_manager : BookmarkManager = mm_globals.main_window.bookmark_manager - bookmark_manager.add_bookmark_from_path(node_path, node.generator.name) + if not bookmark_manager.bookmarks.has(node_path) and node.name == "node_Material": + bookmark_manager.add_bookmark_from_path(node_path, BookmarkManager.get_label_from_node(node)) diff --git a/material_maker/projects_panel.tscn b/material_maker/projects_panel.tscn index 65c5551b5..50662611e 100644 --- a/material_maker/projects_panel.tscn +++ b/material_maker/projects_panel.tscn @@ -11,7 +11,7 @@ [ext_resource type="Script" uid="uid://bxwor0k6svci8" path="res://material_maker/panels/graph_edit/graph_view_menu.gd" id="8_nl2qi"] [ext_resource type="Script" uid="uid://pqxjwlcff5ko" path="res://material_maker/panels/graph_edit/graph_align_menu.gd" id="8_r5hxx"] [ext_resource type="ButtonGroup" uid="uid://biv6we3po8wbb" path="res://material_maker/line_style_btn_group.tres" id="10_lbgjg"] -[ext_resource type="Script" path="res://material_maker/panels/graph_edit/graph_bookmark_menu.gd" id="11_qnupl"] +[ext_resource type="Script" uid="uid://dxreq1nitp4as" path="res://material_maker/panels/graph_edit/graph_bookmark_menu.gd" id="11_qnupl"] [sub_resource type="Shader" id="1"] resource_local_to_scene = true diff --git a/material_maker/tools/bookmark_manager/bookmark_manager.gd b/material_maker/tools/bookmark_manager/bookmark_manager.gd index faadf5a0c..f755444e7 100644 --- a/material_maker/tools/bookmark_manager/bookmark_manager.gd +++ b/material_maker/tools/bookmark_manager/bookmark_manager.gd @@ -17,15 +17,26 @@ func set_bookmarks(new_bookmarks: Dictionary) -> void: static func is_default_bookmark_node(node: GraphElement) -> bool: - return (node.get_script() in [MMGraphReroute, MMGraphComment, MMGraphCommentLine] + return (node.get_script() in [MMGraphComment, MMGraphCommentLine] or node.name in ["node_Material"]) +static func get_label_from_node(node: GraphElement) -> String: + var label : String = "" + if node is GraphNode and node.get("title"): + label = node.title + elif node is MMGraphComment: + label = node.generator.title + elif node is MMGraphCommentLine: + label = node.generator.text + if label == "": + label = node.name.trim_prefix("node_") + return label + + func add_bookmark(node: GraphElement, gen_path: String) -> void: if not bookmarks.has(gen_path): - var label : String = node.title - if label == "": - label = node.name.trim_prefix("node_") + var label : String = get_label_from_node(node) bookmarks[gen_path] = label mm_globals.set_tip_text("Added bookmark for %s" % label, 1.0, 1) bookmarks_added.emit() From 1e2a42ff143e7efeb2582db97c879accc283e804 Mon Sep 17 00:00:00 2001 From: LMW Date: Thu, 26 Mar 2026 22:27:53 +0800 Subject: [PATCH 25/27] format --- .../panels/graph_edit/graph_bookmark_menu.gd | 28 +++++-------------- .../bookmark_manager/bookmark_manager.gd | 22 ++++++--------- 2 files changed, 15 insertions(+), 35 deletions(-) diff --git a/material_maker/panels/graph_edit/graph_bookmark_menu.gd b/material_maker/panels/graph_edit/graph_bookmark_menu.gd index 2517cfe4b..96790ba07 100644 --- a/material_maker/panels/graph_edit/graph_bookmark_menu.gd +++ b/material_maker/panels/graph_edit/graph_bookmark_menu.gd @@ -1,6 +1,5 @@ extends PanelContainer - @onready var tree := $Tree var bookmark_manager : BookmarkManager @@ -16,7 +15,6 @@ enum ContextMenu { func _open() -> void: update_bookmarks() - func _ready() -> void: if not mm_globals.main_window.is_node_ready(): await mm_globals.main_window.ready @@ -34,7 +32,6 @@ func _ready() -> void: %Projects.tab_changed.connect(projects_panel_tab_changed.unbind(1)) - func projects_panel_tab_changed() -> void: var graph : MMGraphEdit = owner.current_graph_edit if not graph.view_updated.is_connected(update_bookmarks): @@ -43,8 +40,7 @@ func projects_panel_tab_changed() -> void: await get_tree().process_frame update_bookmarks(graph.top_generator) - -func fix_tree_line_edit_size(p: Popup) -> void: +func fix_tree_line_edit_size(p : Popup) -> void: var vbox : VBoxContainer = p.get_child(0) vbox.minimum_size_changed.connect( func(): @@ -53,21 +49,18 @@ func fix_tree_line_edit_size(p: Popup) -> void: @warning_ignore("narrowing_conversion") vbox.get_window().max_size.y = contents_min_size + get_theme_constant("v_separation", "Tree")) - -func update_bookmarks(updated_view: MMGenGraph = null) -> void: +func update_bookmarks(updated_view : MMGenGraph = null) -> void: validate_bookmarks(updated_view) save_bookmarks() rebuild_bookmark_tree() - func save_bookmarks() -> void: var graph : MMGraphEdit = owner.current_graph_edit if graph.top_generator != null: var current_bookmarks = bookmark_manager.bookmarks.duplicate() graph.top_generator.bookmarks = current_bookmarks - -func validate_bookmarks(updated_view: MMGenGraph = null) -> void: +func validate_bookmarks(updated_view : MMGenGraph = null) -> void: # Update and remove invalid references var graph : MMGraphEdit = owner.current_graph_edit if updated_view != null and updated_view == graph.top_generator: @@ -115,7 +108,6 @@ func rebuild_bookmark_tree() -> void: tree.visible = tree.get_root().get_child_count() != 0 $MarginContainer.visible = tree.get_root().get_child_count() == 0 - func _on_tree_item_lmb_selected() -> void: var selected_item : TreeItem = tree.get_selected() var path : String = selected_item.get_metadata(0) @@ -146,7 +138,6 @@ func _on_tree_item_lmb_selected() -> void: if graph.generator != target_gen.get_parent(): graph.update_view(target_gen.get_parent()) - # Center view on bookmarked node var bookmark_node_path : NodePath = "node_" + target_gen.name if graph.has_node(bookmark_node_path): @@ -160,12 +151,10 @@ func _on_tree_item_lmb_selected() -> void: tween.tween_property(graph, "scroll_offset", target_offset, 0.5).set_ease( Tween.EASE_IN_OUT).set_trans(Tween.TRANS_CUBIC) - -func _on_tree_item_rmb_selected(_mouse_position: Vector2i) -> void: +func _on_tree_item_rmb_selected(_mouse_position : Vector2i) -> void: mm_globals.popup_menu($ContextMenu, self) - -func _on_tree_gui_input(event: InputEvent) -> void: +func _on_tree_gui_input(event : InputEvent) -> void: if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT: if event.double_click: accept_event() @@ -179,15 +168,13 @@ func _on_tree_gui_input(event: InputEvent) -> void: KEY_X, KEY_DELETE: _on_context_menu_id_pressed(ContextMenu.DELETE) - -func _on_tree_item_mouse_selected(mouse_position: Vector2, mouse_button_index: int) -> void: +func _on_tree_item_mouse_selected(mouse_position : Vector2, mouse_button_index : int) -> void: if mouse_button_index == MOUSE_BUTTON_RIGHT: _on_tree_item_rmb_selected(mouse_position) elif mouse_button_index == MOUSE_BUTTON_LEFT: _on_tree_item_lmb_selected() - -func _on_context_menu_id_pressed(id: int) -> void: +func _on_context_menu_id_pressed(id : int) -> void: var item : TreeItem = tree.get_selected() match id: ContextMenu.RENAME: @@ -198,7 +185,6 @@ func _on_context_menu_id_pressed(id: int) -> void: bookmark_manager.remove_bookmark(item.get_metadata(0)) rebuild_bookmark_tree() - func _on_tree_item_edited() -> void: var item : TreeItem = tree.get_selected() item.set_editable(0, false) diff --git a/material_maker/tools/bookmark_manager/bookmark_manager.gd b/material_maker/tools/bookmark_manager/bookmark_manager.gd index f755444e7..6dfbcc1cb 100644 --- a/material_maker/tools/bookmark_manager/bookmark_manager.gd +++ b/material_maker/tools/bookmark_manager/bookmark_manager.gd @@ -1,6 +1,6 @@ +class_name BookmarkManager extends Node -class_name BookmarkManager ## Graph bookmarks to revisit them later @@ -12,16 +12,14 @@ signal bookmarks_edit_removed @warning_ignore("unused_signal") signal updated_from_graph -func set_bookmarks(new_bookmarks: Dictionary) -> void: +func set_bookmarks(new_bookmarks : Dictionary) -> void: bookmarks = new_bookmarks - -static func is_default_bookmark_node(node: GraphElement) -> bool: +static func is_default_bookmark_node(node : GraphElement) -> bool: return (node.get_script() in [MMGraphComment, MMGraphCommentLine] or node.name in ["node_Material"]) - -static func get_label_from_node(node: GraphElement) -> String: +static func get_label_from_node(node : GraphElement) -> String: var label : String = "" if node is GraphNode and node.get("title"): label = node.title @@ -33,25 +31,21 @@ static func get_label_from_node(node: GraphElement) -> String: label = node.name.trim_prefix("node_") return label - -func add_bookmark(node: GraphElement, gen_path: String) -> void: +func add_bookmark(node : GraphElement, gen_path : String) -> void: if not bookmarks.has(gen_path): var label : String = get_label_from_node(node) bookmarks[gen_path] = label mm_globals.set_tip_text("Added bookmark for %s" % label, 1.0, 1) bookmarks_added.emit() - -func add_bookmark_from_path(path: String, label: String) -> void: +func add_bookmark_from_path(path : String, label : String) -> void: bookmarks[path] = label bookmarks_added.emit() - -func remove_bookmark(path: String) -> void: +func remove_bookmark(path : String) -> void: bookmarks.erase(path) bookmarks_edit_removed.emit() - -func edit_bookmark(path: String, new_label: String) -> void: +func edit_bookmark(path : String, new_label : String) -> void: bookmarks[path] = new_label bookmarks_edit_removed.emit() From 7f42fd9eab1e9a9edf1c78bfd81b2936a4227b11 Mon Sep 17 00:00:00 2001 From: LMW Date: Thu, 26 Mar 2026 22:29:45 +0800 Subject: [PATCH 26/27] fix bookmark icon --- material_maker/theme/default.tres | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/material_maker/theme/default.tres b/material_maker/theme/default.tres index ef9e2ddbc..4544429d7 100644 --- a/material_maker/theme/default.tres +++ b/material_maker/theme/default.tres @@ -1,4 +1,4 @@ -[gd_resource type="Theme" load_steps=171 format=3 uid="uid://b628lwfk6ig2c"] +[gd_resource type="Theme" load_steps=172 format=3 uid="uid://b628lwfk6ig2c"] [ext_resource type="FontFile" uid="uid://lro0qdrhfytt" path="res://material_maker/theme/font_rubik/Rubik-Light.ttf" id="1_5tfb1"] [ext_resource type="Texture2D" uid="uid://1s0c37uoj4rf" path="res://material_maker/theme/default_theme_icons.svg" id="1_s43fy"] @@ -425,7 +425,7 @@ region = Rect2(48, 48, 16, 16) atlas = ExtResource("1_s43fy") region = Rect2(112, 176, 16, 16) -[sub_resource type="AtlasTexture" id="AtlasTexture_0jwmb"] +[sub_resource type="AtlasTexture" id="AtlasTexture_8xpdb"] atlas = ExtResource("1_s43fy") region = Rect2(48, 208, 16, 16) @@ -1269,7 +1269,7 @@ MM_Icons/icons/arrange_nodes = SubResource("AtlasTexture_60g77") MM_Icons/icons/arrow_left = SubResource("AtlasTexture_q32qs") MM_Icons/icons/arrow_right = SubResource("AtlasTexture_r3xak") MM_Icons/icons/arrow_updown = SubResource("AtlasTexture_ovvp6") -MM_Icons/icons/bookmark = SubResource("AtlasTexture_0jwmb") +MM_Icons/icons/bookmark = SubResource("AtlasTexture_8xpdb") MM_Icons/icons/camera = SubResource("AtlasTexture_cscp3") MM_Icons/icons/color_picker = SubResource("AtlasTexture_j13i3") MM_Icons/icons/connection_bezier = SubResource("AtlasTexture_rqjp3") From b118e670a533ac89ae508af90588bc66be373b21 Mon Sep 17 00:00:00 2001 From: LMW Date: Thu, 26 Mar 2026 23:18:47 +0800 Subject: [PATCH 27/27] use existing name when grouping bookmarked node --- material_maker/panels/graph_edit/graph_bookmark_menu.gd | 3 ++- material_maker/projects_panel.tscn | 4 ++-- material_maker/tools/bookmark_manager/bookmark_manager.gd | 7 +++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/material_maker/panels/graph_edit/graph_bookmark_menu.gd b/material_maker/panels/graph_edit/graph_bookmark_menu.gd index 96790ba07..a97406503 100644 --- a/material_maker/panels/graph_edit/graph_bookmark_menu.gd +++ b/material_maker/panels/graph_edit/graph_bookmark_menu.gd @@ -91,7 +91,7 @@ func validate_bookmarks(updated_view : MMGenGraph = null) -> void: if graph.has_node(node_path): var gen : MMGenBase = graph.get_node(node_path).generator var new_path : String = "./" + str(graph.top_generator.get_path_to(gen)) - bookmark_manager.add_bookmark_from_path(new_path, target_node) + bookmark_manager.add_bookmark_from_path(new_path, item.get_text(0)) func rebuild_bookmark_tree() -> void: await get_tree().process_frame @@ -121,6 +121,7 @@ func _on_tree_item_lmb_selected() -> void: # Jump back to top if we are in a subgraph if graph.generator != graph.top_generator: graph.update_view(graph.top_generator) + # Get bookmarked node from current graph var node_path := NodePath("node_" + path) if graph.has_node(node_path): diff --git a/material_maker/projects_panel.tscn b/material_maker/projects_panel.tscn index 54dcf1460..2dfa7239a 100644 --- a/material_maker/projects_panel.tscn +++ b/material_maker/projects_panel.tscn @@ -5,7 +5,7 @@ [ext_resource type="PackedScene" uid="uid://dpaxvlnn2u1f6" path="res://material_maker/panels/preview_3d/preview_3d.tscn" id="3_qvj7k"] [ext_resource type="Script" uid="uid://bl15iwn2k8qm" path="res://material_maker/widgets/tabs/tabs.gd" id="4_mpinq"] [ext_resource type="Script" uid="uid://c37lcka7r53wk" path="res://material_maker/panels/common/menu_bar_button_with_panel.gd" id="6_r5hxx"] -[ext_resource type="Script" path="res://material_maker/panels/graph_edit/graph_zoom_menu.gd" id="7_lbgjg"] +[ext_resource type="Script" uid="uid://jvurydhtpvc2" path="res://material_maker/panels/graph_edit/graph_zoom_menu.gd" id="7_lbgjg"] [ext_resource type="Script" uid="uid://bos2fu0tsood3" path="res://material_maker/panels/preview_2d/simple_button.gd" id="7_qnupl"] [ext_resource type="PackedScene" uid="uid://rflulhsuy3ax" path="res://material_maker/widgets/float_edit/float_edit.tscn" id="8_1w3oe"] [ext_resource type="Script" uid="uid://bxwor0k6svci8" path="res://material_maker/panels/graph_edit/graph_view_menu.gd" id="8_nl2qi"] @@ -431,7 +431,7 @@ vertical_alignment = 1 layout_mode = 2 theme_override_constants/item_margin = 0 allow_reselect = true -allow_rmb_select = true +allow_search = false hide_root = true auto_tooltip = false diff --git a/material_maker/tools/bookmark_manager/bookmark_manager.gd b/material_maker/tools/bookmark_manager/bookmark_manager.gd index 6dfbcc1cb..8ae4fd261 100644 --- a/material_maker/tools/bookmark_manager/bookmark_manager.gd +++ b/material_maker/tools/bookmark_manager/bookmark_manager.gd @@ -1,10 +1,9 @@ class_name BookmarkManager extends Node - ## Graph bookmarks to revisit them later -var bookmarks : Dictionary +var bookmarks : Dictionary[String, String] signal bookmarks_added signal bookmarks_edit_removed @@ -12,7 +11,7 @@ signal bookmarks_edit_removed @warning_ignore("unused_signal") signal updated_from_graph -func set_bookmarks(new_bookmarks : Dictionary) -> void: +func set_bookmarks(new_bookmarks : Dictionary[String, String]) -> void: bookmarks = new_bookmarks static func is_default_bookmark_node(node : GraphElement) -> bool: @@ -35,7 +34,7 @@ func add_bookmark(node : GraphElement, gen_path : String) -> void: if not bookmarks.has(gen_path): var label : String = get_label_from_node(node) bookmarks[gen_path] = label - mm_globals.set_tip_text("Added bookmark for %s" % label, 1.0, 1) + mm_globals.set_tip_text("Added bookmark for \"%s\"" % label, 1.0, 1) bookmarks_added.emit() func add_bookmark_from_path(path : String, label : String) -> void: