diff --git a/Bindings/Python/tests/test_sockets_inputs_outputs.py b/Bindings/Python/tests/test_sockets_inputs_outputs.py index feccd8d450..78952da8c0 100644 --- a/Bindings/Python/tests/test_sockets_inputs_outputs.py +++ b/Bindings/Python/tests/test_sockets_inputs_outputs.py @@ -203,7 +203,7 @@ def test_connecting_and_iterate_inputs(self): coord = j.get_coordinates(0) rep.updInput('inputs').connect(coord.getOutput('value')) rep.connectInput_inputs(coord.getOutput('speed'), 'spd') - rep.connectInput_inputs( + rep.appendInputChannel_inputs( source.getOutput('column').getChannel('col1')) rep.addToReport( source.getOutput('column').getChannel('col2'), 'second_col') diff --git a/OpenSim/Common/ComponentSocket.h b/OpenSim/Common/ComponentSocket.h index 0f07eff334..5bdebef34b 100644 --- a/OpenSim/Common/ComponentSocket.h +++ b/OpenSim/Common/ComponentSocket.h @@ -386,7 +386,7 @@ class Socket : public AbstractSocket { } /** Return a const reference to the Object connected to this Socket. */ - const T& getConnecteeAsObject(int index = -1) const override { + const Object& getConnecteeAsObject(int index = -1) const override { if (index < 0) { if (!isListSocket()) { index = 0; } else { @@ -471,7 +471,7 @@ class Socket : public AbstractSocket { private: - const T& getConnecteeAsObjectInternal(int index) const { + const Object& getConnecteeAsObjectInternal(int index) const { OPENSIM_THROW_IF(!isConnected(), Exception, "Socket '{}' not connected.", getName()); using SimTK::isIndexInRange; @@ -1135,13 +1135,25 @@ class Input : public AbstractInput { /** @endcond */ \ /** @name Socket-related functions */ \ /** @{ */ \ - /** Connect the '##cname##' Socket to an object of type T##. */ \ + /** Append an object of type T## to the list of connectees in the */ \ + /** list Socket. */ \ /** Call finalizeConnections() afterwards to update the socket's */ \ /** connectee path property. The reference to the connectee set here */ \ /** takes precedence over the connectee path property. */ \ - void connectSocket_##cname(const OpenSim::Object& object) { \ + void appendSocketConnectee_##cname(const OpenSim::Object& object) { \ this->updSocket(#cname).connect(object); \ } \ + /** Connect the '##cname##' Socket to a list of objects of type T##. */ \ + /** Call finalizeConnections() afterwards to update the socket's */ \ + /** connectee path property. The reference to the connectee set here */ \ + /** takes precedence over the connectee path property. */ \ + void connectSocket_##cname( \ + const std::vector< \ + SimTK::ReferencePtr>& objects) { \ + for (const auto& object : objects) { \ + this->updSocket(#cname).connect(object.getRef()); \ + } \ + } \ /** @} */ // The following doxygen-like description does NOT actually appear in doxygen. @@ -1315,13 +1327,15 @@ OpenSim::PropertyIndex Class::constructSocket_##cname() { \ updInput(#iname).connect(output, alias); \ } \ /** Connect this Input to an output channel of type T##. */ \ + /** This overrides any existing channel connections. */ \ /** You can optionally provide an alias that will be used by this */ \ /** component to refer to the channel. */ \ /** Call finalizeConnections() afterwards to update the input's */ \ /** connectee path property. The reference to the channel set here */ \ /** takes precedence over the connectee path property. */ \ - void connectInput_##iname(const OpenSim::AbstractChannel& channel, \ - const std::string& alias = "") { \ + void connectInputChannel_##iname( \ + const OpenSim::AbstractChannel& channel, \ + const std::string& alias = "") { \ updInput(#iname).connect(channel, alias); \ } \ /** @} */ @@ -1382,14 +1396,16 @@ OpenSim::PropertyIndex Class::constructSocket_##cname() { \ const std::string& alias = "") { \ updInput(#iname).connect(output, alias); \ } \ - /** Connect this Input to an output channel of type T##. */ \ + /** Append an output channel to the list of connectees in the list */ \ + /** Input. */ \ /** You can optionally provide an alias that will be used by this */ \ /** component to refer to the channel. */ \ /** Call finalizeConnections() afterwards to update the input's */ \ /** connectee path property. The reference to the channel set here */ \ /** takes precedence over the connectee path property. */ \ - void connectInput_##iname(const OpenSim::AbstractChannel& channel, \ - const std::string& alias = "") { \ + void appendInputChannel_##iname( \ + const OpenSim::AbstractChannel& channel, \ + const std::string& alias = "") { \ updInput(#iname).connect(channel, alias); \ } \ /** @} */ diff --git a/OpenSim/Common/Reporter.h b/OpenSim/Common/Reporter.h index 9a73be1f87..8e10f6f2e4 100644 --- a/OpenSim/Common/Reporter.h +++ b/OpenSim/Common/Reporter.h @@ -145,10 +145,10 @@ class Reporter : public AbstractReporter { reporter->addToReport(src->getOutput("column").getChannel("ankle")); @endcode This method is equivalent to - connectInput_inputs(const AbstractChannel&, const std::string&). */ + appendInputChannel_inputs(const AbstractChannel&, const std::string&). */ void addToReport(const AbstractChannel& channel, const std::string& alias = "") { - connectInput_inputs(channel, alias); + appendInputChannel_inputs(channel, alias); } protected: diff --git a/OpenSim/Common/Test/testComponentInterface.cpp b/OpenSim/Common/Test/testComponentInterface.cpp index 9498e51ab8..bb03e4a0d7 100644 --- a/OpenSim/Common/Test/testComponentInterface.cpp +++ b/OpenSim/Common/Test/testComponentInterface.cpp @@ -583,13 +583,13 @@ TEST_CASE("Component Interface Misc.") foo3.setName("Foo3"); theWorld.add(&foo3); foo3.set_mass(4.0); - bar.connectSocket_listFoo(foo3); + bar.appendSocketConnectee_listFoo(foo3); Foo& foo4 = *new Foo(); foo4.setName("Foo4"); theWorld.add(&foo4); foo4.set_mass(5.0); - bar.connectSocket_listFoo(foo4); + bar.appendSocketConnectee_listFoo(foo4); std::cout << "Iterate over Foo's after adding Foo2, Foo3, and Foo4." << std::endl; for (auto& component : theWorld.getComponentList()) { @@ -754,7 +754,7 @@ TEST_CASE("Component Interface Misc.") compFoo.getRelativePathString(bar2)); bar2.connectSocket_childFoo(compFoo.get_Foo1()); - bar2.connectSocket_listFoo(compFoo.get_Foo3()); + bar2.appendSocketConnectee_listFoo(compFoo.get_Foo3()); compFoo.upd_Foo1().updInput("input1") .connect(bar2.getOutput("PotentialEnergy")); @@ -1018,18 +1018,18 @@ TEST_CASE("Component Interface Sockets") CHECK(bar.getSocket("listFoo").getNumConnectees() == 0); // Connect to list socket. - bar.connectSocket_listFoo(foo1); - bar.connectSocket_listFoo(foo2); + bar.appendSocketConnectee_listFoo(foo1); + bar.appendSocketConnectee_listFoo(foo2); theWorld.connect(); theWorld.buildUpSystem(system); CHECK(bar.getSocket("listFoo").getNumConnectees() == 2); // Check that connecting to the same component throws an Exception. - CHECK_THROWS_WITH(bar.connectSocket_listFoo(foo2), + CHECK_THROWS_WITH(bar.appendSocketConnectee_listFoo(foo2), Catch::Matchers::Contains("Socket 'listFoo' already has a " "connectee of type 'Foo' named 'foo2'.")); - bar.connectSocket_listFoo(foo3); + bar.appendSocketConnectee_listFoo(foo3); theWorld.connect(); theWorld.buildUpSystem(system); CHECK(bar.getSocket("listFoo").getNumConnectees() == 3); @@ -2201,9 +2201,9 @@ TEST_CASE("Component Interface Single Value Input Connectee Serialization Behavi // Connect, finalize, etc. const auto& output = source->getOutput("column"); // See if we preserve the ordering of the channels. - foo->connectInput_input1(output.getChannel("b")); + foo->appendInputChannel_listInput1(output.getChannel("b")); // We want to make sure aliases are preserved. - foo->connectInput_fiberLength(output.getChannel("d"), "desert"); + foo->connectInputChannel_fiberLength(output.getChannel("d"), "desert"); // Ensure that re-finalizing from properties does not cause Inputs // to hold onto stale references to the outputs' channels. world.finalizeFromProperties();