From c866d170451b3f4b67316cf42389590bd8c28ac8 Mon Sep 17 00:00:00 2001 From: Chris Cranford Date: Sun, 11 Aug 2024 02:39:31 -0400 Subject: [PATCH] GH-707 Add GraphNode alignment options --- src/editor/graph/graph_node.cpp | 82 +++++++++++++++++++++++++++++++++ src/editor/graph/graph_node.h | 6 +++ 2 files changed, 88 insertions(+) diff --git a/src/editor/graph/graph_node.cpp b/src/editor/graph/graph_node.cpp index 9c40fb5e..be9f6d12 100644 --- a/src/editor/graph/graph_node.cpp +++ b/src/editor/graph/graph_node.cpp @@ -474,6 +474,16 @@ void OrchestratorGraphNode::_show_context_menu(const Vector2& p_position) if (!call_script_function.is_valid()) _context_menu->set_item_disabled(_context_menu->get_item_index(CM_EXPAND_NODE), true); + PopupMenu* alignment_menu = memnew(PopupMenu); + alignment_menu->add_icon_item(SceneUtils::get_editor_icon("ControlAlignTopWide"), "Align Top", CM_ALIGN_TOP); + alignment_menu->add_icon_item(SceneUtils::get_editor_icon("ControlAlignHCenterWide"), "Align Middle", CM_ALIGN_MIDDLE); + alignment_menu->add_icon_item(SceneUtils::get_editor_icon("ControlAlignBottomWide"), "Align Bottom", CM_ALIGN_BOTTOM); + alignment_menu->add_icon_item(SceneUtils::get_editor_icon("ControlAlignLeftWide"), "Align Left", CM_ALIGN_LEFT); + alignment_menu->add_icon_item(SceneUtils::get_editor_icon("ControlAlignVCenterWide"), "Align Center", CM_ALIGN_CENTER); + alignment_menu->add_icon_item(SceneUtils::get_editor_icon("ControlAlignRightWide"), "Align Right", CM_ALIGN_RIGHT); + alignment_menu->connect("id_pressed", callable_mp(this, &OrchestratorGraphNode::_handle_context_menu)); + _context_menu->add_submenu_node_item("Alignment", alignment_menu); + #if GODOT_VERSION >= 0x040300 if (!multi_selections) { @@ -805,6 +815,78 @@ void OrchestratorGraphNode::_handle_context_menu(int p_id) break; } #endif + case CM_ALIGN_TOP: + { + // Align all selected nodes to match top of this specific node. + const float top = get_position_offset().y; + for (OrchestratorGraphNode* node : get_graph()->get_selected_nodes()) + { + const float adjust = top - node->get_position_offset().y; + node->set_position_offset(node->get_position_offset() + Vector2(0, adjust)); + node->get_script_node()->set_position(node->get_position_offset()); + } + break; + } + case CM_ALIGN_MIDDLE: + { + // Align all selected nodes to center to this specific node. + const float mid_y = get_position_offset().y + (get_size().y / 2); + for (OrchestratorGraphNode* node : get_graph()->get_selected_nodes()) + { + const float node_mid_y = node->get_position_offset().y + (node->get_size().y / 2); + node->set_position_offset(node->get_position_offset() + Vector2(0, mid_y - node_mid_y)); + node->get_script_node()->set_position(node->get_position_offset()); + } + break; + } + case CM_ALIGN_BOTTOM: + { + // Align all selected nodes to match bottom of this specific node. + const float bottom = get_position_offset().y + get_size().y; + for (OrchestratorGraphNode* node : get_graph()->get_selected_nodes()) + { + const float adjust = bottom - (node->get_position_offset().y + node->get_size().y); + node->set_position_offset(node->get_position_offset() + Vector2(0, adjust)); + node->get_script_node()->set_position(node->get_position_offset()); + } + break; + } + case CM_ALIGN_LEFT: + { + // Align all selected nodes to this specific node. + const Vector2 pos = _node->get_position(); + for (OrchestratorGraphNode* node : get_graph()->get_selected_nodes()) + { + const float left = node->get_position_offset().x; + node->set_position_offset(node->get_position_offset() + Vector2(pos.x - left, 0)); + node->get_script_node()->set_position(node->get_position_offset()); + } + break; + } + case CM_ALIGN_CENTER: + { + // Align all selected nodes to center to this specific node. + const float mid_x = get_position_offset().x + (get_size().x / 2); + for (OrchestratorGraphNode* node : get_graph()->get_selected_nodes()) + { + const float node_mid_x = node->get_position_offset().x + (node->get_size().x / 2); + node->set_position_offset(node->get_position_offset() + Vector2(mid_x - node_mid_x, 0)); + node->get_script_node()->set_position(node->get_position_offset()); + } + break; + } + case CM_ALIGN_RIGHT: + { + // Align all selected nodes to this specific node. + const float right = get_position_offset().x + get_size().x; + for (OrchestratorGraphNode* node : get_graph()->get_selected_nodes()) + { + const float adjust = right - (node->get_position_offset().x + node->get_size().x); + node->set_position_offset(node->get_position_offset() + Vector2(adjust, 0)); + node->get_script_node()->set_position(node->get_position_offset()); + } + break; + } default: { WARN_PRINT("Feature not yet implemented"); diff --git a/src/editor/graph/graph_node.h b/src/editor/graph/graph_node.h index 619ae646..b7a13330 100644 --- a/src/editor/graph/graph_node.h +++ b/src/editor/graph/graph_node.h @@ -66,6 +66,12 @@ class OrchestratorGraphNode : public GraphNode CM_RESIZABLE, CM_MAKE_PURE_GETTER, CM_MAKE_VALIDATED_GETTER, + CM_ALIGN_TOP, + CM_ALIGN_MIDDLE, + CM_ALIGN_BOTTOM, + CM_ALIGN_LEFT, + CM_ALIGN_CENTER, + CM_ALIGN_RIGHT, CM_NODE_ACTION = 1000 };