@@ -692,6 +692,22 @@ void OrchestratorGraphEdit::_drop_data_variable(const String& p_name, const Vect
692692 spawn_node (options);
693693}
694694
695+ bool OrchestratorGraphEdit::_is_in_port_hotzone (const Vector2& p_pos, const Vector2& p_mouse_pos, const Vector2i& p_port_size, bool p_left)
696+ {
697+ const int32_t port_hotzone_outer_extent = get_theme_constant (" port_hotzone_outer_extent" );
698+ const int32_t port_hotzone_inner_extent = get_theme_constant (" port_hotzone_inner_extent" );
699+
700+ const String hotzone_percent = ORCHESTRATOR_GET (" ui/nodes/connection_hotzone_scale" , " 100%" );
701+ const Vector2i port_size = p_port_size * (hotzone_percent.replace (" %" , " " ).to_float () / 100.0 );
702+
703+ const Rect2 hotzone = Rect2 (
704+ p_pos.x - (p_left ? port_hotzone_outer_extent : port_hotzone_inner_extent),
705+ p_pos.y - port_size.height / 2.0 ,
706+ port_hotzone_inner_extent + port_hotzone_outer_extent,
707+ port_size.height );
708+
709+ return hotzone.has_point (p_mouse_pos);
710+ }
695711
696712void OrchestratorGraphEdit::_gui_input (const Ref<InputEvent>& p_event)
697713{
@@ -1295,6 +1311,46 @@ PackedVector2Array OrchestratorGraphEdit::_get_connection_line(const Vector2& p_
12951311 return curve_points;
12961312}
12971313
1314+ bool OrchestratorGraphEdit::_is_in_input_hotzone (Object* p_in_node, int32_t p_in_port, const Vector2& p_mouse_position)
1315+ {
1316+ GraphNode* node = cast_to<GraphNode>(p_in_node);
1317+ if (!node)
1318+ return false ;
1319+
1320+ const Ref<Texture2D> icon = node->get_slot_custom_icon_left (p_in_port);
1321+ if (!icon.is_valid ())
1322+ return false ;
1323+
1324+ Vector2i port_size = Vector2i (icon->get_width (), icon->get_height ());
1325+ int slot_index = node->get_input_port_slot (p_in_port);
1326+ Control* child = cast_to<Control>(node->get_child (slot_index, false ));
1327+ port_size.height = MAX (port_size.height , child ? child->get_size ().y : 0 );
1328+
1329+ const float zoom = get_zoom ();
1330+ const Vector2 pos = node->get_input_port_position (p_in_port) * zoom + node->get_position ();
1331+ return _is_in_port_hotzone (pos / zoom, p_mouse_position, port_size, true );
1332+ }
1333+
1334+ bool OrchestratorGraphEdit::_is_in_output_hotzone (Object* p_in_node, int32_t p_in_port, const Vector2& p_mouse_position)
1335+ {
1336+ GraphNode* node = cast_to<GraphNode>(p_in_node);
1337+ if (!node)
1338+ return false ;
1339+
1340+ const Ref<Texture2D> icon = node->get_slot_custom_icon_right (p_in_port);
1341+ if (!icon.is_valid ())
1342+ return false ;
1343+
1344+ Vector2i port_size = Vector2i (icon->get_width (), icon->get_height ());
1345+ int slot_index = node->get_output_port_slot (p_in_port);
1346+ Control* child = cast_to<Control>(node->get_child (slot_index, false ));
1347+ port_size.height = MAX (port_size.height , child ? child->get_size ().y : 0 );
1348+
1349+ const float zoom = get_zoom ();
1350+ const Vector2 pos = node->get_output_port_position (p_in_port) * zoom + node->get_position ();
1351+ return _is_in_port_hotzone (pos / zoom, p_mouse_position, port_size, false );
1352+ }
1353+
12981354bool OrchestratorGraphEdit::_get_connection_for_points (const Vector2& p_from_position,
12991355 const Vector2& p_to_position,
13001356 OScriptConnection& r_connection) const
0 commit comments