diff --git a/src/editor/graph/graph_node.cpp b/src/editor/graph/graph_node.cpp index b2306701..910cc6ab 100644 --- a/src/editor/graph/graph_node.cpp +++ b/src/editor/graph/graph_node.cpp @@ -90,14 +90,6 @@ void OrchestratorGraphNode::_notification(int p_what) // Update the pin display upon entering _update_pins(); - - // IMPORTANT - // The context menu must be attached to the title bar or else this will cause - // problems with the GraphNode and slot/index logic when calling set_slot - // functions. - _context_menu = memnew(PopupMenu); - _context_menu->connect("id_pressed", callable_mp(this, &OrchestratorGraphNode::_on_context_menu_selection)); - get_titlebar_hbox()->add_child(_context_menu); } } @@ -407,6 +399,15 @@ void OrchestratorGraphNode::_update_tooltip() void OrchestratorGraphNode::_show_context_menu(const Vector2& p_position) { + // IMPORTANT + // The context menu must be attached to the title bar or else this will cause + // problems with the GraphNode and slot/index logic when calling set_slot + // functions. + _context_menu = memnew(PopupMenu); + _context_menu->connect("id_pressed", callable_mp(this, &OrchestratorGraphNode::_handle_context_menu)); + _context_menu->connect("close_requested", callable_mp(this, &OrchestratorGraphNode::_cleanup_context_menu)); + get_titlebar_hbox()->add_child(_context_menu); + // When showing the context-menu, if the current node is not selected, we should clear the // selection and the operation will only be applicable for this node and its pin. if (!is_selected()) @@ -655,7 +656,7 @@ void OrchestratorGraphNode::_on_add_pin_pressed() _add_option_pin(); } -void OrchestratorGraphNode::_on_context_menu_selection(int p_id) +void OrchestratorGraphNode::_handle_context_menu(int p_id) { if (p_id >= CM_NODE_ACTION) { @@ -781,4 +782,15 @@ void OrchestratorGraphNode::_on_context_menu_selection(int p_id) // Cleanup actions _context_actions.clear(); + _cleanup_context_menu(); +} + +void OrchestratorGraphNode::_cleanup_context_menu() +{ + if (_context_menu) + { + _context_menu->queue_free(); + _context_menu = nullptr; + } } + diff --git a/src/editor/graph/graph_node.h b/src/editor/graph/graph_node.h index c7846a44..589a30ca 100644 --- a/src/editor/graph/graph_node.h +++ b/src/editor/graph/graph_node.h @@ -41,7 +41,6 @@ class OrchestratorGraphNode : public GraphNode { GDCLASS(OrchestratorGraphNode, GraphNode); -private: enum ContextMenuId { CM_NONE, @@ -245,9 +244,12 @@ class OrchestratorGraphNode : public GraphNode /// Called when the "add-pin" button pressed void _on_add_pin_pressed(); - /// Dispatched when a context-menu option is selected + /// Handles the selection of a context menu item /// @param p_id the selected context-menu option - void _on_context_menu_selection(int p_id); + void _handle_context_menu(int p_id); + + /// Cleans up the context menu after it has closed + void _cleanup_context_menu(); }; #endif // ORCHESTRATOR_GRAPH_NODE_H \ No newline at end of file diff --git a/src/editor/graph/graph_node_pin.cpp b/src/editor/graph/graph_node_pin.cpp index db3da23d..be10a405 100644 --- a/src/editor/graph/graph_node_pin.cpp +++ b/src/editor/graph/graph_node_pin.cpp @@ -80,13 +80,7 @@ void OrchestratorGraphNodePin::_update_label() void OrchestratorGraphNodePin::_notification(int p_what) { if (p_what == NOTIFICATION_READY) - { _create_widgets(); - - _context_menu = memnew(PopupMenu); - _context_menu->connect("id_pressed", callable_mp(this, &OrchestratorGraphNodePin::_on_context_menu_selection)); - add_child(_context_menu); - } } void OrchestratorGraphNodePin::_gui_input(const Ref& p_event) @@ -460,6 +454,11 @@ void OrchestratorGraphNodePin::_populate_graph_node_in_sub_menu(int p_id, const void OrchestratorGraphNodePin::_show_context_menu(const Vector2& p_position) { + _context_menu = memnew(PopupMenu); + _context_menu->connect("id_pressed", callable_mp(this, &OrchestratorGraphNodePin::_handle_context_menu)); + _context_menu->connect("close_requested", callable_mp(this, &OrchestratorGraphNodePin::_cleanup_context_menu)); + add_child(_context_menu); + // When showing the context-menu, if the current node is not selected, we should clear the // selection and the operation will only be applicable for this node and its pin. if (!_node->is_selected()) @@ -514,7 +513,7 @@ void OrchestratorGraphNodePin::_show_context_menu(const Vector2& p_position) { PopupMenu* sub_menu = memnew(PopupMenu); sub_menu->set_name("change_pin_type_options"); - sub_menu->connect("id_pressed", callable_mp(this, &OrchestratorGraphNodePin::_on_context_menu_change_pin_type)); + sub_menu->connect("id_pressed", callable_mp(this, &OrchestratorGraphNodePin::_change_pin_type)); for (int i = 0; i < options.size(); i++) { @@ -540,7 +539,7 @@ void OrchestratorGraphNodePin::_show_context_menu(const Vector2& p_position) PopupMenu* sub_menu = memnew(PopupMenu); sub_menu->set_name("break_pin"); - sub_menu->connect("id_pressed", callable_mp(this, &OrchestratorGraphNodePin::_on_context_menu_break_pin)); + sub_menu->connect("id_pressed", callable_mp(this, &OrchestratorGraphNodePin::_link_pin)); _populate_graph_node_in_sub_menu(CM_BREAK_LINK, "Break Pin Link to", sub_menu, connections); _context_menu->add_child(sub_menu); _context_menu->add_submenu_item("Break Link to...", sub_menu->get_name(), CM_BREAK_LINK); @@ -550,7 +549,7 @@ void OrchestratorGraphNodePin::_show_context_menu(const Vector2& p_position) { PopupMenu* sub_menu = memnew(PopupMenu); sub_menu->set_name("node_jump"); - sub_menu->connect("id_pressed", callable_mp(this, &OrchestratorGraphNodePin::_on_context_menu_jump_node)); + sub_menu->connect("id_pressed", callable_mp(this, &OrchestratorGraphNodePin::_jump_to_adjacent_node)); _populate_graph_node_in_sub_menu(CM_JUMP_NODE, "Jump to", sub_menu, connections); _context_menu->add_child(sub_menu); _context_menu->add_submenu_item("Jump to connected node...", sub_menu->get_name(), CM_JUMP_NODE); @@ -618,7 +617,7 @@ Ref OrchestratorGraphNodePin::_get_connected_pin_by_sub_menu_met return {}; } -void OrchestratorGraphNodePin::_on_context_menu_selection(int p_id) +void OrchestratorGraphNodePin::_handle_context_menu(int p_id) { // Handle others switch (p_id) @@ -660,9 +659,20 @@ void OrchestratorGraphNodePin::_on_context_menu_selection(int p_id) // no-op break; } + + _cleanup_context_menu(); } -void OrchestratorGraphNodePin::_on_context_menu_change_pin_type(int p_id) +void OrchestratorGraphNodePin::_cleanup_context_menu() +{ + if (_context_menu) + { + _context_menu->queue_free(); + _context_menu = nullptr; + } +} + +void OrchestratorGraphNodePin::_change_pin_type(int p_id) { Variant metadata = _get_context_sub_menu_item_metadata(CM_CHANGE_PIN_TYPE, p_id); if (metadata.get_type() == Variant::INT) @@ -670,16 +680,20 @@ void OrchestratorGraphNodePin::_on_context_menu_change_pin_type(int p_id) const int type = metadata; get_graph_node()->get_script_node()->change_pin_types(VariantUtils::to_type(type)); } + + _cleanup_context_menu(); } -void OrchestratorGraphNodePin::_on_context_menu_break_pin(int p_id) +void OrchestratorGraphNodePin::_link_pin(int p_id) { const Ref connection = _get_connected_pin_by_sub_menu_metadata(CM_BREAK_LINK, p_id); if (connection.is_valid()) _pin->unlink(connection); + + _cleanup_context_menu(); } -void OrchestratorGraphNodePin::_on_context_menu_jump_node(int p_id) +void OrchestratorGraphNodePin::_jump_to_adjacent_node(int p_id) { const Ref connection = _get_connected_pin_by_sub_menu_metadata(CM_JUMP_NODE, p_id); if (connection.is_valid()) @@ -687,4 +701,6 @@ void OrchestratorGraphNodePin::_on_context_menu_jump_node(int p_id) const int node_id = connection->get_owning_node()->get_id(); get_graph()->focus_node(node_id); } + + _cleanup_context_menu(); } \ No newline at end of file diff --git a/src/editor/graph/graph_node_pin.h b/src/editor/graph/graph_node_pin.h index e0affeeb..78e925c1 100644 --- a/src/editor/graph/graph_node_pin.h +++ b/src/editor/graph/graph_node_pin.h @@ -257,21 +257,24 @@ class OrchestratorGraphNodePin : public HBoxContainer /// @return the connection pin, could be invalid if the connection lookup fails Ref _get_connected_pin_by_sub_menu_metadata(int p_menu_id, int p_id); - /// Observes when a context menu item is selected + /// Handles the selection of a context menu item /// @param p_id the selected item id - void _on_context_menu_selection(int p_id); + void _handle_context_menu(int p_id); - /// Dispatched when requesting the pin's type to be changed + /// Cleans up the context menu after it has closed + void _cleanup_context_menu(); + + /// Changes the pin's type to the selected type /// @param p_id the menu id of the new pin type - void _on_context_menu_change_pin_type(int p_id); + void _change_pin_type(int p_id); - /// Dispatched when requesting to break a specific pin + /// Breaks or unlinks a pin's connection /// @param p_id the menu id of the pin to break - void _on_context_menu_break_pin(int p_id); + void _link_pin(int p_id); - /// Dispatched when requesting to jump to an adjacent node + /// Jumps to an adjacent node /// @param p_id the menu id of the node to jump to - void _on_context_menu_jump_node(int p_id); + void _jump_to_adjacent_node(int p_id); }; #endif // ORCHESTRATOR_GRAPH_NODE_PIN_H \ No newline at end of file