Skip to content

Commit

Permalink
GH-490 Make PopupMenu instances dynamic for Node/Pins
Browse files Browse the repository at this point in the history
  • Loading branch information
Naros committed Jul 11, 2024
1 parent 6f1d40b commit 9d7ebfc
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 33 deletions.
30 changes: 21 additions & 9 deletions src/editor/graph/graph_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
}
}

8 changes: 5 additions & 3 deletions src/editor/graph/graph_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ class OrchestratorGraphNode : public GraphNode
{
GDCLASS(OrchestratorGraphNode, GraphNode);

private:
enum ContextMenuId
{
CM_NONE,
Expand Down Expand Up @@ -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
42 changes: 29 additions & 13 deletions src/editor/graph/graph_node_pin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<InputEvent>& p_event)
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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++)
{
Expand All @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -618,7 +617,7 @@ Ref<OScriptNodePin> 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)
Expand Down Expand Up @@ -660,31 +659,48 @@ 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)
{
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<OScriptNodePin> 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<OScriptNodePin> connection = _get_connected_pin_by_sub_menu_metadata(CM_JUMP_NODE, p_id);
if (connection.is_valid())
{
const int node_id = connection->get_owning_node()->get_id();
get_graph()->focus_node(node_id);
}

_cleanup_context_menu();
}
19 changes: 11 additions & 8 deletions src/editor/graph/graph_node_pin.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,21 +257,24 @@ class OrchestratorGraphNodePin : public HBoxContainer
/// @return the connection pin, could be invalid if the connection lookup fails
Ref<OScriptNodePin> _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

0 comments on commit 9d7ebfc

Please sign in to comment.