From 378e1681affceff9511992bc5247685270fa72d1 Mon Sep 17 00:00:00 2001 From: LMW Date: Wed, 31 Dec 2025 18:42:39 +0800 Subject: [PATCH] Animated highlighted connections --- material_maker/nodes/base.gd | 3 + .../graph_edit/animated_connection.tres | 11 ++ .../panels/graph_edit/graph_edit.gd | 14 --- .../panels/graph_edit/graph_edit.tscn | 7 +- .../panels/graph_edit/highlights_overlay.gd | 111 ++++++++++++++++++ .../graph_edit/highlights_overlay.gd.uid | 1 + 6 files changed, 132 insertions(+), 15 deletions(-) create mode 100644 material_maker/panels/graph_edit/animated_connection.tres create mode 100644 material_maker/panels/graph_edit/highlights_overlay.gd create mode 100644 material_maker/panels/graph_edit/highlights_overlay.gd.uid diff --git a/material_maker/nodes/base.gd b/material_maker/nodes/base.gd index 08d947736..72f5e781f 100644 --- a/material_maker/nodes/base.gd +++ b/material_maker/nodes/base.gd @@ -247,6 +247,9 @@ func _draw() -> void: if control.get("modulate"): control.modulate.a = opacity + get_parent().get_node("HighlightsOverlay").update_connections() + + func draw_portgroup_stylebox(first_port : Vector2, last_port : Vector2) -> void: var stylebox_position: Vector2 = first_port + Vector2(-0.5,-0.5) * portgroup_width var stylebox_size: Vector2 = Vector2(portgroup_width, last_port.y - first_port.y + portgroup_width) diff --git a/material_maker/panels/graph_edit/animated_connection.tres b/material_maker/panels/graph_edit/animated_connection.tres new file mode 100644 index 000000000..0c1b66f7d --- /dev/null +++ b/material_maker/panels/graph_edit/animated_connection.tres @@ -0,0 +1,11 @@ +[gd_resource type="ShaderMaterial" load_steps=2 format=3 uid="uid://cvfcub2mms71a"] + +[sub_resource type="Shader" id="Shader_pewh7"] +code = "shader_type canvas_item; + +void fragment() { + COLOR = vec4(vec3(0.0), 0.25 * sin(UV.x - TIME * TAU) + 0.25); +}" + +[resource] +shader = SubResource("Shader_pewh7") diff --git a/material_maker/panels/graph_edit/graph_edit.gd b/material_maker/panels/graph_edit/graph_edit.gd index e5e7af604..d058fdbcb 100644 --- a/material_maker/panels/graph_edit/graph_edit.gd +++ b/material_maker/panels/graph_edit/graph_edit.gd @@ -1025,18 +1025,6 @@ func _on_ButtonTransmitsSeed_toggled(button_pressed) -> void: # Node selection -var highlighting_connections : bool = false - -func highlight_connections() -> void: - if highlighting_connections: - return - highlighting_connections = true - while Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT): - await get_tree().process_frame - for c in get_connection_list(): - set_connection_activity(c.from_node, c.from_port, c.to_node, c.to_port, 1.0 if get_node(NodePath(c.from_node)).selected or get_node(NodePath(c.to_node)).selected else 0.0) - highlighting_connections = false - func _on_GraphEdit_node_selected(node : GraphElement) -> void: if node is MMGraphComment: #print("Selecting enclosed nodes...") @@ -1047,7 +1035,6 @@ func _on_GraphEdit_node_selected(node : GraphElement) -> void: elif node is MMGraphCommentLine: pass else: - highlight_connections() await get_tree().process_frame if current_preview[0] != null: for n in get_selected_nodes(): @@ -1066,7 +1053,6 @@ func _on_GraphEdit_node_selected(node : GraphElement) -> void: mm_globals.main_window.update_menus() func _on_GraphEdit_node_unselected(_node): - highlight_connections() undoredo_move_node_selection_changed = true mm_globals.main_window.update_menus() diff --git a/material_maker/panels/graph_edit/graph_edit.tscn b/material_maker/panels/graph_edit/graph_edit.tscn index b4542f682..48dbbd7c4 100644 --- a/material_maker/panels/graph_edit/graph_edit.tscn +++ b/material_maker/panels/graph_edit/graph_edit.tscn @@ -1,9 +1,10 @@ -[gd_scene load_steps=8 format=3 uid="uid://dy1u50we7gtru"] +[gd_scene load_steps=9 format=3 uid="uid://dy1u50we7gtru"] [ext_resource type="Script" uid="uid://dkp4w3at1o6cm" path="res://material_maker/panels/graph_edit/graph_edit.gd" id="1"] [ext_resource type="Texture2D" uid="uid://c0j4px4n72di5" path="res://material_maker/icons/icons.tres" id="2"] [ext_resource type="Script" uid="uid://bne3k0g56crmy" path="res://material_maker/tools/undo_redo/undo_redo.gd" id="3"] [ext_resource type="PackedScene" uid="uid://buj231c2gxm4o" path="res://material_maker/widgets/desc_button/desc_button.tscn" id="4"] +[ext_resource type="Script" uid="uid://dlah77kjy12l6" path="res://material_maker/panels/graph_edit/highlights_overlay.gd" id="5_u5byk"] [sub_resource type="AtlasTexture" id="3"] atlas = ExtResource("2") @@ -85,6 +86,10 @@ layout_mode = 2 [node name="UndoRedo" type="Node" parent="."] script = ExtResource("3") +[node name="HighlightsOverlay" type="Control" parent="."] +anchors_preset = 0 +script = ExtResource("5_u5byk") + [connection signal="connection_from_empty" from="." to="." method="request_popup" binds= [true]] [connection signal="connection_request" from="." to="." method="on_connect_node"] [connection signal="connection_to_empty" from="." to="." method="request_popup" binds= [false]] diff --git a/material_maker/panels/graph_edit/highlights_overlay.gd b/material_maker/panels/graph_edit/highlights_overlay.gd new file mode 100644 index 000000000..d96b9563a --- /dev/null +++ b/material_maker/panels/graph_edit/highlights_overlay.gd @@ -0,0 +1,111 @@ +class_name HighlightsOverlay +extends Control + + +class AnimatedConnection extends Line2D: + var connection : Dictionary + +@onready var graph : MMGraphEdit = owner + +var active_connections : Array[Dictionary] +var is_updating_connections := false + +const LINE_MATERIAL := preload("res://material_maker/panels/graph_edit/animated_connection.tres") + +func _ready() -> void: + graph.child_order_changed.connect(_move_above_connections.call_deferred) + graph.get_node("_connection_layer").draw.connect(queue_redraw) + graph.get_node("_connection_layer").child_order_changed.connect(update_connections) + graph.connection_drag_started.connect(update_connections.bind(1).unbind(3)) + graph.node_selected.connect(update_connections.unbind(1)) + graph.node_deselected.connect(update_connections.unbind(1)) + graph.gui_input.connect(_graph_gui_input) + +func _draw() -> void: + if get_children().is_empty(): + return + + for line : AnimatedConnection in get_children(): + var conn : Dictionary = line.connection + var positions := get_connection_positions(conn) + if positions.is_empty(): + continue + + line.visible = get_viewport_rect().intersects( + Rect2(positions.from, positions.to - positions.from).abs()) + + line.points = graph._get_connection_line(positions.from, positions.to) + line.width = graph.connection_lines_thickness + +func _move_above_connections() -> void: + graph.move_child(self, graph.get_node("_connection_layer").get_index() + 1) + +func _graph_gui_input(e : InputEvent) -> void: + if e is InputEventKey: + update_connections(true) + +func update_connections(should_hide_when_updating : bool = false) -> void: + if is_updating_connections: + return + is_updating_connections = true + + if should_hide_when_updating: + hide() + + while Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT): + await get_tree().process_frame + + active_connections.clear() + for c in graph.get_connection_list(): + if (graph.get_node(NodePath(c.from_node)).selected + or graph.get_node(NodePath(c.to_node)).selected): + active_connections.append(c) + await get_tree().process_frame + create_animated_connections() + + # Remove inactive/invalid animated conections + if get_children().size(): + for anim_line : AnimatedConnection in get_children(): + if (anim_line.connection not in active_connections + or get_connection_positions(anim_line.connection).is_empty()): + remove_child(anim_line) + anim_line.free() + + queue_redraw() + is_updating_connections = false + show.call_deferred() + +func create_animated_connections() -> void: + if active_connections.size(): + for active_connection in active_connections: + var positions := get_connection_positions(active_connection) + if positions.is_empty(): + continue + + var has_existing_connection : bool = false + for c in get_children(): + if c.connection == active_connection: + has_existing_connection = true + break + + if not has_existing_connection: + var ac := AnimatedConnection.new() + ac.connection = active_connection + ac.texture_mode = Line2D.LINE_TEXTURE_TILE + ac.material = LINE_MATERIAL + ac.points = graph._get_connection_line(positions.from, positions.to) + ac.width = graph.connection_lines_thickness + add_child(ac) + +func get_connection_positions(from_connection : Dictionary) -> Dictionary: + var c := from_connection + var positions : Dictionary + if graph.has_node(NodePath(c.from_node)) and graph.has_node(NodePath(c.to_node)): + var from_node : GraphNode = graph.get_node(NodePath(c.from_node)) + var to_node : GraphNode = graph.get_node(NodePath(c.to_node)) + if from_node and to_node: + var from_pos := from_node.get_output_port_position(c.from_port) + var to_pos := to_node.get_input_port_position(c.to_port) + positions.from = from_pos * graph.zoom + from_node.position + positions.to = to_pos * graph.zoom + to_node.position + return positions diff --git a/material_maker/panels/graph_edit/highlights_overlay.gd.uid b/material_maker/panels/graph_edit/highlights_overlay.gd.uid new file mode 100644 index 000000000..b8762680f --- /dev/null +++ b/material_maker/panels/graph_edit/highlights_overlay.gd.uid @@ -0,0 +1 @@ +uid://dlah77kjy12l6