source: finroc_plugins_composite_ports/auto_connect.cpp @ 11:ca584c3bd2d4

Last change on this file since 11:ca584c3bd2d4 was 11:ca584c3bd2d4, checked in by Max Reichardt <max.reichardt@…>, 3 years ago

Adds another auto-connect function for convenience (ConnectUnconnectedMatchingInterfaces)

File size: 6.8 KB
Line 
1//
2// You received this file as part of Finroc
3// A framework for intelligent robot control
4//
5// Copyright (C) Finroc GbR (finroc.org)
6//
7// This program is free software; you can redistribute it and/or modify
8// it under the terms of the GNU General Public License as published by
9// the Free Software Foundation; either version 2 of the License, or
10// (at your option) any later version.
11//
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License along
18// with this program; if not, write to the Free Software Foundation, Inc.,
19// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20//
21//----------------------------------------------------------------------
22/*!\file    plugins/composite_ports/auto_connect.cpp
23 *
24 * \author  Max Reichardt
25 *
26 * \date    2020-02-18
27 *
28 */
29//----------------------------------------------------------------------
30#include "plugins/composite_ports/auto_connect.h"
31
32//----------------------------------------------------------------------
33// External includes (system with <>, local with "")
34//----------------------------------------------------------------------
35#include "rrlib/rtti_conversion/tStaticCastOperation.h"
36
37//----------------------------------------------------------------------
38// Internal includes with ""
39//----------------------------------------------------------------------
40
41//----------------------------------------------------------------------
42// Debugging
43//----------------------------------------------------------------------
44#include <cassert>
45
46//----------------------------------------------------------------------
47// Namespace usage
48//----------------------------------------------------------------------
49
50//----------------------------------------------------------------------
51// Namespace declaration
52//----------------------------------------------------------------------
53namespace finroc
54{
55namespace composite_ports
56{
57
58//----------------------------------------------------------------------
59// Forward declarations / typedefs / enums
60//----------------------------------------------------------------------
61
62typedef core::tFrameworkElementFlag tFlag;
63typedef tInterfaceBase::tBackend tBackend;
64
65//----------------------------------------------------------------------
66// Const values
67//----------------------------------------------------------------------
68
69//----------------------------------------------------------------------
70// Implementation
71//----------------------------------------------------------------------
72
73namespace
74{
75
76bool IsConnectedToComponent(core::tFrameworkElement& component, tInterfaceBase::tBackend& primary_backend)
77{
78  for (auto it = primary_backend.IncomingConnectionsBegin(); it != primary_backend.IncomingConnectionsEnd(); ++it)
79  {
80    auto aggregator = core::tEdgeAggregator::GetAggregator(it->Source());
81    if (aggregator && aggregator->GetParent() == &component)
82    {
83      return true;
84    }
85  }
86  for (auto it = primary_backend.OutgoingConnectionsBegin(); it != primary_backend.OutgoingConnectionsEnd(); ++it)
87  {
88    auto aggregator = core::tEdgeAggregator::GetAggregator(it->Destination());
89    if (aggregator && aggregator->GetParent() == &component)
90    {
91      return true;
92    }
93  }
94  return false;
95}
96
97}
98
99namespace internal
100{
101
102std::vector<tInterfaceBase> GetChildComponentInterfaces(core::tFrameworkElement& composite_component, const rrlib::rtti::tType& interface_type, bool unconnected_only)
103{
104  std::vector<tInterfaceBase> result;
105  if (!interface_type)
106  {
107    // -> no interfaces of this type exist
108    return result;
109  }
110
111  for (auto component_element = composite_component.ChildrenBegin(); component_element != composite_component.ChildrenEnd(); ++component_element)
112  {
113    if (IsComponent(&*component_element))
114    {
115      core::tFrameworkElement& component = *component_element;
116      for (auto component_interface = component.ChildrenBegin(); component_interface != component.ChildrenEnd(); ++component_interface)
117      {
118        if (component_interface->GetFlag(tFlag::EDGE_AGGREGATOR))
119        {
120          for (auto element_in_interface = component_interface->ChildrenBegin(); element_in_interface != component_interface->ChildrenEnd(); ++element_in_interface)
121          {
122            if (tInterfaceBase::IsInterface(*element_in_interface))
123            {
124              tBackend& backend = static_cast<tBackend&>(*element_in_interface);
125              if (backend.AllBackends().front() == &backend && backend.GetDataType() == interface_type && ((!unconnected_only) || (!IsConnectedToComponent(composite_component, backend)))) // only return primary interfaces
126              {
127                result.emplace_back(&backend);
128              }
129            }
130          }
131        }
132      }
133    }
134  }
135  return result;
136}
137
138}
139
140void ConnectUnconnectedMatchingInterfaces(core::tPortGroup& source_component_interface, core::tPortGroup& destination_component_interface, bool connect_derived_interfaces)
141{
142  for (auto destination_port = destination_component_interface.ChildPortsBegin(); destination_port != destination_component_interface.ChildPortsEnd(); ++destination_port)
143  {
144    if (destination_port->IsReady() && destination_port->GetDataType().GetTypeClassification() == rrlib::rtti::tTypeClassification::PORT_COMPOSITE_INTERFACE && destination_port->CountIncomingConnections() == 0)
145    {
146      for (auto source_port = source_component_interface.ChildPortsBegin(); source_port != source_component_interface.ChildPortsEnd(); ++source_port)
147      {
148        if (source_port->IsReady() && source_port->GetDataType().GetTypeClassification() == rrlib::rtti::tTypeClassification::PORT_COMPOSITE_INTERFACE && (source_port->GetDataType() == destination_port->GetDataType() || (connect_derived_interfaces && rrlib::rtti::conversion::tStaticCastOperation::IsImplicitlyConvertibleTo(source_port->GetDataType(), destination_port->GetDataType()))))
149        {
150          bool already_connected = false;
151          for (auto connector = source_port->OutgoingConnectionsBegin(); connector != source_port->OutgoingConnectionsEnd(); ++connector)
152          {
153            auto aggregator = core::tEdgeAggregator::GetAggregator(connector->Destination());
154            if (aggregator == &destination_component_interface)
155            {
156              already_connected = true;
157              break;
158            }
159          }
160          if (!already_connected)
161          {
162            source_port->ConnectTo(*destination_port);
163          }
164        }
165      }
166    }
167  }
168}
169
170
171//----------------------------------------------------------------------
172// End of namespace declaration
173//----------------------------------------------------------------------
174}
175}
Note: See TracBrowser for help on using the repository browser.