diff --git a/addons/material_maker/engine/nodes/gen_graph.gd b/addons/material_maker/engine/nodes/gen_graph.gd index 09fa29f52..05fcb182b 100644 --- a/addons/material_maker/engine/nodes/gen_graph.gd +++ b/addons/material_maker/engine/nodes/gen_graph.gd @@ -13,6 +13,7 @@ var transmits_seed : bool = true var current_mesh : Mesh = null +var bookmarks = null var scroll_offset = null signal graph_changed() @@ -23,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(): @@ -535,6 +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() and bookmarks != null: + data.bookmarks = bookmarks if scroll_offset: data.scroll_offset = { x=scroll_offset.x, y=scroll_offset.y } return data @@ -556,6 +562,8 @@ func _deserialize(data : Dictionary) -> void: if data.has("scroll_offset"): scroll_offset = Vector2(data.scroll_offset.x, data.scroll_offset.y) var new_stuff = await mm_loader.add_to_gen_graph(self, nodes, connection_array) + 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/main_window.gd b/material_maker/main_window.gd index 48db5a475..4fbfcaf9c 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 ce6dc267e..28d8ca35a 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"] @@ -141,6 +142,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 @@ -166,10 +170,14 @@ allow_undock = true [node name="Main" parent="VBoxContainer/Layout/FlexibleLayout" instance=ExtResource("7_ih0ps")] 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/nodes/reroute/reroute.gd b/material_maker/nodes/reroute/reroute.gd index 8bbcbb9fb..b3431dd64 100644 --- a/material_maker/nodes/reroute/reroute.gd +++ b/material_maker/nodes/reroute/reroute.gd @@ -1,6 +1,5 @@ extends MMGraphNodeMinimal - const PREVIEW_SIZES : Array[int] = [ 0, 64, 128, 192] 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 new file mode 100644 index 000000000..023bf2d04 --- /dev/null +++ b/material_maker/panels/graph_edit/graph_bookmark_menu.gd @@ -0,0 +1,179 @@ +extends PanelContainer + +@onready var tree := $Tree + +var bookmark_manager : BookmarkManager + +var is_unpinned_double_click_edited := false + +enum ContextMenu { + RENAME, + DELETE, +} + + +func _open() -> void: + update_bookmarks() + +func _ready() -> void: + if not mm_globals.main_window.is_node_ready(): + await mm_globals.main_window.ready + + bookmark_manager = mm_globals.main_window.bookmark_manager + 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)) + +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 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: + # 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: + bookmark_manager.bookmarks = updated_view.bookmarks + + if tree.get_root() == null: + return + + 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"]: + continue + + # Bookmarked path does not point to anything + if not graph.top_generator.has_node(bookmark_path): + var target_node : String = bookmark_path.split("/")[-1] + + # Remove invalid reference + bookmark_manager.remove_bookmark(bookmark_path) + + # Check if the node is part of the updated graph view + # i.e. from grouping the currently bookmarked node + 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 : String = "./" + str(graph.top_generator.get_path_to(gen)) + bookmark_manager.add_bookmark_from_path(new_path, item.get_text(0)) + +func rebuild_bookmark_tree() -> void: + await get_tree().process_frame + tree.clear() + var root : TreeItem = tree.create_item() + + var bookmarks := bookmark_manager.bookmarks + for path : String in bookmarks: + var new_item : TreeItem = tree.create_item(root) + 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 + $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) + path = path.get_slice("./", 1) + var graph : MMGraphEdit = owner.current_graph_edit + + 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 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 + 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 + 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 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) + +func _on_tree_item_rmb_selected(_mouse_position : Vector2i) -> void: + 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: + 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 + 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: + 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: + ContextMenu.RENAME: + item.set_editable(0, true) + tree.edit_selected() + ContextMenu.DELETE: + if item != null: + 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) + 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/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 ee4079441..a837990fa 100644 --- a/material_maker/panels/graph_edit/graph_edit.gd +++ b/material_maker/panels/graph_edit/graph_edit.gd @@ -294,6 +294,8 @@ func _gui_input(event) -> void: accept_event() KEY_F: colorize_nodes() + KEY_B: + bookmark_node() KEY_G: if not get_selected_nodes().is_empty(): has_grab = true @@ -376,6 +378,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() @@ -536,6 +539,7 @@ func do_remove_node(node) -> void: remove_child(node) node.queue_free() send_changed_signal() + get_node("/root/MainWindow/BookmarkManager").updated_from_graph.emit() # Global operations on graph @@ -1065,7 +1069,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) @@ -1868,6 +1871,28 @@ func colorize_nodes() -> void: popup.popup_hide.connect(popup.queue_free) popup.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 generator_path : String = "./" + str(top_generator.get_path_to(selected_node.generator)) + 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): + 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 + 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)) + func _on_resized() -> void: $GraphUI.size = Vector2.ZERO $GraphUI.position = global_position 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/projects_panel.tscn b/material_maker/projects_panel.tscn index 538bfa34d..b3caf9fc3 100644 --- a/material_maker/projects_panel.tscn +++ b/material_maker/projects_panel.tscn @@ -11,6 +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" 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 @@ -174,7 +175,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") @@ -407,6 +408,56 @@ 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(200, 200) +layout_mode = 0 +offset_right = 200.0 +offset_bottom = 200.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 = 0 +allow_reselect = true +allow_search = false +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) @@ -522,6 +573,10 @@ 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="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/classic.tres b/material_maker/theme/classic.tres index ee3307336..c5c391144 100644 --- a/material_maker/theme/classic.tres +++ b/material_maker/theme/classic.tres @@ -1,4 +1,4 @@ -[gd_resource type="Theme" script_class="EnhancedTheme" load_steps=4 format=3 uid="uid://wuddtc1fglln"] +[gd_resource type="Theme" script_class="EnhancedTheme" format=3 uid="uid://wuddtc1fglln"] [ext_resource type="Theme" uid="uid://w487nirev8y5" path="res://material_maker/theme/classic_base.tres" id="1_meah8"] [ext_resource type="Script" uid="uid://3ga2k3abkk0d" path="res://material_maker/theme/enhanced_theme_system/color_swap.gd" id="5_qpu3p"] diff --git a/material_maker/theme/default.tres b/material_maker/theme/default.tres index f19d6072b..69e05b275 100644 --- a/material_maker/theme/default.tres +++ b/material_maker/theme/default.tres @@ -367,8 +367,7 @@ metadata/recolor = true [sub_resource type="AtlasTexture" id="AtlasTexture_8xpdb"] atlas = ExtResource("1_s43fy") -region = Rect2(48, 208, 16, 16) -metadata/recolor = true +region = Rect2(32, 224, 16, 16) [sub_resource type="AtlasTexture" id="AtlasTexture_5aawx"] atlas = ExtResource("1_s43fy") @@ -1329,6 +1328,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_8xpdb") 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 1f2fe015f..5b3da27e0 100644 --- a/material_maker/theme/default_theme_icons.svg +++ b/material_maker/theme/default_theme_icons.svg @@ -28,9 +28,9 @@ inkscape:deskcolor="#d1d1d1" inkscape:document-units="mm" showgrid="true" - inkscape:zoom="8" - inkscape:cx="36.6875" - inkscape:cy="213.8125" + inkscape:zoom="22.627417" + inkscape:cx="40.150407" + inkscape:cy="225.01464" inkscape:window-width="1152" inkscape:window-height="981" inkscape:window-x="0" @@ -2739,6 +2739,18 @@ d="m 17.836663,238.07516 2.571223,-9.97576 9.642069,-2.23754" inkscape:label="bevel" style="stroke-linecap:round;stroke-linejoin:round" /> + + + void: + bookmarks = new_bookmarks + +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: + 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 = 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: + bookmarks[path] = label + 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() 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