From 1faedb794d83f139df7f5e092696b0355a433734 Mon Sep 17 00:00:00 2001 From: Damien Marchal Date: Fri, 27 Jun 2025 12:35:35 +0200 Subject: [PATCH 01/19] Merge DAGNode in Node --- .../Core/src/sofa/simulation/Node.cpp | 14 +- .../Core/src/sofa/simulation/Node.h | 196 +++++++++++++---- .../src/sofa/simulation/graph/DAGNode.cpp | 162 +++++++------- .../Graph/src/sofa/simulation/graph/DAGNode.h | 197 +----------------- 4 files changed, 240 insertions(+), 329 deletions(-) diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.cpp index ad554c90d04..53a988adaff 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.cpp @@ -71,7 +71,7 @@ namespace sofa::simulation using core::objectmodel::BaseNode; using core::objectmodel::BaseObject; -Node::Node(const std::string& name) +Node::Node(const std::string& name, Node* parent) : core::objectmodel::BaseNode() , sofa::core::objectmodel::Context() , child(initLink("child", "Child nodes")) @@ -109,7 +109,11 @@ Node::Node(const std::string& name) , debug_(false) , initialized(false) + , l_parents(initLink("parents", "Parents nodes in the graph")) { + if( parent ) + parent->addChild(dynamic_cast(this)); + _context = this; setName(name); f_printLog.setValue(DEBUG_LINK); @@ -118,8 +122,14 @@ Node::Node(const std::string& name) Node::~Node() { + for (ChildIterator it = child.begin(), itend = child.end(); it != itend; ++it) + { + const Node::SPtr dagnode = sofa::core::objectmodel::SPtr_static_cast(*it); + dagnode->l_parents.remove(this); + } } + void Node::parse( sofa::core::objectmodel::BaseObjectDescription* arg ) { Inherit1::parse( arg ); @@ -643,7 +653,7 @@ core::topology::Topology* Node::getTopology() const } /// Mesh Topology (unified interface for both static and dynamic topologies) -core::topology::BaseMeshTopology* Node::getMeshTopologyLink(SearchDirection dir) const +core::topology::BaseMeshTopology* Node::NODEgetMeshTopologyLink(SearchDirection dir) const { SOFA_UNUSED(dir); if (this->meshTopology) diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.h index 4b07b4713ff..8ef3261dec6 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.h @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -149,15 +150,10 @@ class SOFA_SIMULATION_CORE_API Node : public sofa::core::objectmodel::BaseNode, public: SOFA_ABSTRACT_CLASS2(Node, BaseNode, Context); - typedef sofa::core::visual::DisplayFlags DisplayFlags; -protected: - Node(const std::string& name=""); + Node(const std::string& name="", Node* parent=nullptr); virtual ~Node() override; -public: - /// Create, add, then return the new child of this Node - virtual Node::SPtr createChild(const std::string& nodeName)=0; /// @name High-level interface /// @{ @@ -179,9 +175,6 @@ class SOFA_SIMULATION_CORE_API Node : public sofa::core::objectmodel::BaseNode, /// @warning when calling with precomputedOrder=true, the function "precomputeTraversalOrder" must be called before executing the visitor and the user must ensure by himself that the simulation graph has done been modified since the last call to "precomputeTraversalOrder" /// @{ - /// Execute a recursive action starting from this node. - virtual void doExecuteVisitor(Visitor* action, bool precomputedOrder=false)=0; - /// Execute a recursive action starting from this node void executeVisitor(Visitor* action, bool precomputedOrder=false) override; @@ -217,7 +210,7 @@ class SOFA_SIMULATION_CORE_API Node : public sofa::core::objectmodel::BaseNode, } /// Possible optimization with traversal precomputation, not mandatory and does nothing by default - virtual void precomputeTraversalOrder( const sofa::core::ExecParams* ) {} + void precomputeTraversalOrder( const sofa::core::ExecParams* ); /// @} @@ -276,19 +269,6 @@ class SOFA_SIMULATION_CORE_API Node : public sofa::core::objectmodel::BaseNode, virtual void removeChild(BaseNode::SPtr node) final; /// Move a node in this from another node virtual void moveChild(BaseNode::SPtr node, BaseNode::SPtr prev_parent) final; - /// Move a node in this from another node - virtual void moveChild(BaseNode::SPtr node) override = 0; - - /// Delegate methods overridden in child classes - /// Add a child node - virtual void doAddChild(BaseNode::SPtr node) = 0; - /// Remove a child node - virtual void doRemoveChild(BaseNode::SPtr node) = 0; - /// Move a node from another node - virtual void doMoveChild(BaseNode::SPtr node, BaseNode::SPtr prev_parent) = 0; - - /// @} - /// @name Set/get objects /// @{ @@ -309,27 +289,13 @@ class SOFA_SIMULATION_CORE_API Node : public sofa::core::objectmodel::BaseNode, /// Generic object access, given a set of required tags, possibly searching up or down from the current context /// - /// Note that the template wrapper method should generally be used to have the correct return type, - void* getObject(const sofa::core::objectmodel::ClassInfo& class_info, const sofa::core::objectmodel::TagSet& tags, SearchDirection dir = SearchUp) const override = 0; - /// Generic object access, possibly searching up or down from the current context - /// /// Note that the template wrapper method should generally be used to have the correct return type, void* getObject(const sofa::core::objectmodel::ClassInfo& class_info, SearchDirection dir = SearchUp) const override { return getObject(class_info, sofa::core::objectmodel::TagSet(), dir); } - /// Generic object access, given a path from the current context - /// - /// Note that the template wrapper method should generally be used to have the correct return type, - void* getObject(const sofa::core::objectmodel::ClassInfo& class_info, const std::string& path) const override = 0; - - /// Generic list of objects access, given a set of required tags, possibly searching up or down from the current context - /// - /// Note that the template wrapper method should generally be used to have the correct return type, - void getObjects(const sofa::core::objectmodel::ClassInfo& class_info, GetObjectsCallBack& container, const sofa::core::objectmodel::TagSet& tags, SearchDirection dir = SearchUp) const override = 0; - /// Generic list of objects access, possibly searching up or down from the current context /// /// Note that the template wrapper method should generally be used to have the correct return type, @@ -497,7 +463,7 @@ class SOFA_SIMULATION_CORE_API Node : public sofa::core::objectmodel::BaseNode, virtual void updateSimulationContext(); /// Called during initialization to correctly propagate the visual context to the children - virtual void initVisualContext() {} + virtual void initVisualContext(); /// Propagate an event void propagateEvent(const sofa::core::ExecParams* params, sofa::core::objectmodel::Event* event) override; @@ -517,9 +483,6 @@ class SOFA_SIMULATION_CORE_API Node : public sofa::core::objectmodel::BaseNode, template static Node::SPtr create(RealObject*, sofa::core::objectmodel::BaseObjectDescription* arg); - /// return the smallest common parent between this and node2 (returns nullptr if separated sub-graphes) - virtual Node* findCommonParent( simulation::Node* node2 ) = 0; - /// override context setSleeping to add notification. void setSleeping(bool val) override; @@ -607,6 +570,157 @@ class SOFA_SIMULATION_CORE_API Node : public sofa::core::objectmodel::BaseNode, /// @} + + /// FROM DAG NODE + + typedef MultiLink LinkParents; + typedef LinkParents::const_iterator ParentIterator; + +public: + static const std::string GetCustomClassName(){ return "Node"; } + + Node::SPtr createChild(const std::string& nodeName); + + /// Remove the current node from the graph: consists in removing the link to its parent + void detachFromGraph() override; + + /// Get a list of parent node + Parents getParents() const override; + + /// returns number of parents + size_t getNbParents() const override; + + /// return the first parent (returns nullptr if no parent) + BaseNode* getFirstParent() const override; + + /// Test if the given node is a parent of this node. + bool hasParent(const BaseNode* node) const override; + + /// Test if the given context is a parent of this context. + bool hasParent(const BaseContext* context) const; + + /// Test if the given context is an ancestor of this context. + /// An ancestor is a parent or (recursively) the parent of an ancestor. + bool hasAncestor(const BaseNode* node) const override + { + return hasAncestor(node->getContext()); + } + + /// Test if the given context is an ancestor of this context. + /// An ancestor is a parent or (recursively) the parent of an ancestor. + bool hasAncestor(const BaseContext* context) const override; + + + /// Generic object access, given a set of required tags, possibly searching up or down from the current context + /// + /// Note that the template wrapper method should generally be used to have the correct return type, + void* getObject(const sofa::core::objectmodel::ClassInfo& class_info, const sofa::core::objectmodel::TagSet& tags, SearchDirection dir = SearchUp) const override; + + /// Generic object access, given a path from the current context + /// + /// Note that the template wrapper method should generally be used to have the correct return type, + void* getObject(const sofa::core::objectmodel::ClassInfo& class_info, const std::string& path) const override; + + /// Generic list of objects access, given a set of required tags, possibly searching up or down from the current context + /// + /// Note that the template wrapper method should generally be used to have the correct return type, + void getObjects(const sofa::core::objectmodel::ClassInfo& class_info, GetObjectsCallBack& container, const sofa::core::objectmodel::TagSet& tags, SearchDirection dir = SearchUp) const override; + + /// Mesh Topology that is relevant for this context + /// (within it or its parents until a mapping is reached that does not preserve topologies). + sofa::core::topology::BaseMeshTopology* NODEgetMeshTopologyLink(SearchDirection dir = SearchUp) const; + + static Node::SPtr create(Node*, sofa::core::objectmodel::BaseObjectDescription* arg) + { + Node::SPtr obj = Node::SPtr(new Node()); + obj->parse(arg); + return obj; + } + + void moveChild(BaseNode::SPtr node) override; + + /// return the smallest common parent between this and node2 (returns nullptr if separated sub-graphes) + Node* findCommonParent( simulation::Node* node2 ); + +protected: + /// bottom-up traversal, returning the first node which have a descendancy containing both node1 & node2 + Node* findCommonParent( Node* node1, Node* node2 ); + + LinkParents l_parents; + + void doAddChild(BaseNode::SPtr node); + void doRemoveChild(BaseNode::SPtr node); + void doMoveChild(BaseNode::SPtr node, BaseNode::SPtr previous_parent); + + /// Execute a recursive action starting from this node. + void doExecuteVisitor(simulation::Visitor* action, bool precomputedOrder=false); + + + /// @name @internal stuff related to the DAG traversal + /// @{ + + + /// all child nodes (unordered) + std::set _descendancy; + + /// bottom-up traversal removing descendancy + void setDirtyDescendancy(); + + /// traversal updating the descendancy + void updateDescendancy(); + + /// traversal flags + typedef enum + { + NOT_VISITED=0, + VISITED, + PRUNED + } VisitedStatus; + + + + /// wrapper to use VisitedStatus in a std::map (to ensure the default map insertion will give NOT_VISITED) + struct StatusStruct + { + StatusStruct() : status(NOT_VISITED) {} + StatusStruct( const VisitedStatus& s ) : status(s) {} + inline void operator=( const VisitedStatus& s ) { status=s; } + inline bool operator==( const VisitedStatus& s ) const { return status==s; } + inline bool operator==( const StatusStruct& s ) const { return status==s.status; } + inline bool operator!=( const VisitedStatus& s ) const { return status!=s; } + inline bool operator!=( const StatusStruct& s ) const { return status!=s.status; } + VisitedStatus status; + }; + + /// map structure to store a traversal flag for each Node + typedef std::map StatusMap; + + /// list of Node* + typedef std::list NodeList; + + /// the ordered list of Node to traverse from this Node + NodeList _precomputedTraversalOrder; + + /// @internal performing only the top-down traversal on a DAG + /// @executedNodes will be fill with the Nodes where the top-down action is processed + /// @statusMap the visitor's flag map + /// @visitorRoot node from where the visitor has been run + void executeVisitorTopDown(simulation::Visitor* action, NodeList& executedNodes, StatusMap& statusMap, Node* visitorRoot ); + void executeVisitorBottomUp(simulation::Visitor* action, NodeList& executedNodes ); + /// @} + + /// @internal tree traversal implementation + void executeVisitorTreeTraversal( Visitor* action, StatusMap& statusMap, Visitor::TreeTraversalRepetition repeat, bool alreadyRepeated=false ); + + /// @name @internal stuff related to getObjects + /// @{ + + /// get node's local objects respecting specified class_info and tags + void getLocalObjects( const sofa::core::objectmodel::ClassInfo& class_info, Node::GetObjectsCallBack& container, const sofa::core::objectmodel::TagSet& tags ) const ; + + friend class GetDownObjectsVisitor ; + friend class GetUpObjectsVisitor ; + /// @} }; } diff --git a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGNode.cpp b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGNode.cpp index bed1314039a..f0d36b47d66 100644 --- a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGNode.cpp +++ b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGNode.cpp @@ -19,12 +19,12 @@ * * * Contact information: contact@sofa-framework.org * ******************************************************************************/ -#include +#include #include #include #include -namespace sofa::simulation::graph +namespace sofa::simulation { /// get all down objects respecting specified class_info and tags @@ -32,12 +32,12 @@ class GetDownObjectsVisitor : public Visitor { public: - GetDownObjectsVisitor(const sofa::core::objectmodel::ClassInfo& class_info, DAGNode::GetObjectsCallBack& container, const sofa::core::objectmodel::TagSet& tags); - ~GetDownObjectsVisitor() override; + GetDownObjectsVisitor(const sofa::core::objectmodel::ClassInfo& class_info, Node::GetObjectsCallBack& container, const sofa::core::objectmodel::TagSet& tags); + ~GetDownObjectsVisitor() ; Result processNodeTopDown(simulation::Node* node) override { - static_cast(node)->getLocalObjects( _class_info, _container, _tags ); + static_cast(node)->getLocalObjects( _class_info, _container, _tags ); return RESULT_CONTINUE; } @@ -51,12 +51,12 @@ class GetDownObjectsVisitor : public Visitor protected: const sofa::core::objectmodel::ClassInfo& _class_info; - DAGNode::GetObjectsCallBack& _container; + Node::GetObjectsCallBack& _container; const sofa::core::objectmodel::TagSet& _tags; }; GetDownObjectsVisitor::GetDownObjectsVisitor(const sofa::core::objectmodel::ClassInfo& class_info, - DAGNode::GetObjectsCallBack& container, + Node::GetObjectsCallBack& container, const sofa::core::objectmodel::TagSet& tags) : Visitor( sofa::core::execparams::defaultInstance() ) , _class_info(class_info) @@ -71,12 +71,12 @@ class GetUpObjectsVisitor : public Visitor { public: - GetUpObjectsVisitor(DAGNode* searchNode, const sofa::core::objectmodel::ClassInfo& class_info, DAGNode::GetObjectsCallBack& container, const sofa::core::objectmodel::TagSet& tags); + GetUpObjectsVisitor(Node* searchNode, const sofa::core::objectmodel::ClassInfo& class_info, Node::GetObjectsCallBack& container, const sofa::core::objectmodel::TagSet& tags); ~GetUpObjectsVisitor() override; Result processNodeTopDown(simulation::Node* node) override { - const DAGNode* dagnode = dynamic_cast(node); + const Node* dagnode = dynamic_cast(node); if( dagnode->_descendancy.contains(_searchNode) ) // searchNode is in the current node descendancy, so the current node is a parent of searchNode { dagnode->getLocalObjects( _class_info, _container, _tags ); @@ -99,16 +99,16 @@ class GetUpObjectsVisitor : public Visitor protected: - DAGNode* _searchNode; + Node* _searchNode; const sofa::core::objectmodel::ClassInfo& _class_info; - DAGNode::GetObjectsCallBack& _container; + Node::GetObjectsCallBack& _container; const sofa::core::objectmodel::TagSet& _tags; }; -GetUpObjectsVisitor::GetUpObjectsVisitor(DAGNode* searchNode, +GetUpObjectsVisitor::GetUpObjectsVisitor(Node* searchNode, const sofa::core::objectmodel::ClassInfo& class_info, - DAGNode::GetObjectsCallBack& container, + Node::GetObjectsCallBack& container, const sofa::core::objectmodel::TagSet& tags) : Visitor( sofa::core::execparams::defaultInstance() ) , _searchNode( searchNode ) @@ -119,27 +119,10 @@ GetUpObjectsVisitor::GetUpObjectsVisitor(DAGNode* searchNode, GetUpObjectsVisitor::~GetUpObjectsVisitor(){} -DAGNode::DAGNode(const std::string& name, DAGNode* parent) - : simulation::Node(name) - , l_parents(initLink("parents", "Parents nodes in the graph")) -{ - if( parent ) - parent->addChild(dynamic_cast(this)); -} - -DAGNode::~DAGNode() -{ - for (ChildIterator it = child.begin(), itend = child.end(); it != itend; ++it) - { - const DAGNode::SPtr dagnode = sofa::core::objectmodel::SPtr_static_cast(*it); - dagnode->l_parents.remove(this); - } -} - /// Create, add, then return the new child of this Node -Node::SPtr DAGNode::createChild(const std::string& nodeName) +Node::SPtr Node::createChild(const std::string& nodeName) { - DAGNode::SPtr newchild; + Node::SPtr newchild; if (nodeName.empty()) { int i = 0; @@ -167,18 +150,18 @@ Node::SPtr DAGNode::createChild(const std::string& nodeName) } msg_error("Node::createChild()") << "Empty string given to property 'name': Forcefully setting an empty name is forbidden.\n" "Renaming to " + newName + " to avoid unexpected behaviors."; - newchild = sofa::core::objectmodel::New(newName); + newchild = sofa::core::objectmodel::New(newName); } else - newchild = sofa::core::objectmodel::New(nodeName); + newchild = sofa::core::objectmodel::New(nodeName); this->addChild(newchild); newchild->updateSimulationContext(); return newchild; } -void DAGNode::moveChild(BaseNode::SPtr node) +void Node::moveChild(BaseNode::SPtr node) { - const DAGNode::SPtr dagnode = sofa::core::objectmodel::SPtr_static_cast(node); + const Node::SPtr dagnode = sofa::core::objectmodel::SPtr_static_cast(node); for (const auto& parent : dagnode->getParents()) { Node::moveChild(node, parent); } @@ -186,9 +169,9 @@ void DAGNode::moveChild(BaseNode::SPtr node) /// Add a child node -void DAGNode::doAddChild(BaseNode::SPtr node) +void Node::doAddChild(BaseNode::SPtr node) { - const DAGNode::SPtr dagnode = sofa::core::objectmodel::SPtr_static_cast(node); + const Node::SPtr dagnode = sofa::core::objectmodel::SPtr_static_cast(node); setDirtyDescendancy(); child.add(dagnode); dagnode->l_parents.add(this); @@ -196,18 +179,18 @@ void DAGNode::doAddChild(BaseNode::SPtr node) } /// Remove a child -void DAGNode::doRemoveChild(BaseNode::SPtr node) +void Node::doRemoveChild(BaseNode::SPtr node) { - const DAGNode::SPtr dagnode = sofa::core::objectmodel::SPtr_static_cast(node); + const Node::SPtr dagnode = sofa::core::objectmodel::SPtr_static_cast(node); setDirtyDescendancy(); child.remove(dagnode); dagnode->l_parents.remove(this); } /// Move a node from another node -void DAGNode::doMoveChild(BaseNode::SPtr node, BaseNode::SPtr previous_parent) +void Node::doMoveChild(BaseNode::SPtr node, BaseNode::SPtr previous_parent) { - const DAGNode::SPtr dagnode = sofa::core::objectmodel::SPtr_static_cast(node); + const Node::SPtr dagnode = sofa::core::objectmodel::SPtr_static_cast(node); if (!dagnode) return; setDirtyDescendancy(); @@ -217,9 +200,9 @@ void DAGNode::doMoveChild(BaseNode::SPtr node, BaseNode::SPtr previous_parent) } /// Remove a child -void DAGNode::detachFromGraph() +void Node::detachFromGraph() { - DAGNode::SPtr me = this; // make sure we don't delete ourself before the end of this method + Node::SPtr me = this; // make sure we don't delete ourself before the end of this method const LinkParents::Container& parents = l_parents.getValue(); while(!parents.empty()) parents.back()->removeChild(this); @@ -228,7 +211,7 @@ void DAGNode::detachFromGraph() /// Generic object access, possibly searching up or down from the current context /// /// Note that the template wrapper method should generally be used to have the correct return type, -void* DAGNode::getObject(const sofa::core::objectmodel::ClassInfo& class_info, const sofa::core::objectmodel::TagSet& tags, SearchDirection dir) const +void* Node::getObject(const sofa::core::objectmodel::ClassInfo& class_info, const sofa::core::objectmodel::TagSet& tags, SearchDirection dir) const { if (dir == SearchRoot) { @@ -277,7 +260,7 @@ void* DAGNode::getObject(const sofa::core::objectmodel::ClassInfo& class_info, c } break; case SearchRoot: - dmsg_error("DAGNode") << "SearchRoot SHOULD NOT BE POSSIBLE HERE."; + dmsg_error("Node") << "SearchRoot SHOULD NOT BE POSSIBLE HERE."; break; } } @@ -288,7 +271,7 @@ void* DAGNode::getObject(const sofa::core::objectmodel::ClassInfo& class_info, c /// Generic object access, given a path from the current context /// /// Note that the template wrapper method should generally be used to have the correct return type, -void* DAGNode::getObject(const sofa::core::objectmodel::ClassInfo& class_info, const std::string& path) const +void* Node::getObject(const sofa::core::objectmodel::ClassInfo& class_info, const std::string& path) const { if (path.empty()) { @@ -355,7 +338,7 @@ void* DAGNode::getObject(const sofa::core::objectmodel::ClassInfo& class_info, c void* result = class_info.dynamicCast(obj); if (result == nullptr) { - dmsg_error("DAGNode") << "Object "<(this), class_info, container, tags); + GetUpObjectsVisitor vis( const_cast(this), class_info, container, tags); getRootContext()->executeVisitor(&vis); } break; @@ -406,7 +389,7 @@ void DAGNode::getObjects(const sofa::core::objectmodel::ClassInfo& class_info, G { // a regular visitor is enforcing the selected object unicity GetDownObjectsVisitor vis(class_info, container, tags); - (const_cast(this))->executeVisitor(&vis); + (const_cast(this))->executeVisitor(&vis); break; } default: @@ -415,7 +398,7 @@ void DAGNode::getObjects(const sofa::core::objectmodel::ClassInfo& class_info, G } /// Get a list of parent node -sofa::core::objectmodel::BaseNode::Parents DAGNode::getParents() const +sofa::core::objectmodel::BaseNode::Parents Node::getParents() const { Parents p; @@ -428,13 +411,13 @@ sofa::core::objectmodel::BaseNode::Parents DAGNode::getParents() const /// returns number of parents -size_t DAGNode::getNbParents() const +size_t Node::getNbParents() const { return l_parents.getValue().size(); } /// return the first parent (returns nullptr if no parent) -sofa::core::objectmodel::BaseNode* DAGNode::getFirstParent() const +sofa::core::objectmodel::BaseNode* Node::getFirstParent() const { const LinkParents::Container& parents = l_parents.getValue(); if( parents.empty() ) return nullptr; @@ -443,7 +426,7 @@ sofa::core::objectmodel::BaseNode* DAGNode::getFirstParent() const /// Test if the given node is a parent of this node. -bool DAGNode::hasParent(const BaseNode* node) const +bool Node::hasParent(const BaseNode* node) const { const LinkParents::Container& parents = l_parents.getValue(); for ( unsigned int i = 0; i < parents.size() ; ++i) @@ -454,7 +437,7 @@ bool DAGNode::hasParent(const BaseNode* node) const } /// Test if the given context is a parent of this context. -bool DAGNode::hasParent(const BaseContext* context) const +bool Node::hasParent(const BaseContext* context) const { if (context == nullptr) return !getNbParents(); @@ -469,7 +452,7 @@ bool DAGNode::hasParent(const BaseContext* context) const /// Test if the given context is an ancestor of this context. /// An ancestor is a parent or (recursively) the parent of an ancestor. -bool DAGNode::hasAncestor(const BaseContext* context) const +bool Node::hasAncestor(const BaseContext* context) const { const LinkParents::Container& parents = l_parents.getValue(); for ( unsigned int i = 0; i < parents.size() ; ++i) @@ -482,7 +465,7 @@ bool DAGNode::hasAncestor(const BaseContext* context) const /// Mesh Topology that is relevant for this context /// (within it or its parents until a mapping is reached that does not preserve topologies). -sofa::core::topology::BaseMeshTopology* DAGNode::getMeshTopologyLink(SearchDirection dir) const +sofa::core::topology::BaseMeshTopology* Node::getMeshTopologyLink(SearchDirection dir) const { if (this->meshTopology) return this->meshTopology; @@ -519,8 +502,7 @@ sofa::core::topology::BaseMeshTopology* DAGNode::getMeshTopologyLink(SearchDirec return nullptr; // not found in any parents } - -void DAGNode::precomputeTraversalOrder( const sofa::core::ExecParams* params ) +void Node::precomputeTraversalOrder( const sofa::core::ExecParams* params ) { // accumulating traversed Nodes class TraversalOrderVisitor : public Visitor @@ -536,7 +518,7 @@ void DAGNode::precomputeTraversalOrder( const sofa::core::ExecParams* params ) Result processNodeTopDown(Node* node) override { - _orderList.push_back( static_cast(node) ); + _orderList.push_back( static_cast(node) ); return RESULT_CONTINUE; } @@ -550,7 +532,7 @@ void DAGNode::precomputeTraversalOrder( const sofa::core::ExecParams* params ) /// Execute a recursive action starting from this node -void DAGNode::doExecuteVisitor(simulation::Visitor* action, bool precomputedOrder) +void Node::doExecuteVisitor(simulation::Visitor* action, bool precomputedOrder) { if( precomputedOrder && !_precomputedTraversalOrder.empty() ) { @@ -568,7 +550,7 @@ void DAGNode::doExecuteVisitor(simulation::Visitor* action, bool precomputedOrde } else { - // WARNING: do not store the traversal infos in the DAGNode, as several visitors could traversed the graph simultaneously + // WARNING: do not store the traversal infos in the Node, as several visitors could traversed the graph simultaneously // These infos are stored in a StatusMap per visitor. updateDescendancy(); @@ -612,7 +594,7 @@ void DAGNode::doExecuteVisitor(simulation::Visitor* action, bool precomputedOrde } -void DAGNode::executeVisitorTopDown(simulation::Visitor* action, NodeList& executedNodes, StatusMap& statusMap, DAGNode* visitorRoot ) +void Node::executeVisitorTopDown(simulation::Visitor* action, NodeList& executedNodes, StatusMap& statusMap, Node* visitorRoot ) { if ( statusMap[this] != NOT_VISITED ) { @@ -674,10 +656,10 @@ void DAGNode::executeVisitorTopDown(simulation::Visitor* action, NodeList& execu // ... but continue the recursion anyway! if( action->childOrderReversed(this) ) for(unsigned int i = unsigned(child.size()); i>0;) - static_cast(child[--i].get())->executeVisitorTopDown(action,executedNodes,statusMap,visitorRoot); + static_cast(child[--i].get())->executeVisitorTopDown(action,executedNodes,statusMap,visitorRoot); else for(unsigned int i = 0; i(child[i].get())->executeVisitorTopDown(action,executedNodes,statusMap,visitorRoot); + static_cast(child[i].get())->executeVisitorTopDown(action,executedNodes,statusMap,visitorRoot); } else { @@ -692,10 +674,10 @@ void DAGNode::executeVisitorTopDown(simulation::Visitor* action, NodeList& execu // ... and continue the recursion if( action->childOrderReversed(this) ) for(unsigned int i = unsigned(child.size()); i>0;) - static_cast(child[--i].get())->executeVisitorTopDown(action,executedNodes,statusMap,visitorRoot); + static_cast(child[--i].get())->executeVisitorTopDown(action,executedNodes,statusMap,visitorRoot); else for(unsigned int i = 0; i(child[i].get())->executeVisitorTopDown(action,executedNodes,statusMap,visitorRoot); + static_cast(child[i].get())->executeVisitorTopDown(action,executedNodes,statusMap,visitorRoot); } } @@ -704,7 +686,7 @@ void DAGNode::executeVisitorTopDown(simulation::Visitor* action, NodeList& execu // warning nodes that are dynamically created during the traversal, but that have not been traversed during the top-down, won't be traversed during the bottom-up // TODO is it what we want? // otherwise it is possible to restart from top, go to leaves and running bottom-up action while going up -void DAGNode::executeVisitorBottomUp( simulation::Visitor* action, NodeList& executedNodes ) +void Node::executeVisitorBottomUp( simulation::Visitor* action, NodeList& executedNodes ) { for( NodeList::reverse_iterator it = executedNodes.rbegin(), itend = executedNodes.rend() ; it != itend ; ++it ) { @@ -714,7 +696,7 @@ void DAGNode::executeVisitorBottomUp( simulation::Visitor* action, NodeList& exe } -void DAGNode::setDirtyDescendancy() +void Node::setDirtyDescendancy() { _descendancy.clear(); const LinkParents::Container &parents = l_parents.getValue(); @@ -724,13 +706,13 @@ void DAGNode::setDirtyDescendancy() } } -void DAGNode::updateDescendancy() +void Node::updateDescendancy() { if( _descendancy.empty() && !child.empty() ) { for(unsigned int i = 0; i(child[i].get()); + Node* dagnode = static_cast(child[i].get()); dagnode->updateDescendancy(); _descendancy.insert( dagnode->_descendancy.begin(), dagnode->_descendancy.end() ); _descendancy.insert( dagnode ); @@ -740,7 +722,7 @@ void DAGNode::updateDescendancy() -void DAGNode::executeVisitorTreeTraversal( simulation::Visitor* action, StatusMap& statusMap, Visitor::TreeTraversalRepetition repeat, bool alreadyRepeated ) +void Node::executeVisitorTreeTraversal( simulation::Visitor* action, StatusMap& statusMap, Visitor::TreeTraversalRepetition repeat, bool alreadyRepeated ) { if( !this->isActive() ) { @@ -768,10 +750,10 @@ void DAGNode::executeVisitorTreeTraversal( simulation::Visitor* action, StatusMa statusMap[this] = VISITED; if( action->childOrderReversed(this) ) for(unsigned int i = unsigned(child.size()); i>0;) - static_cast(child[--i].get())->executeVisitorTreeTraversal(action,statusMap,repeat,alreadyRepeated); + static_cast(child[--i].get())->executeVisitorTreeTraversal(action,statusMap,repeat,alreadyRepeated); else for(unsigned int i = 0; i(child[i].get())->executeVisitorTreeTraversal(action,statusMap,repeat,alreadyRepeated); + static_cast(child[i].get())->executeVisitorTreeTraversal(action,statusMap,repeat,alreadyRepeated); } else { @@ -782,7 +764,7 @@ void DAGNode::executeVisitorTreeTraversal( simulation::Visitor* action, StatusMa } -void DAGNode::initVisualContext() +void Node::initVisualContext() { if (getNbParents()) { @@ -790,7 +772,7 @@ void DAGNode::initVisualContext() } } -void DAGNode::updateContext() +void Node::updateContext() { sofa::core::objectmodel::BaseNode* firstParent = getFirstParent(); @@ -798,16 +780,16 @@ void DAGNode::updateContext() { if( debug_ ) { - msg_info()<<"DAGNode::updateContext, node = "< DAGNodeClass("DAGNode"); +//helper::Creator NodeDefaultClass("default"); +static helper::Creator NodeClass("Node"); } // namespace sofa::simulation::graph diff --git a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGNode.h b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGNode.h index d258e206705..16042bd4764 100644 --- a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGNode.h +++ b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGNode.h @@ -22,203 +22,8 @@ #pragma once #include #include -#include -#include namespace sofa::simulation::graph { - -/** Define the structure of the scene as a Directed Acyclic Graph. Contains component objects (as pointer lists) and parents/childs (as DAGNode objects). - * - * The visitor traversal is performed in two passes: - * - a complete top-down traversal - * - then a complete bottom-up traversal in the exact invert order than the top-down traversal - * NB: contrary to the "tree" traversal, there are no interlinked forward/backward callbacks. There are only forward then only backward callbacks. - * - * Note that nodes created during a traversal are not traversed if they are created upper than the current node during the top-down traversal or if they are created during the bottom-up traversal. - */ -class SOFA_SIMULATION_GRAPH_API DAGNode : public simulation::Node -{ -public: - typedef Node::DisplayFlags DisplayFlags; - SOFA_CLASS(DAGNode, simulation::Node); - - typedef MultiLink LinkParents; - typedef LinkParents::const_iterator ParentIterator; - - -protected: - DAGNode( const std::string& name="", DAGNode* parent=nullptr ); - - virtual ~DAGNode() override; - -public: - static const std::string GetCustomClassName(){ return "Node"; } - - /// Pure Virtual method from Node - virtual Node::SPtr createChild(const std::string& nodeName) override; - - /// Remove the current node from the graph: consists in removing the link to its parent - void detachFromGraph() override; - - /// Get a list of parent node - Parents getParents() const override; - - /// returns number of parents - size_t getNbParents() const override; - - /// return the first parent (returns nullptr if no parent) - BaseNode* getFirstParent() const override; - - /// Test if the given node is a parent of this node. - bool hasParent(const BaseNode* node) const override; - - /// Test if the given context is a parent of this context. - bool hasParent(const BaseContext* context) const; - - /// Test if the given context is an ancestor of this context. - /// An ancestor is a parent or (recursively) the parent of an ancestor. - bool hasAncestor(const BaseNode* node) const override - { - return hasAncestor(node->getContext()); - } - - /// Test if the given context is an ancestor of this context. - /// An ancestor is a parent or (recursively) the parent of an ancestor. - bool hasAncestor(const BaseContext* context) const override; - - - /// Generic object access, given a set of required tags, possibly searching up or down from the current context - /// - /// Note that the template wrapper method should generally be used to have the correct return type, - void* getObject(const sofa::core::objectmodel::ClassInfo& class_info, const sofa::core::objectmodel::TagSet& tags, SearchDirection dir = SearchUp) const override; - - /// Generic object access, given a path from the current context - /// - /// Note that the template wrapper method should generally be used to have the correct return type, - void* getObject(const sofa::core::objectmodel::ClassInfo& class_info, const std::string& path) const override; - - /// Generic list of objects access, given a set of required tags, possibly searching up or down from the current context - /// - /// Note that the template wrapper method should generally be used to have the correct return type, - void getObjects(const sofa::core::objectmodel::ClassInfo& class_info, GetObjectsCallBack& container, const sofa::core::objectmodel::TagSet& tags, SearchDirection dir = SearchUp) const override; - - - /// Mesh Topology that is relevant for this context - /// (within it or its parents until a mapping is reached that does not preserve topologies). - sofa::core::topology::BaseMeshTopology* getMeshTopologyLink(SearchDirection dir = SearchUp) const override; - - - /// Called during initialization to correctly propagate the visual context to the children - void initVisualContext() override; - - /// Update the whole context values, based on parent and local ContextObjects - void updateContext() override; - - /// Update the simulation context values(gravity, time...), based on parent and local ContextObjects - void updateSimulationContext() override; - - static DAGNode::SPtr create(DAGNode*, sofa::core::objectmodel::BaseObjectDescription* arg) - { - DAGNode::SPtr obj = DAGNode::SPtr(new DAGNode()); - obj->parse(arg); - return obj; - } - - - /// return the smallest common parent between this and node2 (returns nullptr if separated sub-graphes) - /// it assumes that the DAG node is a tree node. In case of multiple parents it returns any of the parents. - /// it uses the node descendancy information. - Node* findCommonParent( Node* node2 ) override; - - /// compute the traversal order from this Node - void precomputeTraversalOrder( const sofa::core::ExecParams* params ) override; - - virtual void moveChild(BaseNode::SPtr node) override; - -protected: - - /// bottom-up traversal, returning the first node which have a descendancy containing both node1 & node2 - DAGNode* findCommonParent( DAGNode* node1, DAGNode* node2 ); - - - LinkParents l_parents; - - - virtual void doAddChild(BaseNode::SPtr node) override; - virtual void doRemoveChild(BaseNode::SPtr node) override; - virtual void doMoveChild(BaseNode::SPtr node, BaseNode::SPtr previous_parent) override; - - - /// Execute a recursive action starting from this node. - void doExecuteVisitor(simulation::Visitor* action, bool precomputedOrder=false) override; - - - /// @name @internal stuff related to the DAG traversal - /// @{ - - - /// all child nodes (unordered) - std::set _descendancy; - - /// bottom-up traversal removing descendancy - void setDirtyDescendancy(); - - /// traversal updating the descendancy - void updateDescendancy(); - - /// traversal flags - typedef enum - { - NOT_VISITED=0, - VISITED, - PRUNED - } VisitedStatus; - - - - /// wrapper to use VisitedStatus in a std::map (to ensure the default map insertion will give NOT_VISITED) - struct StatusStruct - { - StatusStruct() : status(NOT_VISITED) {} - StatusStruct( const VisitedStatus& s ) : status(s) {} - inline void operator=( const VisitedStatus& s ) { status=s; } - inline bool operator==( const VisitedStatus& s ) const { return status==s; } - inline bool operator==( const StatusStruct& s ) const { return status==s.status; } - inline bool operator!=( const VisitedStatus& s ) const { return status!=s; } - inline bool operator!=( const StatusStruct& s ) const { return status!=s.status; } - VisitedStatus status; - }; - - /// map structure to store a traversal flag for each DAGNode - typedef std::map StatusMap; - - /// list of DAGNode* - typedef std::list NodeList; - - /// the ordered list of Node to traverse from this Node - NodeList _precomputedTraversalOrder; - - /// @internal performing only the top-down traversal on a DAG - /// @executedNodes will be fill with the DAGNodes where the top-down action is processed - /// @statusMap the visitor's flag map - /// @visitorRoot node from where the visitor has been run - void executeVisitorTopDown(simulation::Visitor* action, NodeList& executedNodes, StatusMap& statusMap, DAGNode* visitorRoot ); - void executeVisitorBottomUp(simulation::Visitor* action, NodeList& executedNodes ); - /// @} - - /// @internal tree traversal implementation - void executeVisitorTreeTraversal( Visitor* action, StatusMap& statusMap, Visitor::TreeTraversalRepetition repeat, bool alreadyRepeated=false ); - - /// @name @internal stuff related to getObjects - /// @{ - - /// get node's local objects respecting specified class_info and tags - void getLocalObjects( const sofa::core::objectmodel::ClassInfo& class_info, DAGNode::GetObjectsCallBack& container, const sofa::core::objectmodel::TagSet& tags ) const ; - - friend class GetDownObjectsVisitor ; - friend class GetUpObjectsVisitor ; - /// @} -}; - + using DAGNode = sofa::simulation::Node; } // namespace sofa::simulation::graph From 8f897b8d010d6fccb49adc640c98b15e7decd013 Mon Sep 17 00:00:00 2001 From: Damien Marchal Date: Fri, 27 Jun 2025 12:59:06 +0200 Subject: [PATCH 02/19] Use Node in place of DAGNode in sofa's code. --- .../Collision/Geometry/tests/Sphere_test.cpp | 16 +- .../Geometry/tests/Triangle_test.cpp | 6 +- .../Response/Mapper/tests/BaryMapper_test.cpp | 6 +- .../LinearSystem/tests/MappingGraph_test.cpp | 10 +- .../tests/MatrixLinearSystem_test.cpp | 8 +- .../Helper/test/system/PluginManager_test.cpp | 4 +- .../src/sofa/simpleapi/SimpleApi.cpp | 6 +- .../Core/src/sofa/simulation/Node.h | 155 +++++++++--------- .../framework/Simulation/Graph/CMakeLists.txt | 2 +- .../sofa/simulation/graph/DAGSimulation.cpp | 2 +- .../graph/{DAGNode.cpp => NodeDagImpl.cpp} | 0 .../Simulation/Graph/test/CMakeLists.txt | 2 +- .../Simulation/Graph/test/DAGNode_test.cpp | 36 ++-- .../Simulation/Graph/test/DAG_test.cpp | 16 +- .../Graph/test/MutationListener_test.cpp | 32 ++-- .../SceneCreatorBenchmarks.cpp | 2 +- 16 files changed, 148 insertions(+), 155 deletions(-) rename Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/{DAGNode.cpp => NodeDagImpl.cpp} (100%) diff --git a/Sofa/Component/Collision/Geometry/tests/Sphere_test.cpp b/Sofa/Component/Collision/Geometry/tests/Sphere_test.cpp index 9f5e300a56c..8f14b6da125 100644 --- a/Sofa/Component/Collision/Geometry/tests/Sphere_test.cpp +++ b/Sofa/Component/Collision/Geometry/tests/Sphere_test.cpp @@ -58,7 +58,7 @@ using sofa::helper::logging::MessageDispatcher ; #include using sofa::helper::logging::ClangMessageHandler ; -#include +#include #include using sofa::testing::BaseSimulationTest; @@ -101,7 +101,7 @@ bool TestSphere::rigidRigid1(){ angles[1] = 0; angles[2] = 0; - Node::SPtr scn = New(); + Node::SPtr scn = New(); //the center of this OBB is (0,0,-1) and its extent is 1 //we construct the falling sphere @@ -157,7 +157,7 @@ bool TestSphere::rigidRigid2(){ angles_2[1] = 0; angles_2[2] = 0; - Node::SPtr scn = New(); + Node::SPtr scn = New(); //the center of this OBB is (0,0,-1) and its extent is 1 //we construct the falling sphere @@ -204,7 +204,7 @@ bool TestSphere::rigidSoft2(){ angles[1] = M_PI/4; angles[2] = M_PI/3; - Node::SPtr scn = New(); + Node::SPtr scn = New(); //the center of this OBB is (0,0,-1) and its extent is 1 //we construct the falling sphere @@ -251,7 +251,7 @@ bool TestSphere::rigidSoft1(){ angles[1] = 0; angles[2] = 0; - Node::SPtr scn = New(); + Node::SPtr scn = New(); //the center of this OBB is (0,0,-1) and its extent is 1 //we construct the falling sphere @@ -299,7 +299,7 @@ bool TestSphere::rigidSoft3(){ angles[1] = M_PI/4; angles[2] = M_PI/3; - Node::SPtr scn = New(); + Node::SPtr scn = New(); //the center of this OBB is (0,0,-1) and its extent is 1 //we construct the falling sphere @@ -346,7 +346,7 @@ bool TestSphere::rigidSoft4(){ angles[1] = 0; angles[2] = 0; - Node::SPtr scn = New(); + Node::SPtr scn = New(); //the center of this OBB is (0,0,-1) and its extent is 1 //we construct the falling sphere @@ -384,7 +384,7 @@ bool TestSphere::rigidSoft4(){ bool TestSphere::softSoft1(){ - Node::SPtr scn = New(); + Node::SPtr scn = New(); //the center of this OBB is (0,0,-1) and its extent is 1 //we construct the falling sphere diff --git a/Sofa/Component/Collision/Geometry/tests/Triangle_test.cpp b/Sofa/Component/Collision/Geometry/tests/Triangle_test.cpp index e6f8567a262..0727f317683 100644 --- a/Sofa/Component/Collision/Geometry/tests/Triangle_test.cpp +++ b/Sofa/Component/Collision/Geometry/tests/Triangle_test.cpp @@ -47,7 +47,7 @@ using sofa::helper::logging::MessageDispatcher; #include using sofa::testing::BaseTest; -#include +#include #include #include @@ -82,7 +82,7 @@ bool TestTriangle::rigidTriangle(sofa::component::collision::detection::intersec angles[1] = 0; angles[2] = 0; - Node::SPtr scn = New(); + Node::SPtr scn = New(); //the center of this OBB is (0,0,-1) and its extent is 1 //we construct the falling sphere @@ -121,7 +121,7 @@ bool TestTriangle::rigidTriangle(sofa::component::collision::detection::intersec template bool TestTriangle::softTriangle(sofa::component::collision::detection::intersection::BaseProximityIntersection::SPtr intersectionMethod, Intersector& bi) { - Node::SPtr scn = New(); + Node::SPtr scn = New(); //the center of this OBB is (0,0,-1) and its extent is 1 //we construct the falling sphere diff --git a/Sofa/Component/Collision/Response/Mapper/tests/BaryMapper_test.cpp b/Sofa/Component/Collision/Response/Mapper/tests/BaryMapper_test.cpp index aa69dc976da..08d4c4b4866 100644 --- a/Sofa/Component/Collision/Response/Mapper/tests/BaryMapper_test.cpp +++ b/Sofa/Component/Collision/Response/Mapper/tests/BaryMapper_test.cpp @@ -20,7 +20,7 @@ * Contact information: contact@sofa-framework.org * ******************************************************************************/ -#include +#include #include #include #include @@ -84,7 +84,7 @@ MeshTopology* BaryMapperTest::initMesh(NodePtr &father){ bool BaryMapperTest::test_inside(SReal alpha,SReal beta){ initTriPts(); - sofa::simulation::Node::SPtr father = New(); + sofa::simulation::Node::SPtr father = New(); MeshTopology * topo = initMesh(father); //makeTri() const component::mapping::linear::BarycentricMapperMeshTopology::SPtr mapper = sofa::core::objectmodel::New >(topo, (component::topology::container::dynamic::PointSetTopologyContainer*)0x0); @@ -103,7 +103,7 @@ bool BaryMapperTest::test_inside(SReal alpha,SReal beta){ bool BaryMapperTest::test_outside(int index){ initTriPts(); - sofa::simulation::Node::SPtr father = New(); + sofa::simulation::Node::SPtr father = New(); MeshTopology * topo = initMesh(father); //makeTri() const component::mapping::linear::BarycentricMapperMeshTopology::SPtr mapper = sofa::core::objectmodel::New >(topo,(component::topology::container::dynamic::PointSetTopologyContainer*)0x0); diff --git a/Sofa/Component/LinearSystem/tests/MappingGraph_test.cpp b/Sofa/Component/LinearSystem/tests/MappingGraph_test.cpp index e0c21d2a512..7de0406d2b5 100644 --- a/Sofa/Component/LinearSystem/tests/MappingGraph_test.cpp +++ b/Sofa/Component/LinearSystem/tests/MappingGraph_test.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -65,7 +65,7 @@ TEST(MappingGraph, nullRootNode) TEST(MappingGraph, emptyRootNode) { - const sofa::simulation::Node::SPtr root = sofa::core::objectmodel::New(); + const sofa::simulation::Node::SPtr root = sofa::core::objectmodel::New(); sofa::component::linearsystem::MappingGraph graph; graph.build(sofa::core::MechanicalParams::defaultInstance(), root.get()); @@ -85,7 +85,7 @@ TEST(MappingGraph, emptyRootNode) TEST(MappingGraph, oneMechanicalObject) { - const sofa::simulation::Node::SPtr root = sofa::core::objectmodel::New(); + const sofa::simulation::Node::SPtr root = sofa::core::objectmodel::New(); const auto mstate = sofa::core::objectmodel::New >(); root->addObject(mstate); @@ -107,7 +107,7 @@ TEST(MappingGraph, oneMechanicalObject) TEST(MappingGraph, twoMechanicalObject) { - const sofa::simulation::Node::SPtr root = sofa::core::objectmodel::New(); + const sofa::simulation::Node::SPtr root = sofa::core::objectmodel::New(); const auto mstate1 = sofa::core::objectmodel::New >(); root->addObject(mstate1); @@ -135,7 +135,7 @@ TEST(MappingGraph, twoMechanicalObject) TEST(MappingGraph, oneMapping) { - const sofa::simulation::Node::SPtr root = sofa::core::objectmodel::New(); + const sofa::simulation::Node::SPtr root = sofa::core::objectmodel::New(); const auto mstate1 = sofa::core::objectmodel::New >(); root->addObject(mstate1); diff --git a/Sofa/Component/LinearSystem/tests/MatrixLinearSystem_test.cpp b/Sofa/Component/LinearSystem/tests/MatrixLinearSystem_test.cpp index c8163bfdb3d..104a062297a 100644 --- a/Sofa/Component/LinearSystem/tests/MatrixLinearSystem_test.cpp +++ b/Sofa/Component/LinearSystem/tests/MatrixLinearSystem_test.cpp @@ -30,7 +30,7 @@ #include #include -#include +#include #include #include @@ -62,7 +62,7 @@ TEST(LinearSystem, MatrixSystem_noContext) TEST(LinearSystem, MatrixSystem) { - const sofa::simulation::Node::SPtr root = sofa::core::objectmodel::New(); + const sofa::simulation::Node::SPtr root = sofa::core::objectmodel::New(); using MatrixType = sofa::linearalgebra::CompressedRowSparseMatrix; using MatrixSystem = sofa::component::linearsystem::MatrixLinearSystem >; @@ -92,7 +92,7 @@ TEST(LinearSystem, MatrixSystem_springForceField) // required to be able to use EXPECT_MSG_NOEMIT and EXPECT_MSG_EMIT sofa::helper::logging::MessageDispatcher::addHandler(sofa::testing::MainGtestMessageHandler::getInstance() ) ; - sofa::simulation::Node::SPtr root = sofa::core::objectmodel::New(); + sofa::simulation::Node::SPtr root = sofa::core::objectmodel::New(); using MatrixType = sofa::linearalgebra::FullMatrix; using MatrixSystem = sofa::component::linearsystem::MatrixLinearSystem >; @@ -332,7 +332,7 @@ TEST(LinearSystem, MatrixSystem_buggyForceField) // required to be able to use EXPECT_MSG_NOEMIT and EXPECT_MSG_EMIT sofa::helper::logging::MessageDispatcher::addHandler(sofa::testing::MainGtestMessageHandler::getInstance() ) ; - const sofa::simulation::Node::SPtr root = sofa::core::objectmodel::New(); + const sofa::simulation::Node::SPtr root = sofa::core::objectmodel::New(); using MatrixSystem = sofa::component::linearsystem::MatrixLinearSystem >; const MatrixSystem::SPtr linearSystem = sofa::core::objectmodel::New(); diff --git a/Sofa/framework/Helper/test/system/PluginManager_test.cpp b/Sofa/framework/Helper/test/system/PluginManager_test.cpp index c27aee28fe9..453c9ccb243 100644 --- a/Sofa/framework/Helper/test/system/PluginManager_test.cpp +++ b/Sofa/framework/Helper/test/system/PluginManager_test.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include using sofa::testing::BaseTest; @@ -319,7 +319,7 @@ TEST_F(PluginManager_test, failingPlugin) EXPECT_TRUE(sofa::core::ObjectFactory::getInstance()->hasCreator("ComponentFailingPlugin")); sofa::core::objectmodel::BaseObjectDescription description("ComponentFailingPlugin", "ComponentFailingPlugin"); - const auto tmpNode = sofa::core::objectmodel::New("tmp"); + const auto tmpNode = sofa::core::objectmodel::New("tmp"); EXPECT_EQ(sofa::core::ObjectFactory::getInstance()->createObject(tmpNode.get(), &description), nullptr); EXPECT_FALSE(description.getErrors().empty()); diff --git a/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.cpp b/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.cpp index 4d0935ab8c9..63555fcb1d4 100644 --- a/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.cpp +++ b/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.cpp @@ -29,8 +29,8 @@ using sofa::core::ObjectFactory ; #include using sofa::simulation::graph::DAGSimulation ; -#include -using sofa::simulation::graph::DAGNode; +#include +using sofa::simulation::Node; using sofa::core::objectmodel::BaseObjectDescription ; #include @@ -144,7 +144,7 @@ Node::SPtr createChild(Node::SPtr node, BaseObjectDescription& desc) Node::SPtr createNode(const std::string& name) { - return core::objectmodel::New(name); + return core::objectmodel::New(name); } } // namespace sofa::simpleapi diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.h index 8ef3261dec6..46c640679c2 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.h @@ -290,6 +290,7 @@ class SOFA_SIMULATION_CORE_API Node : public sofa::core::objectmodel::BaseNode, /// Generic object access, given a set of required tags, possibly searching up or down from the current context /// + /// Note that the template wrapper method should generally be used to have the correct return type, void* getObject(const sofa::core::objectmodel::ClassInfo& class_info, SearchDirection dir = SearchUp) const override { @@ -304,6 +305,9 @@ class SOFA_SIMULATION_CORE_API Node : public sofa::core::objectmodel::BaseNode, getObjects(class_info, container, sofa::core::objectmodel::TagSet(), dir); } + /// get node's local objects respecting specified class_info and tags + void getLocalObjects( const sofa::core::objectmodel::ClassInfo& class_info, Node::GetObjectsCallBack& container, const sofa::core::objectmodel::TagSet& tags ) const ; + /// List all objects of this node deriving from a given class template void getNodeObjects(Container* list) @@ -486,6 +490,75 @@ class SOFA_SIMULATION_CORE_API Node : public sofa::core::objectmodel::BaseNode, /// override context setSleeping to add notification. void setSleeping(bool val) override; +public: + virtual void addListener(MutationListener* obj); + virtual void removeListener(MutationListener* obj); + + static const std::string GetCustomClassName(){ return "Node"; } + + Node::SPtr createChild(const std::string& nodeName); + + /// Remove the current node from the graph: consists in removing the link to its parent + void detachFromGraph() override; + + /// Get a list of parent node + Parents getParents() const override; + + /// returns number of parents + size_t getNbParents() const override; + + /// return the first parent (returns nullptr if no parent) + BaseNode* getFirstParent() const override; + + /// Test if the given node is a parent of this node. + bool hasParent(const BaseNode* node) const override; + + /// Test if the given context is a parent of this context. + bool hasParent(const BaseContext* context) const; + + /// Test if the given context is an ancestor of this context. + /// An ancestor is a parent or (recursively) the parent of an ancestor. + bool hasAncestor(const BaseNode* node) const override + { + return hasAncestor(node->getContext()); + } + + /// Test if the given context is an ancestor of this context. + /// An ancestor is a parent or (recursively) the parent of an ancestor. + bool hasAncestor(const BaseContext* context) const override; + + + /// Generic object access, given a set of required tags, possibly searching up or down from the current context + /// + /// Note that the template wrapper method should generally be used to have the correct return type, + void* getObject(const sofa::core::objectmodel::ClassInfo& class_info, const sofa::core::objectmodel::TagSet& tags, SearchDirection dir = SearchUp) const override; + + /// Generic object access, given a path from the current context + /// + /// Note that the template wrapper method should generally be used to have the correct return type, + void* getObject(const sofa::core::objectmodel::ClassInfo& class_info, const std::string& path) const override; + + /// Generic list of objects access, given a set of required tags, possibly searching up or down from the current context + /// + /// Note that the template wrapper method should generally be used to have the correct return type, + void getObjects(const sofa::core::objectmodel::ClassInfo& class_info, GetObjectsCallBack& container, const sofa::core::objectmodel::TagSet& tags, SearchDirection dir = SearchUp) const override; + + /// Mesh Topology that is relevant for this context + /// (within it or its parents until a mapping is reached that does not preserve topologies). + sofa::core::topology::BaseMeshTopology* NODEgetMeshTopologyLink(SearchDirection dir = SearchUp) const; + + static Node::SPtr create(Node*, sofa::core::objectmodel::BaseObjectDescription* arg) + { + Node::SPtr obj = Node::SPtr(new Node()); + obj->parse(arg); + return obj; + } + + void moveChild(BaseNode::SPtr node) override; + + /// return the smallest common parent between this and node2 (returns nullptr if separated sub-graphes) + Node* findCommonParent( simulation::Node* node2 ); + protected: bool debug_; bool initialized; @@ -495,6 +568,7 @@ class SOFA_SIMULATION_CORE_API Node : public sofa::core::objectmodel::BaseNode, virtual void doMoveObject(sofa::core::objectmodel::BaseObject::SPtr sobj, Node* prev_parent); std::stack actionStack; + private: virtual void notifyBeginAddChild(Node::SPtr parent, Node::SPtr child) const; virtual void notifyBeginRemoveChild(Node::SPtr parent, Node::SPtr child) const; @@ -522,11 +596,6 @@ class SOFA_SIMULATION_CORE_API Node : public sofa::core::objectmodel::BaseNode, type::vector listener; - -public: - virtual void addListener(MutationListener* obj); - virtual void removeListener(MutationListener* obj); - /// @name virtual functions to add/remove some special components directly in the right Sequence /// @{ @@ -576,73 +645,7 @@ class SOFA_SIMULATION_CORE_API Node : public sofa::core::objectmodel::BaseNode, typedef MultiLink LinkParents; typedef LinkParents::const_iterator ParentIterator; -public: - static const std::string GetCustomClassName(){ return "Node"; } - - Node::SPtr createChild(const std::string& nodeName); - - /// Remove the current node from the graph: consists in removing the link to its parent - void detachFromGraph() override; - - /// Get a list of parent node - Parents getParents() const override; - - /// returns number of parents - size_t getNbParents() const override; - - /// return the first parent (returns nullptr if no parent) - BaseNode* getFirstParent() const override; - - /// Test if the given node is a parent of this node. - bool hasParent(const BaseNode* node) const override; - - /// Test if the given context is a parent of this context. - bool hasParent(const BaseContext* context) const; - - /// Test if the given context is an ancestor of this context. - /// An ancestor is a parent or (recursively) the parent of an ancestor. - bool hasAncestor(const BaseNode* node) const override - { - return hasAncestor(node->getContext()); - } - - /// Test if the given context is an ancestor of this context. - /// An ancestor is a parent or (recursively) the parent of an ancestor. - bool hasAncestor(const BaseContext* context) const override; - - - /// Generic object access, given a set of required tags, possibly searching up or down from the current context - /// - /// Note that the template wrapper method should generally be used to have the correct return type, - void* getObject(const sofa::core::objectmodel::ClassInfo& class_info, const sofa::core::objectmodel::TagSet& tags, SearchDirection dir = SearchUp) const override; - - /// Generic object access, given a path from the current context - /// - /// Note that the template wrapper method should generally be used to have the correct return type, - void* getObject(const sofa::core::objectmodel::ClassInfo& class_info, const std::string& path) const override; - - /// Generic list of objects access, given a set of required tags, possibly searching up or down from the current context - /// - /// Note that the template wrapper method should generally be used to have the correct return type, - void getObjects(const sofa::core::objectmodel::ClassInfo& class_info, GetObjectsCallBack& container, const sofa::core::objectmodel::TagSet& tags, SearchDirection dir = SearchUp) const override; - - /// Mesh Topology that is relevant for this context - /// (within it or its parents until a mapping is reached that does not preserve topologies). - sofa::core::topology::BaseMeshTopology* NODEgetMeshTopologyLink(SearchDirection dir = SearchUp) const; - - static Node::SPtr create(Node*, sofa::core::objectmodel::BaseObjectDescription* arg) - { - Node::SPtr obj = Node::SPtr(new Node()); - obj->parse(arg); - return obj; - } - - void moveChild(BaseNode::SPtr node) override; - - /// return the smallest common parent between this and node2 (returns nullptr if separated sub-graphes) - Node* findCommonParent( simulation::Node* node2 ); - -protected: +private: /// bottom-up traversal, returning the first node which have a descendancy containing both node1 & node2 Node* findCommonParent( Node* node1, Node* node2 ); @@ -655,11 +658,9 @@ class SOFA_SIMULATION_CORE_API Node : public sofa::core::objectmodel::BaseNode, /// Execute a recursive action starting from this node. void doExecuteVisitor(simulation::Visitor* action, bool precomputedOrder=false); - /// @name @internal stuff related to the DAG traversal /// @{ - /// all child nodes (unordered) std::set _descendancy; @@ -677,8 +678,6 @@ class SOFA_SIMULATION_CORE_API Node : public sofa::core::objectmodel::BaseNode, PRUNED } VisitedStatus; - - /// wrapper to use VisitedStatus in a std::map (to ensure the default map insertion will give NOT_VISITED) struct StatusStruct { @@ -714,10 +713,6 @@ class SOFA_SIMULATION_CORE_API Node : public sofa::core::objectmodel::BaseNode, /// @name @internal stuff related to getObjects /// @{ - - /// get node's local objects respecting specified class_info and tags - void getLocalObjects( const sofa::core::objectmodel::ClassInfo& class_info, Node::GetObjectsCallBack& container, const sofa::core::objectmodel::TagSet& tags ) const ; - friend class GetDownObjectsVisitor ; friend class GetUpObjectsVisitor ; /// @} diff --git a/Sofa/framework/Simulation/Graph/CMakeLists.txt b/Sofa/framework/Simulation/Graph/CMakeLists.txt index b3d07bd5a51..31d593432f0 100644 --- a/Sofa/framework/Simulation/Graph/CMakeLists.txt +++ b/Sofa/framework/Simulation/Graph/CMakeLists.txt @@ -14,7 +14,7 @@ set(HEADER_FILES set(SOURCE_FILES ${SOFASIMULATIONGRAPH_SRC}/init.cpp ${SOFASIMULATIONGRAPH_SRC}/initSofaSimulationGraph.cpp - ${SOFASIMULATIONGRAPH_SRC}/DAGNode.cpp + ${SOFASIMULATIONGRAPH_SRC}/NodeDagImpl.cpp ${SOFASIMULATIONGRAPH_SRC}/DAGSimulation.cpp ) diff --git a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.cpp b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.cpp index 7a351f1075a..baa0bbf1a22 100644 --- a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.cpp +++ b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.cpp @@ -54,7 +54,7 @@ Node::SPtr DAGSimulation::createNewGraph(const std::string& name) Node::SPtr DAGSimulation::createNewNode(const std::string& name) { - return sofa::core::objectmodel::New(name); + return sofa::core::objectmodel::New(name); } } // namespace sofa::simulation::graph diff --git a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGNode.cpp b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/NodeDagImpl.cpp similarity index 100% rename from Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGNode.cpp rename to Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/NodeDagImpl.cpp diff --git a/Sofa/framework/Simulation/Graph/test/CMakeLists.txt b/Sofa/framework/Simulation/Graph/test/CMakeLists.txt index de06e21da16..7c8fcc01857 100644 --- a/Sofa/framework/Simulation/Graph/test/CMakeLists.txt +++ b/Sofa/framework/Simulation/Graph/test/CMakeLists.txt @@ -7,7 +7,7 @@ set(HEADER_FILES set(SOURCE_FILES DAG_test.cpp - DAGNode_test.cpp + Node_test.cpp MutationListener_test.cpp Node_test.cpp Simulation_test.cpp diff --git a/Sofa/framework/Simulation/Graph/test/DAGNode_test.cpp b/Sofa/framework/Simulation/Graph/test/DAGNode_test.cpp index 3c629dc074b..3fd22f68dff 100644 --- a/Sofa/framework/Simulation/Graph/test/DAGNode_test.cpp +++ b/Sofa/framework/Simulation/Graph/test/DAGNode_test.cpp @@ -22,24 +22,24 @@ #include using sofa::testing::BaseTest; -#include +#include using namespace sofa; using namespace simulation::graph; -struct DAGNode_test : public BaseTest +struct Node_test : public BaseTest { - DAGNode_test() {} + Node_test() {} void test_findCommonParent() { - const DAGNode::SPtr root = core::objectmodel::New("root"); - const DAGNode::SPtr node1 = core::objectmodel::New("node1"); - const DAGNode::SPtr node2 = core::objectmodel::New("node2"); - const DAGNode::SPtr node3 = core::objectmodel::New("node3"); - const DAGNode::SPtr node11 = core::objectmodel::New("node11"); - const DAGNode::SPtr node12 = core::objectmodel::New("node12"); - const DAGNode::SPtr node31 = core::objectmodel::New("node31"); + const Node::SPtr root = core::objectmodel::New("root"); + const Node::SPtr node1 = core::objectmodel::New("node1"); + const Node::SPtr node2 = core::objectmodel::New("node2"); + const Node::SPtr node3 = core::objectmodel::New("node3"); + const Node::SPtr node11 = core::objectmodel::New("node11"); + const Node::SPtr node12 = core::objectmodel::New("node12"); + const Node::SPtr node31 = core::objectmodel::New("node31"); root->addChild(node1); root->addChild(node2); @@ -62,12 +62,12 @@ struct DAGNode_test : public BaseTest void test_findCommonParent_MultipleParents() { - const DAGNode::SPtr root = core::objectmodel::New("root"); - const DAGNode::SPtr node1 = core::objectmodel::New("node1"); - const DAGNode::SPtr node2 = core::objectmodel::New("node2"); - const DAGNode::SPtr node11 = core::objectmodel::New("node11"); - const DAGNode::SPtr node22 = core::objectmodel::New("node22"); - const DAGNode::SPtr node23 = core::objectmodel::New("node23"); + const Node::SPtr root = core::objectmodel::New("root"); + const Node::SPtr node1 = core::objectmodel::New("node1"); + const Node::SPtr node2 = core::objectmodel::New("node2"); + const Node::SPtr node11 = core::objectmodel::New("node11"); + const Node::SPtr node22 = core::objectmodel::New("node22"); + const Node::SPtr node23 = core::objectmodel::New("node23"); root->addChild(node1); root->addChild(node2); @@ -93,5 +93,5 @@ struct DAGNode_test : public BaseTest } }; -TEST_F(DAGNode_test, test_findCommonParent) { test_findCommonParent(); } -TEST_F(DAGNode_test, test_findCommonParent_MultipleParents) { test_findCommonParent_MultipleParents(); } +TEST_F(Node_test, test_findCommonParent) { test_findCommonParent(); } +TEST_F(Node_test, test_findCommonParent_MultipleParents) { test_findCommonParent_MultipleParents(); } diff --git a/Sofa/framework/Simulation/Graph/test/DAG_test.cpp b/Sofa/framework/Simulation/Graph/test/DAG_test.cpp index 3cf4a4ea1a5..5984c42a507 100644 --- a/Sofa/framework/Simulation/Graph/test/DAG_test.cpp +++ b/Sofa/framework/Simulation/Graph/test/DAG_test.cpp @@ -377,29 +377,29 @@ TEST_F( DAG_test, traverse ) traverse_morecomplex2(); } -TEST(DAGNodeTest, objectDestruction_singleObject) +TEST(NodeTest, objectDestruction_singleObject) { EXPECT_MSG_NOEMIT(Error) ; - Node_test_objectDestruction_singleObject(); + Node_test_objectDestruction_singleObject(); } -TEST(DAGNodeTest, objectDestruction_multipleObjects) +TEST(NodeTest, objectDestruction_multipleObjects) { EXPECT_MSG_NOEMIT(Error) ; - Node_test_objectDestruction_multipleObjects(); + Node_test_objectDestruction_multipleObjects(); } -TEST(DAGNodeTest, objectDestruction_childNode_singleObject) +TEST(NodeTest, objectDestruction_childNode_singleObject) { EXPECT_MSG_NOEMIT(Error) ; - Node_test_objectDestruction_childNode_singleObject(); + Node_test_objectDestruction_childNode_singleObject(); } -TEST(DAGNodeTest, objectDestruction_childNode_complexChild) +TEST(NodeTest, objectDestruction_childNode_complexChild) { EXPECT_MSG_NOEMIT(Error) ; - Node_test_objectDestruction_childNode_complexChild(); + Node_test_objectDestruction_childNode_complexChild(); } diff --git a/Sofa/framework/Simulation/Graph/test/MutationListener_test.cpp b/Sofa/framework/Simulation/Graph/test/MutationListener_test.cpp index c2d20e7bc9c..bca065e28a5 100644 --- a/Sofa/framework/Simulation/Graph/test/MutationListener_test.cpp +++ b/Sofa/framework/Simulation/Graph/test/MutationListener_test.cpp @@ -23,15 +23,13 @@ using sofa::testing::BaseTest; #include -#include +#include #include #include using sofa::simulation::MutationListener; using sofa::core::objectmodel::BaseObject; using sofa::simulation::Simulation; using sofa::simulation::Node; -using sofa::simulation::graph::DAGNode; - class TestMutationListener : public MutationListener { @@ -291,8 +289,8 @@ struct MutationListener_test : public BaseTest void test_addChildWithDescendency() { - const DAGNode::SPtr node1 = sofa::core::objectmodel::New("node1"); - const DAGNode::SPtr node2 = sofa::core::objectmodel::New("node2"); + const Node::SPtr node1 = sofa::core::objectmodel::New("node1"); + const Node::SPtr node2 = sofa::core::objectmodel::New("node2"); node1->addChild(node2); sofa::core::objectmodel::BaseObjectDescription bod1("obj1", "BaseObject"); obj1 = sofa::core::objectmodel::New(); @@ -313,8 +311,8 @@ struct MutationListener_test : public BaseTest void test_removeChildWithDescendency() { - const DAGNode::SPtr node1 = sofa::core::objectmodel::New("node1"); - const DAGNode::SPtr node2 = sofa::core::objectmodel::New("node2"); + const Node::SPtr node1 = sofa::core::objectmodel::New("node1"); + const Node::SPtr node2 = sofa::core::objectmodel::New("node2"); node1->addChild(node2); sofa::core::objectmodel::BaseObjectDescription bod1("obj1", "BaseObject"); obj1 = sofa::core::objectmodel::New(); @@ -336,8 +334,8 @@ struct MutationListener_test : public BaseTest void test_moveChildWithDescendency() { - const DAGNode::SPtr node1 = sofa::core::objectmodel::New("node1"); - const DAGNode::SPtr node2 = sofa::core::objectmodel::New("node2"); + const Node::SPtr node1 = sofa::core::objectmodel::New("node1"); + const Node::SPtr node2 = sofa::core::objectmodel::New("node2"); node1->addChild(node2); sofa::core::objectmodel::BaseObjectDescription bod1("obj1", "BaseObject"); obj1 = sofa::core::objectmodel::New(); @@ -362,14 +360,14 @@ struct MutationListener_test : public BaseTest void test_moveChildWithDescendencyAndMultipleParents() { - const DAGNode::SPtr node1 = sofa::core::objectmodel::New("node1"); - const DAGNode::SPtr node2 = sofa::core::objectmodel::New("node2"); - const DAGNode::SPtr node3 = sofa::core::objectmodel::New("node3"); - const DAGNode::SPtr node4 = sofa::core::objectmodel::New("node4"); - const DAGNode::SPtr node5 = sofa::core::objectmodel::New("node5"); - const DAGNode::SPtr node6 = sofa::core::objectmodel::New("node6"); - const DAGNode::SPtr node7 = sofa::core::objectmodel::New("node7"); - const DAGNode::SPtr node8 = sofa::core::objectmodel::New("node8"); + const Node::SPtr node1 = sofa::core::objectmodel::New("node1"); + const Node::SPtr node2 = sofa::core::objectmodel::New("node2"); + const Node::SPtr node3 = sofa::core::objectmodel::New("node3"); + const Node::SPtr node4 = sofa::core::objectmodel::New("node4"); + const Node::SPtr node5 = sofa::core::objectmodel::New("node5"); + const Node::SPtr node6 = sofa::core::objectmodel::New("node6"); + const Node::SPtr node7 = sofa::core::objectmodel::New("node7"); + const Node::SPtr node8 = sofa::core::objectmodel::New("node8"); sofa::core::objectmodel::BaseObjectDescription bod1("obj1", "BaseObject"); obj1 = sofa::core::objectmodel::New(); diff --git a/applications/plugins/SceneCreator/sceneCreatorExamples/SceneCreatorBenchmarks.cpp b/applications/plugins/SceneCreator/sceneCreatorExamples/SceneCreatorBenchmarks.cpp index 15fab358841..5b856a67269 100644 --- a/applications/plugins/SceneCreator/sceneCreatorExamples/SceneCreatorBenchmarks.cpp +++ b/applications/plugins/SceneCreator/sceneCreatorExamples/SceneCreatorBenchmarks.cpp @@ -28,7 +28,7 @@ #include #include -#include +#include #include #include From 4d0de258e5855bf8ec345339b6a2b618f64f04f8 Mon Sep 17 00:00:00 2001 From: Damien Marchal Date: Fri, 27 Jun 2025 15:54:54 +0200 Subject: [PATCH 03/19] Copy past content of DAGNode in Node --- .../Core/src/sofa/simulation/Node.cpp | 842 ++++++++++++++++- .../framework/Simulation/Graph/CMakeLists.txt | 2 +- .../src/sofa/simulation/graph/DAGNode.cpp | 31 + .../src/sofa/simulation/graph/NodeDagImpl.cpp | 851 ------------------ 4 files changed, 857 insertions(+), 869 deletions(-) create mode 100644 Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGNode.cpp delete mode 100644 Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/NodeDagImpl.cpp diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.cpp index 53a988adaff..b35300735fc 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.cpp @@ -850,23 +850,6 @@ void Node::initialize() updateSimulationContext(); } -void Node::updateContext() -{ - updateSimulationContext(); - updateVisualContext(); - if ( debug_ ) - msg_info()<<"Node::updateContext, node = "<(node); + if( dagnode->_descendancy.contains(_searchNode) ) // searchNode is in the current node descendancy, so the current node is a parent of searchNode + { + dagnode->getLocalObjects( _class_info, _container, _tags ); + return RESULT_CONTINUE; + } + else // the current node is NOT a parent of searchNode, stop here + { + return RESULT_PRUNE; + } + } + + /// Specify whether this action can be parallelized. + bool isThreadSafe() const override { return false; } + + /// Return a category name for this action. + /// Only used for debugging / profiling purposes + const char* getCategoryName() const override { return "GetUpObjectsVisitor"; } + const char* getClassName() const override { return "GetUpObjectsVisitor"; } + + +protected: + + Node* _searchNode; + const sofa::core::objectmodel::ClassInfo& _class_info; + Node::GetObjectsCallBack& _container; + const sofa::core::objectmodel::TagSet& _tags; + +}; + +GetUpObjectsVisitor::GetUpObjectsVisitor(Node* searchNode, + const sofa::core::objectmodel::ClassInfo& class_info, + Node::GetObjectsCallBack& container, + const sofa::core::objectmodel::TagSet& tags) + : Visitor( sofa::core::execparams::defaultInstance() ) + , _searchNode( searchNode ) + , _class_info(class_info) + , _container(container) + , _tags(tags) +{} + +GetUpObjectsVisitor::~GetUpObjectsVisitor(){} + +/// Create, add, then return the new child of this Node +Node::SPtr Node::createChild(const std::string& nodeName) +{ + Node::SPtr newchild; + if (nodeName.empty()) + { + int i = 0; + std::string newName = "unnamed"; + bool uid_found = false; + while (!uid_found) + { + uid_found = true; + for (const auto& c : this->child) + { + if (c->getName() == newName) + { + newName = "unnamed" + std::to_string(++i); + uid_found = true; + } + } + for (const auto& o : this->object) + { + if (o->getName() == newName) + { + newName = "unnamed" + std::to_string(++i); + uid_found = true; + } + } + } + msg_error("Node::createChild()") << "Empty string given to property 'name': Forcefully setting an empty name is forbidden.\n" + "Renaming to " + newName + " to avoid unexpected behaviors."; + newchild = sofa::core::objectmodel::New(newName); + } + else + newchild = sofa::core::objectmodel::New(nodeName); + this->addChild(newchild); newchild->updateSimulationContext(); + return newchild; +} + + +void Node::moveChild(BaseNode::SPtr node) +{ + const Node::SPtr dagnode = sofa::core::objectmodel::SPtr_static_cast(node); + for (const auto& parent : dagnode->getParents()) { + Node::moveChild(node, parent); + } +} + + +/// Add a child node +void Node::doAddChild(BaseNode::SPtr node) +{ + const Node::SPtr dagnode = sofa::core::objectmodel::SPtr_static_cast(node); + setDirtyDescendancy(); + child.add(dagnode); + dagnode->l_parents.add(this); + dagnode->l_parents.updateLinks(); // to fix load-time unresolved links +} + +/// Remove a child +void Node::doRemoveChild(BaseNode::SPtr node) +{ + const Node::SPtr dagnode = sofa::core::objectmodel::SPtr_static_cast(node); + setDirtyDescendancy(); + child.remove(dagnode); + dagnode->l_parents.remove(this); +} + +/// Move a node from another node +void Node::doMoveChild(BaseNode::SPtr node, BaseNode::SPtr previous_parent) +{ + const Node::SPtr dagnode = sofa::core::objectmodel::SPtr_static_cast(node); + if (!dagnode) return; + + setDirtyDescendancy(); + previous_parent->removeChild(node); + + addChild(node); +} + +/// Remove a child +void Node::detachFromGraph() +{ + Node::SPtr me = this; // make sure we don't delete ourself before the end of this method + const LinkParents::Container& parents = l_parents.getValue(); + while(!parents.empty()) + parents.back()->removeChild(this); +} + +/// Generic object access, possibly searching up or down from the current context +/// +/// Note that the template wrapper method should generally be used to have the correct return type, +void* Node::getObject(const sofa::core::objectmodel::ClassInfo& class_info, const sofa::core::objectmodel::TagSet& tags, SearchDirection dir) const +{ + if (dir == SearchRoot) + { + if (getNbParents()) return getRootContext()->getObject(class_info, tags, dir); + else dir = SearchDown; // we are the root, search down from here. + } + void *result = nullptr; + + if (dir != SearchParents) + for (ObjectIterator it = this->object.begin(); it != this->object.end(); ++it) + { + sofa::core::objectmodel::BaseObject* obj = it->get(); + if (tags.empty() || (obj)->getTags().includes(tags)) + { + + result = class_info.dynamicCast(obj); + if (result != nullptr) + { + + break; + } + } + } + + if (result == nullptr) + { + switch(dir) + { + case Local: + break; + case SearchParents: + case SearchUp: + { + const LinkParents::Container& parents = l_parents.getValue(); + for ( unsigned int i = 0; i < parents.size() ; ++i){ + result = parents[i]->getObject(class_info, tags, SearchUp); + if (result != nullptr) break; + } + } + break; + case SearchDown: + for(ChildIterator it = child.begin(); it != child.end(); ++it) + { + result = (*it)->getObject(class_info, tags, dir); + if (result != nullptr) break; + } + break; + case SearchRoot: + dmsg_error("Node") << "SearchRoot SHOULD NOT BE POSSIBLE HERE."; + break; + } + } + + return result; +} + +/// Generic object access, given a path from the current context +/// +/// Note that the template wrapper method should generally be used to have the correct return type, +void* Node::getObject(const sofa::core::objectmodel::ClassInfo& class_info, const std::string& path) const +{ + if (path.empty()) + { + // local object + return Node::getObject(class_info, Local); + } + else if (path[0] == '/') + { + // absolute path; let's start from root + if (!getNbParents()) return getObject(class_info,std::string(path,1)); + else return getRootContext()->getObject(class_info,path); + } + else if (std::string(path,0,2)==std::string("./")) + { + std::string newpath = std::string(path, 2); + while (!newpath.empty() && path[0] == '/') + newpath.erase(0); + return getObject(class_info,newpath); + } + else if (std::string(path,0,3)==std::string("../")) + { + // tricky case: + // let's test EACH parent and return the first object found (if any) + std::string newpath = std::string(path, 3); + while (!newpath.empty() && path[0] == '/') + newpath.erase(0); + if (getNbParents()) + { + const LinkParents::Container& parents = l_parents.getValue(); + for ( unsigned int i = 0; i < parents.size() ; ++i) + { + void* obj = parents[i]->getObject(class_info,newpath); + if (obj) return obj; + } + return nullptr; // not found in any parent node at all + } + else return getObject(class_info,newpath); + } + else + { + std::string::size_type pend = path.find('/'); + if (pend == std::string::npos) pend = path.length(); + const std::string name ( path, 0, pend ); + const Node* child = getChild(name); + if (child) + { + while (pend < path.length() && path[pend] == '/') + ++pend; + return child->getObject(class_info, std::string(path, pend)); + } + else if (pend < path.length()) + { + return nullptr; + } + else + { + sofa::core::objectmodel::BaseObject* obj = simulation::Node::getObject(name); + if (obj == nullptr) + { + return nullptr; + } + else + { + void* result = class_info.dynamicCast(obj); + if (result == nullptr) + { + dmsg_error("Node") << "Object "<getObjects( class_info, container, tags, dir ); + return; + } + else dir = SearchDown; // we are the root, search down from here. + } + + + switch( dir ) + { + case Local: + this->getLocalObjects( class_info, container, tags ); + break; + + case SearchUp: + this->getLocalObjects( class_info, container, tags ); // add locals then SearchParents + // no break here, we want to execute the SearchParents code. + [[fallthrough]]; + case SearchParents: + { + // a visitor executed from top but only run for this' parents will enforce the selected object unicity due even with diamond graph setups + GetUpObjectsVisitor vis( const_cast(this), class_info, container, tags); + getRootContext()->executeVisitor(&vis); + } + break; + + case SearchDown: + { + // a regular visitor is enforcing the selected object unicity + GetDownObjectsVisitor vis(class_info, container, tags); + (const_cast(this))->executeVisitor(&vis); + break; + } + default: + break; + } +} + +/// Get a list of parent node +sofa::core::objectmodel::BaseNode::Parents Node::getParents() const +{ + Parents p; + + const LinkParents::Container& parents = l_parents.getValue(); + for ( unsigned int i = 0; i < parents.size() ; ++i) + p.push_back(parents[i]); + + return p; +} + + +/// returns number of parents +size_t Node::getNbParents() const +{ + return l_parents.getValue().size(); +} + +/// return the first parent (returns nullptr if no parent) +sofa::core::objectmodel::BaseNode* Node::getFirstParent() const +{ + const LinkParents::Container& parents = l_parents.getValue(); + if( parents.empty() ) return nullptr; + else return l_parents.getValue()[0]; +} + + +/// Test if the given node is a parent of this node. +bool Node::hasParent(const BaseNode* node) const +{ + const LinkParents::Container& parents = l_parents.getValue(); + for ( unsigned int i = 0; i < parents.size() ; ++i) + { + if (parents[i]==node) return true; + } + return false; +} + +/// Test if the given context is a parent of this context. +bool Node::hasParent(const BaseContext* context) const +{ + if (context == nullptr) return !getNbParents(); + + const LinkParents::Container& parents = l_parents.getValue(); + for ( unsigned int i = 0; i < parents.size() ; ++i) + if (context == parents[i]->getContext()) return true; + return false; + +} + + + +/// Test if the given context is an ancestor of this context. +/// An ancestor is a parent or (recursively) the parent of an ancestor. +bool Node::hasAncestor(const BaseContext* context) const +{ + const LinkParents::Container& parents = l_parents.getValue(); + for ( unsigned int i = 0; i < parents.size() ; ++i) + if (context == parents[i]->getContext() + || parents[i]->hasAncestor(context)) + return true; + return false; +} + + +/// Mesh Topology that is relevant for this context +/// (within it or its parents until a mapping is reached that does not preserve topologies). +sofa::core::topology::BaseMeshTopology* Node::getMeshTopologyLink(SearchDirection dir) const +{ + if (this->meshTopology) + return this->meshTopology; + + if (dir != Local) + return Node::getMeshTopologyLink(dir); + + //local case similar to getActiveMeshTopology ... + + // Check if a local mapping stops the search + if (this->mechanicalMapping && !this->mechanicalMapping->sameTopology()) + { + return nullptr; + } + for ( Sequence::iterator i=this->mapping.begin(), iend=this->mapping.end(); i!=iend; ++i ) + { + if (!(*i)->sameTopology()) + { + return nullptr; + } + } + // No mapping with a different topology, continue on to the parents + const LinkParents::Container &parents = l_parents.getValue(); + for ( unsigned int i = 0; i < parents.size() ; i++ ) + { + // if the visitor is run from a sub-graph containing a multinode linked with a node outside of the subgraph, do not consider the outside node by looking on the sub-graph descendancy + if ( parents[i] ) + { + sofa::core::topology::BaseMeshTopology* res = parents[i]->getMeshTopologyLink(Local); + if (res) + return res; + } + } + return nullptr; // not found in any parents +} + +void Node::precomputeTraversalOrder( const sofa::core::ExecParams* params ) +{ + // accumulating traversed Nodes + class TraversalOrderVisitor : public Visitor + { + NodeList& _orderList; + public: + TraversalOrderVisitor(const sofa::core::ExecParams* params, NodeList& orderList ) + : Visitor(params) + , _orderList( orderList ) + { + _orderList.clear(); + } + + Result processNodeTopDown(Node* node) override + { + _orderList.push_back( static_cast(node) ); + return RESULT_CONTINUE; + } + + const char* getClassName() const override {return "TraversalOrderVisitor";} + }; + + TraversalOrderVisitor tov( params, _precomputedTraversalOrder ); + executeVisitor( &tov, false ); +} + + + +/// Execute a recursive action starting from this node +void Node::doExecuteVisitor(simulation::Visitor* action, bool precomputedOrder) +{ + if( precomputedOrder && !_precomputedTraversalOrder.empty() ) + { + for( NodeList::iterator it = _precomputedTraversalOrder.begin(), itend = _precomputedTraversalOrder.end() ; it != itend ; ++it ) + { + if ( action->canAccessSleepingNode || !(*it)->getContext()->isSleeping() ) + action->processNodeTopDown( *it ); + } + + for( NodeList::reverse_iterator it = _precomputedTraversalOrder.rbegin(), itend = _precomputedTraversalOrder.rend() ; it != itend ; ++it ) + { + if ( action->canAccessSleepingNode || !(*it)->getContext()->isSleeping() ) + action->processNodeBottomUp( *it ); + } + } + else + { + // WARNING: do not store the traversal infos in the Node, as several visitors could traversed the graph simultaneously + // These infos are stored in a StatusMap per visitor. + updateDescendancy(); + + Visitor::TreeTraversalRepetition repeat; + if( action->treeTraversal(repeat) ) + { + // Tree traversal order + // + // Diamond shapes are ignored, a child node is visited as soon as a parent node has been visited. + // The multi-nodes (with several parents) are visited either: only once, only twice or for every times + // depending on the visitor's 'repeat' + // + // Some particular visitors such as a flat graph display or VisualVisitors must follow such a traversal order. + + StatusMap statusMap; + executeVisitorTreeTraversal( action, statusMap, repeat ); + } + else + { + // Direct acyclic graph traversal order + // + // This is the default order, used for mechanics. + // + // A child node is visited only when all its parents have been visited. + // A child node is 'pruned' only if all its parents are 'pruned'. + // Every executed node in the forward traversal are stored in 'executedNodes', + // its reverse order is used for the backward traversal. + + // Note that a newly 'pruned' node is still traversed (w/o execution) to be sure to execute its child nodes, + // that can have ancestors in another branch that is not pruned... + // An already pruned node is ignored. + + NodeList executedNodes; + { + StatusMap statusMap; + executeVisitorTopDown( action, executedNodes, statusMap, this ); + } + executeVisitorBottomUp( action, executedNodes ); + } + } +} + + +void Node::executeVisitorTopDown(simulation::Visitor* action, NodeList& executedNodes, StatusMap& statusMap, Node* visitorRoot ) +{ + if ( statusMap[this] != NOT_VISITED ) + { + return; // skipped (already visited) + } + + if( !this->isActive() ) + { + // do not execute the visitor on this node + statusMap[this] = PRUNED; + + // in that case we can considerer if some child are activated, the graph is not valid, so no need to continue the recursion + return; + } + + if( this->isSleeping() && !action->canAccessSleepingNode ) + { + // do not execute the visitor on this node + statusMap[this] = PRUNED; + + return; + } + + // pour chaque noeud "prune" on continue à parcourir quand même juste pour marquer le noeud comme parcouru + + // check du "visitedStatus" des parents: + // un enfant n'est pruné que si tous ses parents le sont + // on ne passe à un enfant que si tous ses parents ont été visités + bool allParentsPruned = true; + bool hasParent = false; + + if( visitorRoot != this ) + { + // the graph structure is generally modified during an action anterior to the traversal but can possibly be modified during the current traversal + visitorRoot->updateDescendancy(); + + const LinkParents::Container &parents = l_parents.getValue(); + for ( unsigned int i = 0; i < parents.size() ; i++ ) + { + // if the visitor is run from a sub-graph containing a multinode linked with a node outside of the subgraph, do not consider the outside node by looking on the sub-graph descendancy + if ( visitorRoot->_descendancy.contains(parents[i]) || parents[i]==visitorRoot ) + { + // all parents must have been visited before + if ( statusMap[parents[i]] == NOT_VISITED ) + return; // skipped for now... the other parent should come later + + allParentsPruned = allParentsPruned && ( statusMap[parents[i]] == PRUNED ); + hasParent = true; + } + } + } + + // all parents have been visited, let's go with the visitor + if ( allParentsPruned && hasParent ) + { + // do not execute the visitor on this node + statusMap[this] = PRUNED; + + // ... but continue the recursion anyway! + if( action->childOrderReversed(this) ) + for(unsigned int i = unsigned(child.size()); i>0;) + static_cast(child[--i].get())->executeVisitorTopDown(action,executedNodes,statusMap,visitorRoot); + else + for(unsigned int i = 0; i(child[i].get())->executeVisitorTopDown(action,executedNodes,statusMap,visitorRoot); + } + else + { + // execute the visitor on this node + const Visitor::Result result = action->processNodeTopDown(this); + + // update status + statusMap[this] = ( result == simulation::Visitor::RESULT_PRUNE ? PRUNED : VISITED ); + + executedNodes.push_back(this); + + // ... and continue the recursion + if( action->childOrderReversed(this) ) + for(unsigned int i = unsigned(child.size()); i>0;) + static_cast(child[--i].get())->executeVisitorTopDown(action,executedNodes,statusMap,visitorRoot); + else + for(unsigned int i = 0; i(child[i].get())->executeVisitorTopDown(action,executedNodes,statusMap,visitorRoot); + + } +} + + +// warning nodes that are dynamically created during the traversal, but that have not been traversed during the top-down, won't be traversed during the bottom-up +// TODO is it what we want? +// otherwise it is possible to restart from top, go to leaves and running bottom-up action while going up +void Node::executeVisitorBottomUp( simulation::Visitor* action, NodeList& executedNodes ) +{ + for( NodeList::reverse_iterator it = executedNodes.rbegin(), itend = executedNodes.rend() ; it != itend ; ++it ) + { + (*it)->updateDescendancy(); + action->processNodeBottomUp( *it ); + } +} + + +void Node::setDirtyDescendancy() +{ + _descendancy.clear(); + const LinkParents::Container &parents = l_parents.getValue(); + for ( unsigned int i = 0; i < parents.size() ; i++ ) + { + parents[i]->setDirtyDescendancy(); + } +} + +void Node::updateDescendancy() +{ + if( _descendancy.empty() && !child.empty() ) + { + for(unsigned int i = 0; i(child[i].get()); + dagnode->updateDescendancy(); + _descendancy.insert( dagnode->_descendancy.begin(), dagnode->_descendancy.end() ); + _descendancy.insert( dagnode ); + } + } +} + + + +void Node::executeVisitorTreeTraversal( simulation::Visitor* action, StatusMap& statusMap, Visitor::TreeTraversalRepetition repeat, bool alreadyRepeated ) +{ + if( !this->isActive() ) + { + // do not execute the visitor on this node + statusMap[this] = PRUNED; + return; + } + + if( this->isSleeping() && !action->canAccessSleepingNode ) + { + // do not execute the visitor on this node + statusMap[this] = PRUNED; + return; + } + + // node already visited and repetition must be avoid + if( statusMap[this] != NOT_VISITED ) + { + if( repeat==Visitor::NO_REPETITION || ( alreadyRepeated && repeat==Visitor::REPEAT_ONCE ) ) return; + else alreadyRepeated = true; + } + + if( action->processNodeTopDown(this) != simulation::Visitor::RESULT_PRUNE ) + { + statusMap[this] = VISITED; + if( action->childOrderReversed(this) ) + for(unsigned int i = unsigned(child.size()); i>0;) + static_cast(child[--i].get())->executeVisitorTreeTraversal(action,statusMap,repeat,alreadyRepeated); + else + for(unsigned int i = 0; i(child[i].get())->executeVisitorTreeTraversal(action,statusMap,repeat,alreadyRepeated); + } + else + { + statusMap[this] = PRUNED; + } + + action->processNodeBottomUp(this); +} + + +void Node::initVisualContext() +{ + if (getNbParents()) + { + this->setDisplayWorldGravity(false); //only display gravity for the root: it will be propagated at each time step + } +} + +void Node::updateContext() +{ + sofa::core::objectmodel::BaseNode* firstParent = getFirstParent(); + + if ( firstParent ) + { + if( debug_ ) + { + msg_info()<<"Node::updateContext, node = "< NodeClass("Node"); + +} diff --git a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/NodeDagImpl.cpp b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/NodeDagImpl.cpp deleted file mode 100644 index f0d36b47d66..00000000000 --- a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/NodeDagImpl.cpp +++ /dev/null @@ -1,851 +0,0 @@ -/****************************************************************************** -* SOFA, Simulation Open-Framework Architecture * -* (c) 2006 INRIA, USTL, UJF, CNRS, MGH * -* * -* This program is free software; you can redistribute it and/or modify it * -* under the terms of the GNU Lesser General Public License as published by * -* the Free Software Foundation; either version 2.1 of the License, or (at * -* your option) any later version. * -* * -* This program is distributed in the hope that it will be useful, but WITHOUT * -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * -* for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with this program. If not, see . * -******************************************************************************* -* Authors: The SOFA Team and external contributors (see Authors.txt) * -* * -* Contact information: contact@sofa-framework.org * -******************************************************************************/ -#include -#include -#include -#include - -namespace sofa::simulation -{ - -/// get all down objects respecting specified class_info and tags -class GetDownObjectsVisitor : public Visitor -{ -public: - - GetDownObjectsVisitor(const sofa::core::objectmodel::ClassInfo& class_info, Node::GetObjectsCallBack& container, const sofa::core::objectmodel::TagSet& tags); - ~GetDownObjectsVisitor() ; - - Result processNodeTopDown(simulation::Node* node) override - { - static_cast(node)->getLocalObjects( _class_info, _container, _tags ); - return RESULT_CONTINUE; - } - - /// Specify whether this action can be parallelized. - bool isThreadSafe() const override { return false; } - - /// Return a category name for this action. - /// Only used for debugging / profiling purposes - const char* getCategoryName() const override { return "GetDownObjectsVisitor"; } - const char* getClassName() const override { return "GetDownObjectsVisitor"; } - -protected: - const sofa::core::objectmodel::ClassInfo& _class_info; - Node::GetObjectsCallBack& _container; - const sofa::core::objectmodel::TagSet& _tags; -}; - -GetDownObjectsVisitor::GetDownObjectsVisitor(const sofa::core::objectmodel::ClassInfo& class_info, - Node::GetObjectsCallBack& container, - const sofa::core::objectmodel::TagSet& tags) - : Visitor( sofa::core::execparams::defaultInstance() ) - , _class_info(class_info) - , _container(container) - , _tags(tags) -{} - -GetDownObjectsVisitor::~GetDownObjectsVisitor(){} - -/// get all up objects respecting specified class_info and tags -class GetUpObjectsVisitor : public Visitor -{ -public: - - GetUpObjectsVisitor(Node* searchNode, const sofa::core::objectmodel::ClassInfo& class_info, Node::GetObjectsCallBack& container, const sofa::core::objectmodel::TagSet& tags); - ~GetUpObjectsVisitor() override; - - Result processNodeTopDown(simulation::Node* node) override - { - const Node* dagnode = dynamic_cast(node); - if( dagnode->_descendancy.contains(_searchNode) ) // searchNode is in the current node descendancy, so the current node is a parent of searchNode - { - dagnode->getLocalObjects( _class_info, _container, _tags ); - return RESULT_CONTINUE; - } - else // the current node is NOT a parent of searchNode, stop here - { - return RESULT_PRUNE; - } - } - - /// Specify whether this action can be parallelized. - bool isThreadSafe() const override { return false; } - - /// Return a category name for this action. - /// Only used for debugging / profiling purposes - const char* getCategoryName() const override { return "GetUpObjectsVisitor"; } - const char* getClassName() const override { return "GetUpObjectsVisitor"; } - - -protected: - - Node* _searchNode; - const sofa::core::objectmodel::ClassInfo& _class_info; - Node::GetObjectsCallBack& _container; - const sofa::core::objectmodel::TagSet& _tags; - -}; - -GetUpObjectsVisitor::GetUpObjectsVisitor(Node* searchNode, - const sofa::core::objectmodel::ClassInfo& class_info, - Node::GetObjectsCallBack& container, - const sofa::core::objectmodel::TagSet& tags) - : Visitor( sofa::core::execparams::defaultInstance() ) - , _searchNode( searchNode ) - , _class_info(class_info) - , _container(container) - , _tags(tags) -{} - -GetUpObjectsVisitor::~GetUpObjectsVisitor(){} - -/// Create, add, then return the new child of this Node -Node::SPtr Node::createChild(const std::string& nodeName) -{ - Node::SPtr newchild; - if (nodeName.empty()) - { - int i = 0; - std::string newName = "unnamed"; - bool uid_found = false; - while (!uid_found) - { - uid_found = true; - for (const auto& c : this->child) - { - if (c->getName() == newName) - { - newName = "unnamed" + std::to_string(++i); - uid_found = true; - } - } - for (const auto& o : this->object) - { - if (o->getName() == newName) - { - newName = "unnamed" + std::to_string(++i); - uid_found = true; - } - } - } - msg_error("Node::createChild()") << "Empty string given to property 'name': Forcefully setting an empty name is forbidden.\n" - "Renaming to " + newName + " to avoid unexpected behaviors."; - newchild = sofa::core::objectmodel::New(newName); - } - else - newchild = sofa::core::objectmodel::New(nodeName); - this->addChild(newchild); newchild->updateSimulationContext(); - return newchild; -} - - -void Node::moveChild(BaseNode::SPtr node) -{ - const Node::SPtr dagnode = sofa::core::objectmodel::SPtr_static_cast(node); - for (const auto& parent : dagnode->getParents()) { - Node::moveChild(node, parent); - } -} - - -/// Add a child node -void Node::doAddChild(BaseNode::SPtr node) -{ - const Node::SPtr dagnode = sofa::core::objectmodel::SPtr_static_cast(node); - setDirtyDescendancy(); - child.add(dagnode); - dagnode->l_parents.add(this); - dagnode->l_parents.updateLinks(); // to fix load-time unresolved links -} - -/// Remove a child -void Node::doRemoveChild(BaseNode::SPtr node) -{ - const Node::SPtr dagnode = sofa::core::objectmodel::SPtr_static_cast(node); - setDirtyDescendancy(); - child.remove(dagnode); - dagnode->l_parents.remove(this); -} - -/// Move a node from another node -void Node::doMoveChild(BaseNode::SPtr node, BaseNode::SPtr previous_parent) -{ - const Node::SPtr dagnode = sofa::core::objectmodel::SPtr_static_cast(node); - if (!dagnode) return; - - setDirtyDescendancy(); - previous_parent->removeChild(node); - - addChild(node); -} - -/// Remove a child -void Node::detachFromGraph() -{ - Node::SPtr me = this; // make sure we don't delete ourself before the end of this method - const LinkParents::Container& parents = l_parents.getValue(); - while(!parents.empty()) - parents.back()->removeChild(this); -} - -/// Generic object access, possibly searching up or down from the current context -/// -/// Note that the template wrapper method should generally be used to have the correct return type, -void* Node::getObject(const sofa::core::objectmodel::ClassInfo& class_info, const sofa::core::objectmodel::TagSet& tags, SearchDirection dir) const -{ - if (dir == SearchRoot) - { - if (getNbParents()) return getRootContext()->getObject(class_info, tags, dir); - else dir = SearchDown; // we are the root, search down from here. - } - void *result = nullptr; - - if (dir != SearchParents) - for (ObjectIterator it = this->object.begin(); it != this->object.end(); ++it) - { - sofa::core::objectmodel::BaseObject* obj = it->get(); - if (tags.empty() || (obj)->getTags().includes(tags)) - { - - result = class_info.dynamicCast(obj); - if (result != nullptr) - { - - break; - } - } - } - - if (result == nullptr) - { - switch(dir) - { - case Local: - break; - case SearchParents: - case SearchUp: - { - const LinkParents::Container& parents = l_parents.getValue(); - for ( unsigned int i = 0; i < parents.size() ; ++i){ - result = parents[i]->getObject(class_info, tags, SearchUp); - if (result != nullptr) break; - } - } - break; - case SearchDown: - for(ChildIterator it = child.begin(); it != child.end(); ++it) - { - result = (*it)->getObject(class_info, tags, dir); - if (result != nullptr) break; - } - break; - case SearchRoot: - dmsg_error("Node") << "SearchRoot SHOULD NOT BE POSSIBLE HERE."; - break; - } - } - - return result; -} - -/// Generic object access, given a path from the current context -/// -/// Note that the template wrapper method should generally be used to have the correct return type, -void* Node::getObject(const sofa::core::objectmodel::ClassInfo& class_info, const std::string& path) const -{ - if (path.empty()) - { - // local object - return Node::getObject(class_info, Local); - } - else if (path[0] == '/') - { - // absolute path; let's start from root - if (!getNbParents()) return getObject(class_info,std::string(path,1)); - else return getRootContext()->getObject(class_info,path); - } - else if (std::string(path,0,2)==std::string("./")) - { - std::string newpath = std::string(path, 2); - while (!newpath.empty() && path[0] == '/') - newpath.erase(0); - return getObject(class_info,newpath); - } - else if (std::string(path,0,3)==std::string("../")) - { - // tricky case: - // let's test EACH parent and return the first object found (if any) - std::string newpath = std::string(path, 3); - while (!newpath.empty() && path[0] == '/') - newpath.erase(0); - if (getNbParents()) - { - const LinkParents::Container& parents = l_parents.getValue(); - for ( unsigned int i = 0; i < parents.size() ; ++i) - { - void* obj = parents[i]->getObject(class_info,newpath); - if (obj) return obj; - } - return nullptr; // not found in any parent node at all - } - else return getObject(class_info,newpath); - } - else - { - std::string::size_type pend = path.find('/'); - if (pend == std::string::npos) pend = path.length(); - const std::string name ( path, 0, pend ); - const Node* child = getChild(name); - if (child) - { - while (pend < path.length() && path[pend] == '/') - ++pend; - return child->getObject(class_info, std::string(path, pend)); - } - else if (pend < path.length()) - { - return nullptr; - } - else - { - sofa::core::objectmodel::BaseObject* obj = simulation::Node::getObject(name); - if (obj == nullptr) - { - return nullptr; - } - else - { - void* result = class_info.dynamicCast(obj); - if (result == nullptr) - { - dmsg_error("Node") << "Object "<getObjects( class_info, container, tags, dir ); - return; - } - else dir = SearchDown; // we are the root, search down from here. - } - - - switch( dir ) - { - case Local: - this->getLocalObjects( class_info, container, tags ); - break; - - case SearchUp: - this->getLocalObjects( class_info, container, tags ); // add locals then SearchParents - // no break here, we want to execute the SearchParents code. - [[fallthrough]]; - case SearchParents: - { - // a visitor executed from top but only run for this' parents will enforce the selected object unicity due even with diamond graph setups - GetUpObjectsVisitor vis( const_cast(this), class_info, container, tags); - getRootContext()->executeVisitor(&vis); - } - break; - - case SearchDown: - { - // a regular visitor is enforcing the selected object unicity - GetDownObjectsVisitor vis(class_info, container, tags); - (const_cast(this))->executeVisitor(&vis); - break; - } - default: - break; - } -} - -/// Get a list of parent node -sofa::core::objectmodel::BaseNode::Parents Node::getParents() const -{ - Parents p; - - const LinkParents::Container& parents = l_parents.getValue(); - for ( unsigned int i = 0; i < parents.size() ; ++i) - p.push_back(parents[i]); - - return p; -} - - -/// returns number of parents -size_t Node::getNbParents() const -{ - return l_parents.getValue().size(); -} - -/// return the first parent (returns nullptr if no parent) -sofa::core::objectmodel::BaseNode* Node::getFirstParent() const -{ - const LinkParents::Container& parents = l_parents.getValue(); - if( parents.empty() ) return nullptr; - else return l_parents.getValue()[0]; -} - - -/// Test if the given node is a parent of this node. -bool Node::hasParent(const BaseNode* node) const -{ - const LinkParents::Container& parents = l_parents.getValue(); - for ( unsigned int i = 0; i < parents.size() ; ++i) - { - if (parents[i]==node) return true; - } - return false; -} - -/// Test if the given context is a parent of this context. -bool Node::hasParent(const BaseContext* context) const -{ - if (context == nullptr) return !getNbParents(); - - const LinkParents::Container& parents = l_parents.getValue(); - for ( unsigned int i = 0; i < parents.size() ; ++i) - if (context == parents[i]->getContext()) return true; - return false; - -} - - - -/// Test if the given context is an ancestor of this context. -/// An ancestor is a parent or (recursively) the parent of an ancestor. -bool Node::hasAncestor(const BaseContext* context) const -{ - const LinkParents::Container& parents = l_parents.getValue(); - for ( unsigned int i = 0; i < parents.size() ; ++i) - if (context == parents[i]->getContext() - || parents[i]->hasAncestor(context)) - return true; - return false; -} - - -/// Mesh Topology that is relevant for this context -/// (within it or its parents until a mapping is reached that does not preserve topologies). -sofa::core::topology::BaseMeshTopology* Node::getMeshTopologyLink(SearchDirection dir) const -{ - if (this->meshTopology) - return this->meshTopology; - - if (dir != Local) - return Node::getMeshTopologyLink(dir); - - //local case similar to getActiveMeshTopology ... - - // Check if a local mapping stops the search - if (this->mechanicalMapping && !this->mechanicalMapping->sameTopology()) - { - return nullptr; - } - for ( Sequence::iterator i=this->mapping.begin(), iend=this->mapping.end(); i!=iend; ++i ) - { - if (!(*i)->sameTopology()) - { - return nullptr; - } - } - // No mapping with a different topology, continue on to the parents - const LinkParents::Container &parents = l_parents.getValue(); - for ( unsigned int i = 0; i < parents.size() ; i++ ) - { - // if the visitor is run from a sub-graph containing a multinode linked with a node outside of the subgraph, do not consider the outside node by looking on the sub-graph descendancy - if ( parents[i] ) - { - sofa::core::topology::BaseMeshTopology* res = parents[i]->getMeshTopologyLink(Local); - if (res) - return res; - } - } - return nullptr; // not found in any parents -} - -void Node::precomputeTraversalOrder( const sofa::core::ExecParams* params ) -{ - // accumulating traversed Nodes - class TraversalOrderVisitor : public Visitor - { - NodeList& _orderList; - public: - TraversalOrderVisitor(const sofa::core::ExecParams* params, NodeList& orderList ) - : Visitor(params) - , _orderList( orderList ) - { - _orderList.clear(); - } - - Result processNodeTopDown(Node* node) override - { - _orderList.push_back( static_cast(node) ); - return RESULT_CONTINUE; - } - - const char* getClassName() const override {return "TraversalOrderVisitor";} - }; - - TraversalOrderVisitor tov( params, _precomputedTraversalOrder ); - executeVisitor( &tov, false ); -} - - - -/// Execute a recursive action starting from this node -void Node::doExecuteVisitor(simulation::Visitor* action, bool precomputedOrder) -{ - if( precomputedOrder && !_precomputedTraversalOrder.empty() ) - { - for( NodeList::iterator it = _precomputedTraversalOrder.begin(), itend = _precomputedTraversalOrder.end() ; it != itend ; ++it ) - { - if ( action->canAccessSleepingNode || !(*it)->getContext()->isSleeping() ) - action->processNodeTopDown( *it ); - } - - for( NodeList::reverse_iterator it = _precomputedTraversalOrder.rbegin(), itend = _precomputedTraversalOrder.rend() ; it != itend ; ++it ) - { - if ( action->canAccessSleepingNode || !(*it)->getContext()->isSleeping() ) - action->processNodeBottomUp( *it ); - } - } - else - { - // WARNING: do not store the traversal infos in the Node, as several visitors could traversed the graph simultaneously - // These infos are stored in a StatusMap per visitor. - updateDescendancy(); - - Visitor::TreeTraversalRepetition repeat; - if( action->treeTraversal(repeat) ) - { - // Tree traversal order - // - // Diamond shapes are ignored, a child node is visited as soon as a parent node has been visited. - // The multi-nodes (with several parents) are visited either: only once, only twice or for every times - // depending on the visitor's 'repeat' - // - // Some particular visitors such as a flat graph display or VisualVisitors must follow such a traversal order. - - StatusMap statusMap; - executeVisitorTreeTraversal( action, statusMap, repeat ); - } - else - { - // Direct acyclic graph traversal order - // - // This is the default order, used for mechanics. - // - // A child node is visited only when all its parents have been visited. - // A child node is 'pruned' only if all its parents are 'pruned'. - // Every executed node in the forward traversal are stored in 'executedNodes', - // its reverse order is used for the backward traversal. - - // Note that a newly 'pruned' node is still traversed (w/o execution) to be sure to execute its child nodes, - // that can have ancestors in another branch that is not pruned... - // An already pruned node is ignored. - - NodeList executedNodes; - { - StatusMap statusMap; - executeVisitorTopDown( action, executedNodes, statusMap, this ); - } - executeVisitorBottomUp( action, executedNodes ); - } - } -} - - -void Node::executeVisitorTopDown(simulation::Visitor* action, NodeList& executedNodes, StatusMap& statusMap, Node* visitorRoot ) -{ - if ( statusMap[this] != NOT_VISITED ) - { - return; // skipped (already visited) - } - - if( !this->isActive() ) - { - // do not execute the visitor on this node - statusMap[this] = PRUNED; - - // in that case we can considerer if some child are activated, the graph is not valid, so no need to continue the recursion - return; - } - - if( this->isSleeping() && !action->canAccessSleepingNode ) - { - // do not execute the visitor on this node - statusMap[this] = PRUNED; - - return; - } - - // pour chaque noeud "prune" on continue à parcourir quand même juste pour marquer le noeud comme parcouru - - // check du "visitedStatus" des parents: - // un enfant n'est pruné que si tous ses parents le sont - // on ne passe à un enfant que si tous ses parents ont été visités - bool allParentsPruned = true; - bool hasParent = false; - - if( visitorRoot != this ) - { - // the graph structure is generally modified during an action anterior to the traversal but can possibly be modified during the current traversal - visitorRoot->updateDescendancy(); - - const LinkParents::Container &parents = l_parents.getValue(); - for ( unsigned int i = 0; i < parents.size() ; i++ ) - { - // if the visitor is run from a sub-graph containing a multinode linked with a node outside of the subgraph, do not consider the outside node by looking on the sub-graph descendancy - if ( visitorRoot->_descendancy.contains(parents[i]) || parents[i]==visitorRoot ) - { - // all parents must have been visited before - if ( statusMap[parents[i]] == NOT_VISITED ) - return; // skipped for now... the other parent should come later - - allParentsPruned = allParentsPruned && ( statusMap[parents[i]] == PRUNED ); - hasParent = true; - } - } - } - - // all parents have been visited, let's go with the visitor - if ( allParentsPruned && hasParent ) - { - // do not execute the visitor on this node - statusMap[this] = PRUNED; - - // ... but continue the recursion anyway! - if( action->childOrderReversed(this) ) - for(unsigned int i = unsigned(child.size()); i>0;) - static_cast(child[--i].get())->executeVisitorTopDown(action,executedNodes,statusMap,visitorRoot); - else - for(unsigned int i = 0; i(child[i].get())->executeVisitorTopDown(action,executedNodes,statusMap,visitorRoot); - } - else - { - // execute the visitor on this node - const Visitor::Result result = action->processNodeTopDown(this); - - // update status - statusMap[this] = ( result == simulation::Visitor::RESULT_PRUNE ? PRUNED : VISITED ); - - executedNodes.push_back(this); - - // ... and continue the recursion - if( action->childOrderReversed(this) ) - for(unsigned int i = unsigned(child.size()); i>0;) - static_cast(child[--i].get())->executeVisitorTopDown(action,executedNodes,statusMap,visitorRoot); - else - for(unsigned int i = 0; i(child[i].get())->executeVisitorTopDown(action,executedNodes,statusMap,visitorRoot); - - } -} - - -// warning nodes that are dynamically created during the traversal, but that have not been traversed during the top-down, won't be traversed during the bottom-up -// TODO is it what we want? -// otherwise it is possible to restart from top, go to leaves and running bottom-up action while going up -void Node::executeVisitorBottomUp( simulation::Visitor* action, NodeList& executedNodes ) -{ - for( NodeList::reverse_iterator it = executedNodes.rbegin(), itend = executedNodes.rend() ; it != itend ; ++it ) - { - (*it)->updateDescendancy(); - action->processNodeBottomUp( *it ); - } -} - - -void Node::setDirtyDescendancy() -{ - _descendancy.clear(); - const LinkParents::Container &parents = l_parents.getValue(); - for ( unsigned int i = 0; i < parents.size() ; i++ ) - { - parents[i]->setDirtyDescendancy(); - } -} - -void Node::updateDescendancy() -{ - if( _descendancy.empty() && !child.empty() ) - { - for(unsigned int i = 0; i(child[i].get()); - dagnode->updateDescendancy(); - _descendancy.insert( dagnode->_descendancy.begin(), dagnode->_descendancy.end() ); - _descendancy.insert( dagnode ); - } - } -} - - - -void Node::executeVisitorTreeTraversal( simulation::Visitor* action, StatusMap& statusMap, Visitor::TreeTraversalRepetition repeat, bool alreadyRepeated ) -{ - if( !this->isActive() ) - { - // do not execute the visitor on this node - statusMap[this] = PRUNED; - return; - } - - if( this->isSleeping() && !action->canAccessSleepingNode ) - { - // do not execute the visitor on this node - statusMap[this] = PRUNED; - return; - } - - // node already visited and repetition must be avoid - if( statusMap[this] != NOT_VISITED ) - { - if( repeat==Visitor::NO_REPETITION || ( alreadyRepeated && repeat==Visitor::REPEAT_ONCE ) ) return; - else alreadyRepeated = true; - } - - if( action->processNodeTopDown(this) != simulation::Visitor::RESULT_PRUNE ) - { - statusMap[this] = VISITED; - if( action->childOrderReversed(this) ) - for(unsigned int i = unsigned(child.size()); i>0;) - static_cast(child[--i].get())->executeVisitorTreeTraversal(action,statusMap,repeat,alreadyRepeated); - else - for(unsigned int i = 0; i(child[i].get())->executeVisitorTreeTraversal(action,statusMap,repeat,alreadyRepeated); - } - else - { - statusMap[this] = PRUNED; - } - - action->processNodeBottomUp(this); -} - - -void Node::initVisualContext() -{ - if (getNbParents()) - { - this->setDisplayWorldGravity(false); //only display gravity for the root: it will be propagated at each time step - } -} - -void Node::updateContext() -{ - sofa::core::objectmodel::BaseNode* firstParent = getFirstParent(); - - if ( firstParent ) - { - if( debug_ ) - { - msg_info()<<"Node::updateContext, node = "< NodeClass("Node"); - -} // namespace sofa::simulation::graph From a3a1734036fc859e64da876fd80d4745574f7ad0 Mon Sep 17 00:00:00 2001 From: Damien Marchal Date: Fri, 27 Jun 2025 23:38:16 +0200 Subject: [PATCH 04/19] FIXUP forward declaration of BaseMechanicalstate --- Sofa/framework/Core/src/sofa/core/fwd.h | 1 + .../Simulation/Core/src/sofa/simulation/Visitor.h | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Sofa/framework/Core/src/sofa/core/fwd.h b/Sofa/framework/Core/src/sofa/core/fwd.h index 622a30e1394..33b99fdc89c 100644 --- a/Sofa/framework/Core/src/sofa/core/fwd.h +++ b/Sofa/framework/Core/src/sofa/core/fwd.h @@ -110,6 +110,7 @@ class BaseInteractionForceField; class BaseProjectiveConstraintSet; class BaseInteractionProjectiveConstraintSet; class BaseInteractionConstraint; +class BaseMechanicalState; class LinearSolver; class MultiMatrixAccessor; diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/Visitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/Visitor.h index f64eb8e801f..f24d6173b09 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/Visitor.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/Visitor.h @@ -190,11 +190,11 @@ class SOFA_SIMULATION_CORE_API Visitor static void printNode(const char* type); static void printCloseNode(const char* type); - static void printVector(core::behavior::BaseMechanicalState *mm, core::ConstVecId id); + static void printVector(sofa::core::behavior::BaseMechanicalState *mm, sofa::core::ConstVecId id); - virtual void printInfo(const core::objectmodel::BaseContext* context, bool dirDown); + virtual void printInfo(const sofa::core::objectmodel::BaseContext* context, bool dirDown); - void setNode(core::objectmodel::Base* c); + void setNode(sofa::core::objectmodel::Base* c); static void EnableExportStateVector(bool activation) {outputStateVector=activation;} static void SetFirstIndexStateVector(unsigned int first) {firstIndexStateVector=first;} @@ -213,7 +213,7 @@ class SOFA_SIMULATION_CORE_API Visitor static ctime_t initDumpTime; static std::vector< ctime_t > initNodeTime; - core::objectmodel::Base* enteringBase; + sofa::core::objectmodel::Base* enteringBase; bool infoPrinted; private: From d3f502bd8131e8f3286844de2debe1779001aa36 Mon Sep 17 00:00:00 2001 From: Damien Marchal Date: Mon, 14 Jul 2025 08:36:18 +0200 Subject: [PATCH 05/19] FIX Node refactoring invalid merge. --- Sofa/framework/Simulation/Core/src/sofa/simulation/Node.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.cpp index b35300735fc..df9c4e7d209 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.cpp @@ -1469,7 +1469,7 @@ sofa::core::topology::BaseMeshTopology* Node::getMeshTopologyLink(SearchDirectio return this->meshTopology; if (dir != Local) - return Node::getMeshTopologyLink(dir); + return NODEgetMeshTopologyLink(dir); //local case similar to getActiveMeshTopology ... From 2a3482f4531d20b4c2e961df1b207fa7ba456fda Mon Sep 17 00:00:00 2001 From: Damien Marchal Date: Mon, 14 Jul 2025 16:00:56 +0200 Subject: [PATCH 06/19] Remove DAGNode and DAGSimulation --- .../src/sofa/simulation/common/init.cpp | 3 +- .../Core/src/sofa/simulation/Simulation.cpp | 14 +++++++ .../Core/src/sofa/simulation/Simulation.h | 6 +-- .../src/sofa/simulation/graph/DAGNode.cpp | 31 --------------- .../sofa/simulation/graph/DAGSimulation.cpp | 39 ------------------- .../src/sofa/simulation/graph/DAGSimulation.h | 20 +--------- 6 files changed, 20 insertions(+), 93 deletions(-) diff --git a/Sofa/framework/Simulation/Common/src/sofa/simulation/common/init.cpp b/Sofa/framework/Simulation/Common/src/sofa/simulation/common/init.cpp index e6622d961b7..ea9a1dfdb2c 100644 --- a/Sofa/framework/Simulation/Common/src/sofa/simulation/common/init.cpp +++ b/Sofa/framework/Simulation/Common/src/sofa/simulation/common/init.cpp @@ -35,7 +35,8 @@ static bool s_initialized = false; static bool s_cleanedUp = false; //create method of Node called if the user wants the default node. The object created will depend on the simulation currently in use. -SOFA_SIMULATION_COMMON_API sofa::helper::Creator NodeClass("default"); +SOFA_SIMULATION_COMMON_API sofa::helper::Creator defaultNodeClassRegistration("default"); +SOFA_SIMULATION_COMMON_API sofa::helper::Creator nodeClassRegistration("Node"); SOFA_SIMULATION_COMMON_API void init() { diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp index cfade426869..79e58e3540f 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp @@ -487,4 +487,18 @@ Simulation* getSimulation() return Simulation::theSimulation.get(); } +/// create a new graph(or tree) and return its root node. +NodeSPtr Simulation::createNewGraph(const std::string& name) +{ + return createNewNode( name ); +} + +NodeSPtr Simulation::createNewNode(const std::string& name) +{ + return sofa::core::objectmodel::New(name); +} + +bool Simulation::isDirectedAcyclicGraph() { return true; } + + } // namespace sofa::simulation diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h index a6befd116e5..342dd5c50d2 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h @@ -103,13 +103,13 @@ class SOFA_SIMULATION_CORE_API Simulation Simulation& operator=(const Simulation& n) = delete; /// create a new graph(or tree) and return its root node. - virtual NodeSPtr createNewGraph(const std::string& name)=0;//Todo replace newNode method + virtual NodeSPtr createNewGraph(const std::string& name);//Todo replace newNode method /// creates and returns a new node. - virtual NodeSPtr createNewNode(const std::string& name)=0; + virtual NodeSPtr createNewNode(const std::string& name); /// Can the simulation handle a directed acyclic graph? - virtual bool isDirectedAcyclicGraph() = 0; + virtual bool isDirectedAcyclicGraph(); inline static Simulation::SPtr theSimulation { nullptr }; }; diff --git a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGNode.cpp b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGNode.cpp index 4507024ebd5..e69de29bb2d 100644 --- a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGNode.cpp +++ b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGNode.cpp @@ -1,31 +0,0 @@ -/****************************************************************************** -* SOFA, Simulation Open-Framework Architecture * -* (c) 2006 INRIA, USTL, UJF, CNRS, MGH * -* * -* This program is free software; you can redistribute it and/or modify it * -* under the terms of the GNU Lesser General Public License as published by * -* the Free Software Foundation; either version 2.1 of the License, or (at * -* your option) any later version. * -* * -* This program is distributed in the hope that it will be useful, but WITHOUT * -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * -* for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with this program. If not, see . * -******************************************************************************* -* Authors: The SOFA Team and external contributors (see Authors.txt) * -* * -* Contact information: contact@sofa-framework.org * -******************************************************************************/ -#include -#include - -namespace sofa::simulation -{ - -//helper::Creator NodeDefaultClass("default"); -static helper::Creator NodeClass("Node"); - -} diff --git a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.cpp b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.cpp index baa0bbf1a22..07a5b93af86 100644 --- a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.cpp +++ b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.cpp @@ -19,42 +19,3 @@ * * * Contact information: contact@sofa-framework.org * ******************************************************************************/ -#include - -#include -#include -#include - -#include -#include -#include - -namespace sofa::simulation::graph -{ - -using namespace sofa::defaulttype; - - -DAGSimulation::DAGSimulation() -{ - // Safety check; it could be elsewhere, but here is a good place, I guess. - if (!sofa::simulation::graph::isInitialized()) - sofa::helper::printUninitializedLibraryWarning("Sofa.Simulation.Graph", "sofa::simulation::graph::init()"); -} - -DAGSimulation::~DAGSimulation() -{ - -} - -Node::SPtr DAGSimulation::createNewGraph(const std::string& name) -{ - return createNewNode( name ); -} - -Node::SPtr DAGSimulation::createNewNode(const std::string& name) -{ - return sofa::core::objectmodel::New(name); -} - -} // namespace sofa::simulation::graph diff --git a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.h b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.h index 00f00178a23..9a46c12e3ee 100644 --- a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.h +++ b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.h @@ -30,24 +30,6 @@ namespace sofa::simulation::graph { -/** Main controller of the scene. -Defines how the scene is inited at the beginning, and updated at each time step. -Derives from BaseObject in order to model the parameters as Datas, which makes their edition easy in the GUI. - */ -class SOFA_SIMULATION_GRAPH_API DAGSimulation: public Simulation -{ -public: - DAGSimulation(); - ~DAGSimulation() override; // this is a terminal class - - /// create a new graph(or tree) and return its root node. - virtual NodeSPtr createNewGraph(const std::string& name) override; - - /// creates and returns a new node. - virtual NodeSPtr createNewNode(const std::string& name) override; - - /// Can the simulation handle a directed acyclic graph? - bool isDirectedAcyclicGraph() override { return true; } -}; +using DAGSimulation = Simulation; } // namespace sofa::simulation::graph From 9ba0c0b60e9bdc18590b28cd1c473696716f4278 Mon Sep 17 00:00:00 2001 From: Damien Marchal Date: Mon, 14 Jul 2025 16:10:03 +0200 Subject: [PATCH 07/19] Move Simulation's singleton initialization from graph/init.cpp to Simulation.cpp Not perfect but much better. Next step is to remove the singleton. --- .../Simulation/Core/src/sofa/simulation/Simulation.cpp | 2 ++ Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h | 2 +- .../Simulation/Graph/src/sofa/simulation/graph/init.cpp | 1 - 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp index 79e58e3540f..e42b522d989 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp @@ -501,4 +501,6 @@ NodeSPtr Simulation::createNewNode(const std::string& name) bool Simulation::isDirectedAcyclicGraph() { return true; } +sofa::simulation::Simulation::SPtr sofa::simulation::Simulation::theSimulation = std::make_shared(); + } // namespace sofa::simulation diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h index 342dd5c50d2..848ba9ee832 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h @@ -111,7 +111,7 @@ class SOFA_SIMULATION_CORE_API Simulation /// Can the simulation handle a directed acyclic graph? virtual bool isDirectedAcyclicGraph(); - inline static Simulation::SPtr theSimulation { nullptr }; + static Simulation::SPtr theSimulation; }; } // namespace sofa::simulation diff --git a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/init.cpp b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/init.cpp index 4d1fa04597f..d8d62c33432 100644 --- a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/init.cpp +++ b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/init.cpp @@ -37,7 +37,6 @@ SOFA_SIMULATION_GRAPH_API void init() { sofa::simulation::common::init(); s_initialized = true; - sofa::simulation::Simulation::theSimulation = std::make_shared(); } } From d6d5603dcd35fa03042657565c220a02d41ff441 Mon Sep 17 00:00:00 2001 From: Damien Marchal Date: Mon, 14 Jul 2025 16:43:45 +0200 Subject: [PATCH 08/19] [Sofa.Simulation.Core] Clean of Simulation --- Sofa/framework/Core/src/sofa/core/fwd.h | 1 + .../src/sofa/simpleapi/SimpleApi.cpp | 4 ++-- .../SimpleApi/src/sofa/simpleapi/SimpleApi.h | 8 ++++---- .../Core/src/sofa/simulation/Node.inl | 10 +++------- .../Core/src/sofa/simulation/Simulation.cpp | 19 +++++-------------- .../Core/src/sofa/simulation/Simulation.h | 12 ++---------- .../Simulation/Core/src/sofa/simulation/fwd.h | 2 +- 7 files changed, 18 insertions(+), 38 deletions(-) diff --git a/Sofa/framework/Core/src/sofa/core/fwd.h b/Sofa/framework/Core/src/sofa/core/fwd.h index 33b99fdc89c..bdeda1ee1ad 100644 --- a/Sofa/framework/Core/src/sofa/core/fwd.h +++ b/Sofa/framework/Core/src/sofa/core/fwd.h @@ -73,6 +73,7 @@ namespace sofa::core::objectmodel { class Base; class BaseObject; +class BaseObjectDescription; class BaseNode; class BaseContext; class BaseData; diff --git a/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.cpp b/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.cpp index 63555fcb1d4..99c7664f2d7 100644 --- a/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.cpp +++ b/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.cpp @@ -60,7 +60,7 @@ void dumpScene(Node::SPtr root) p.execute(root.get()) ; } -Simulation::SPtr createSimulation(const std::string& type) +SimulationSPtr createSimulation(const std::string& type) { if(type!="DAG") { @@ -68,7 +68,7 @@ Simulation::SPtr createSimulation(const std::string& type) return nullptr ; } - return std::make_shared(); + return std::make_shared(); } diff --git a/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.h b/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.h index e7b6fc4fa82..3b2022a893b 100644 --- a/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.h +++ b/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.h @@ -22,7 +22,6 @@ #pragma once #include - #include #include @@ -36,15 +35,16 @@ namespace sofa::simpleapi using sofa::core::objectmodel::BaseObject; using sofa::core::objectmodel::BaseObjectDescription; -using sofa::simulation::Simulation ; +using sofa::simulation::Simulation; +using sofa::simulation::SimulationSPtr ; using sofa::simulation::Node ; using sofa::simulation::NodeSPtr ; bool SOFA_SIMPLEAPI_API importPlugin(const std::string& name) ; -Simulation::SPtr SOFA_SIMPLEAPI_API createSimulation(const std::string& type="DAG") ; +SimulationSPtr SOFA_SIMPLEAPI_API createSimulation(const std::string& type="DAG") ; -NodeSPtr SOFA_SIMPLEAPI_API createRootNode( Simulation::SPtr, const std::string& name, +NodeSPtr SOFA_SIMPLEAPI_API createRootNode( SimulationSPtr, const std::string& name, const std::map& params = std::map{} ); NodeSPtr SOFA_SIMPLEAPI_API createRootNode( Simulation* s, const std::string& name, diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.inl b/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.inl index 14cf15f7a1c..b2467477125 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.inl +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.inl @@ -29,13 +29,9 @@ namespace sofa::simulation template Node::SPtr Node::create( RealObject*, sofa::core::objectmodel::BaseObjectDescription* arg) { - if (Simulation* simulation = getSimulation()) - { - Node::SPtr obj = simulation->createNewNode(arg->getName()); - obj->parse(arg); - return obj; - } - return nullptr; + Node::SPtr obj = getSimulation()->createNewNode(arg->getName()); + obj->parse(arg); + return obj; } } diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp index e42b522d989..5177f080bec 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp @@ -472,21 +472,15 @@ void unload(NodeSPtr root) } } -Simulation::Simulation() -{ - // Safety check; it could be elsewhere, but here is a good place, I guess. - if (!sofa::simulation::core::isInitialized()) - sofa::helper::printUninitializedLibraryWarning("Sofa.Simulation.Core", "sofa::simulation::common::init()"); -} - -Simulation::~Simulation() -{} - +Simulation theSimulation; Simulation* getSimulation() { - return Simulation::theSimulation.get(); + return &theSimulation; } +Simulation::Simulation(){} +Simulation::~Simulation(){} + /// create a new graph(or tree) and return its root node. NodeSPtr Simulation::createNewGraph(const std::string& name) { @@ -500,7 +494,4 @@ NodeSPtr Simulation::createNewNode(const std::string& name) bool Simulation::isDirectedAcyclicGraph() { return true; } - -sofa::simulation::Simulation::SPtr sofa::simulation::Simulation::theSimulation = std::make_shared(); - } // namespace sofa::simulation diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h index 848ba9ee832..5b9d0f08463 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h @@ -22,14 +22,8 @@ #pragma once #include -#include -#include - -namespace sofa::simulation -{ - class Node; - typedef sofa::core::sptr NodeSPtr; -} +#include +#include namespace sofa::simulation { @@ -110,8 +104,6 @@ class SOFA_SIMULATION_CORE_API Simulation /// Can the simulation handle a directed acyclic graph? virtual bool isDirectedAcyclicGraph(); - - static Simulation::SPtr theSimulation; }; } // namespace sofa::simulation diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/fwd.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/fwd.h index f8ab1cf945e..460e575c789 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/fwd.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/fwd.h @@ -34,7 +34,7 @@ namespace sofa::simulation typedef sofa::core::sptr NodeSPtr; class Simulation; - typedef sofa::core::sptr SimulationSPtr; + using SimulationSPtr = std::shared_ptr; /** Get the (unique) simulation which controls the scene. Automatically creates one if no Simulation has been set. From db0bcb66b5963e43919c4d5082d51ea798e27d78 Mon Sep 17 00:00:00 2001 From: Damien Marchal Date: Mon, 14 Jul 2025 17:05:37 +0200 Subject: [PATCH 09/19] Bye bye DAGNode --- .../tests/CollisionPipeline_test.cpp | 3 -- .../tests/LocalMinDistance_test.cpp | 3 +- .../Analyze/tests/AverageCoord_test.cpp | 3 +- .../Analyze/tests/ClusteringEngine_test.cpp | 3 +- .../ExtrudeEdgesAndGenerateQuads_test.cpp | 3 +- .../Generate/tests/MergePoints_test.cpp | 3 +- .../Engine/Select/tests/BoxROI_test.cpp | 3 +- .../Select/tests/ComplementaryROI_test.cpp | 3 +- .../Engine/Select/tests/MeshROI_test.cpp | 3 +- .../Engine/Select/tests/PlaneROI_test.cpp | 3 +- .../Engine/Select/tests/SphereROI_test.cpp | 3 +- .../Transform/tests/DifferenceEngine_test.cpp | 3 +- .../Transform/tests/DilateEngine_test.cpp | 3 +- .../Transform/tests/SmoothMeshEngine_test.cpp | 3 +- .../IO/Mesh/tests/MeshExporter_test.cpp | 3 -- .../IO/Mesh/tests/STLExporter_test.cpp | 3 -- .../tests/VisualModelOBJExporter_test.cpp | 3 -- .../Linear/tests/BarycentricMapping_test.cpp | 7 +-- .../tests/DistanceToPlaneMapping_test.cpp | 14 ++--- .../Component/Mass/tests/UniformMass_test.cpp | 3 -- .../tests/PlaneForceField_test.cpp | 5 +- .../Backward/tests/StaticSolver_test.cpp | 2 - .../tests/MessageHandlerComponent_test.cpp | 3 -- .../src/sofa/simpleapi/SimpleApi.cpp | 3 -- .../Core/src/sofa/simulation/Simulation.cpp | 4 ++ .../Core/src/sofa/simulation/Simulation.h | 52 ------------------- .../Simulation/Core/src/sofa/simulation/fwd.h | 51 ++++++++++++++++++ .../src/sofa/simulation/graph/DAGSimulation.h | 4 +- .../src/SceneCreator/SceneCreator.cpp | 2 - .../src/SceneCreator/SceneUtils.cpp | 2 - applications/projects/runSofa/Main.cpp | 5 +- 31 files changed, 78 insertions(+), 130 deletions(-) diff --git a/Sofa/Component/Collision/Detection/Algorithm/tests/CollisionPipeline_test.cpp b/Sofa/Component/Collision/Detection/Algorithm/tests/CollisionPipeline_test.cpp index 75536b51a12..225947eaa15 100644 --- a/Sofa/Component/Collision/Detection/Algorithm/tests/CollisionPipeline_test.cpp +++ b/Sofa/Component/Collision/Detection/Algorithm/tests/CollisionPipeline_test.cpp @@ -34,9 +34,6 @@ using sofa::core::objectmodel::BaseObject ; #include using sofa::component::collision::detection::algorithm::CollisionPipeline ; -#include -using sofa::simulation::graph::DAGSimulation ; - #include using sofa::simulation::Node ; diff --git a/Sofa/Component/Collision/Detection/Intersection/tests/LocalMinDistance_test.cpp b/Sofa/Component/Collision/Detection/Intersection/tests/LocalMinDistance_test.cpp index 76d43def6a6..566d64d730f 100644 --- a/Sofa/Component/Collision/Detection/Intersection/tests/LocalMinDistance_test.cpp +++ b/Sofa/Component/Collision/Detection/Intersection/tests/LocalMinDistance_test.cpp @@ -29,8 +29,7 @@ using std::string; #include using sofa::testing::BaseSimulationTest; -#include -using sofa::simulation::graph::DAGSimulation ; +#include using sofa::simulation::Node ; #include diff --git a/Sofa/Component/Engine/Analyze/tests/AverageCoord_test.cpp b/Sofa/Component/Engine/Analyze/tests/AverageCoord_test.cpp index 96d9416c4f6..5d755bbcf41 100644 --- a/Sofa/Component/Engine/Analyze/tests/AverageCoord_test.cpp +++ b/Sofa/Component/Engine/Analyze/tests/AverageCoord_test.cpp @@ -27,12 +27,11 @@ using sofa::testing::BaseSimulationTest; #include using sofa::component::statecontainer::MechanicalObject ; -#include +#include using sofa::simulation::Simulation ; using sofa::simulation::Node ; using sofa::core::objectmodel::New ; using sofa::core::objectmodel::BaseData ; -using sofa::simulation::graph::DAGSimulation; #include using sofa::component::engine::analyze::AverageCoord ; diff --git a/Sofa/Component/Engine/Analyze/tests/ClusteringEngine_test.cpp b/Sofa/Component/Engine/Analyze/tests/ClusteringEngine_test.cpp index b57ca438e54..747e930e971 100644 --- a/Sofa/Component/Engine/Analyze/tests/ClusteringEngine_test.cpp +++ b/Sofa/Component/Engine/Analyze/tests/ClusteringEngine_test.cpp @@ -26,12 +26,11 @@ using sofa::testing::BaseSimulationTest; #include using sofa::component::statecontainer::MechanicalObject ; -#include +#include using sofa::simulation::Simulation ; using sofa::simulation::Node ; using sofa::core::objectmodel::New ; using sofa::core::objectmodel::BaseData ; -using sofa::simulation::graph::DAGSimulation; #include using sofa::core::visual::VisualParams; diff --git a/Sofa/Component/Engine/Generate/tests/ExtrudeEdgesAndGenerateQuads_test.cpp b/Sofa/Component/Engine/Generate/tests/ExtrudeEdgesAndGenerateQuads_test.cpp index c7a2fdd853c..65ce5e8a263 100644 --- a/Sofa/Component/Engine/Generate/tests/ExtrudeEdgesAndGenerateQuads_test.cpp +++ b/Sofa/Component/Engine/Generate/tests/ExtrudeEdgesAndGenerateQuads_test.cpp @@ -25,12 +25,11 @@ using sofa::testing::BaseSimulationTest; #include -#include +#include using sofa::simulation::Simulation ; using sofa::simulation::Node ; using sofa::core::objectmodel::New ; using sofa::core::objectmodel::BaseData ; -using sofa::simulation::graph::DAGSimulation; #include using sofa::component::engine::generate::ExtrudeEdgesAndGenerateQuads ; diff --git a/Sofa/Component/Engine/Generate/tests/MergePoints_test.cpp b/Sofa/Component/Engine/Generate/tests/MergePoints_test.cpp index 5f50d949e1f..27457424ec9 100644 --- a/Sofa/Component/Engine/Generate/tests/MergePoints_test.cpp +++ b/Sofa/Component/Engine/Generate/tests/MergePoints_test.cpp @@ -22,8 +22,7 @@ #include using sofa::testing::BaseSimulationTest; -#include -using sofa::simulation::graph::DAGSimulation; +#include using sofa::simulation::Simulation ; using sofa::core::objectmodel::New ; diff --git a/Sofa/Component/Engine/Select/tests/BoxROI_test.cpp b/Sofa/Component/Engine/Select/tests/BoxROI_test.cpp index 08425f2c4cb..9e47440ca84 100644 --- a/Sofa/Component/Engine/Select/tests/BoxROI_test.cpp +++ b/Sofa/Component/Engine/Select/tests/BoxROI_test.cpp @@ -37,9 +37,8 @@ using sofa::core::objectmodel::ComponentState; #include using sofa::component::engine::select::BoxROI; -#include +#include using sofa::simulation::Simulation; -using sofa::simulation::graph::DAGSimulation; #include using sofa::simulation::Node; using sofa::core::objectmodel::BaseObject; diff --git a/Sofa/Component/Engine/Select/tests/ComplementaryROI_test.cpp b/Sofa/Component/Engine/Select/tests/ComplementaryROI_test.cpp index ec055b0321a..48a44458bf9 100644 --- a/Sofa/Component/Engine/Select/tests/ComplementaryROI_test.cpp +++ b/Sofa/Component/Engine/Select/tests/ComplementaryROI_test.cpp @@ -25,12 +25,11 @@ using sofa::testing::BaseSimulationTest; #include -#include +#include using sofa::simulation::Simulation ; using sofa::simulation::Node ; using sofa::core::objectmodel::New ; using sofa::core::objectmodel::BaseData ; -using sofa::simulation::graph::DAGSimulation; #include using sofa::core::visual::VisualParams; diff --git a/Sofa/Component/Engine/Select/tests/MeshROI_test.cpp b/Sofa/Component/Engine/Select/tests/MeshROI_test.cpp index 66867cba9b5..ff9bcf9ee97 100644 --- a/Sofa/Component/Engine/Select/tests/MeshROI_test.cpp +++ b/Sofa/Component/Engine/Select/tests/MeshROI_test.cpp @@ -25,12 +25,11 @@ using sofa::testing::BaseSimulationTest; #include -#include +#include using sofa::simulation::Simulation ; using sofa::simulation::Node ; using sofa::core::objectmodel::New ; using sofa::core::objectmodel::BaseData ; -using sofa::simulation::graph::DAGSimulation; #include using sofa::component::engine::select::MeshROI ; diff --git a/Sofa/Component/Engine/Select/tests/PlaneROI_test.cpp b/Sofa/Component/Engine/Select/tests/PlaneROI_test.cpp index a50e5cb6519..8b7d48f8e2f 100644 --- a/Sofa/Component/Engine/Select/tests/PlaneROI_test.cpp +++ b/Sofa/Component/Engine/Select/tests/PlaneROI_test.cpp @@ -25,12 +25,11 @@ using sofa::testing::BaseSimulationTest; #include -#include +#include using sofa::simulation::Simulation ; using sofa::simulation::Node ; using sofa::core::objectmodel::New ; using sofa::core::objectmodel::BaseData ; -using sofa::simulation::graph::DAGSimulation; #include using sofa::component::engine::select::PlaneROI ; diff --git a/Sofa/Component/Engine/Select/tests/SphereROI_test.cpp b/Sofa/Component/Engine/Select/tests/SphereROI_test.cpp index 0bfb8a12387..317fff9f93c 100644 --- a/Sofa/Component/Engine/Select/tests/SphereROI_test.cpp +++ b/Sofa/Component/Engine/Select/tests/SphereROI_test.cpp @@ -25,12 +25,11 @@ using sofa::testing::BaseSimulationTest; #include -#include +#include using sofa::simulation::Simulation ; using sofa::simulation::Node ; using sofa::core::objectmodel::New ; using sofa::core::objectmodel::BaseData ; -using sofa::simulation::graph::DAGSimulation; #include using sofa::component::engine::select::SphereROI ; diff --git a/Sofa/Component/Engine/Transform/tests/DifferenceEngine_test.cpp b/Sofa/Component/Engine/Transform/tests/DifferenceEngine_test.cpp index d2f7ecddbbd..91d7d47db54 100644 --- a/Sofa/Component/Engine/Transform/tests/DifferenceEngine_test.cpp +++ b/Sofa/Component/Engine/Transform/tests/DifferenceEngine_test.cpp @@ -25,12 +25,11 @@ using sofa::testing::BaseSimulationTest; #include -#include +#include using sofa::simulation::Simulation ; using sofa::simulation::Node ; using sofa::core::objectmodel::New ; using sofa::core::objectmodel::BaseData ; -using sofa::simulation::graph::DAGSimulation; #include using sofa::core::visual::VisualParams; diff --git a/Sofa/Component/Engine/Transform/tests/DilateEngine_test.cpp b/Sofa/Component/Engine/Transform/tests/DilateEngine_test.cpp index bbed29b8fa5..2c64a808610 100644 --- a/Sofa/Component/Engine/Transform/tests/DilateEngine_test.cpp +++ b/Sofa/Component/Engine/Transform/tests/DilateEngine_test.cpp @@ -25,12 +25,11 @@ using sofa::testing::BaseSimulationTest; #include -#include +#include using sofa::simulation::Simulation ; using sofa::simulation::Node ; using sofa::core::objectmodel::New ; using sofa::core::objectmodel::BaseData ; -using sofa::simulation::graph::DAGSimulation; #include using sofa::component::engine::transform::DilateEngine ; diff --git a/Sofa/Component/Engine/Transform/tests/SmoothMeshEngine_test.cpp b/Sofa/Component/Engine/Transform/tests/SmoothMeshEngine_test.cpp index d28d41321e9..303c174e273 100644 --- a/Sofa/Component/Engine/Transform/tests/SmoothMeshEngine_test.cpp +++ b/Sofa/Component/Engine/Transform/tests/SmoothMeshEngine_test.cpp @@ -24,12 +24,11 @@ using sofa::testing::BaseSimulationTest; #include -#include +#include using sofa::simulation::Simulation ; using sofa::simulation::Node ; using sofa::core::objectmodel::New ; using sofa::core::objectmodel::BaseData ; -using sofa::simulation::graph::DAGSimulation; #include using sofa::component::engine::transform::SmoothMeshEngine ; diff --git a/Sofa/Component/IO/Mesh/tests/MeshExporter_test.cpp b/Sofa/Component/IO/Mesh/tests/MeshExporter_test.cpp index 112017d7a2d..c89bc983c1c 100644 --- a/Sofa/Component/IO/Mesh/tests/MeshExporter_test.cpp +++ b/Sofa/Component/IO/Mesh/tests/MeshExporter_test.cpp @@ -33,9 +33,6 @@ using sofa::testing::BaseSimulationTest; #include using sofa::core::objectmodel::BaseObject ; -#include -using sofa::simulation::graph::DAGSimulation ; - #include using sofa::simulation::Node ; diff --git a/Sofa/Component/IO/Mesh/tests/STLExporter_test.cpp b/Sofa/Component/IO/Mesh/tests/STLExporter_test.cpp index 9753bd4101c..1534b318377 100644 --- a/Sofa/Component/IO/Mesh/tests/STLExporter_test.cpp +++ b/Sofa/Component/IO/Mesh/tests/STLExporter_test.cpp @@ -31,9 +31,6 @@ using sofa::testing::BaseSimulationTest; #include using sofa::core::objectmodel::BaseObject ; -#include -using sofa::simulation::graph::DAGSimulation ; - #include using sofa::simulation::Node ; diff --git a/Sofa/Component/IO/Mesh/tests/VisualModelOBJExporter_test.cpp b/Sofa/Component/IO/Mesh/tests/VisualModelOBJExporter_test.cpp index eeb1810bcd0..526563cd35d 100644 --- a/Sofa/Component/IO/Mesh/tests/VisualModelOBJExporter_test.cpp +++ b/Sofa/Component/IO/Mesh/tests/VisualModelOBJExporter_test.cpp @@ -31,9 +31,6 @@ using sofa::testing::BaseSimulationTest; #include using sofa::core::objectmodel::BaseObject ; -#include -using sofa::simulation::graph::DAGSimulation ; - #include using sofa::simulation::Node ; diff --git a/Sofa/Component/Mapping/Linear/tests/BarycentricMapping_test.cpp b/Sofa/Component/Mapping/Linear/tests/BarycentricMapping_test.cpp index 2f923ea9221..4071abd3a44 100644 --- a/Sofa/Component/Mapping/Linear/tests/BarycentricMapping_test.cpp +++ b/Sofa/Component/Mapping/Linear/tests/BarycentricMapping_test.cpp @@ -34,13 +34,12 @@ using sofa::core::topology::BaseMeshTopology; #include using sofa::testing::BaseTest; - using sofa::type::Vec3; using sofa::type::Vec3u; using sofa::core::objectmodel::New; -#include -using sofa::simulation::graph::DAGSimulation; +#include +#include using sofa::simulation::Node ; using sofa::core::objectmodel::New ; using sofa::core::objectmodel::BaseData ; @@ -48,8 +47,6 @@ using sofa::core::objectmodel::BaseData ; #include using sofa::component::statecontainer::MechanicalObject ; -#include - using sofa::defaulttype::Vec3Types; template diff --git a/Sofa/Component/Mapping/Linear/tests/DistanceToPlaneMapping_test.cpp b/Sofa/Component/Mapping/Linear/tests/DistanceToPlaneMapping_test.cpp index 85165f8a9bc..e8fe9ea2215 100644 --- a/Sofa/Component/Mapping/Linear/tests/DistanceToPlaneMapping_test.cpp +++ b/Sofa/Component/Mapping/Linear/tests/DistanceToPlaneMapping_test.cpp @@ -28,9 +28,7 @@ #include "sofa/core/MechanicalParams.h" using sofa::testing::BaseTest; - -#include -using sofa::simulation::graph::DAGSimulation; +#include using sofa::simulation::Node ; using sofa::core::objectmodel::New ; using sofa::core::objectmodel::BaseData ; @@ -53,13 +51,9 @@ class PlaneMappingTest : public testing::Test typedef sofa::type::Vec::spatial_dimensions,typename sofa::Deriv_t::value_type> PlaneNormalType; typedef sofa::type::Vec::spatial_dimensions,typename sofa::Coord_t::value_type> PlanePointType; public: - sofa::simulation::Simulation* createSimpleScene(typename sofa::component::mapping::linear::DistanceToPlaneMapping::SPtr mapping) + Node::SPtr createSimpleScene(typename sofa::component::mapping::linear::DistanceToPlaneMapping::SPtr mapping) { - - - sofa::simulation::Simulation* simu = sofa::simulation::getSimulation(); - - const Node::SPtr node = simu->createNewGraph("root"); + const Node::SPtr node = sofa::simulation::node::createNewNode("root"); typename MechanicalObject::SPtr mechanical = New>(); mechanical->resize(10); @@ -80,7 +74,7 @@ class PlaneMappingTest : public testing::Test EXPECT_NO_THROW( sofa::simulation::node::initRoot(node.get()) ); - return simu; + return node; } PlaneNormalType getPseudoRandomNormal() diff --git a/Sofa/Component/Mass/tests/UniformMass_test.cpp b/Sofa/Component/Mass/tests/UniformMass_test.cpp index b027671c1f5..a7f76feb247 100644 --- a/Sofa/Component/Mass/tests/UniformMass_test.cpp +++ b/Sofa/Component/Mass/tests/UniformMass_test.cpp @@ -30,10 +30,7 @@ using namespace sofa::defaulttype ; using sofa::component::mass::UniformMass ; #include - -#include using sofa::simulation::Simulation ; -using sofa::simulation::graph::DAGSimulation ; #include using sofa::simulation::Node; diff --git a/Sofa/Component/MechanicalLoad/tests/PlaneForceField_test.cpp b/Sofa/Component/MechanicalLoad/tests/PlaneForceField_test.cpp index 20eced1a952..9efb4164b2b 100644 --- a/Sofa/Component/MechanicalLoad/tests/PlaneForceField_test.cpp +++ b/Sofa/Component/MechanicalLoad/tests/PlaneForceField_test.cpp @@ -23,9 +23,8 @@ #include using sofa::testing::BaseSimulationTest; -#include +#include using sofa::simulation::Simulation ; -using sofa::simulation::graph::DAGSimulation ; using sofa::simulation::Node ; using sofa::core::objectmodel::BaseObject ; using sofa::core::objectmodel::BaseData ; @@ -69,8 +68,6 @@ using sofa::component::linearsolver::GraphScatteredMatrix ; using sofa::component::linearsolver::GraphScatteredVector ; using sofa::component::linearsolver::iterative::CGLinearSolver ; -using sofa::simulation::graph::DAGSimulation ; - using sofa::component::mass::UniformMass ; using sofa::component::mechanicalload::PlaneForceField ; diff --git a/Sofa/Component/ODESolver/Backward/tests/StaticSolver_test.cpp b/Sofa/Component/ODESolver/Backward/tests/StaticSolver_test.cpp index 8a78b4dc8fd..ccb1f6fb721 100644 --- a/Sofa/Component/ODESolver/Backward/tests/StaticSolver_test.cpp +++ b/Sofa/Component/ODESolver/Backward/tests/StaticSolver_test.cpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -32,7 +31,6 @@ using namespace sofa::simulation; using namespace sofa::simpleapi; using namespace sofa::helper::logging; -using sofa::simulation::graph::DAGSimulation; using sofa::component::odesolver::backward::StaticSolver; static constexpr SReal poissonRatio = 0; diff --git a/Sofa/Component/SceneUtility/tests/MessageHandlerComponent_test.cpp b/Sofa/Component/SceneUtility/tests/MessageHandlerComponent_test.cpp index 94b69d307c0..40ed35d0a29 100644 --- a/Sofa/Component/SceneUtility/tests/MessageHandlerComponent_test.cpp +++ b/Sofa/Component/SceneUtility/tests/MessageHandlerComponent_test.cpp @@ -27,9 +27,6 @@ using std::string ; #include #include -#include -using sofa::simulation::graph::DAGSimulation ; - #include using sofa::simulation::Node ; diff --git a/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.cpp b/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.cpp index 99c7664f2d7..cbaba2bce62 100644 --- a/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.cpp +++ b/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.cpp @@ -26,9 +26,6 @@ #include using sofa::core::ObjectFactory ; -#include -using sofa::simulation::graph::DAGSimulation ; - #include using sofa::simulation::Node; using sofa::core::objectmodel::BaseObjectDescription ; diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp index 5177f080bec..b96fb431063 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp @@ -78,6 +78,10 @@ using namespace sofa; namespace node { +NodeSPtr createNewNode(const std::string& name){ + return sofa::core::objectmodel::New(name); +} + void initRoot(Node* root) { SCOPED_TIMER("Simulation::init"); diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h index 5b9d0f08463..889da81ee05 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h @@ -28,58 +28,6 @@ namespace sofa::simulation { -namespace node -{ - -/// Initialize the objects -void SOFA_SIMULATION_CORE_API initRoot(Node* root); -///Init a node without changing the context of the simulation. -void SOFA_SIMULATION_CORE_API init(Node* node); -/// Print all object in the graph in XML format -void SOFA_SIMULATION_CORE_API exportInXML(Node* root, const char* fileName); -/// Print all object in the graph -void SOFA_SIMULATION_CORE_API print(Node* root); -/// Update contexts. Required before drawing the scene if root flags are modified. -void SOFA_SIMULATION_CORE_API updateVisualContext(Node* root); -/// Execute one timestep. If dt is 0, the dt parameter in the graph will be used -void SOFA_SIMULATION_CORE_API animate(Node* root, SReal dt=0.0); -/// Update the Visual Models: triggers the Mappings -void SOFA_SIMULATION_CORE_API updateVisual(Node* root); -/// Reset to initial state -void SOFA_SIMULATION_CORE_API reset(Node* root); -/// Initialize the textures -void SOFA_SIMULATION_CORE_API initTextures(Node* root); -/// Update contexts. Required before drawing the scene if root flags are modified. -void SOFA_SIMULATION_CORE_API updateContext(Node* root); - -/** Compute the bounding box of the scene. - * If init is set to "true", then minBBox and maxBBox will be initialised to a default value - * @warning MechanicalObjects with showObject member set to false are ignored - * @sa computeTotalBBox(Node* root, SReal* minBBox, SReal* maxBBox) - */ -void SOFA_SIMULATION_CORE_API computeBBox(Node* root, SReal* minBBox, SReal* maxBBox, bool init=true); - -/** Compute the bounding box of the scene. - * Includes all objects, may they be displayed or not. - * @sa computeBBox(Node* root, SReal* minBBox, SReal* maxBBox, bool init=true) - * @deprecated - */ -void SOFA_SIMULATION_CORE_API computeTotalBBox(Node* root, SReal* minBBox, SReal* maxBBox); -/// Render the scene -void SOFA_SIMULATION_CORE_API draw(sofa::core::visual::VisualParams* vparams, Node* root); -/// Export a scene to an OBJ 3D Scene -void SOFA_SIMULATION_CORE_API exportOBJ(Node* root, const char* filename, bool exportMTL = true); -/// Print all objects in the graph in the given file (format is given by the filename extension) -void SOFA_SIMULATION_CORE_API exportGraph(Node* root, const char* filename=nullptr); -/// Dump the current state in the given stream -void SOFA_SIMULATION_CORE_API dumpState( Node* root, std::ofstream& out ); -/// Load a scene from a file -NodeSPtr SOFA_SIMULATION_CORE_API load(const std::string& /* filename */, bool reload = false, const std::vector& sceneArgs = std::vector(0)); -/// Unload a scene from a Node. -void SOFA_SIMULATION_CORE_API unload(NodeSPtr root); - -} - /** Main controller of the scene. Defines how the scene is inited at the beginning, and updated at each time step. Derives from Base in order to use smart pointers and model the parameters as Datas, which makes their edition easy in the GUI. diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/fwd.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/fwd.h index 460e575c789..38466120ee3 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/fwd.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/fwd.h @@ -51,6 +51,57 @@ namespace sofa::simulation::node { SOFA_SIMULATION_CORE_API sofa::core::objectmodel::BaseContext* toBaseContext(Node*); SOFA_SIMULATION_CORE_API Node* getNodeFrom(sofa::core::objectmodel::BaseContext*); + +// Create a new node; +NodeSPtr createNewNode(const std::string& name); + +/// Initialize the objects +void SOFA_SIMULATION_CORE_API initRoot(Node* root); +///Init a node without changing the context of the simulation. +void SOFA_SIMULATION_CORE_API init(Node* node); +/// Print all object in the graph in XML format +void SOFA_SIMULATION_CORE_API exportInXML(Node* root, const char* fileName); +/// Print all object in the graph +void SOFA_SIMULATION_CORE_API print(Node* root); +/// Update contexts. Required before drawing the scene if root flags are modified. +void SOFA_SIMULATION_CORE_API updateVisualContext(Node* root); +/// Execute one timestep. If dt is 0, the dt parameter in the graph will be used +void SOFA_SIMULATION_CORE_API animate(Node* root, SReal dt=0.0); +/// Update the Visual Models: triggers the Mappings +void SOFA_SIMULATION_CORE_API updateVisual(Node* root); +/// Reset to initial state +void SOFA_SIMULATION_CORE_API reset(Node* root); +/// Initialize the textures +void SOFA_SIMULATION_CORE_API initTextures(Node* root); +/// Update contexts. Required before drawing the scene if root flags are modified. +void SOFA_SIMULATION_CORE_API updateContext(Node* root); + +/** Compute the bounding box of the scene. + * If init is set to "true", then minBBox and maxBBox will be initialised to a default value + * @warning MechanicalObjects with showObject member set to false are ignored + * @sa computeTotalBBox(Node* root, SReal* minBBox, SReal* maxBBox) + */ +void SOFA_SIMULATION_CORE_API computeBBox(Node* root, SReal* minBBox, SReal* maxBBox, bool init=true); + +/** Compute the bounding box of the scene. + * Includes all objects, may they be displayed or not. + * @sa computeBBox(Node* root, SReal* minBBox, SReal* maxBBox, bool init=true) + * @deprecated + */ +void SOFA_SIMULATION_CORE_API computeTotalBBox(Node* root, SReal* minBBox, SReal* maxBBox); +/// Render the scene +void SOFA_SIMULATION_CORE_API draw(sofa::core::visual::VisualParams* vparams, Node* root); +/// Export a scene to an OBJ 3D Scene +void SOFA_SIMULATION_CORE_API exportOBJ(Node* root, const char* filename, bool exportMTL = true); +/// Print all objects in the graph in the given file (format is given by the filename extension) +void SOFA_SIMULATION_CORE_API exportGraph(Node* root, const char* filename=nullptr); +/// Dump the current state in the given stream +void SOFA_SIMULATION_CORE_API dumpState( Node* root, std::ofstream& out ); +/// Load a scene from a file +NodeSPtr SOFA_SIMULATION_CORE_API load(const std::string& /* filename */, bool reload = false, const std::vector& sceneArgs = std::vector(0)); +/// Unload a scene from a Node. +void SOFA_SIMULATION_CORE_API unload(NodeSPtr root); + } namespace sofa::core diff --git a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.h b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.h index 9a46c12e3ee..c3b2177b424 100644 --- a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.h +++ b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.h @@ -29,7 +29,5 @@ namespace sofa::simulation::graph { - -using DAGSimulation = Simulation; - + using DAGSimulation = Simulation; } // namespace sofa::simulation::graph diff --git a/applications/plugins/SceneCreator/src/SceneCreator/SceneCreator.cpp b/applications/plugins/SceneCreator/src/SceneCreator/SceneCreator.cpp index 61ab852d8b2..febbd3e8e02 100644 --- a/applications/plugins/SceneCreator/src/SceneCreator/SceneCreator.cpp +++ b/applications/plugins/SceneCreator/src/SceneCreator/SceneCreator.cpp @@ -24,7 +24,6 @@ #include #include -#include #include "GetVectorVisitor.h" #include "GetAssembledSizeVisitor.h" @@ -50,7 +49,6 @@ using namespace sofa::defaulttype ; using type::vector; -using sofa::simulation::graph::DAGSimulation ; using sofa::simulation::GetAssembledSizeVisitor ; using sofa::simulation::GetVectorVisitor ; using sofa::simulation::Node ; diff --git a/applications/plugins/SceneCreator/src/SceneCreator/SceneUtils.cpp b/applications/plugins/SceneCreator/src/SceneCreator/SceneUtils.cpp index 991f3a59e40..70dcebd8692 100644 --- a/applications/plugins/SceneCreator/src/SceneCreator/SceneUtils.cpp +++ b/applications/plugins/SceneCreator/src/SceneCreator/SceneUtils.cpp @@ -22,7 +22,6 @@ #include "SceneCreator.h" #include "SceneUtils.h" -#include #include "GetVectorVisitor.h" #include "GetAssembledSizeVisitor.h" @@ -52,7 +51,6 @@ typedef linearalgebra::FullVector FullVector ; using type::vector; -using sofa::simulation::graph::DAGSimulation ; using sofa::simulation::GetAssembledSizeVisitor ; using sofa::simulation::GetVectorVisitor ; using sofa::simulation::Node ; diff --git a/applications/projects/runSofa/Main.cpp b/applications/projects/runSofa/Main.cpp index 52ddbd3548f..e3f9b385e7d 100644 --- a/applications/projects/runSofa/Main.cpp +++ b/applications/projects/runSofa/Main.cpp @@ -36,7 +36,7 @@ using std::vector; #include #include #include -#include +#include using sofa::simulation::Node; #include #include @@ -59,7 +59,6 @@ using sofa::core::ExecParams ; #include using sofa::helper::Utils; -using sofa::simulation::graph::DAGSimulation; using sofa::helper::system::SetDirectory; using sofa::core::objectmodel::BaseNode ; @@ -471,7 +470,7 @@ int main(int argc, char** argv) const std::vector sceneArgs = sofa::gui::common::ArgumentParser::extra_args(); Node::SPtr groot = sofa::simulation::node::load(fileName, false, sceneArgs); if( !groot ) - groot = sofa::simulation::getSimulation()->createNewGraph(""); + groot = sofa::simulation::node::createNewNode(""); if (!verif.empty()) { From 00acc17f2752ad3cda2c9b67d7e5a3759c2af389 Mon Sep 17 00:00:00 2001 From: Damien Marchal Date: Wed, 16 Jul 2025 17:01:31 +0200 Subject: [PATCH 10/19] Clean of the integration of DAGNode into Node Important things are: - integration of NODEgetMeshTopologyLink into getMeshTopologyLink - refactoring of updateContext, updateVisualContext and updateSimulationContext Some code was shared between them.. so I factorize that into a new method called initializeContexts() non important things are removal of un-needed static_cast --- .../src/sofa/core/objectmodel/Context.cpp | 4 - .../Core/src/sofa/simulation/Node.cpp | 139 +++++++++--------- .../Core/src/sofa/simulation/Node.h | 8 +- 3 files changed, 72 insertions(+), 79 deletions(-) diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Context.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Context.cpp index 1bc2b619271..2c9c3ec331f 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Context.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Context.cpp @@ -130,7 +130,6 @@ void Context::copyContext(const Context& c) // *this = c; copySimulationContext(c); - } @@ -140,9 +139,6 @@ void Context::copySimulationContext(const Context& c) setDt(c.getDt()); setTime(c.getTime()); setAnimate(c.getAnimate()); - - - } } // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.cpp index df9c4e7d209..aa0c484b1f4 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.cpp @@ -112,7 +112,7 @@ Node::Node(const std::string& name, Node* parent) , l_parents(initLink("parents", "Parents nodes in the graph")) { if( parent ) - parent->addChild(dynamic_cast(this)); + parent->addChild(this); _context = this; setName(name); @@ -122,11 +122,8 @@ Node::Node(const std::string& name, Node* parent) Node::~Node() { - for (ChildIterator it = child.begin(), itend = child.end(); it != itend; ++it) - { - const Node::SPtr dagnode = sofa::core::objectmodel::SPtr_static_cast(*it); - dagnode->l_parents.remove(this); - } + for (auto& aChild : child ) + aChild->l_parents.remove(this); } @@ -652,16 +649,6 @@ core::topology::Topology* Node::getTopology() const return get(SearchParents); } -/// Mesh Topology (unified interface for both static and dynamic topologies) -core::topology::BaseMeshTopology* Node::NODEgetMeshTopologyLink(SearchDirection dir) const -{ - SOFA_UNUSED(dir); - if (this->meshTopology) - return this->meshTopology; - else - return get(SearchParents); -} - /// Degrees-of-Freedom core::BaseState* Node::getState() const { @@ -823,7 +810,6 @@ const core::objectmodel::BaseContext* Node::getContext() const return _context; } - void Node::setDefaultVisualContextValue() { //TODO(dmarchal 2017-07-20) please say who have to do that and when it will be done. @@ -852,15 +838,9 @@ void Node::initialize() void Node::updateVisualContext() { - // Apply local modifications to the context - for ( unsigned i=0; iinit(); - contextObject[i]->apply(); - } + initializeContexts(); - if ( debug_ ) - msg_info()<<"Node::updateVisualContext, node = "<sameTopology()) return nullptr; - } - for ( Sequence::iterator i=this->mapping.begin(), iend=this->mapping.end(); i!=iend; ++i ) + + // TODO(dmarchal, 2025-07-16): This tests seems to do exactly the same as the one on MechanicalMapping. + // The test before can probably be removed + // Check if any of the other mapping does not have the same + for ( auto& aMapping : mapping) { - if (!(*i)->sameTopology()) - { + if (!aMapping->sameTopology()) return nullptr; - } } + + // TODO(dmarchal, 2025-07-16): The following code is probably ill-defined, what it does it probably going to search + // in parents... for a topology, priorizing the "first" parent that returns one. It is kind of strange to search in parent + // while because at that step the search is: dir == Local ... so searching in parent is just "weird". + // No mapping with a different topology, continue on to the parents const LinkParents::Container &parents = l_parents.getValue(); for ( unsigned int i = 0; i < parents.size() ; i++ ) @@ -1516,7 +1507,7 @@ void Node::precomputeTraversalOrder( const sofa::core::ExecParams* params ) Result processNodeTopDown(Node* node) override { - _orderList.push_back( static_cast(node) ); + _orderList.push_back(node); return RESULT_CONTINUE; } @@ -1654,10 +1645,10 @@ void Node::executeVisitorTopDown(simulation::Visitor* action, NodeList& executed // ... but continue the recursion anyway! if( action->childOrderReversed(this) ) for(unsigned int i = unsigned(child.size()); i>0;) - static_cast(child[--i].get())->executeVisitorTopDown(action,executedNodes,statusMap,visitorRoot); + child[--i].get()->executeVisitorTopDown(action,executedNodes,statusMap,visitorRoot); else for(unsigned int i = 0; i(child[i].get())->executeVisitorTopDown(action,executedNodes,statusMap,visitorRoot); + child[i].get()->executeVisitorTopDown(action,executedNodes,statusMap,visitorRoot); } else { @@ -1672,10 +1663,10 @@ void Node::executeVisitorTopDown(simulation::Visitor* action, NodeList& executed // ... and continue the recursion if( action->childOrderReversed(this) ) for(unsigned int i = unsigned(child.size()); i>0;) - static_cast(child[--i].get())->executeVisitorTopDown(action,executedNodes,statusMap,visitorRoot); + child[--i].get()->executeVisitorTopDown(action,executedNodes,statusMap,visitorRoot); else for(unsigned int i = 0; i(child[i].get())->executeVisitorTopDown(action,executedNodes,statusMap,visitorRoot); + child[i].get()->executeVisitorTopDown(action,executedNodes,statusMap,visitorRoot); } } @@ -1710,10 +1701,10 @@ void Node::updateDescendancy() { for(unsigned int i = 0; i(child[i].get()); - dagnode->updateDescendancy(); - _descendancy.insert( dagnode->_descendancy.begin(), dagnode->_descendancy.end() ); - _descendancy.insert( dagnode ); + Node* node = child[i].get(); + node->updateDescendancy(); + _descendancy.insert( node->_descendancy.begin(), node->_descendancy.end() ); + _descendancy.insert( node ); } } } @@ -1748,10 +1739,10 @@ void Node::executeVisitorTreeTraversal( simulation::Visitor* action, StatusMap& statusMap[this] = VISITED; if( action->childOrderReversed(this) ) for(unsigned int i = unsigned(child.size()); i>0;) - static_cast(child[--i].get())->executeVisitorTreeTraversal(action,statusMap,repeat,alreadyRepeated); + child[--i].get()->executeVisitorTreeTraversal(action,statusMap,repeat,alreadyRepeated); else for(unsigned int i = 0; i(child[i].get())->executeVisitorTreeTraversal(action,statusMap,repeat,alreadyRepeated); + child[i].get()->executeVisitorTreeTraversal(action,statusMap,repeat,alreadyRepeated); } else { @@ -1761,7 +1752,6 @@ void Node::executeVisitorTreeTraversal( simulation::Visitor* action, StatusMap& action->processNodeBottomUp(this); } - void Node::initVisualContext() { if (getNbParents()) @@ -1770,52 +1760,61 @@ void Node::initVisualContext() } } +void Node::initializeContexts() +{ + for ( unsigned i=0; iinit(); // Call init of a ContextObject (a component in the scene) + contextObject[i]->apply(); // The component copy its internal state in the node's (that is inheriting from Contexte) + } +} + void Node::updateContext() { + // if there is a parent sofa::core::objectmodel::BaseNode* firstParent = getFirstParent(); - if ( firstParent ) { - if( debug_ ) - { - msg_info()<<"Node::updateContext, node = "< Date: Mon, 14 Jul 2025 16:00:56 +0200 Subject: [PATCH 12/19] Remove DAGNode and DAGSimulation --- .../src/sofa/simulation/common/init.cpp | 3 +- .../Core/src/sofa/simulation/Simulation.cpp | 14 +++++++ .../Core/src/sofa/simulation/Simulation.h | 6 +-- .../src/sofa/simulation/graph/DAGNode.cpp | 31 --------------- .../sofa/simulation/graph/DAGSimulation.cpp | 39 ------------------- .../src/sofa/simulation/graph/DAGSimulation.h | 20 +--------- 6 files changed, 20 insertions(+), 93 deletions(-) diff --git a/Sofa/framework/Simulation/Common/src/sofa/simulation/common/init.cpp b/Sofa/framework/Simulation/Common/src/sofa/simulation/common/init.cpp index e6622d961b7..ea9a1dfdb2c 100644 --- a/Sofa/framework/Simulation/Common/src/sofa/simulation/common/init.cpp +++ b/Sofa/framework/Simulation/Common/src/sofa/simulation/common/init.cpp @@ -35,7 +35,8 @@ static bool s_initialized = false; static bool s_cleanedUp = false; //create method of Node called if the user wants the default node. The object created will depend on the simulation currently in use. -SOFA_SIMULATION_COMMON_API sofa::helper::Creator NodeClass("default"); +SOFA_SIMULATION_COMMON_API sofa::helper::Creator defaultNodeClassRegistration("default"); +SOFA_SIMULATION_COMMON_API sofa::helper::Creator nodeClassRegistration("Node"); SOFA_SIMULATION_COMMON_API void init() { diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp index cfade426869..79e58e3540f 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp @@ -487,4 +487,18 @@ Simulation* getSimulation() return Simulation::theSimulation.get(); } +/// create a new graph(or tree) and return its root node. +NodeSPtr Simulation::createNewGraph(const std::string& name) +{ + return createNewNode( name ); +} + +NodeSPtr Simulation::createNewNode(const std::string& name) +{ + return sofa::core::objectmodel::New(name); +} + +bool Simulation::isDirectedAcyclicGraph() { return true; } + + } // namespace sofa::simulation diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h index a6befd116e5..342dd5c50d2 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h @@ -103,13 +103,13 @@ class SOFA_SIMULATION_CORE_API Simulation Simulation& operator=(const Simulation& n) = delete; /// create a new graph(or tree) and return its root node. - virtual NodeSPtr createNewGraph(const std::string& name)=0;//Todo replace newNode method + virtual NodeSPtr createNewGraph(const std::string& name);//Todo replace newNode method /// creates and returns a new node. - virtual NodeSPtr createNewNode(const std::string& name)=0; + virtual NodeSPtr createNewNode(const std::string& name); /// Can the simulation handle a directed acyclic graph? - virtual bool isDirectedAcyclicGraph() = 0; + virtual bool isDirectedAcyclicGraph(); inline static Simulation::SPtr theSimulation { nullptr }; }; diff --git a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGNode.cpp b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGNode.cpp index 4507024ebd5..e69de29bb2d 100644 --- a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGNode.cpp +++ b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGNode.cpp @@ -1,31 +0,0 @@ -/****************************************************************************** -* SOFA, Simulation Open-Framework Architecture * -* (c) 2006 INRIA, USTL, UJF, CNRS, MGH * -* * -* This program is free software; you can redistribute it and/or modify it * -* under the terms of the GNU Lesser General Public License as published by * -* the Free Software Foundation; either version 2.1 of the License, or (at * -* your option) any later version. * -* * -* This program is distributed in the hope that it will be useful, but WITHOUT * -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * -* for more details. * -* * -* You should have received a copy of the GNU Lesser General Public License * -* along with this program. If not, see . * -******************************************************************************* -* Authors: The SOFA Team and external contributors (see Authors.txt) * -* * -* Contact information: contact@sofa-framework.org * -******************************************************************************/ -#include -#include - -namespace sofa::simulation -{ - -//helper::Creator NodeDefaultClass("default"); -static helper::Creator NodeClass("Node"); - -} diff --git a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.cpp b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.cpp index baa0bbf1a22..07a5b93af86 100644 --- a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.cpp +++ b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.cpp @@ -19,42 +19,3 @@ * * * Contact information: contact@sofa-framework.org * ******************************************************************************/ -#include - -#include -#include -#include - -#include -#include -#include - -namespace sofa::simulation::graph -{ - -using namespace sofa::defaulttype; - - -DAGSimulation::DAGSimulation() -{ - // Safety check; it could be elsewhere, but here is a good place, I guess. - if (!sofa::simulation::graph::isInitialized()) - sofa::helper::printUninitializedLibraryWarning("Sofa.Simulation.Graph", "sofa::simulation::graph::init()"); -} - -DAGSimulation::~DAGSimulation() -{ - -} - -Node::SPtr DAGSimulation::createNewGraph(const std::string& name) -{ - return createNewNode( name ); -} - -Node::SPtr DAGSimulation::createNewNode(const std::string& name) -{ - return sofa::core::objectmodel::New(name); -} - -} // namespace sofa::simulation::graph diff --git a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.h b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.h index 00f00178a23..9a46c12e3ee 100644 --- a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.h +++ b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.h @@ -30,24 +30,6 @@ namespace sofa::simulation::graph { -/** Main controller of the scene. -Defines how the scene is inited at the beginning, and updated at each time step. -Derives from BaseObject in order to model the parameters as Datas, which makes their edition easy in the GUI. - */ -class SOFA_SIMULATION_GRAPH_API DAGSimulation: public Simulation -{ -public: - DAGSimulation(); - ~DAGSimulation() override; // this is a terminal class - - /// create a new graph(or tree) and return its root node. - virtual NodeSPtr createNewGraph(const std::string& name) override; - - /// creates and returns a new node. - virtual NodeSPtr createNewNode(const std::string& name) override; - - /// Can the simulation handle a directed acyclic graph? - bool isDirectedAcyclicGraph() override { return true; } -}; +using DAGSimulation = Simulation; } // namespace sofa::simulation::graph From f7755e7cee92a01b38336c15237a2c992fcf8c73 Mon Sep 17 00:00:00 2001 From: Damien Marchal Date: Mon, 14 Jul 2025 16:10:03 +0200 Subject: [PATCH 13/19] Move Simulation's singleton initialization from graph/init.cpp to Simulation.cpp Not perfect but much better. Next step is to remove the singleton. --- .../Simulation/Core/src/sofa/simulation/Simulation.cpp | 2 ++ Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h | 2 +- .../Simulation/Graph/src/sofa/simulation/graph/init.cpp | 1 - 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp index 79e58e3540f..e42b522d989 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp @@ -501,4 +501,6 @@ NodeSPtr Simulation::createNewNode(const std::string& name) bool Simulation::isDirectedAcyclicGraph() { return true; } +sofa::simulation::Simulation::SPtr sofa::simulation::Simulation::theSimulation = std::make_shared(); + } // namespace sofa::simulation diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h index 342dd5c50d2..848ba9ee832 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h @@ -111,7 +111,7 @@ class SOFA_SIMULATION_CORE_API Simulation /// Can the simulation handle a directed acyclic graph? virtual bool isDirectedAcyclicGraph(); - inline static Simulation::SPtr theSimulation { nullptr }; + static Simulation::SPtr theSimulation; }; } // namespace sofa::simulation diff --git a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/init.cpp b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/init.cpp index 4d1fa04597f..d8d62c33432 100644 --- a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/init.cpp +++ b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/init.cpp @@ -37,7 +37,6 @@ SOFA_SIMULATION_GRAPH_API void init() { sofa::simulation::common::init(); s_initialized = true; - sofa::simulation::Simulation::theSimulation = std::make_shared(); } } From 54e96250e864fa85afd7d255a49aa2c9e70313e0 Mon Sep 17 00:00:00 2001 From: Damien Marchal Date: Mon, 14 Jul 2025 16:43:45 +0200 Subject: [PATCH 14/19] [Sofa.Simulation.Core] Clean of Simulation --- Sofa/framework/Core/src/sofa/core/fwd.h | 1 + .../src/sofa/simpleapi/SimpleApi.cpp | 4 ++-- .../SimpleApi/src/sofa/simpleapi/SimpleApi.h | 8 ++++---- .../Core/src/sofa/simulation/Node.inl | 10 +++------- .../Core/src/sofa/simulation/Simulation.cpp | 19 +++++-------------- .../Core/src/sofa/simulation/Simulation.h | 12 ++---------- .../Simulation/Core/src/sofa/simulation/fwd.h | 2 +- 7 files changed, 18 insertions(+), 38 deletions(-) diff --git a/Sofa/framework/Core/src/sofa/core/fwd.h b/Sofa/framework/Core/src/sofa/core/fwd.h index 33b99fdc89c..bdeda1ee1ad 100644 --- a/Sofa/framework/Core/src/sofa/core/fwd.h +++ b/Sofa/framework/Core/src/sofa/core/fwd.h @@ -73,6 +73,7 @@ namespace sofa::core::objectmodel { class Base; class BaseObject; +class BaseObjectDescription; class BaseNode; class BaseContext; class BaseData; diff --git a/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.cpp b/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.cpp index 63555fcb1d4..99c7664f2d7 100644 --- a/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.cpp +++ b/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.cpp @@ -60,7 +60,7 @@ void dumpScene(Node::SPtr root) p.execute(root.get()) ; } -Simulation::SPtr createSimulation(const std::string& type) +SimulationSPtr createSimulation(const std::string& type) { if(type!="DAG") { @@ -68,7 +68,7 @@ Simulation::SPtr createSimulation(const std::string& type) return nullptr ; } - return std::make_shared(); + return std::make_shared(); } diff --git a/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.h b/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.h index e7b6fc4fa82..3b2022a893b 100644 --- a/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.h +++ b/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.h @@ -22,7 +22,6 @@ #pragma once #include - #include #include @@ -36,15 +35,16 @@ namespace sofa::simpleapi using sofa::core::objectmodel::BaseObject; using sofa::core::objectmodel::BaseObjectDescription; -using sofa::simulation::Simulation ; +using sofa::simulation::Simulation; +using sofa::simulation::SimulationSPtr ; using sofa::simulation::Node ; using sofa::simulation::NodeSPtr ; bool SOFA_SIMPLEAPI_API importPlugin(const std::string& name) ; -Simulation::SPtr SOFA_SIMPLEAPI_API createSimulation(const std::string& type="DAG") ; +SimulationSPtr SOFA_SIMPLEAPI_API createSimulation(const std::string& type="DAG") ; -NodeSPtr SOFA_SIMPLEAPI_API createRootNode( Simulation::SPtr, const std::string& name, +NodeSPtr SOFA_SIMPLEAPI_API createRootNode( SimulationSPtr, const std::string& name, const std::map& params = std::map{} ); NodeSPtr SOFA_SIMPLEAPI_API createRootNode( Simulation* s, const std::string& name, diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.inl b/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.inl index 14cf15f7a1c..b2467477125 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.inl +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.inl @@ -29,13 +29,9 @@ namespace sofa::simulation template Node::SPtr Node::create( RealObject*, sofa::core::objectmodel::BaseObjectDescription* arg) { - if (Simulation* simulation = getSimulation()) - { - Node::SPtr obj = simulation->createNewNode(arg->getName()); - obj->parse(arg); - return obj; - } - return nullptr; + Node::SPtr obj = getSimulation()->createNewNode(arg->getName()); + obj->parse(arg); + return obj; } } diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp index e42b522d989..5177f080bec 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp @@ -472,21 +472,15 @@ void unload(NodeSPtr root) } } -Simulation::Simulation() -{ - // Safety check; it could be elsewhere, but here is a good place, I guess. - if (!sofa::simulation::core::isInitialized()) - sofa::helper::printUninitializedLibraryWarning("Sofa.Simulation.Core", "sofa::simulation::common::init()"); -} - -Simulation::~Simulation() -{} - +Simulation theSimulation; Simulation* getSimulation() { - return Simulation::theSimulation.get(); + return &theSimulation; } +Simulation::Simulation(){} +Simulation::~Simulation(){} + /// create a new graph(or tree) and return its root node. NodeSPtr Simulation::createNewGraph(const std::string& name) { @@ -500,7 +494,4 @@ NodeSPtr Simulation::createNewNode(const std::string& name) bool Simulation::isDirectedAcyclicGraph() { return true; } - -sofa::simulation::Simulation::SPtr sofa::simulation::Simulation::theSimulation = std::make_shared(); - } // namespace sofa::simulation diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h index 848ba9ee832..5b9d0f08463 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h @@ -22,14 +22,8 @@ #pragma once #include -#include -#include - -namespace sofa::simulation -{ - class Node; - typedef sofa::core::sptr NodeSPtr; -} +#include +#include namespace sofa::simulation { @@ -110,8 +104,6 @@ class SOFA_SIMULATION_CORE_API Simulation /// Can the simulation handle a directed acyclic graph? virtual bool isDirectedAcyclicGraph(); - - static Simulation::SPtr theSimulation; }; } // namespace sofa::simulation diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/fwd.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/fwd.h index f8ab1cf945e..460e575c789 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/fwd.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/fwd.h @@ -34,7 +34,7 @@ namespace sofa::simulation typedef sofa::core::sptr NodeSPtr; class Simulation; - typedef sofa::core::sptr SimulationSPtr; + using SimulationSPtr = std::shared_ptr; /** Get the (unique) simulation which controls the scene. Automatically creates one if no Simulation has been set. From 3e758a6b7d8f2c07f967608ed4f58168f487ff9c Mon Sep 17 00:00:00 2001 From: Damien Marchal Date: Mon, 14 Jul 2025 17:05:37 +0200 Subject: [PATCH 15/19] Bye bye DAGNode --- .../tests/CollisionPipeline_test.cpp | 3 -- .../tests/LocalMinDistance_test.cpp | 3 +- .../Analyze/tests/AverageCoord_test.cpp | 3 +- .../Analyze/tests/ClusteringEngine_test.cpp | 3 +- .../ExtrudeEdgesAndGenerateQuads_test.cpp | 3 +- .../Generate/tests/MergePoints_test.cpp | 3 +- .../Engine/Select/tests/BoxROI_test.cpp | 3 +- .../Select/tests/ComplementaryROI_test.cpp | 3 +- .../Engine/Select/tests/MeshROI_test.cpp | 3 +- .../Engine/Select/tests/PlaneROI_test.cpp | 3 +- .../Engine/Select/tests/SphereROI_test.cpp | 3 +- .../Transform/tests/DifferenceEngine_test.cpp | 3 +- .../Transform/tests/DilateEngine_test.cpp | 3 +- .../Transform/tests/SmoothMeshEngine_test.cpp | 3 +- .../IO/Mesh/tests/MeshExporter_test.cpp | 3 -- .../IO/Mesh/tests/STLExporter_test.cpp | 3 -- .../tests/VisualModelOBJExporter_test.cpp | 3 -- .../Linear/tests/BarycentricMapping_test.cpp | 7 +-- .../tests/DistanceToPlaneMapping_test.cpp | 14 ++--- .../Component/Mass/tests/UniformMass_test.cpp | 3 -- .../tests/PlaneForceField_test.cpp | 5 +- .../Backward/tests/StaticSolver_test.cpp | 2 - .../tests/MessageHandlerComponent_test.cpp | 3 -- .../src/sofa/simpleapi/SimpleApi.cpp | 3 -- .../Core/src/sofa/simulation/Simulation.cpp | 4 ++ .../Core/src/sofa/simulation/Simulation.h | 52 ------------------- .../Simulation/Core/src/sofa/simulation/fwd.h | 51 ++++++++++++++++++ .../src/sofa/simulation/graph/DAGSimulation.h | 4 +- .../src/SceneCreator/SceneCreator.cpp | 2 - .../src/SceneCreator/SceneUtils.cpp | 2 - applications/projects/runSofa/Main.cpp | 5 +- 31 files changed, 78 insertions(+), 130 deletions(-) diff --git a/Sofa/Component/Collision/Detection/Algorithm/tests/CollisionPipeline_test.cpp b/Sofa/Component/Collision/Detection/Algorithm/tests/CollisionPipeline_test.cpp index 75536b51a12..225947eaa15 100644 --- a/Sofa/Component/Collision/Detection/Algorithm/tests/CollisionPipeline_test.cpp +++ b/Sofa/Component/Collision/Detection/Algorithm/tests/CollisionPipeline_test.cpp @@ -34,9 +34,6 @@ using sofa::core::objectmodel::BaseObject ; #include using sofa::component::collision::detection::algorithm::CollisionPipeline ; -#include -using sofa::simulation::graph::DAGSimulation ; - #include using sofa::simulation::Node ; diff --git a/Sofa/Component/Collision/Detection/Intersection/tests/LocalMinDistance_test.cpp b/Sofa/Component/Collision/Detection/Intersection/tests/LocalMinDistance_test.cpp index 76d43def6a6..566d64d730f 100644 --- a/Sofa/Component/Collision/Detection/Intersection/tests/LocalMinDistance_test.cpp +++ b/Sofa/Component/Collision/Detection/Intersection/tests/LocalMinDistance_test.cpp @@ -29,8 +29,7 @@ using std::string; #include using sofa::testing::BaseSimulationTest; -#include -using sofa::simulation::graph::DAGSimulation ; +#include using sofa::simulation::Node ; #include diff --git a/Sofa/Component/Engine/Analyze/tests/AverageCoord_test.cpp b/Sofa/Component/Engine/Analyze/tests/AverageCoord_test.cpp index 96d9416c4f6..5d755bbcf41 100644 --- a/Sofa/Component/Engine/Analyze/tests/AverageCoord_test.cpp +++ b/Sofa/Component/Engine/Analyze/tests/AverageCoord_test.cpp @@ -27,12 +27,11 @@ using sofa::testing::BaseSimulationTest; #include using sofa::component::statecontainer::MechanicalObject ; -#include +#include using sofa::simulation::Simulation ; using sofa::simulation::Node ; using sofa::core::objectmodel::New ; using sofa::core::objectmodel::BaseData ; -using sofa::simulation::graph::DAGSimulation; #include using sofa::component::engine::analyze::AverageCoord ; diff --git a/Sofa/Component/Engine/Analyze/tests/ClusteringEngine_test.cpp b/Sofa/Component/Engine/Analyze/tests/ClusteringEngine_test.cpp index b57ca438e54..747e930e971 100644 --- a/Sofa/Component/Engine/Analyze/tests/ClusteringEngine_test.cpp +++ b/Sofa/Component/Engine/Analyze/tests/ClusteringEngine_test.cpp @@ -26,12 +26,11 @@ using sofa::testing::BaseSimulationTest; #include using sofa::component::statecontainer::MechanicalObject ; -#include +#include using sofa::simulation::Simulation ; using sofa::simulation::Node ; using sofa::core::objectmodel::New ; using sofa::core::objectmodel::BaseData ; -using sofa::simulation::graph::DAGSimulation; #include using sofa::core::visual::VisualParams; diff --git a/Sofa/Component/Engine/Generate/tests/ExtrudeEdgesAndGenerateQuads_test.cpp b/Sofa/Component/Engine/Generate/tests/ExtrudeEdgesAndGenerateQuads_test.cpp index c7a2fdd853c..65ce5e8a263 100644 --- a/Sofa/Component/Engine/Generate/tests/ExtrudeEdgesAndGenerateQuads_test.cpp +++ b/Sofa/Component/Engine/Generate/tests/ExtrudeEdgesAndGenerateQuads_test.cpp @@ -25,12 +25,11 @@ using sofa::testing::BaseSimulationTest; #include -#include +#include using sofa::simulation::Simulation ; using sofa::simulation::Node ; using sofa::core::objectmodel::New ; using sofa::core::objectmodel::BaseData ; -using sofa::simulation::graph::DAGSimulation; #include using sofa::component::engine::generate::ExtrudeEdgesAndGenerateQuads ; diff --git a/Sofa/Component/Engine/Generate/tests/MergePoints_test.cpp b/Sofa/Component/Engine/Generate/tests/MergePoints_test.cpp index 5f50d949e1f..27457424ec9 100644 --- a/Sofa/Component/Engine/Generate/tests/MergePoints_test.cpp +++ b/Sofa/Component/Engine/Generate/tests/MergePoints_test.cpp @@ -22,8 +22,7 @@ #include using sofa::testing::BaseSimulationTest; -#include -using sofa::simulation::graph::DAGSimulation; +#include using sofa::simulation::Simulation ; using sofa::core::objectmodel::New ; diff --git a/Sofa/Component/Engine/Select/tests/BoxROI_test.cpp b/Sofa/Component/Engine/Select/tests/BoxROI_test.cpp index 08425f2c4cb..9e47440ca84 100644 --- a/Sofa/Component/Engine/Select/tests/BoxROI_test.cpp +++ b/Sofa/Component/Engine/Select/tests/BoxROI_test.cpp @@ -37,9 +37,8 @@ using sofa::core::objectmodel::ComponentState; #include using sofa::component::engine::select::BoxROI; -#include +#include using sofa::simulation::Simulation; -using sofa::simulation::graph::DAGSimulation; #include using sofa::simulation::Node; using sofa::core::objectmodel::BaseObject; diff --git a/Sofa/Component/Engine/Select/tests/ComplementaryROI_test.cpp b/Sofa/Component/Engine/Select/tests/ComplementaryROI_test.cpp index ec055b0321a..48a44458bf9 100644 --- a/Sofa/Component/Engine/Select/tests/ComplementaryROI_test.cpp +++ b/Sofa/Component/Engine/Select/tests/ComplementaryROI_test.cpp @@ -25,12 +25,11 @@ using sofa::testing::BaseSimulationTest; #include -#include +#include using sofa::simulation::Simulation ; using sofa::simulation::Node ; using sofa::core::objectmodel::New ; using sofa::core::objectmodel::BaseData ; -using sofa::simulation::graph::DAGSimulation; #include using sofa::core::visual::VisualParams; diff --git a/Sofa/Component/Engine/Select/tests/MeshROI_test.cpp b/Sofa/Component/Engine/Select/tests/MeshROI_test.cpp index 66867cba9b5..ff9bcf9ee97 100644 --- a/Sofa/Component/Engine/Select/tests/MeshROI_test.cpp +++ b/Sofa/Component/Engine/Select/tests/MeshROI_test.cpp @@ -25,12 +25,11 @@ using sofa::testing::BaseSimulationTest; #include -#include +#include using sofa::simulation::Simulation ; using sofa::simulation::Node ; using sofa::core::objectmodel::New ; using sofa::core::objectmodel::BaseData ; -using sofa::simulation::graph::DAGSimulation; #include using sofa::component::engine::select::MeshROI ; diff --git a/Sofa/Component/Engine/Select/tests/PlaneROI_test.cpp b/Sofa/Component/Engine/Select/tests/PlaneROI_test.cpp index a50e5cb6519..8b7d48f8e2f 100644 --- a/Sofa/Component/Engine/Select/tests/PlaneROI_test.cpp +++ b/Sofa/Component/Engine/Select/tests/PlaneROI_test.cpp @@ -25,12 +25,11 @@ using sofa::testing::BaseSimulationTest; #include -#include +#include using sofa::simulation::Simulation ; using sofa::simulation::Node ; using sofa::core::objectmodel::New ; using sofa::core::objectmodel::BaseData ; -using sofa::simulation::graph::DAGSimulation; #include using sofa::component::engine::select::PlaneROI ; diff --git a/Sofa/Component/Engine/Select/tests/SphereROI_test.cpp b/Sofa/Component/Engine/Select/tests/SphereROI_test.cpp index 0bfb8a12387..317fff9f93c 100644 --- a/Sofa/Component/Engine/Select/tests/SphereROI_test.cpp +++ b/Sofa/Component/Engine/Select/tests/SphereROI_test.cpp @@ -25,12 +25,11 @@ using sofa::testing::BaseSimulationTest; #include -#include +#include using sofa::simulation::Simulation ; using sofa::simulation::Node ; using sofa::core::objectmodel::New ; using sofa::core::objectmodel::BaseData ; -using sofa::simulation::graph::DAGSimulation; #include using sofa::component::engine::select::SphereROI ; diff --git a/Sofa/Component/Engine/Transform/tests/DifferenceEngine_test.cpp b/Sofa/Component/Engine/Transform/tests/DifferenceEngine_test.cpp index d2f7ecddbbd..91d7d47db54 100644 --- a/Sofa/Component/Engine/Transform/tests/DifferenceEngine_test.cpp +++ b/Sofa/Component/Engine/Transform/tests/DifferenceEngine_test.cpp @@ -25,12 +25,11 @@ using sofa::testing::BaseSimulationTest; #include -#include +#include using sofa::simulation::Simulation ; using sofa::simulation::Node ; using sofa::core::objectmodel::New ; using sofa::core::objectmodel::BaseData ; -using sofa::simulation::graph::DAGSimulation; #include using sofa::core::visual::VisualParams; diff --git a/Sofa/Component/Engine/Transform/tests/DilateEngine_test.cpp b/Sofa/Component/Engine/Transform/tests/DilateEngine_test.cpp index bbed29b8fa5..2c64a808610 100644 --- a/Sofa/Component/Engine/Transform/tests/DilateEngine_test.cpp +++ b/Sofa/Component/Engine/Transform/tests/DilateEngine_test.cpp @@ -25,12 +25,11 @@ using sofa::testing::BaseSimulationTest; #include -#include +#include using sofa::simulation::Simulation ; using sofa::simulation::Node ; using sofa::core::objectmodel::New ; using sofa::core::objectmodel::BaseData ; -using sofa::simulation::graph::DAGSimulation; #include using sofa::component::engine::transform::DilateEngine ; diff --git a/Sofa/Component/Engine/Transform/tests/SmoothMeshEngine_test.cpp b/Sofa/Component/Engine/Transform/tests/SmoothMeshEngine_test.cpp index d28d41321e9..303c174e273 100644 --- a/Sofa/Component/Engine/Transform/tests/SmoothMeshEngine_test.cpp +++ b/Sofa/Component/Engine/Transform/tests/SmoothMeshEngine_test.cpp @@ -24,12 +24,11 @@ using sofa::testing::BaseSimulationTest; #include -#include +#include using sofa::simulation::Simulation ; using sofa::simulation::Node ; using sofa::core::objectmodel::New ; using sofa::core::objectmodel::BaseData ; -using sofa::simulation::graph::DAGSimulation; #include using sofa::component::engine::transform::SmoothMeshEngine ; diff --git a/Sofa/Component/IO/Mesh/tests/MeshExporter_test.cpp b/Sofa/Component/IO/Mesh/tests/MeshExporter_test.cpp index 112017d7a2d..c89bc983c1c 100644 --- a/Sofa/Component/IO/Mesh/tests/MeshExporter_test.cpp +++ b/Sofa/Component/IO/Mesh/tests/MeshExporter_test.cpp @@ -33,9 +33,6 @@ using sofa::testing::BaseSimulationTest; #include using sofa::core::objectmodel::BaseObject ; -#include -using sofa::simulation::graph::DAGSimulation ; - #include using sofa::simulation::Node ; diff --git a/Sofa/Component/IO/Mesh/tests/STLExporter_test.cpp b/Sofa/Component/IO/Mesh/tests/STLExporter_test.cpp index 9753bd4101c..1534b318377 100644 --- a/Sofa/Component/IO/Mesh/tests/STLExporter_test.cpp +++ b/Sofa/Component/IO/Mesh/tests/STLExporter_test.cpp @@ -31,9 +31,6 @@ using sofa::testing::BaseSimulationTest; #include using sofa::core::objectmodel::BaseObject ; -#include -using sofa::simulation::graph::DAGSimulation ; - #include using sofa::simulation::Node ; diff --git a/Sofa/Component/IO/Mesh/tests/VisualModelOBJExporter_test.cpp b/Sofa/Component/IO/Mesh/tests/VisualModelOBJExporter_test.cpp index eeb1810bcd0..526563cd35d 100644 --- a/Sofa/Component/IO/Mesh/tests/VisualModelOBJExporter_test.cpp +++ b/Sofa/Component/IO/Mesh/tests/VisualModelOBJExporter_test.cpp @@ -31,9 +31,6 @@ using sofa::testing::BaseSimulationTest; #include using sofa::core::objectmodel::BaseObject ; -#include -using sofa::simulation::graph::DAGSimulation ; - #include using sofa::simulation::Node ; diff --git a/Sofa/Component/Mapping/Linear/tests/BarycentricMapping_test.cpp b/Sofa/Component/Mapping/Linear/tests/BarycentricMapping_test.cpp index 2f923ea9221..4071abd3a44 100644 --- a/Sofa/Component/Mapping/Linear/tests/BarycentricMapping_test.cpp +++ b/Sofa/Component/Mapping/Linear/tests/BarycentricMapping_test.cpp @@ -34,13 +34,12 @@ using sofa::core::topology::BaseMeshTopology; #include using sofa::testing::BaseTest; - using sofa::type::Vec3; using sofa::type::Vec3u; using sofa::core::objectmodel::New; -#include -using sofa::simulation::graph::DAGSimulation; +#include +#include using sofa::simulation::Node ; using sofa::core::objectmodel::New ; using sofa::core::objectmodel::BaseData ; @@ -48,8 +47,6 @@ using sofa::core::objectmodel::BaseData ; #include using sofa::component::statecontainer::MechanicalObject ; -#include - using sofa::defaulttype::Vec3Types; template diff --git a/Sofa/Component/Mapping/Linear/tests/DistanceToPlaneMapping_test.cpp b/Sofa/Component/Mapping/Linear/tests/DistanceToPlaneMapping_test.cpp index 85165f8a9bc..e8fe9ea2215 100644 --- a/Sofa/Component/Mapping/Linear/tests/DistanceToPlaneMapping_test.cpp +++ b/Sofa/Component/Mapping/Linear/tests/DistanceToPlaneMapping_test.cpp @@ -28,9 +28,7 @@ #include "sofa/core/MechanicalParams.h" using sofa::testing::BaseTest; - -#include -using sofa::simulation::graph::DAGSimulation; +#include using sofa::simulation::Node ; using sofa::core::objectmodel::New ; using sofa::core::objectmodel::BaseData ; @@ -53,13 +51,9 @@ class PlaneMappingTest : public testing::Test typedef sofa::type::Vec::spatial_dimensions,typename sofa::Deriv_t::value_type> PlaneNormalType; typedef sofa::type::Vec::spatial_dimensions,typename sofa::Coord_t::value_type> PlanePointType; public: - sofa::simulation::Simulation* createSimpleScene(typename sofa::component::mapping::linear::DistanceToPlaneMapping::SPtr mapping) + Node::SPtr createSimpleScene(typename sofa::component::mapping::linear::DistanceToPlaneMapping::SPtr mapping) { - - - sofa::simulation::Simulation* simu = sofa::simulation::getSimulation(); - - const Node::SPtr node = simu->createNewGraph("root"); + const Node::SPtr node = sofa::simulation::node::createNewNode("root"); typename MechanicalObject::SPtr mechanical = New>(); mechanical->resize(10); @@ -80,7 +74,7 @@ class PlaneMappingTest : public testing::Test EXPECT_NO_THROW( sofa::simulation::node::initRoot(node.get()) ); - return simu; + return node; } PlaneNormalType getPseudoRandomNormal() diff --git a/Sofa/Component/Mass/tests/UniformMass_test.cpp b/Sofa/Component/Mass/tests/UniformMass_test.cpp index b027671c1f5..a7f76feb247 100644 --- a/Sofa/Component/Mass/tests/UniformMass_test.cpp +++ b/Sofa/Component/Mass/tests/UniformMass_test.cpp @@ -30,10 +30,7 @@ using namespace sofa::defaulttype ; using sofa::component::mass::UniformMass ; #include - -#include using sofa::simulation::Simulation ; -using sofa::simulation::graph::DAGSimulation ; #include using sofa::simulation::Node; diff --git a/Sofa/Component/MechanicalLoad/tests/PlaneForceField_test.cpp b/Sofa/Component/MechanicalLoad/tests/PlaneForceField_test.cpp index 20eced1a952..9efb4164b2b 100644 --- a/Sofa/Component/MechanicalLoad/tests/PlaneForceField_test.cpp +++ b/Sofa/Component/MechanicalLoad/tests/PlaneForceField_test.cpp @@ -23,9 +23,8 @@ #include using sofa::testing::BaseSimulationTest; -#include +#include using sofa::simulation::Simulation ; -using sofa::simulation::graph::DAGSimulation ; using sofa::simulation::Node ; using sofa::core::objectmodel::BaseObject ; using sofa::core::objectmodel::BaseData ; @@ -69,8 +68,6 @@ using sofa::component::linearsolver::GraphScatteredMatrix ; using sofa::component::linearsolver::GraphScatteredVector ; using sofa::component::linearsolver::iterative::CGLinearSolver ; -using sofa::simulation::graph::DAGSimulation ; - using sofa::component::mass::UniformMass ; using sofa::component::mechanicalload::PlaneForceField ; diff --git a/Sofa/Component/ODESolver/Backward/tests/StaticSolver_test.cpp b/Sofa/Component/ODESolver/Backward/tests/StaticSolver_test.cpp index 8a78b4dc8fd..ccb1f6fb721 100644 --- a/Sofa/Component/ODESolver/Backward/tests/StaticSolver_test.cpp +++ b/Sofa/Component/ODESolver/Backward/tests/StaticSolver_test.cpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -32,7 +31,6 @@ using namespace sofa::simulation; using namespace sofa::simpleapi; using namespace sofa::helper::logging; -using sofa::simulation::graph::DAGSimulation; using sofa::component::odesolver::backward::StaticSolver; static constexpr SReal poissonRatio = 0; diff --git a/Sofa/Component/SceneUtility/tests/MessageHandlerComponent_test.cpp b/Sofa/Component/SceneUtility/tests/MessageHandlerComponent_test.cpp index 94b69d307c0..40ed35d0a29 100644 --- a/Sofa/Component/SceneUtility/tests/MessageHandlerComponent_test.cpp +++ b/Sofa/Component/SceneUtility/tests/MessageHandlerComponent_test.cpp @@ -27,9 +27,6 @@ using std::string ; #include #include -#include -using sofa::simulation::graph::DAGSimulation ; - #include using sofa::simulation::Node ; diff --git a/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.cpp b/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.cpp index 99c7664f2d7..cbaba2bce62 100644 --- a/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.cpp +++ b/Sofa/framework/SimpleApi/src/sofa/simpleapi/SimpleApi.cpp @@ -26,9 +26,6 @@ #include using sofa::core::ObjectFactory ; -#include -using sofa::simulation::graph::DAGSimulation ; - #include using sofa::simulation::Node; using sofa::core::objectmodel::BaseObjectDescription ; diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp index 5177f080bec..b96fb431063 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.cpp @@ -78,6 +78,10 @@ using namespace sofa; namespace node { +NodeSPtr createNewNode(const std::string& name){ + return sofa::core::objectmodel::New(name); +} + void initRoot(Node* root) { SCOPED_TIMER("Simulation::init"); diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h index 5b9d0f08463..889da81ee05 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/Simulation.h @@ -28,58 +28,6 @@ namespace sofa::simulation { -namespace node -{ - -/// Initialize the objects -void SOFA_SIMULATION_CORE_API initRoot(Node* root); -///Init a node without changing the context of the simulation. -void SOFA_SIMULATION_CORE_API init(Node* node); -/// Print all object in the graph in XML format -void SOFA_SIMULATION_CORE_API exportInXML(Node* root, const char* fileName); -/// Print all object in the graph -void SOFA_SIMULATION_CORE_API print(Node* root); -/// Update contexts. Required before drawing the scene if root flags are modified. -void SOFA_SIMULATION_CORE_API updateVisualContext(Node* root); -/// Execute one timestep. If dt is 0, the dt parameter in the graph will be used -void SOFA_SIMULATION_CORE_API animate(Node* root, SReal dt=0.0); -/// Update the Visual Models: triggers the Mappings -void SOFA_SIMULATION_CORE_API updateVisual(Node* root); -/// Reset to initial state -void SOFA_SIMULATION_CORE_API reset(Node* root); -/// Initialize the textures -void SOFA_SIMULATION_CORE_API initTextures(Node* root); -/// Update contexts. Required before drawing the scene if root flags are modified. -void SOFA_SIMULATION_CORE_API updateContext(Node* root); - -/** Compute the bounding box of the scene. - * If init is set to "true", then minBBox and maxBBox will be initialised to a default value - * @warning MechanicalObjects with showObject member set to false are ignored - * @sa computeTotalBBox(Node* root, SReal* minBBox, SReal* maxBBox) - */ -void SOFA_SIMULATION_CORE_API computeBBox(Node* root, SReal* minBBox, SReal* maxBBox, bool init=true); - -/** Compute the bounding box of the scene. - * Includes all objects, may they be displayed or not. - * @sa computeBBox(Node* root, SReal* minBBox, SReal* maxBBox, bool init=true) - * @deprecated - */ -void SOFA_SIMULATION_CORE_API computeTotalBBox(Node* root, SReal* minBBox, SReal* maxBBox); -/// Render the scene -void SOFA_SIMULATION_CORE_API draw(sofa::core::visual::VisualParams* vparams, Node* root); -/// Export a scene to an OBJ 3D Scene -void SOFA_SIMULATION_CORE_API exportOBJ(Node* root, const char* filename, bool exportMTL = true); -/// Print all objects in the graph in the given file (format is given by the filename extension) -void SOFA_SIMULATION_CORE_API exportGraph(Node* root, const char* filename=nullptr); -/// Dump the current state in the given stream -void SOFA_SIMULATION_CORE_API dumpState( Node* root, std::ofstream& out ); -/// Load a scene from a file -NodeSPtr SOFA_SIMULATION_CORE_API load(const std::string& /* filename */, bool reload = false, const std::vector& sceneArgs = std::vector(0)); -/// Unload a scene from a Node. -void SOFA_SIMULATION_CORE_API unload(NodeSPtr root); - -} - /** Main controller of the scene. Defines how the scene is inited at the beginning, and updated at each time step. Derives from Base in order to use smart pointers and model the parameters as Datas, which makes their edition easy in the GUI. diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/fwd.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/fwd.h index 460e575c789..38466120ee3 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/fwd.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/fwd.h @@ -51,6 +51,57 @@ namespace sofa::simulation::node { SOFA_SIMULATION_CORE_API sofa::core::objectmodel::BaseContext* toBaseContext(Node*); SOFA_SIMULATION_CORE_API Node* getNodeFrom(sofa::core::objectmodel::BaseContext*); + +// Create a new node; +NodeSPtr createNewNode(const std::string& name); + +/// Initialize the objects +void SOFA_SIMULATION_CORE_API initRoot(Node* root); +///Init a node without changing the context of the simulation. +void SOFA_SIMULATION_CORE_API init(Node* node); +/// Print all object in the graph in XML format +void SOFA_SIMULATION_CORE_API exportInXML(Node* root, const char* fileName); +/// Print all object in the graph +void SOFA_SIMULATION_CORE_API print(Node* root); +/// Update contexts. Required before drawing the scene if root flags are modified. +void SOFA_SIMULATION_CORE_API updateVisualContext(Node* root); +/// Execute one timestep. If dt is 0, the dt parameter in the graph will be used +void SOFA_SIMULATION_CORE_API animate(Node* root, SReal dt=0.0); +/// Update the Visual Models: triggers the Mappings +void SOFA_SIMULATION_CORE_API updateVisual(Node* root); +/// Reset to initial state +void SOFA_SIMULATION_CORE_API reset(Node* root); +/// Initialize the textures +void SOFA_SIMULATION_CORE_API initTextures(Node* root); +/// Update contexts. Required before drawing the scene if root flags are modified. +void SOFA_SIMULATION_CORE_API updateContext(Node* root); + +/** Compute the bounding box of the scene. + * If init is set to "true", then minBBox and maxBBox will be initialised to a default value + * @warning MechanicalObjects with showObject member set to false are ignored + * @sa computeTotalBBox(Node* root, SReal* minBBox, SReal* maxBBox) + */ +void SOFA_SIMULATION_CORE_API computeBBox(Node* root, SReal* minBBox, SReal* maxBBox, bool init=true); + +/** Compute the bounding box of the scene. + * Includes all objects, may they be displayed or not. + * @sa computeBBox(Node* root, SReal* minBBox, SReal* maxBBox, bool init=true) + * @deprecated + */ +void SOFA_SIMULATION_CORE_API computeTotalBBox(Node* root, SReal* minBBox, SReal* maxBBox); +/// Render the scene +void SOFA_SIMULATION_CORE_API draw(sofa::core::visual::VisualParams* vparams, Node* root); +/// Export a scene to an OBJ 3D Scene +void SOFA_SIMULATION_CORE_API exportOBJ(Node* root, const char* filename, bool exportMTL = true); +/// Print all objects in the graph in the given file (format is given by the filename extension) +void SOFA_SIMULATION_CORE_API exportGraph(Node* root, const char* filename=nullptr); +/// Dump the current state in the given stream +void SOFA_SIMULATION_CORE_API dumpState( Node* root, std::ofstream& out ); +/// Load a scene from a file +NodeSPtr SOFA_SIMULATION_CORE_API load(const std::string& /* filename */, bool reload = false, const std::vector& sceneArgs = std::vector(0)); +/// Unload a scene from a Node. +void SOFA_SIMULATION_CORE_API unload(NodeSPtr root); + } namespace sofa::core diff --git a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.h b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.h index 9a46c12e3ee..c3b2177b424 100644 --- a/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.h +++ b/Sofa/framework/Simulation/Graph/src/sofa/simulation/graph/DAGSimulation.h @@ -29,7 +29,5 @@ namespace sofa::simulation::graph { - -using DAGSimulation = Simulation; - + using DAGSimulation = Simulation; } // namespace sofa::simulation::graph diff --git a/applications/plugins/SceneCreator/src/SceneCreator/SceneCreator.cpp b/applications/plugins/SceneCreator/src/SceneCreator/SceneCreator.cpp index 61ab852d8b2..febbd3e8e02 100644 --- a/applications/plugins/SceneCreator/src/SceneCreator/SceneCreator.cpp +++ b/applications/plugins/SceneCreator/src/SceneCreator/SceneCreator.cpp @@ -24,7 +24,6 @@ #include #include -#include #include "GetVectorVisitor.h" #include "GetAssembledSizeVisitor.h" @@ -50,7 +49,6 @@ using namespace sofa::defaulttype ; using type::vector; -using sofa::simulation::graph::DAGSimulation ; using sofa::simulation::GetAssembledSizeVisitor ; using sofa::simulation::GetVectorVisitor ; using sofa::simulation::Node ; diff --git a/applications/plugins/SceneCreator/src/SceneCreator/SceneUtils.cpp b/applications/plugins/SceneCreator/src/SceneCreator/SceneUtils.cpp index 991f3a59e40..70dcebd8692 100644 --- a/applications/plugins/SceneCreator/src/SceneCreator/SceneUtils.cpp +++ b/applications/plugins/SceneCreator/src/SceneCreator/SceneUtils.cpp @@ -22,7 +22,6 @@ #include "SceneCreator.h" #include "SceneUtils.h" -#include #include "GetVectorVisitor.h" #include "GetAssembledSizeVisitor.h" @@ -52,7 +51,6 @@ typedef linearalgebra::FullVector FullVector ; using type::vector; -using sofa::simulation::graph::DAGSimulation ; using sofa::simulation::GetAssembledSizeVisitor ; using sofa::simulation::GetVectorVisitor ; using sofa::simulation::Node ; diff --git a/applications/projects/runSofa/Main.cpp b/applications/projects/runSofa/Main.cpp index 52ddbd3548f..e3f9b385e7d 100644 --- a/applications/projects/runSofa/Main.cpp +++ b/applications/projects/runSofa/Main.cpp @@ -36,7 +36,7 @@ using std::vector; #include #include #include -#include +#include using sofa::simulation::Node; #include #include @@ -59,7 +59,6 @@ using sofa::core::ExecParams ; #include using sofa::helper::Utils; -using sofa::simulation::graph::DAGSimulation; using sofa::helper::system::SetDirectory; using sofa::core::objectmodel::BaseNode ; @@ -471,7 +470,7 @@ int main(int argc, char** argv) const std::vector sceneArgs = sofa::gui::common::ArgumentParser::extra_args(); Node::SPtr groot = sofa::simulation::node::load(fileName, false, sceneArgs); if( !groot ) - groot = sofa::simulation::getSimulation()->createNewGraph(""); + groot = sofa::simulation::node::createNewNode(""); if (!verif.empty()) { From cbf11676699719336fd5bc6f09d740b4be53d644 Mon Sep 17 00:00:00 2001 From: Damien Marchal Date: Sat, 4 Oct 2025 20:58:28 +0200 Subject: [PATCH 16/19] Add missing #include --- Sofa/framework/Simulation/Core/src/sofa/simulation/fwd.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/fwd.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/fwd.h index 38466120ee3..f3adcc0303b 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/fwd.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/fwd.h @@ -24,6 +24,7 @@ #include #include #include +#include #include namespace sofa::core::objectmodel { class BaseContext; } From 9e1e43e86c0ca6ec983a4813d25fc2d438c96e06 Mon Sep 17 00:00:00 2001 From: Damien Marchal Date: Fri, 17 Oct 2025 09:22:15 +0200 Subject: [PATCH 17/19] Fix link problem with createNewNode (missing SOFA_SIMULATION_CORE_API) --- Sofa/framework/Simulation/Core/src/sofa/simulation/fwd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/fwd.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/fwd.h index f3adcc0303b..f17f85db33e 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/fwd.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/fwd.h @@ -54,7 +54,7 @@ SOFA_SIMULATION_CORE_API sofa::core::objectmodel::BaseContext* toBaseContext(Nod SOFA_SIMULATION_CORE_API Node* getNodeFrom(sofa::core::objectmodel::BaseContext*); // Create a new node; -NodeSPtr createNewNode(const std::string& name); +SOFA_SIMULATION_CORE_API NodeSPtr createNewNode(const std::string& name); /// Initialize the objects void SOFA_SIMULATION_CORE_API initRoot(Node* root); From eca4767a60c513ce012010a79b84d941f09f542d Mon Sep 17 00:00:00 2001 From: Damien Marchal Date: Thu, 30 Oct 2025 22:51:47 +0100 Subject: [PATCH 18/19] [Sofa.Core] Add a castTo in fwd.h to support "const" conversion --- Sofa/framework/Core/src/sofa/core/fwd.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Sofa/framework/Core/src/sofa/core/fwd.h b/Sofa/framework/Core/src/sofa/core/fwd.h index bdeda1ee1ad..ffbc7fb31f3 100644 --- a/Sofa/framework/Core/src/sofa/core/fwd.h +++ b/Sofa/framework/Core/src/sofa/core/fwd.h @@ -212,6 +212,9 @@ sofa::core::objectmodel::Base* castToBase(Source*b){ return b; } template Dest castTo(sofa::core::objectmodel::Base* base){ return dynamic_cast(base); } +template +const Dest castTo(const sofa::core::objectmodel::Base* base){ return dynamic_cast(base); } + namespace objectmodel::base { /// Returns the BaseClass* from type parameter B, hiding B::GetClass() From 6782a19764f8dd4f8090ec80bc52a13c50f4ef8a Mon Sep 17 00:00:00 2001 From: Damien Marchal Date: Thu, 30 Oct 2025 22:54:38 +0100 Subject: [PATCH 19/19] [Sofa.Core] Add a getPathName() method in BaseData There was no method to get the PathName() to a BaseData only a linkpath (so with the "@" prefix indicating a link). I add the missing feature and make some minor cleaning --- .../Core/src/sofa/core/objectmodel/Base.h | 1 + .../src/sofa/core/objectmodel/BaseData.cpp | 9 +++++- .../Core/src/sofa/core/objectmodel/BaseData.h | 1 + .../src/sofa/core/objectmodel/BaseObject.cpp | 29 +++++++++---------- 4 files changed, 23 insertions(+), 17 deletions(-) diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h index c554389c032..597c97148ac 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h @@ -97,6 +97,7 @@ class SOFA_CORE_API Base : public IntrusiveObject void addOutputsToCallback(const std::string& name, std::initializer_list outputs); + /// Returns the path to the Base. it is possible to use different character as separator. virtual std::string getPathName() const { return ""; } /// Accessor to the object name diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseData.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseData.cpp index d449b0b7a7e..3dee5f991d8 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseData.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseData.cpp @@ -140,10 +140,17 @@ bool BaseData::setParent(BaseData* parent, const std::string& path) return true; } +std::string BaseData::getPathName() const +{ + if(m_owner) + return m_owner->getPathName()+"."+getName(); + return ""; +} + std::string BaseData::getLinkPath() const { if(m_owner) - return "@"+m_owner->getPathName()+"."+getName(); + return "@"+getPathName(); return ""; } diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseData.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseData.h index 3c45a0d52dd..eafe21c81ca 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseData.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseData.h @@ -194,6 +194,7 @@ class SOFA_CORE_API BaseData : public DDGNode /// If we use the Data as a link and not as value directly virtual std::string getLinkPath() const; + std::string getPathName()const; /// Return whether this %Data can be used as a linkPath. /// diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseObject.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseObject.cpp index 390116d17ef..da7c23524dc 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseObject.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseObject.cpp @@ -342,22 +342,19 @@ SReal BaseObject::getTime() const return getContext()->getTime(); } -std::string BaseObject::getPathName() const { - - const BaseContext* context = this->getContext(); - std::string result = ""; - if( context ) - { - const BaseNode* node = context->toBaseNode(); - if( node ) { - result += node->getPathName(); - if (node->getPathName() != "/") - result += "/"; - } - - } - result += getName(); - return result; +std::string BaseObject::getPathName() const +{ + auto node = sofa::core::castTo(getContext()); + if(!node) + return ""; + + std::stringstream tmp; + auto pathname = node->getPathName(); + tmp << pathname; + if (pathname != "/") + tmp << "/"; + tmp << getName(); + return tmp.str(); } } // namespace sofa::core::objectmodel