Skip to content

Commit 6e1fb68

Browse files
committed
Fix GraphNode frag/vert port positions misaligned
Issue conclusion: GraphNode port connections appear misaligned when switching between vertex and fragment modes, only realigning after zoom or layout refresh. Investigation: The root cause was due to port positions being calculated before child layouts had finalized, resulting in inaccurate Y positions for ports. The original implementation relied on Control::position.y, which was not yet updated during the initial layout pass. Explaination: This fix computes vertical offset using titlebar and stylebox sizes instead, ensuring port alignment is correct immediately after layout, without relying on zoom-triggered re-layouts. Resolves: #105232 Add layout mode check to distinguish GraphEditor and ShaderGraphEditor Fix port position calculation by distinguishing between GraphEditor and ShaderGraphEditor layouts. Due to differences in layout flow and update timing (CPU vs GPU), ShaderGraphEditor requires manual vertical offset calculation, while standard GraphEditor can directly get the actual child positions after layout in run time. This change adds a layout mode check (`is_using_resort_layout) to determine the appropriate method for computing port positions. Fixed nits using cached values and removed redundant condition variable definition. Add comment for the condition checking.
1 parent 215acd5 commit 6e1fb68

File tree

1 file changed

+29
-22
lines changed

1 file changed

+29
-22
lines changed

scene/gui/graph_node.cpp

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -980,42 +980,49 @@ Size2 GraphNode::get_minimum_size() const {
980980

981981
void GraphNode::_port_pos_update() {
982982
int edgeofs = theme_cache.port_h_offset;
983+
int separation = theme_cache.separation;
984+
985+
// This helps to immediately achieve the initial y "original point" of the slots, which the sum of the titlebar height and the top margin of the panel.
986+
int vertical_ofs = titlebar_hbox->get_size().height + theme_cache.titlebar->get_minimum_size().height + theme_cache.panel->get_margin(SIDE_TOP);
983987

984988
left_port_cache.clear();
985989
right_port_cache.clear();
986-
int slot_index = 0;
990+
991+
slot_count = 0; // Reset the slot count, which is the index of the current slot.
987992

988993
for (int i = 0; i < get_child_count(false); i++) {
989994
Control *child = as_sortable_control(get_child(i, false), SortableVisibilityMode::IGNORE);
990995
if (!child) {
991996
continue;
992997
}
993998

994-
Size2i size = child->get_rect().size;
995-
Point2 pos = child->get_position();
996-
997-
if (slot_table.has(slot_index)) {
998-
if (slot_table[slot_index].enable_left) {
999-
PortCache port_cache;
1000-
port_cache.pos = Point2i(edgeofs, pos.y + size.height / 2);
1001-
port_cache.type = slot_table[slot_index].type_left;
1002-
port_cache.color = slot_table[slot_index].color_left;
1003-
port_cache.slot_index = slot_index;
1004-
left_port_cache.push_back(port_cache);
999+
Size2 size = child->get_size();
1000+
1001+
if (slot_table.has(slot_count)) {
1002+
const Slot &slot = slot_table[slot_count];
1003+
1004+
int port_y;
1005+
1006+
// Check if it is using resort layout (e.g. Shader Graph nodes slots).
1007+
if (slot_y_cache.is_empty()) {
1008+
port_y = vertical_ofs + size.height * 0.5; // The y centor is calculated from the widget position.
1009+
} else {
1010+
port_y = child->get_position().y + size.height * 0.5; // The y centor is calculated from the class object position.
1011+
}
1012+
1013+
if (slot.enable_left) {
1014+
PortCache port_cache_left{ Point2i(edgeofs, port_y), slot_count, slot.type_left, slot.color_left };
1015+
left_port_cache.push_back(port_cache_left);
10051016
}
1006-
if (slot_table[slot_index].enable_right) {
1007-
PortCache port_cache;
1008-
port_cache.pos = Point2i(get_size().width - edgeofs, pos.y + size.height / 2);
1009-
port_cache.type = slot_table[slot_index].type_right;
1010-
port_cache.color = slot_table[slot_index].color_right;
1011-
port_cache.slot_index = slot_index;
1012-
right_port_cache.push_back(port_cache);
1017+
if (slot.enable_right) {
1018+
PortCache port_cache_right{ Point2i(get_size().width - edgeofs, port_y), slot_count, slot.type_right, slot.color_right };
1019+
right_port_cache.push_back(port_cache_right);
10131020
}
10141021
}
1015-
1016-
slot_index++;
1022+
vertical_ofs += size.height + separation; // Add the height of the child and the separation to the vertical offset.
1023+
slot_count++; // Go to the next slot
10171024
}
1018-
slot_count = slot_index;
1025+
10191026
if (selected_slot >= slot_count) {
10201027
selected_slot = -1;
10211028
}

0 commit comments

Comments
 (0)