From 5d9d5f4a5f3706b8b74576e8814c1ddd260d62ce Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Thu, 11 Dec 2025 14:40:31 +0100 Subject: [PATCH 01/57] savesnapshot + unit test savesnapshot print name, type and value of a componant + unit test with a scene in order to test saveSnapshot --- .../Core/simutest/objectmodel/Base_test.cpp | 57 +++++++++++++++++++ .../Core/src/sofa/core/objectmodel/Base.h | 42 ++++++++++++++ 2 files changed, 99 insertions(+) diff --git a/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp index e6a54bce469..5406514ad2a 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp @@ -36,6 +36,7 @@ using sofa::defaulttype::Rigid3Types; #include using sofa::defaulttype::Vec3Types; + namespace customns { class CustomBaseObject : public sofa::core::objectmodel::BaseComponent @@ -122,3 +123,59 @@ TEST_F(Base_test , testGetClassName) EXPECT_EQ(o.getClass()->className, "CustomBaseObject"); } +TEST_F(Base_test, testSaveSnapshot) +{ + const std::string scene = R"( + + + + + + + + + + + + )"; + + SceneInstance c("xml", scene) ; + c.initScene() ; + + Node* root = c.root.get() ; + + sofa::core::objectmodel::BaseObject* Obj = root->getTreeObject(); + std::vector vObj = root->getTreeObjects(); + + // un seul obj + // std::cout << "Obj std::cout -> " << Obj->getName() << std::endl; + sofa::core::objectmodel::Base* BaseSnap; + // BaseSnap->saveSnapshot(Obj); + + for (auto* comp : vObj) + { + std::cout << "******************Nouvelle objet******************"<< std::endl; + BaseSnap->saveSnapshot(comp); + std::cout << " "<< std::endl; + std::cout << " "<< std::endl; + std::cout << " "<< std::endl; + std::cout << " "<< std::endl; + std::cout << " "<< std::endl; + std::cout << " "<< std::endl; + + } + + + // for(BaseObject* tree : root->getTreeObjects()) + // { + // std::cout << tree->getClassName() << std::endl; + // + // } + + + // std::vector tree ; + // root->getTreeObject(tree) ; + + // sofa::core::objectmodel::Base* sBase; + // sBase->saveSnapshot(RequiredPlugin); +} \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h index ce62107d239..04e69930700 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h @@ -40,6 +40,8 @@ #include #include +#include + #define SOFA_BASE_CAST_IMPLEMENTATION(CLASSNAME) \ virtual const CLASSNAME* to##CLASSNAME() const override { return this; } \ virtual CLASSNAME* to##CLASSNAME() override { return this; } @@ -357,6 +359,46 @@ class SOFA_CORE_API Base : public IntrusiveObject ///@} +public : + + struct SnapshotContainer + { + std::string dataname; + + std::string datavalue; + }; + + template + void saveSnapshot(T* component) + { + VecData datafield = component->getDataFields(); + VecLink componentlinks = component->getLinks(); + int i = 1; + // À partir de chq composant, trouver chaque data possible + for (auto* data : datafield) + { + /// ReadAccessor data ? + std::cout << "getName : " << (*data).getName() << std::endl; + std::cout << "getValueTypeString : " << (*data).getValueTypeString() << std::endl; + std::cout << "getValueString : " << (*data).getValueString() << std::endl; + std::cout << "getHelp : " << (*data).getHelp() << std::endl; + std::cout << "============================================" << std::endl; + i+=1; + } + + // for (auto* links : componentlinks) + // { + // /// ReadAccessor pour les links ? + + // } + + SnapshotContainer snapContainer; + + /// Tout regrouper dans le container + + } + + protected: /// List of fields (Data instances) VecData m_vecData; From 3cda227fc07ef73fdfb8d5fd2b6ac5b8f47e19b9 Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Mon, 15 Dec 2025 11:26:42 +0100 Subject: [PATCH 02/57] implements class BaseSnapshot Implementation of BaseSnapShot, JSONSnapshot in order to be used in saveSnapshot --- Sofa/framework/Core/CMakeLists.txt | 6 +++ .../Core/simutest/objectmodel/Base_test.cpp | 12 ++--- .../Core/src/sofa/core/objectmodel/Base.cpp | 29 +++++++++++ .../Core/src/sofa/core/objectmodel/Base.h | 39 +++++---------- .../sofa/core/objectmodel/BaseSnapshot.cpp | 31 ++++++++++++ .../src/sofa/core/objectmodel/BaseSnapshot.h | 46 ++++++++++++++++++ .../sofa/core/objectmodel/JSONSnapshot.cpp | 48 +++++++++++++++++++ .../src/sofa/core/objectmodel/JSONSnapshot.h | 47 ++++++++++++++++++ .../sofa/core/objectmodel/SnapshotFactory.cpp | 46 ++++++++++++++++++ .../sofa/core/objectmodel/SnapshotFactory.h | 37 ++++++++++++++ 10 files changed, 308 insertions(+), 33 deletions(-) create mode 100644 Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp create mode 100644 Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h create mode 100644 Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp create mode 100644 Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h create mode 100644 Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.cpp create mode 100644 Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.h diff --git a/Sofa/framework/Core/CMakeLists.txt b/Sofa/framework/Core/CMakeLists.txt index bd3abe288dc..f6c0dea3656 100644 --- a/Sofa/framework/Core/CMakeLists.txt +++ b/Sofa/framework/Core/CMakeLists.txt @@ -159,6 +159,7 @@ set(HEADER_FILES ${SRC_ROOT}/objectmodel/BaseLink.h ${SRC_ROOT}/objectmodel/BaseNode.h ${SRC_ROOT}/objectmodel/BaseObjectDescription.h + ${SRC_ROOT}/objectmodel/BaseSnapshot.h ${SRC_ROOT}/objectmodel/ClassInfo.h ${SRC_ROOT}/objectmodel/ComponentState.h ${SRC_ROOT}/objectmodel/ConfigurationSetting.h @@ -177,6 +178,7 @@ set(HEADER_FILES ${SRC_ROOT}/objectmodel/HapticDeviceEvent.h ${SRC_ROOT}/objectmodel/IdleEvent.h ${SRC_ROOT}/objectmodel/JoystickEvent.h + ${SRC_ROOT}/objectmodel/JSONSnapshot.h ${SRC_ROOT}/objectmodel/KeypressedEvent.h ${SRC_ROOT}/objectmodel/KeyreleasedEvent.h ${SRC_ROOT}/objectmodel/lifecycle/DeprecatedData.h @@ -185,6 +187,7 @@ set(HEADER_FILES ${SRC_ROOT}/objectmodel/Link.h ${SRC_ROOT}/objectmodel/MouseEvent.h ${SRC_ROOT}/objectmodel/SPtr.h + ${SRC_ROOT}/objectmodel/SnapshotFactory.h ${SRC_ROOT}/objectmodel/ScriptEvent.h ${SRC_ROOT}/objectmodel/TypeOfInsertion.h ${SRC_ROOT}/objectmodel/Tag.h @@ -309,6 +312,7 @@ set(SOURCE_FILES ${SRC_ROOT}/objectmodel/BaseLink.cpp ${SRC_ROOT}/objectmodel/BaseNode.cpp ${SRC_ROOT}/objectmodel/BaseObjectDescription.cpp + ${SRC_ROOT}/objectmodel/BaseSnapshot.cpp ${SRC_ROOT}/objectmodel/ClassInfo.cpp ${SRC_ROOT}/objectmodel/ComponentState.cpp ${SRC_ROOT}/objectmodel/ConfigurationSetting.cpp @@ -327,11 +331,13 @@ set(SOURCE_FILES ${SRC_ROOT}/objectmodel/HapticDeviceEvent.cpp ${SRC_ROOT}/objectmodel/IdleEvent.cpp ${SRC_ROOT}/objectmodel/JoystickEvent.cpp + ${SRC_ROOT}/objectmodel/JSONSnapshot.cpp ${SRC_ROOT}/objectmodel/KeypressedEvent.cpp ${SRC_ROOT}/objectmodel/KeyreleasedEvent.cpp ${SRC_ROOT}/objectmodel/lifecycle/DeprecatedData.cpp ${SRC_ROOT}/objectmodel/MouseEvent.cpp ${SRC_ROOT}/objectmodel/ScriptEvent.cpp + ${SRC_ROOT}/objectmodel/SnapshotFactory.cpp ${SRC_ROOT}/objectmodel/Tag.cpp ${SRC_ROOT}/objectmodel/TagSet.cpp ${SRC_ROOT}/topology/BaseMeshTopology.cpp diff --git a/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp index 5406514ad2a..ad3c33217bc 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp @@ -36,6 +36,9 @@ using sofa::defaulttype::Rigid3Types; #include using sofa::defaulttype::Vec3Types; +#include +using sofa::core::objectmodel::SnapshotType; + namespace customns { @@ -144,18 +147,15 @@ TEST_F(Base_test, testSaveSnapshot) Node* root = c.root.get() ; - sofa::core::objectmodel::BaseObject* Obj = root->getTreeObject(); std::vector vObj = root->getTreeObjects(); - // un seul obj - // std::cout << "Obj std::cout -> " << Obj->getName() << std::endl; - sofa::core::objectmodel::Base* BaseSnap; - // BaseSnap->saveSnapshot(Obj); + auto JSONSnapCont = createSnapshot(SnapshotType::JSON); + for (auto* comp : vObj) { std::cout << "******************Nouvelle objet******************"<< std::endl; - BaseSnap->saveSnapshot(comp); + comp->saveSnapshot(*JSONSnapCont); std::cout << " "<< std::endl; std::cout << " "<< std::endl; std::cout << " "<< std::endl; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index ed3a4d942de..c1db58aac9f 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -680,6 +680,35 @@ int Base::getInstanciationSourceFilePos() const return m_instanciationSourceFilePos; } +void Base::saveSnapshot(BaseSnapshot& type) + { + VecData datafield = this->getDataFields(); + VecLink componentlinks = this->getLinks(); + int i = 1; + + for (auto* data : datafield) + { + /// ReadAccessor data ? + std::cout << "getName : " << (*data).getName() << std::endl; + std::cout << "getValueTypeString : " << (*data).getValueTypeString() << std::endl; + std::cout << "getValueString : " << (*data).getValueString() << std::endl; + std::cout << "getHelp : " << (*data).getHelp() << std::endl; + std::cout << "============================================" << std::endl; + i+=1; + } + + // for (auto* links : componentlinks) + // { + // /// ReadAccessor pour les links ? + + // } + // auto SnapshotType = createSnapshot(type); + type.printSnapshot() ; + + /// Tout regrouper dans le container + + } + } // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h index 04e69930700..3e5421e3212 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h @@ -41,6 +41,10 @@ #include #include +#include +#include + + #define SOFA_BASE_CAST_IMPLEMENTATION(CLASSNAME) \ virtual const CLASSNAME* to##CLASSNAME() const override { return this; } \ @@ -49,6 +53,8 @@ virtual CLASSNAME* to##CLASSNAME() override { return this; } namespace sofa::core::objectmodel { +class BaseSnapshot; + /** * \brief Base class for everything * @@ -368,36 +374,15 @@ public : std::string datavalue; }; - template - void saveSnapshot(T* component) + void setSnapshot(BaseSnapshot* impl) { - VecData datafield = component->getDataFields(); - VecLink componentlinks = component->getLinks(); - int i = 1; - // À partir de chq composant, trouver chaque data possible - for (auto* data : datafield) - { - /// ReadAccessor data ? - std::cout << "getName : " << (*data).getName() << std::endl; - std::cout << "getValueTypeString : " << (*data).getValueTypeString() << std::endl; - std::cout << "getValueString : " << (*data).getValueString() << std::endl; - std::cout << "getHelp : " << (*data).getHelp() << std::endl; - std::cout << "============================================" << std::endl; - i+=1; - } - - // for (auto* links : componentlinks) - // { - // /// ReadAccessor pour les links ? - - // } - - SnapshotContainer snapContainer; - - /// Tout regrouper dans le container - + Snapshot_impl = impl; } + void saveSnapshot(BaseSnapshot& SnapshotImpl); + +private : + BaseSnapshot* Snapshot_impl; protected: /// List of fields (Data instances) diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp new file mode 100644 index 00000000000..2587e5e8969 --- /dev/null +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp @@ -0,0 +1,31 @@ +/****************************************************************************** +* 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 + +namespace sofa::core::objectmodel +{ + +BaseSnapshot::BaseSnapshot() +{} +BaseSnapshot::~BaseSnapshot() = default; + +} // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h new file mode 100644 index 00000000000..40228ed097a --- /dev/null +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h @@ -0,0 +1,46 @@ +/****************************************************************************** +* 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 * +******************************************************************************/ +#pragma once +#include + +namespace sofa::core::objectmodel +{ + +class SOFA_CORE_API BaseSnapshot +{ + +public: + virtual void printSnapshot() = 0; + virtual void exportSnapshot() = 0; + virtual void importSnapshot() = 0; + + + BaseSnapshot(); + virtual ~BaseSnapshot() = 0; + +public: + std::string dataName; + std::string dataValueType; + std::string valueStr; + +}; +} // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp new file mode 100644 index 00000000000..2c46a569e00 --- /dev/null +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp @@ -0,0 +1,48 @@ +/****************************************************************************** +* 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::core::objectmodel +{ + +JSONSnapshot::JSONSnapshot() +{} +JSONSnapshot::~JSONSnapshot() = default; + +void JSONSnapshot::printSnapshot() +{ + std::cout << "printJSONSnapshot" << std::endl; +} + +void JSONSnapshot::exportSnapshot() +{ + std::cout << "exportSnapshot" << std::endl; +} + +void JSONSnapshot::importSnapshot() +{ + std::cout << "importSnapshot" << std::endl; +} + +} // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h new file mode 100644 index 00000000000..19fd8e0b222 --- /dev/null +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h @@ -0,0 +1,47 @@ +/****************************************************************************** +* 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 * +******************************************************************************/ +#pragma once +#include +#include + +namespace sofa::core::objectmodel +{ + +class SOFA_CORE_API JSONSnapshot : public BaseSnapshot +{ + +public: + void printSnapshot() override; + void exportSnapshot() override; + void importSnapshot() override; + + + JSONSnapshot(); + ~JSONSnapshot(); + +public: + std::string dataName; + std::string dataValueType; + std::string valueStr; + +}; +} // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.cpp new file mode 100644 index 00000000000..7b705e06559 --- /dev/null +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.cpp @@ -0,0 +1,46 @@ +/****************************************************************************** +* 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 * +******************************************************************************/ +#pragma once +#include +#include +#include + + + +namespace sofa::core::objectmodel +{ + +std::unique_ptr createSnapshot(SnapshotType type) +{ + std::cout << "CreateSnapshot !" << std::endl; + switch (type) + { + case SnapshotType::JSON: + std::cout << "CreateSnapshot : JSON !" << std::endl; + return std::make_unique(); + + default: + return nullptr; + } +} + +} // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.h b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.h new file mode 100644 index 00000000000..5d7b5a88f22 --- /dev/null +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.h @@ -0,0 +1,37 @@ +/****************************************************************************** +* 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 * +******************************************************************************/ +#pragma once +#include +// #include +#include + +namespace sofa::core::objectmodel +{ + class BaseSnapshot; +enum class SnapshotType +{ + JSON, + Print +}; +std::unique_ptr createSnapshot(SnapshotType type); + +} // namespace sofa::core::objectmodel \ No newline at end of file From f51c239bc1f547a426fe700f1592d291a7ac15b8 Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Mon, 15 Dec 2025 16:23:49 +0100 Subject: [PATCH 03/57] update BaseSnapshot and JSONSnapshot --- .../Core/simutest/objectmodel/Base_test.cpp | 24 +++++++++----- .../Core/src/sofa/core/objectmodel/Base.cpp | 31 +++++++++++++------ .../Core/src/sofa/core/objectmodel/Base.h | 2 +- .../src/sofa/core/objectmodel/BaseSnapshot.h | 8 ++++- .../sofa/core/objectmodel/JSONSnapshot.cpp | 21 +++++++++++++ .../src/sofa/core/objectmodel/JSONSnapshot.h | 9 +++++- 6 files changed, 74 insertions(+), 21 deletions(-) diff --git a/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp index ad3c33217bc..29532ed016d 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp @@ -151,21 +151,29 @@ TEST_F(Base_test, testSaveSnapshot) auto JSONSnapCont = createSnapshot(SnapshotType::JSON); + int i = -1; for (auto* comp : vObj) { std::cout << "******************Nouvelle objet******************"<< std::endl; - comp->saveSnapshot(*JSONSnapCont); - std::cout << " "<< std::endl; - std::cout << " "<< std::endl; - std::cout << " "<< std::endl; - std::cout << " "<< std::endl; - std::cout << " "<< std::endl; - std::cout << " "<< std::endl; - + std::cout << comp->getPathName() << std::endl; + comp->saveSnapshot(*JSONSnapCont,i); + i+=1; } + std::cout <<"i = " << i << std::endl; + std::vector> testcont = JSONSnapCont->getContainer(); + std::cout << "TEst cont : " << testcont.size() <getTreeObjects()) // { // std::cout << tree->getClassName() << std::endl; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index c1db58aac9f..08b95a44968 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -680,22 +680,32 @@ int Base::getInstanciationSourceFilePos() const return m_instanciationSourceFilePos; } -void Base::saveSnapshot(BaseSnapshot& type) +void Base::saveSnapshot(BaseSnapshot& type, int i) { VecData datafield = this->getDataFields(); VecLink componentlinks = this->getLinks(); - int i = 1; + std::vector vtemp; for (auto* data : datafield) { /// ReadAccessor data ? - std::cout << "getName : " << (*data).getName() << std::endl; - std::cout << "getValueTypeString : " << (*data).getValueTypeString() << std::endl; - std::cout << "getValueString : " << (*data).getValueString() << std::endl; - std::cout << "getHelp : " << (*data).getHelp() << std::endl; - std::cout << "============================================" << std::endl; - i+=1; + // std::cout << "getName : " << (*data).getName() << std::endl; + // std::cout << "getValueTypeString : " << (*data).getValueTypeString() << std::endl; + // std::cout << "getValueString : " << (*data).getValueString() << std::endl; + // std::cout << "getHelp : " << (*data).getHelp() << std::endl; + // std::cout << "============================================" << std::endl; + type.setName( (*data).getName() ); + + //std::cout << "getName : " << type.getName() << std::endl; + + std::string dataname = type.getName(); + + + vtemp.push_back(dataname); + + } + type.fillContainer(vtemp,i); // for (auto* links : componentlinks) // { @@ -703,9 +713,10 @@ void Base::saveSnapshot(BaseSnapshot& type) // } // auto SnapshotType = createSnapshot(type); - type.printSnapshot() ; + // type.printSnapshot() ; - /// Tout regrouper dans le container + + } diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h index 3e5421e3212..22c72d22a5a 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h @@ -379,7 +379,7 @@ public : Snapshot_impl = impl; } - void saveSnapshot(BaseSnapshot& SnapshotImpl); + void saveSnapshot(BaseSnapshot& type, int i); private : BaseSnapshot* Snapshot_impl; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h index 40228ed097a..0f4b8771e02 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h @@ -33,6 +33,12 @@ class SOFA_CORE_API BaseSnapshot virtual void exportSnapshot() = 0; virtual void importSnapshot() = 0; + virtual void setName(const std::string& name) = 0; + virtual std::string getName() const = 0; + + virtual void fillContainer(const std::vector& name, int i) = 0; + virtual std::vector> getContainer() const = 0; + BaseSnapshot(); virtual ~BaseSnapshot() = 0; @@ -41,6 +47,6 @@ class SOFA_CORE_API BaseSnapshot std::string dataName; std::string dataValueType; std::string valueStr; - + std::vector> container; }; } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp index 2c46a569e00..3a487687f81 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp @@ -45,4 +45,25 @@ void JSONSnapshot::importSnapshot() std::cout << "importSnapshot" << std::endl; } +void JSONSnapshot::setName(const std::string& name) +{ + dataName = name; +} + +std::string JSONSnapshot::getName() const +{ + return dataName; +} + +void JSONSnapshot::fillContainer(const std::vector& name, int i) +{ + container.push_back(name); +} + +std::vector> JSONSnapshot::getContainer() const +{ + return container; +} + + } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h index 19fd8e0b222..43d117f3c5b 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h @@ -23,6 +23,7 @@ #include #include + namespace sofa::core::objectmodel { @@ -34,6 +35,12 @@ class SOFA_CORE_API JSONSnapshot : public BaseSnapshot void exportSnapshot() override; void importSnapshot() override; + void setName(const std::string& name) override; + std::string getName() const override; + + void fillContainer(const std::vector& name, int i) override; + std::vector> getContainer() const override; + JSONSnapshot(); ~JSONSnapshot(); @@ -42,6 +49,6 @@ class SOFA_CORE_API JSONSnapshot : public BaseSnapshot std::string dataName; std::string dataValueType; std::string valueStr; - + std::vector> container; }; } // namespace sofa::core::objectmodel \ No newline at end of file From d8a4659239d76fb0c04f6a8bd95934cb9cf45250 Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Wed, 17 Dec 2025 10:01:07 +0100 Subject: [PATCH 04/57] SnapshotVisitor implementation --- .../Core/simutest/objectmodel/Base_test.cpp | 26 ++--- .../Core/src/sofa/core/objectmodel/Base.cpp | 27 +---- .../Core/src/sofa/core/objectmodel/Base.h | 2 +- .../src/sofa/core/objectmodel/BaseSnapshot.h | 2 +- .../sofa/core/objectmodel/JSONSnapshot.cpp | 2 +- .../src/sofa/core/objectmodel/JSONSnapshot.h | 2 +- .../sofa/core/objectmodel/SnapshotFactory.cpp | 2 - Sofa/framework/Simulation/Core/CMakeLists.txt | 2 + .../src/sofa/simulation/SnapshotVisitor.cpp | 103 ++++++++++++++++++ .../src/sofa/simulation/SnapshotVisitor.h | 69 ++++++++++++ 10 files changed, 191 insertions(+), 46 deletions(-) create mode 100644 Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp create mode 100644 Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h diff --git a/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp index 29532ed016d..a6cb2a25292 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp @@ -39,6 +39,8 @@ using sofa::defaulttype::Vec3Types; #include using sofa::core::objectmodel::SnapshotType; +#include +using sofa::simulation::SnapshotVisitor; namespace customns { @@ -146,25 +148,26 @@ TEST_F(Base_test, testSaveSnapshot) c.initScene() ; Node* root = c.root.get() ; + + auto visitor = SnapshotVisitor(nullptr); + root->execute(visitor); std::vector vObj = root->getTreeObjects(); auto JSONSnapCont = createSnapshot(SnapshotType::JSON); - int i = -1; + for (auto* comp : vObj) { std::cout << "******************Nouvelle objet******************"<< std::endl; std::cout << comp->getPathName() << std::endl; - comp->saveSnapshot(*JSONSnapCont,i); - i+=1; + comp->saveSnapshot(*JSONSnapCont); + } - std::cout <<"i = " << i << std::endl; std::vector> testcont = JSONSnapCont->getContainer(); std::cout << "TEst cont : " << testcont.size() <getTreeObjects()) - // { - // std::cout << tree->getClassName() << std::endl; - // - // } - - - // std::vector tree ; - // root->getTreeObject(tree) ; - // sofa::core::objectmodel::Base* sBase; - // sBase->saveSnapshot(RequiredPlugin); } \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index 08b95a44968..de0b9008e77 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -680,7 +680,7 @@ int Base::getInstanciationSourceFilePos() const return m_instanciationSourceFilePos; } -void Base::saveSnapshot(BaseSnapshot& type, int i) +void Base::saveSnapshot(BaseSnapshot& type) { VecData datafield = this->getDataFields(); VecLink componentlinks = this->getLinks(); @@ -688,36 +688,17 @@ void Base::saveSnapshot(BaseSnapshot& type, int i) std::vector vtemp; for (auto* data : datafield) { - /// ReadAccessor data ? - // std::cout << "getName : " << (*data).getName() << std::endl; - // std::cout << "getValueTypeString : " << (*data).getValueTypeString() << std::endl; - // std::cout << "getValueString : " << (*data).getValueString() << std::endl; - // std::cout << "getHelp : " << (*data).getHelp() << std::endl; - // std::cout << "============================================" << std::endl; type.setName( (*data).getName() ); - - //std::cout << "getName : " << type.getName() << std::endl; - std::string dataname = type.getName(); - - - vtemp.push_back(dataname); - - + vtemp.push_back(dataname); } - type.fillContainer(vtemp,i); + type.fillContainer(vtemp); // for (auto* links : componentlinks) // { // /// ReadAccessor pour les links ? - // } - // auto SnapshotType = createSnapshot(type); - // type.printSnapshot() ; - - - - + // } } } // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h index 22c72d22a5a..0616da69a79 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h @@ -379,7 +379,7 @@ public : Snapshot_impl = impl; } - void saveSnapshot(BaseSnapshot& type, int i); + void saveSnapshot(BaseSnapshot& type); private : BaseSnapshot* Snapshot_impl; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h index 0f4b8771e02..1bdd7216449 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h @@ -36,7 +36,7 @@ class SOFA_CORE_API BaseSnapshot virtual void setName(const std::string& name) = 0; virtual std::string getName() const = 0; - virtual void fillContainer(const std::vector& name, int i) = 0; + virtual void fillContainer(const std::vector& name) = 0; virtual std::vector> getContainer() const = 0; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp index 3a487687f81..8f4e6d56ffe 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp @@ -55,7 +55,7 @@ std::string JSONSnapshot::getName() const return dataName; } -void JSONSnapshot::fillContainer(const std::vector& name, int i) +void JSONSnapshot::fillContainer(const std::vector& name) { container.push_back(name); } diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h index 43d117f3c5b..1fdcd02b5f8 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h @@ -38,7 +38,7 @@ class SOFA_CORE_API JSONSnapshot : public BaseSnapshot void setName(const std::string& name) override; std::string getName() const override; - void fillContainer(const std::vector& name, int i) override; + void fillContainer(const std::vector& name) override; std::vector> getContainer() const override; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.cpp index 7b705e06559..3b3761de9cb 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.cpp @@ -31,11 +31,9 @@ namespace sofa::core::objectmodel std::unique_ptr createSnapshot(SnapshotType type) { - std::cout << "CreateSnapshot !" << std::endl; switch (type) { case SnapshotType::JSON: - std::cout << "CreateSnapshot : JSON !" << std::endl; return std::make_unique(); default: diff --git a/Sofa/framework/Simulation/Core/CMakeLists.txt b/Sofa/framework/Simulation/Core/CMakeLists.txt index e16319d1d4e..7128ebce354 100644 --- a/Sofa/framework/Simulation/Core/CMakeLists.txt +++ b/Sofa/framework/Simulation/Core/CMakeLists.txt @@ -44,6 +44,7 @@ set(HEADER_FILES ${SRC_ROOT}/SceneLoaderFactory.h ${SRC_ROOT}/Simulation.h ${SRC_ROOT}/SimulationLoop.h + ${SRC_ROOT}/SnapshotVisitor.h ${SRC_ROOT}/SolveVisitor.h ${SRC_ROOT}/StateChangeVisitor.h ${SRC_ROOT}/TopologyChangeVisitor.h @@ -187,6 +188,7 @@ set(SOURCE_FILES ${SRC_ROOT}/SceneCheckRegistry.cpp ${SRC_ROOT}/SceneCheckMainRegistry.cpp ${SRC_ROOT}/Simulation.cpp + ${SRC_ROOT}/SnapshotVisitor.cpp ${SRC_ROOT}/SolveVisitor.cpp ${SRC_ROOT}/StateChangeVisitor.cpp ${SRC_ROOT}/TopologyChangeVisitor.cpp diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp new file mode 100644 index 00000000000..094cf9ecaa7 --- /dev/null +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp @@ -0,0 +1,103 @@ +/****************************************************************************** +* 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace sofa::simulation +{ + + +template +void SnapshotVisitor::processObject(T obj) +{ + std::cout << ' ' << obj->getName() << '(' << sofa::helper::gettypename(typeid(*obj)) << ')'; +} + +template +void SnapshotVisitor::processObjects(Seq& list, const char* name) +{ + if (list.empty()) return; + for (int i=0; i<=level; i++) + std::cout << "| "; + std::cout << name << ":"; + for (typename Seq::iterator it = list.begin(); it != list.end(); ++it) + { + typename Seq::value_type obj = *it; + this->processObject(obj); + } + std::cout << std::endl; +} + +Visitor::Result SnapshotVisitor::processNodeTopDown(simulation::Node* node) +{ + for (int i=0; igetName()<mechanicalState,"MechanicalState"); + processObjects(node->mechanicalMapping,"MechanicalMapping"); + processObjects(node->solver,"Solver"); + processObjects(node->linearSolver,"LinearSolver"); + processObjects(node->mass,"Mass"); + processObjects(node->topology,"Topology"); + processObjects(node->forceField,"ForceField"); + processObjects(node->interactionForceField,"InteractionForceField"); + processObjects(node->projectiveConstraintSet,"ProjectiveConstraintSet"); + processObjects(node->constraintSet,"ConstraintSet"); + processObjects(node->contextObject,"ContextObject"); + + processObjects(node->mapping,"Mapping"); + processObjects(node->behaviorModel,"BehaviorModel"); + processObjects(node->visualModel,"VisualModel"); + processObjects(node->collisionModel,"CollisionModel"); + processObjects(node->collisionPipeline,"CollisionPipeline"); + processObjects(node->unsorted,"unsorted"); + + return RESULT_CONTINUE; +} + +void SnapshotVisitor::processNodeBottomUp(simulation::Node* /*node*/) +{ + --level; +} + + +} // namespace sofa::simulation + + + diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h new file mode 100644 index 00000000000..786bb9f280d --- /dev/null +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h @@ -0,0 +1,69 @@ +/****************************************************************************** +* 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 + + +namespace sofa::simulation +{ + + +class SOFA_SIMULATION_CORE_API SnapshotVisitor : public Visitor +{ +protected: + int verbose; + int level; + bool visitingOrder; ///< by default print the graph organisation but can print the graph visiting by setting visitingOrder at true +public: + SnapshotVisitor(const sofa::core::ExecParams* eparams, bool bVisitingOrder=false) : Visitor(eparams), verbose(0), level(0), visitingOrder(bVisitingOrder) {} + + void setVerbose(int v) { verbose = v; } + int getVerbose() const { return verbose; } + + bool treeTraversal( TreeTraversalRepetition& repeat ) override + { + if( visitingOrder ) + return Visitor::treeTraversal( repeat ); // run the visitor with a regular traversal + else + { + // run the visitor with a tree traversal + repeat=REPEAT_ONCE; + return true; + } + } + + template + void processObject(T obj); + + template + void processObjects(Seq& list, const char* name); + + Result processNodeTopDown(simulation::Node* node) override; + void processNodeBottomUp(simulation::Node* node) override; + const char* getClassName() const override { return "PrintVisitor"; } +}; + +} // namespace sofa::simulation + From 84e28a68fb04c8e6b0efa850556649892a226ef7 Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Fri, 19 Dec 2025 11:44:08 +0100 Subject: [PATCH 05/57] update JSONSnapshot, SnapshotVisitor --- .../Core/simutest/objectmodel/Base_test.cpp | 42 ++++++------ .../Core/src/sofa/core/objectmodel/Base.cpp | 17 +---- .../sofa/core/objectmodel/BaseSnapshot.cpp | 2 + .../src/sofa/core/objectmodel/BaseSnapshot.h | 36 ++++++---- .../sofa/core/objectmodel/JSONSnapshot.cpp | 30 +++++---- .../src/sofa/core/objectmodel/JSONSnapshot.h | 17 ++--- .../sofa/core/objectmodel/SnapshotFactory.h | 2 +- .../src/sofa/simulation/SnapshotVisitor.cpp | 65 ++++++------------- .../src/sofa/simulation/SnapshotVisitor.h | 32 ++------- 9 files changed, 99 insertions(+), 144 deletions(-) diff --git a/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp index a6cb2a25292..be84b3fa237 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp @@ -149,33 +149,33 @@ TEST_F(Base_test, testSaveSnapshot) Node* root = c.root.get() ; - auto visitor = SnapshotVisitor(nullptr); + auto JSONSnapCont = createSnapshot(SnapshotType::JSON); + auto visitor = SnapshotVisitor(nullptr,*JSONSnapCont); root->execute(visitor); - std::vector vObj = root->getTreeObjects(); - - auto JSONSnapCont = createSnapshot(SnapshotType::JSON); + // std::vector vObj = root->getTreeObjects(); + + - for (auto* comp : vObj) - { - std::cout << "******************Nouvelle objet******************"<< std::endl; - std::cout << comp->getPathName() << std::endl; - comp->saveSnapshot(*JSONSnapCont); + // for (auto* comp : vObj) + // { + // std::cout << comp->getPathName() << std::endl; + // comp->saveSnapshot(*JSONSnapCont); - } - std::vector> testcont = JSONSnapCont->getContainer(); - std::cout << "TEst cont : " << testcont.size() <> testcont = JSONSnapCont->getContainer(); - for (int j = 0; j< testcont.size(); j++) - { - std::cout << "Component n°" << j <getDataFields(); VecLink componentlinks = this->getLinks(); - - std::vector vtemp; - for (auto* data : datafield) - { - type.setName( (*data).getName() ); - std::string dataname = type.getName(); - vtemp.push_back(dataname); - } - type.fillContainer(vtemp); - - // for (auto* links : componentlinks) - // { - // /// ReadAccessor pour les links ? - - // } + type.collectData(datafield, componentlinks); + // type.printSnapshot(); } } // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp index 2587e5e8969..0e7264e9fa4 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp @@ -28,4 +28,6 @@ BaseSnapshot::BaseSnapshot() {} BaseSnapshot::~BaseSnapshot() = default; + + } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h index 1bdd7216449..a32c5ada770 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h @@ -20,33 +20,41 @@ * Contact information: contact@sofa-framework.org * ******************************************************************************/ #pragma once -#include +// #include +#include +#include namespace sofa::core::objectmodel { - +class Base; class SOFA_CORE_API BaseSnapshot { + +protected: + + struct DataSnapshot + { + std::vector dataContainer; + std::vector linkContainer; + }; + + DataSnapshot dataSnapshot_; + + std::vector snapshot; public: virtual void printSnapshot() = 0; virtual void exportSnapshot() = 0; virtual void importSnapshot() = 0; - - virtual void setName(const std::string& name) = 0; - virtual std::string getName() const = 0; - - virtual void fillContainer(const std::vector& name) = 0; - virtual std::vector> getContainer() const = 0; - + virtual void fillDataSnapshot(BaseData* dat) = 0 ; + virtual void fillSnapshot(DataSnapshot datasnap) = 0; + virtual void fillLinkSnapshot(BaseLink* link) = 0; + virtual void collectData(const std::vector& datafield, const std::vector& componentlinks) = 0; BaseSnapshot(); virtual ~BaseSnapshot() = 0; -public: - std::string dataName; - std::string dataValueType; - std::string valueStr; - std::vector> container; + + }; } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp index 8f4e6d56ffe..e516d1d2bf7 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp @@ -32,12 +32,12 @@ JSONSnapshot::~JSONSnapshot() = default; void JSONSnapshot::printSnapshot() { - std::cout << "printJSONSnapshot" << std::endl; + std::cout << "printJSONSnapshot data : " << snapshot.size() << std::endl; } void JSONSnapshot::exportSnapshot() { - std::cout << "exportSnapshot" << std::endl; + std::cout << "exportSnapshot" << std::endl; } void JSONSnapshot::importSnapshot() @@ -45,25 +45,33 @@ void JSONSnapshot::importSnapshot() std::cout << "importSnapshot" << std::endl; } -void JSONSnapshot::setName(const std::string& name) +void JSONSnapshot::fillDataSnapshot(BaseData* dat) { - dataName = name; + dataSnapshot_.dataContainer.push_back(dat); } -std::string JSONSnapshot::getName() const +void JSONSnapshot::fillSnapshot(DataSnapshot datasnap) { - return dataName; + snapshot.push_back(datasnap); } -void JSONSnapshot::fillContainer(const std::vector& name) +void JSONSnapshot::fillLinkSnapshot(BaseLink* link) { - container.push_back(name); + dataSnapshot_.linkContainer.push_back(link); } -std::vector> JSONSnapshot::getContainer() const +void JSONSnapshot::collectData(const std::vector& datafield, const std::vector& componentlinks ) { - return container; + for (auto* data : datafield) + { + fillDataSnapshot(data); + } + + for(auto* link : componentlinks) + { + fillLinkSnapshot(link); + } + fillSnapshot(dataSnapshot_); } - } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h index 1fdcd02b5f8..dec1f749a0e 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h @@ -29,26 +29,19 @@ namespace sofa::core::objectmodel class SOFA_CORE_API JSONSnapshot : public BaseSnapshot { - + public: void printSnapshot() override; void exportSnapshot() override; void importSnapshot() override; - void setName(const std::string& name) override; - std::string getName() const override; - - void fillContainer(const std::vector& name) override; - std::vector> getContainer() const override; - + void fillDataSnapshot(BaseData* dat) override; + void fillSnapshot(DataSnapshot datasnap) override; + void fillLinkSnapshot(BaseLink* link) override; + void collectData(const std::vector& datafield, const std::vector& componentlinks) override; JSONSnapshot(); ~JSONSnapshot(); -public: - std::string dataName; - std::string dataValueType; - std::string valueStr; - std::vector> container; }; } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.h b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.h index 5d7b5a88f22..70f1dc08e72 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.h @@ -26,7 +26,7 @@ namespace sofa::core::objectmodel { - class BaseSnapshot; +class BaseSnapshot; enum class SnapshotType { JSON, diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp index 094cf9ecaa7..7592b16d13d 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp @@ -35,65 +35,40 @@ #include #include #include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +// #include +#include +#include +using sofa::core::objectmodel::SnapshotType; namespace sofa::simulation { - -template -void SnapshotVisitor::processObject(T obj) +void SnapshotVisitor::processObject(core::objectmodel::BaseObject* obj) { - std::cout << ' ' << obj->getName() << '(' << sofa::helper::gettypename(typeid(*obj)) << ')'; -} - -template -void SnapshotVisitor::processObjects(Seq& list, const char* name) -{ - if (list.empty()) return; - for (int i=0; i<=level; i++) - std::cout << "| "; - std::cout << name << ":"; - for (typename Seq::iterator it = list.begin(); it != list.end(); ++it) - { - typename Seq::value_type obj = *it; - this->processObject(obj); - } - std::cout << std::endl; + obj->saveSnapshot(snapCont_); } Visitor::Result SnapshotVisitor::processNodeTopDown(simulation::Node* node) -{ - for (int i=0; igetName()<mechanicalState,"MechanicalState"); - processObjects(node->mechanicalMapping,"MechanicalMapping"); - processObjects(node->solver,"Solver"); - processObjects(node->linearSolver,"LinearSolver"); - processObjects(node->mass,"Mass"); - processObjects(node->topology,"Topology"); - processObjects(node->forceField,"ForceField"); - processObjects(node->interactionForceField,"InteractionForceField"); - processObjects(node->projectiveConstraintSet,"ProjectiveConstraintSet"); - processObjects(node->constraintSet,"ConstraintSet"); - processObjects(node->contextObject,"ContextObject"); - - processObjects(node->mapping,"Mapping"); - processObjects(node->behaviorModel,"BehaviorModel"); - processObjects(node->visualModel,"VisualModel"); - processObjects(node->collisionModel,"CollisionModel"); - processObjects(node->collisionPipeline,"CollisionPipeline"); - processObjects(node->unsorted,"unsorted"); - +{ + for (simulation::Node::ObjectIterator it = node->object.begin(); it != node->object.end(); ++it) + { + this->processObject(it->get()); + } return RESULT_CONTINUE; } void SnapshotVisitor::processNodeBottomUp(simulation::Node* /*node*/) { - --level; } diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h index 786bb9f280d..7494305ea32 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h @@ -24,6 +24,8 @@ #include #include #include +#include +#include namespace sofa::simulation @@ -33,36 +35,16 @@ namespace sofa::simulation class SOFA_SIMULATION_CORE_API SnapshotVisitor : public Visitor { protected: - int verbose; - int level; - bool visitingOrder; ///< by default print the graph organisation but can print the graph visiting by setting visitingOrder at true + core::objectmodel::BaseSnapshot& snapCont_; public: - SnapshotVisitor(const sofa::core::ExecParams* eparams, bool bVisitingOrder=false) : Visitor(eparams), verbose(0), level(0), visitingOrder(bVisitingOrder) {} + SnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::BaseSnapshot& snapCont) : Visitor(eparams), snapCont_(snapCont) {} - void setVerbose(int v) { verbose = v; } - int getVerbose() const { return verbose; } - - bool treeTraversal( TreeTraversalRepetition& repeat ) override - { - if( visitingOrder ) - return Visitor::treeTraversal( repeat ); // run the visitor with a regular traversal - else - { - // run the visitor with a tree traversal - repeat=REPEAT_ONCE; - return true; - } - } - - template - void processObject(T obj); - - template - void processObjects(Seq& list, const char* name); + void processObject(core::objectmodel::BaseObject* obj); Result processNodeTopDown(simulation::Node* node) override; void processNodeBottomUp(simulation::Node* node) override; - const char* getClassName() const override { return "PrintVisitor"; } + const char* getClassName() const override { return "SnapshotVisitor"; } + }; } // namespace sofa::simulation From 755712e69f68de9479e3e95c8f193ef4fe617669 Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Mon, 22 Dec 2025 15:39:21 +0100 Subject: [PATCH 06/57] saveSnapshotV1 (export to JSON) --- .../Core/simutest/objectmodel/Base_test.cpp | 3 +- .../Core/src/sofa/core/objectmodel/Base.cpp | 5 +- .../src/sofa/core/objectmodel/BaseSnapshot.h | 27 +++++- .../sofa/core/objectmodel/JSONSnapshot.cpp | 83 ++++++++++++++++++- .../src/sofa/core/objectmodel/JSONSnapshot.h | 14 +++- 5 files changed, 123 insertions(+), 9 deletions(-) diff --git a/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp index be84b3fa237..9a9d8154bdf 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp @@ -137,7 +137,7 @@ TEST_F(Base_test, testSaveSnapshot) - + @@ -152,6 +152,7 @@ TEST_F(Base_test, testSaveSnapshot) auto JSONSnapCont = createSnapshot(SnapshotType::JSON); auto visitor = SnapshotVisitor(nullptr,*JSONSnapCont); root->execute(visitor); + JSONSnapCont->exportToJSON(); // std::vector vObj = root->getTreeObjects(); diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index 169458ddc7c..a5060a8b9a6 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -684,8 +684,9 @@ void Base::saveSnapshot(BaseSnapshot& type) { VecData datafield = this->getDataFields(); VecLink componentlinks = this->getLinks(); - type.collectData(datafield, componentlinks); - // type.printSnapshot(); + //type.collectData(datafield, componentlinks); + // type.printSnapshot(); + type.exportSnapshot(datafield, componentlinks); } } // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h index a32c5ada770..daaebdcb8b2 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h @@ -41,15 +41,40 @@ class SOFA_CORE_API BaseSnapshot DataSnapshot dataSnapshot_; std::vector snapshot; +public: + struct DataInfo + { + std::string name; + std::string type; + std::string value; + }; + + struct LinkInfo + { + std::string name; + std::string linkedpath; + std::string path; + }; + + struct SparseDataSnapshot + { + std::vector dataContainer; + std::vector linkContainer; + }; + + SparseDataSnapshot SparseDataSnapshot_; + + std::vector SparseSnapshot; public: virtual void printSnapshot() = 0; - virtual void exportSnapshot() = 0; + virtual void exportSnapshot(const std::vector& datafield, const std::vector& linkfield) = 0; virtual void importSnapshot() = 0; virtual void fillDataSnapshot(BaseData* dat) = 0 ; virtual void fillSnapshot(DataSnapshot datasnap) = 0; virtual void fillLinkSnapshot(BaseLink* link) = 0; virtual void collectData(const std::vector& datafield, const std::vector& componentlinks) = 0; + virtual void exportToJSON() = 0; BaseSnapshot(); virtual ~BaseSnapshot() = 0; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp index e516d1d2bf7..8226d2ba759 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp @@ -20,12 +20,18 @@ * Contact information: contact@sofa-framework.org * ******************************************************************************/ #include +#include +#include +#include +#include #include +#include namespace sofa::core::objectmodel { + JSONSnapshot::JSONSnapshot() {} JSONSnapshot::~JSONSnapshot() = default; @@ -35,9 +41,82 @@ void JSONSnapshot::printSnapshot() std::cout << "printJSONSnapshot data : " << snapshot.size() << std::endl; } -void JSONSnapshot::exportSnapshot() +void to_json(nlohmann::json& j, const BaseSnapshot::DataInfo& di ) +{ + j.clear(); + j["name"] = di.name; + j["type"] = di.type; + j["value"] = di.value; +} + +void to_json(nlohmann::json& j, const BaseSnapshot::LinkInfo& li ) +{ + j.clear(); + j["name"] = li.name; + j["linkedpath"] = li.linkedpath; + j["path"] = li.path; +} + +void to_json(nlohmann::json& j, const BaseSnapshot::SparseDataSnapshot& sds ) +{ + j.clear(); + j["datas"] = sds.dataContainer; + j["links"] = sds.linkContainer; +} + +void JSONSnapshot::exportSnapshot(const std::vector& datafield, const std::vector& linkfield) +{ + std::cout << "exportSnapshot" << std::endl; + + DataInfo dinfo; + for (auto* data : datafield) + { + + dinfo.name = data->getName(); + dinfo.type = data->getValueTypeString(); + dinfo.value = data->getValueString(); + SparseDataSnapshot_.dataContainer.push_back(dinfo); + } + LinkInfo linfo; + for (auto* link : linkfield) + { + + linfo.name = link->getName(); + linfo.linkedpath = link->getLinkedPath(); + linfo.path = link->getPath(); + SparseDataSnapshot_.linkContainer.push_back(linfo); + } + + // nlohmann::json j = sdsSnap; + // std::ofstream file("output.json"); + // file << j.dump(4); + // file.close(); +} + +// std::vector JSONSnapshot::getDataField() const +// { +// return dataSnapshot_.dataContainer; +// } + +// std::vector JSONSnapshot::getLinkField() const +// { +// return dataSnapshot_.linkContainer; +// } + + +// void JSONSnapshot::from_json(const nlohmann::json& j, DataSnapshot& ds ) +// { +// j.at("Data").get_to(ds.dataContainer); +// j.at("Link").get_to(ds.linkContainer); +// } + +void JSONSnapshot::exportToJSON() { - std::cout << "exportSnapshot" << std::endl; + std::cout << "exportToJSON" << std::endl; + nlohmann::json j = SparseDataSnapshot_; + std::ofstream file("output.json"); + file << j.dump(4); + file.close(); } void JSONSnapshot::importSnapshot() diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h index dec1f749a0e..87f8efd92bd 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h @@ -22,6 +22,8 @@ #pragma once #include #include +#include + namespace sofa::core::objectmodel @@ -29,19 +31,25 @@ namespace sofa::core::objectmodel class SOFA_CORE_API JSONSnapshot : public BaseSnapshot { - + public: void printSnapshot() override; - void exportSnapshot() override; + void exportSnapshot(const std::vector& datafield, const std::vector& linkfield) override; void importSnapshot() override; void fillDataSnapshot(BaseData* dat) override; void fillSnapshot(DataSnapshot datasnap) override; void fillLinkSnapshot(BaseLink* link) override; void collectData(const std::vector& datafield, const std::vector& componentlinks) override; - + + // std::vector getLinkField() const; + // std::vector getLinkField() const; + void exportToJSON(); JSONSnapshot(); ~JSONSnapshot(); + + + }; } // namespace sofa::core::objectmodel \ No newline at end of file From b9c8cb4b9d35081bdc6f0d3a373eb715c189a575 Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Tue, 23 Dec 2025 15:33:19 +0100 Subject: [PATCH 07/57] fix exportToJSON - we can choose filename --- .../Core/simutest/objectmodel/Base_test.cpp | 2 +- .../Core/src/sofa/core/objectmodel/Base.cpp | 2 +- .../src/sofa/core/objectmodel/BaseSnapshot.h | 5 +- .../sofa/core/objectmodel/JSONSnapshot.cpp | 57 +++++-------------- .../src/sofa/core/objectmodel/JSONSnapshot.h | 6 +- 5 files changed, 22 insertions(+), 50 deletions(-) diff --git a/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp index 9a9d8154bdf..d506c32fe91 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp @@ -152,7 +152,7 @@ TEST_F(Base_test, testSaveSnapshot) auto JSONSnapCont = createSnapshot(SnapshotType::JSON); auto visitor = SnapshotVisitor(nullptr,*JSONSnapCont); root->execute(visitor); - JSONSnapCont->exportToJSON(); + // JSONSnapCont->exportToJSON(); // std::vector vObj = root->getTreeObjects(); diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index a5060a8b9a6..fba7403fb5a 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -686,7 +686,7 @@ void Base::saveSnapshot(BaseSnapshot& type) VecLink componentlinks = this->getLinks(); //type.collectData(datafield, componentlinks); // type.printSnapshot(); - type.exportSnapshot(datafield, componentlinks); + type.collectData(datafield, componentlinks); } } // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h index daaebdcb8b2..9f1e0ee0f9a 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h @@ -68,13 +68,12 @@ class SOFA_CORE_API BaseSnapshot public: virtual void printSnapshot() = 0; - virtual void exportSnapshot(const std::vector& datafield, const std::vector& linkfield) = 0; virtual void importSnapshot() = 0; virtual void fillDataSnapshot(BaseData* dat) = 0 ; virtual void fillSnapshot(DataSnapshot datasnap) = 0; virtual void fillLinkSnapshot(BaseLink* link) = 0; - virtual void collectData(const std::vector& datafield, const std::vector& componentlinks) = 0; - virtual void exportToJSON() = 0; + virtual void collectData(const std::vector& datafield, const std::vector& linkfield) = 0; + virtual void exportToJSON(const std::string filename) = 0; BaseSnapshot(); virtual ~BaseSnapshot() = 0; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp index 8226d2ba759..6ac1ffe269a 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp @@ -64,14 +64,11 @@ void to_json(nlohmann::json& j, const BaseSnapshot::SparseDataSnapshot& sds ) j["links"] = sds.linkContainer; } -void JSONSnapshot::exportSnapshot(const std::vector& datafield, const std::vector& linkfield) +void JSONSnapshot::collectData(const std::vector& datafield, const std::vector& linkfield) { - std::cout << "exportSnapshot" << std::endl; - DataInfo dinfo; for (auto* data : datafield) { - dinfo.name = data->getName(); dinfo.type = data->getValueTypeString(); dinfo.value = data->getValueString(); @@ -80,41 +77,17 @@ void JSONSnapshot::exportSnapshot(const std::vector& datafield, const LinkInfo linfo; for (auto* link : linkfield) { - linfo.name = link->getName(); linfo.linkedpath = link->getLinkedPath(); linfo.path = link->getPath(); SparseDataSnapshot_.linkContainer.push_back(linfo); } - - // nlohmann::json j = sdsSnap; - // std::ofstream file("output.json"); - // file << j.dump(4); - // file.close(); } -// std::vector JSONSnapshot::getDataField() const -// { -// return dataSnapshot_.dataContainer; -// } - -// std::vector JSONSnapshot::getLinkField() const -// { -// return dataSnapshot_.linkContainer; -// } - - -// void JSONSnapshot::from_json(const nlohmann::json& j, DataSnapshot& ds ) -// { -// j.at("Data").get_to(ds.dataContainer); -// j.at("Link").get_to(ds.linkContainer); -// } - -void JSONSnapshot::exportToJSON() +void JSONSnapshot::exportToJSON(const std::string filename) { - std::cout << "exportToJSON" << std::endl; nlohmann::json j = SparseDataSnapshot_; - std::ofstream file("output.json"); + std::ofstream file(filename); file << j.dump(4); file.close(); } @@ -139,18 +112,18 @@ void JSONSnapshot::fillLinkSnapshot(BaseLink* link) dataSnapshot_.linkContainer.push_back(link); } -void JSONSnapshot::collectData(const std::vector& datafield, const std::vector& componentlinks ) -{ - for (auto* data : datafield) - { - fillDataSnapshot(data); - } +// void JSONSnapshot::collectData(const std::vector& datafield, const std::vector& componentlinks ) +// { +// for (auto* data : datafield) +// { +// fillDataSnapshot(data); +// } - for(auto* link : componentlinks) - { - fillLinkSnapshot(link); - } - fillSnapshot(dataSnapshot_); -} +// for(auto* link : componentlinks) +// { +// fillLinkSnapshot(link); +// } +// fillSnapshot(dataSnapshot_); +// } } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h index 87f8efd92bd..84e30b5c1f3 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h @@ -34,17 +34,17 @@ class SOFA_CORE_API JSONSnapshot : public BaseSnapshot public: void printSnapshot() override; - void exportSnapshot(const std::vector& datafield, const std::vector& linkfield) override; + //void exportSnapshot(const std::vector& datafield, const std::vector& linkfield) override; void importSnapshot() override; void fillDataSnapshot(BaseData* dat) override; void fillSnapshot(DataSnapshot datasnap) override; void fillLinkSnapshot(BaseLink* link) override; - void collectData(const std::vector& datafield, const std::vector& componentlinks) override; + void collectData(const std::vector& datafield, const std::vector& linkfield) override; // std::vector getLinkField() const; // std::vector getLinkField() const; - void exportToJSON(); + void exportToJSON(const std::string filename) override; JSONSnapshot(); ~JSONSnapshot(); From 57032942c29e035a716db581d96fe917ab0d24a6 Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Wed, 24 Dec 2025 14:40:15 +0100 Subject: [PATCH 08/57] update load --- .../src/sofa/core/objectmodel/BaseSnapshot.h | 1 + .../sofa/core/objectmodel/JSONSnapshot.cpp | 48 +++++++++++++++++++ .../src/sofa/core/objectmodel/JSONSnapshot.h | 3 +- 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h index 9f1e0ee0f9a..956830559ab 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h @@ -73,6 +73,7 @@ class SOFA_CORE_API BaseSnapshot virtual void fillSnapshot(DataSnapshot datasnap) = 0; virtual void fillLinkSnapshot(BaseLink* link) = 0; virtual void collectData(const std::vector& datafield, const std::vector& linkfield) = 0; + virtual void putData(std::vector& datafield, std::vector& linkfield) = 0; virtual void exportToJSON(const std::string filename) = 0; BaseSnapshot(); diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp index 6ac1ffe269a..8c31bd4218c 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp @@ -97,6 +97,54 @@ void JSONSnapshot::importSnapshot() std::cout << "importSnapshot" << std::endl; } + +void from_json(const nlohmann::json& j,BaseSnapshot::DataInfo& di ) +{ + j.at("name").get_to(di.name); + j.at("type").get_to(di.type); + j.at("value").get_to(di.value); +} + +void from_json(const nlohmann::json& j,BaseSnapshot::LinkInfo& li ) +{ + j.at("name").get_to(li.name); + j.at("linkedpath").get_to(li.linkedpath); + j.at("path").get_to(li.path); +} + +void from_json(const nlohmann::json& j,BaseSnapshot::SparseDataSnapshot& sds ) +{ + j.at("datas").get_to(sds.dataContainer); + j.at("links").get_to(sds.linkContainer); +} + +void JSONSnapshot::importFromJSON(const std::string filename, nlohmann::json& j) +{ + std::ifstream file(filename); + file >> j; +} + +void JSONSnapshot::putData(std::vector& datafield, std::vector& linkfield) +{ + DataInfo dinfo; + for (auto* data : datafield) + { + dinfo.name = data->getName(); + dinfo.type = data->getValueTypeString(); + dinfo.value = data->getValueString(); + SparseDataSnapshot_.dataContainer.push_back(dinfo); + } + LinkInfo linfo; + for (auto* link : linkfield) + { + linfo.name = link->getName(); + linfo.linkedpath = link->getLinkedPath(); + linfo.path = link->getPath(); + SparseDataSnapshot_.linkContainer.push_back(linfo); + } +} + + void JSONSnapshot::fillDataSnapshot(BaseData* dat) { dataSnapshot_.dataContainer.push_back(dat); diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h index 84e30b5c1f3..b1f38fc3108 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h @@ -41,10 +41,11 @@ class SOFA_CORE_API JSONSnapshot : public BaseSnapshot void fillSnapshot(DataSnapshot datasnap) override; void fillLinkSnapshot(BaseLink* link) override; void collectData(const std::vector& datafield, const std::vector& linkfield) override; - + void putData(std::vector& datafield, std::vector& linkfield) override; // std::vector getLinkField() const; // std::vector getLinkField() const; void exportToJSON(const std::string filename) override; + void importFromJSON(const std::string filename,nlohmann::json& j); JSONSnapshot(); ~JSONSnapshot(); From 9aa4690e9a9efa462f535fb1d8f8abf989e10e2e Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Tue, 6 Jan 2026 16:15:06 +0100 Subject: [PATCH 09/57] update 06/01 --- .../Core/src/sofa/core/objectmodel/Base.cpp | 21 +++-- .../Core/src/sofa/core/objectmodel/Base.h | 20 ++--- .../src/sofa/core/objectmodel/BaseSnapshot.h | 1 + .../sofa/core/objectmodel/JSONSnapshot.cpp | 5 +- .../sofa/simulation/LoadSnapshotVisitor.cpp | 78 +++++++++++++++++++ .../src/sofa/simulation/LoadSnapshotVisitor.h | 51 ++++++++++++ 6 files changed, 159 insertions(+), 17 deletions(-) create mode 100644 Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp create mode 100644 Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.h diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index fba7403fb5a..e18ca5e5ad3 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -681,13 +681,20 @@ int Base::getInstanciationSourceFilePos() const } void Base::saveSnapshot(BaseSnapshot& type) - { - VecData datafield = this->getDataFields(); - VecLink componentlinks = this->getLinks(); - //type.collectData(datafield, componentlinks); - // type.printSnapshot(); - type.collectData(datafield, componentlinks); - } +{ + VecData datafield = this->getDataFields(); + VecLink componentlinks = this->getLinks(); + //type.collectData(datafield, componentlinks); + // type.printSnapshot(); + type.collectData(datafield, componentlinks); +} + +void Base::loadSnapshot(BaseSnapshot& type) +{ + VecData datafield = this->getDataFields(); + VecLink componentlinks = this->getLinks(); + +} } // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h index 0616da69a79..93331aebde6 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h @@ -367,20 +367,22 @@ class SOFA_CORE_API Base : public IntrusiveObject public : - struct SnapshotContainer - { - std::string dataname; + // struct SnapshotContainer + // { + // std::string dataname; - std::string datavalue; - }; + // std::string datavalue; + // }; - void setSnapshot(BaseSnapshot* impl) - { - Snapshot_impl = impl; - } + // void setSnapshot(BaseSnapshot* impl) + // { + // Snapshot_impl = impl; + // } void saveSnapshot(BaseSnapshot& type); + void loadSnapshot(BaseSnapshot& type); + private : BaseSnapshot* Snapshot_impl; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h index 956830559ab..e430a92ef38 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h @@ -47,6 +47,7 @@ class SOFA_CORE_API BaseSnapshot std::string name; std::string type; std::string value; + std::string pathname; }; struct LinkInfo diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp index 8c31bd4218c..05090d786e3 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp @@ -47,6 +47,7 @@ void to_json(nlohmann::json& j, const BaseSnapshot::DataInfo& di ) j["name"] = di.name; j["type"] = di.type; j["value"] = di.value; + j["pathname"] = di.pathname; } void to_json(nlohmann::json& j, const BaseSnapshot::LinkInfo& li ) @@ -72,6 +73,7 @@ void JSONSnapshot::collectData(const std::vector& datafield, const st dinfo.name = data->getName(); dinfo.type = data->getValueTypeString(); dinfo.value = data->getValueString(); + dinfo.pathname = data->getPathName(); SparseDataSnapshot_.dataContainer.push_back(dinfo); } LinkInfo linfo; @@ -88,7 +90,7 @@ void JSONSnapshot::exportToJSON(const std::string filename) { nlohmann::json j = SparseDataSnapshot_; std::ofstream file(filename); - file << j.dump(4); + file << j.dump(5); file.close(); } @@ -126,6 +128,7 @@ void JSONSnapshot::importFromJSON(const std::string filename, nlohmann::json& j) void JSONSnapshot::putData(std::vector& datafield, std::vector& linkfield) { + // idea -> while-loop with conditions like : while dataname are same, just set the data. if not DataInfo dinfo; for (auto* data : datafield) { diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp new file mode 100644 index 00000000000..62e7b68a3f5 --- /dev/null +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp @@ -0,0 +1,78 @@ +/****************************************************************************** +* 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +// #include +#include +#include +using sofa::core::objectmodel::SnapshotType; + + +namespace sofa::simulation +{ + +void LoadSnapshotVisitor::processObject(core::objectmodel::BaseObject* obj) +{ + obj->loadSnapshot(snapCont_); +} + +Visitor::Result LoadSnapshotVisitor::processNodeTopDown(simulation::Node* node) +{ + for (simulation::Node::ObjectIterator it = node->object.begin(); it != node->object.end(); ++it) + { + this->processObject(it->get()); + } + return RESULT_CONTINUE; +} + +void LoadSnapshotVisitor::processNodeBottomUp(simulation::Node* /*node*/) +{ +} + + +} // namespace sofa::simulation + + + diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.h new file mode 100644 index 00000000000..f7033fd8fb8 --- /dev/null +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.h @@ -0,0 +1,51 @@ +/****************************************************************************** +* 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 +#include + + +namespace sofa::simulation +{ + + +class SOFA_SIMULATION_CORE_API LoadSnapshotVisitor : public Visitor +{ +protected: + core::objectmodel::BaseSnapshot& snapCont_; +public: + LoadSnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::BaseSnapshot& snapCont) : Visitor(eparams), snapCont_(snapCont) {} + + void processObject(core::objectmodel::BaseObject* obj); + + Result processNodeTopDown(simulation::Node* node) override; + void processNodeBottomUp(simulation::Node* node) override; + const char* getClassName() const override { return "SnapshotVisitor"; } + +}; + +} // namespace sofa::simulation + From 9b2c5f4ab389ff7aa432a0aa7ee0caea4236c7f7 Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Tue, 13 Jan 2026 09:22:36 +0100 Subject: [PATCH 10/57] update tree structure --- .../Core/src/sofa/core/objectmodel/Base.cpp | 7 ++ .../Core/src/sofa/core/objectmodel/Base.h | 2 +- .../src/sofa/core/objectmodel/BaseSnapshot.h | 11 ++- .../sofa/core/objectmodel/JSONSnapshot.cpp | 79 +++++++++++++------ .../src/sofa/core/objectmodel/JSONSnapshot.h | 9 ++- .../src/sofa/simulation/SnapshotVisitor.cpp | 4 + 6 files changed, 82 insertions(+), 30 deletions(-) diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index e18ca5e5ad3..3623b83331b 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -687,6 +687,13 @@ void Base::saveSnapshot(BaseSnapshot& type) //type.collectData(datafield, componentlinks); // type.printSnapshot(); type.collectData(datafield, componentlinks); + //type.ComponentSnapshot.push_back(this->getName()); +} + +void Base::nodeSnapshot(BaseSnapshot& type) +{ + type.ComponentSnapshot.push_back(this->getName()); + type.groupComponent(); } void Base::loadSnapshot(BaseSnapshot& type) diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h index 93331aebde6..e5e7651a08c 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h @@ -380,7 +380,7 @@ public : // } void saveSnapshot(BaseSnapshot& type); - + void nodeSnapshot(BaseSnapshot& type); void loadSnapshot(BaseSnapshot& type); private : diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h index e430a92ef38..aabed522a31 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h @@ -47,7 +47,7 @@ class SOFA_CORE_API BaseSnapshot std::string name; std::string type; std::string value; - std::string pathname; + std::string ownername; }; struct LinkInfo @@ -67,6 +67,10 @@ class SOFA_CORE_API BaseSnapshot std::vector SparseSnapshot; + std::vector ComponentSnapshot; + + std::vector> NodeSnapshot; + public: virtual void printSnapshot() = 0; virtual void importSnapshot() = 0; @@ -74,8 +78,9 @@ class SOFA_CORE_API BaseSnapshot virtual void fillSnapshot(DataSnapshot datasnap) = 0; virtual void fillLinkSnapshot(BaseLink* link) = 0; virtual void collectData(const std::vector& datafield, const std::vector& linkfield) = 0; - virtual void putData(std::vector& datafield, std::vector& linkfield) = 0; - virtual void exportToJSON(const std::string filename) = 0; + virtual void groupComponent() = 0; + virtual void putData(std::vector& datafield, std::vector& linkfield,BaseSnapshot::DataInfo& di) = 0; + virtual void exportTo(const std::string filename) = 0; BaseSnapshot(); virtual ~BaseSnapshot() = 0; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp index 05090d786e3..7c42086c454 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp @@ -28,6 +28,9 @@ #include #include +#include + + namespace sofa::core::objectmodel { @@ -47,7 +50,7 @@ void to_json(nlohmann::json& j, const BaseSnapshot::DataInfo& di ) j["name"] = di.name; j["type"] = di.type; j["value"] = di.value; - j["pathname"] = di.pathname; + j["ownername"] = di.ownername; } void to_json(nlohmann::json& j, const BaseSnapshot::LinkInfo& li ) @@ -67,30 +70,72 @@ void to_json(nlohmann::json& j, const BaseSnapshot::SparseDataSnapshot& sds ) void JSONSnapshot::collectData(const std::vector& datafield, const std::vector& linkfield) { + SparseDataSnapshot_.dataContainer.clear(); + SparseDataSnapshot_.linkContainer.clear(); DataInfo dinfo; for (auto* data : datafield) { + // std::cout << (*data) << std::endl; + dinfo.name = data->getName(); dinfo.type = data->getValueTypeString(); dinfo.value = data->getValueString(); - dinfo.pathname = data->getPathName(); + // (*data).setValueString(dinfo.value); + // data->setValueString(dinfo.value); + + dinfo.ownername = (data->getOwner())->getName(); SparseDataSnapshot_.dataContainer.push_back(dinfo); } LinkInfo linfo; for (auto* link : linkfield) { + // std::cout << (*link) << std::endl; linfo.name = link->getName(); linfo.linkedpath = link->getLinkedPath(); linfo.path = link->getPath(); SparseDataSnapshot_.linkContainer.push_back(linfo); } + SparseSnapshot.push_back(SparseDataSnapshot_); } -void JSONSnapshot::exportToJSON(const std::string filename) +nlohmann::json JSONSnapshot::nodeArray() { - nlohmann::json j = SparseDataSnapshot_; + nlohmann::json jNode = nlohmann::json::array(); + + NodeSnapshot.push_back(SparseSnapshot); + jNode.push_back(NodeSnapshot); + SparseSnapshot.clear(); + + return jNode; +} + +void JSONSnapshot::groupComponent() +{ + NodeSnapshot.push_back(SparseSnapshot); + SparseSnapshot.clear(); +} + +void JSONSnapshot::exportTo(const std::string filename) +{ + nlohmann::json root = nlohmann::json::object(); + + for (size_t ni = 0; ni < NodeSnapshot.size(); ++ni) + { + const auto &components = NodeSnapshot[ni]; + nlohmann::json nodeJson = nlohmann::json::object(); + + for (size_t ci = 0; ci < components.size(); ++ci) + { + const auto &sds = components[ci]; + std::string compName; + compName = sds.dataContainer.front().ownername; + nodeJson[compName] = sds; + } + root[ComponentSnapshot[ni]] = nodeJson; + } + std::ofstream file(filename); - file << j.dump(5); + file << root.dump(5); file.close(); } @@ -105,6 +150,7 @@ void from_json(const nlohmann::json& j,BaseSnapshot::DataInfo& di ) j.at("name").get_to(di.name); j.at("type").get_to(di.type); j.at("value").get_to(di.value); + } void from_json(const nlohmann::json& j,BaseSnapshot::LinkInfo& li ) @@ -120,31 +166,18 @@ void from_json(const nlohmann::json& j,BaseSnapshot::SparseDataSnapshot& sds ) j.at("links").get_to(sds.linkContainer); } -void JSONSnapshot::importFromJSON(const std::string filename, nlohmann::json& j) +void JSONSnapshot::importFrom(const std::string filename, nlohmann::json& j) { std::ifstream file(filename); file >> j; } -void JSONSnapshot::putData(std::vector& datafield, std::vector& linkfield) +void JSONSnapshot::putData(std::vector& datafield, std::vector& linkfield, BaseSnapshot::DataInfo& di) { // idea -> while-loop with conditions like : while dataname are same, just set the data. if not - DataInfo dinfo; - for (auto* data : datafield) - { - dinfo.name = data->getName(); - dinfo.type = data->getValueTypeString(); - dinfo.value = data->getValueString(); - SparseDataSnapshot_.dataContainer.push_back(dinfo); - } - LinkInfo linfo; - for (auto* link : linkfield) - { - linfo.name = link->getName(); - linfo.linkedpath = link->getLinkedPath(); - linfo.path = link->getPath(); - SparseDataSnapshot_.linkContainer.push_back(linfo); - } + + std::cout << "hey" << std::endl; + } diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h index b1f38fc3108..7423d5b09d7 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h @@ -41,14 +41,17 @@ class SOFA_CORE_API JSONSnapshot : public BaseSnapshot void fillSnapshot(DataSnapshot datasnap) override; void fillLinkSnapshot(BaseLink* link) override; void collectData(const std::vector& datafield, const std::vector& linkfield) override; - void putData(std::vector& datafield, std::vector& linkfield) override; + void putData(std::vector& datafield, std::vector& linkfield, BaseSnapshot::DataInfo& di) override; // std::vector getLinkField() const; // std::vector getLinkField() const; - void exportToJSON(const std::string filename) override; - void importFromJSON(const std::string filename,nlohmann::json& j); + void groupComponent() override; + nlohmann::json nodeArray(); + void exportTo(const std::string filename) override; + void importFrom(const std::string filename,nlohmann::json& j); JSONSnapshot(); ~JSONSnapshot(); + //nlohmann::json:: jNode = nlohmann::json::array(); diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp index 7592b16d13d..2afa89bcfa2 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp @@ -55,15 +55,19 @@ namespace sofa::simulation void SnapshotVisitor::processObject(core::objectmodel::BaseObject* obj) { + std::cout << "-" <getName() << std::endl; obj->saveSnapshot(snapCont_); } Visitor::Result SnapshotVisitor::processNodeTopDown(simulation::Node* node) { + std::cout << node->getName() << std::endl; + node->saveSnapshot(snapCont_); for (simulation::Node::ObjectIterator it = node->object.begin(); it != node->object.end(); ++it) { this->processObject(it->get()); } + node->nodeSnapshot(snapCont_); return RESULT_CONTINUE; } From 2f0a75c946a37fcd1fc6a555962fcbbcaa0a8177 Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Mon, 26 Jan 2026 11:16:50 +0100 Subject: [PATCH 11/57] move all functions from JSONSnapshot to BaseSnapshot + fix structure --- .../Core/simutest/objectmodel/Base_test.cpp | 6 +- .../Core/src/sofa/core/objectmodel/Base.cpp | 56 ++++-- .../Core/src/sofa/core/objectmodel/Base.h | 5 +- .../sofa/core/objectmodel/BaseSnapshot.cpp | 107 ++++++++++ .../src/sofa/core/objectmodel/BaseSnapshot.h | 65 ++++-- .../sofa/core/objectmodel/JSONSnapshot.cpp | 190 +++++++++--------- .../src/sofa/core/objectmodel/JSONSnapshot.h | 20 +- .../src/sofa/simulation/SnapshotVisitor.cpp | 30 ++- .../src/sofa/simulation/SnapshotVisitor.h | 10 +- 9 files changed, 332 insertions(+), 157 deletions(-) diff --git a/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp index d506c32fe91..fddae9292ab 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp @@ -149,9 +149,9 @@ TEST_F(Base_test, testSaveSnapshot) Node* root = c.root.get() ; - auto JSONSnapCont = createSnapshot(SnapshotType::JSON); - auto visitor = SnapshotVisitor(nullptr,*JSONSnapCont); - root->execute(visitor); + // auto JSONSnapCont = createSnapshot(SnapshotType::JSON); + // auto visitor = SnapshotVisitor(nullptr,*JSONSnapCont); + // root->execute(visitor); // JSONSnapCont->exportToJSON(); // std::vector vObj = root->getTreeObjects(); diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index 3623b83331b..9383d5c03fe 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -42,6 +42,8 @@ using sofa::helper::getClosestMatch; #include #include + + #define ERROR_LOG_SIZE 100 namespace sofa::core::objectmodel @@ -680,27 +682,51 @@ int Base::getInstanciationSourceFilePos() const return m_instanciationSourceFilePos; } -void Base::saveSnapshot(BaseSnapshot& type) +void Base::saveSnapshot(BaseSnapshot& snap, std::string parent) { - VecData datafield = this->getDataFields(); - VecLink componentlinks = this->getLinks(); - //type.collectData(datafield, componentlinks); - // type.printSnapshot(); - type.collectData(datafield, componentlinks); - //type.ComponentSnapshot.push_back(this->getName()); -} + if(this->getClassName() == "Node") + { + auto snapObj = std::make_shared(); + snapObj->name = this->getName(); + snap.addToSnap(*this, *snapObj); -void Base::nodeSnapshot(BaseSnapshot& type) -{ - type.ComponentSnapshot.push_back(this->getName()); - type.groupComponent(); + snap.nodeList.push_back(snapObj->name); + + if(snap.hasSnapParent(parent)) + { + std::cout << "getSnapParent" << std::endl; + std::shared_ptr snapParent = snap.getSnapParent(snap.treeSnapshot[0],parent); + snapParent->childNode.push_back(snapObj); + } + else + { + snap.treeSnapshot.push_back(snapObj); + } + + } + else + { + auto snapObj = std::make_shared(); + snap.addToSnap(*this, *snapObj); + if(snap.hasSnapParent(parent)) + { + std::shared_ptr snapParent = snap.getSnapParent(snap.treeSnapshot[0],parent); + snapParent->componentList.push_back(*snapObj) ; + } + else + { + snap.treeSnapshot[0]->componentList.push_back(*snapObj); + } + + } } + + void Base::loadSnapshot(BaseSnapshot& type) { - VecData datafield = this->getDataFields(); - VecLink componentlinks = this->getLinks(); - + //type.importSnapshot(filename); + std::cout << "load snapshot" << std::endl; } } // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h index e5e7651a08c..10532a0fdf5 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h @@ -45,7 +45,6 @@ #include - #define SOFA_BASE_CAST_IMPLEMENTATION(CLASSNAME) \ virtual const CLASSNAME* to##CLASSNAME() const override { return this; } \ virtual CLASSNAME* to##CLASSNAME() override { return this; } @@ -379,8 +378,8 @@ public : // Snapshot_impl = impl; // } - void saveSnapshot(BaseSnapshot& type); - void nodeSnapshot(BaseSnapshot& type); + void saveSnapshot(BaseSnapshot& type, std::string parent); + void loadSnapshot(BaseSnapshot& type); private : diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp index 0e7264e9fa4..1a4fcc1ff07 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp @@ -20,6 +20,7 @@ * Contact information: contact@sofa-framework.org * ******************************************************************************/ #include +#include "BaseSnapshot.h" namespace sofa::core::objectmodel { @@ -28,6 +29,112 @@ BaseSnapshot::BaseSnapshot() {} BaseSnapshot::~BaseSnapshot() = default; +void BaseSnapshot::addToSnap(Base& b, SnapNode& snapObject) +{ + std::vector objData = collectSnapData(b.getDataFields()); + snapObject.dataContainer.insert(snapObject.dataContainer.end(),std::make_move_iterator(objData.begin()),std::make_move_iterator(objData.end())); + //snapObject.dataContainer.push_back(objData); + std::vector objLink = collectSnapLink(b.getLinks()); + snapObject.linkContainer.insert(snapObject.linkContainer.end(),std::make_move_iterator(objLink.begin()),std::make_move_iterator(objLink.end())); + //snapObject.linkContainer.push_back(objLink); + + snapObject.name = b.getName(); + + // idea : change collectSnapData() parameter to take snapObject as argument. + // Maybe change/add a new struct to contains datas AND links (!= component) + // collectSnapData(b.getDataFields(), b.getLinks(), snapObject, isBool); + +} + +void BaseSnapshot::addToSnap(Base& b, SnapComponent& snapObject) +{ + std::cout<< "snapcomponent" << std::endl; + std::vector objData = collectSnapData(b.getDataFields()); + snapObject.dataContainer.insert(snapObject.dataContainer.end(),std::make_move_iterator(objData.begin()),std::make_move_iterator(objData.end())); + //snapObject.dataContainer.push_back(objData); + std::vector objLink = collectSnapLink(b.getLinks()); + snapObject.linkContainer.insert(snapObject.linkContainer.end(),std::make_move_iterator(objLink.begin()),std::make_move_iterator(objLink.end())); + //snapObject.linkContainer.push_back(objLink); + + snapObject.name = b.getName(); + + +} + + + +std::vector BaseSnapshot::collectSnapData(const std::vector& datafield) +{ + BaseSnapshot::DataInfo dinfo; + std::vector dataContainer; + for (auto* data : datafield) + { + dinfo.name = data->getName(); + dinfo.type = data->getValueTypeString(); + dinfo.value = data->getValueString(); + dataContainer.push_back(dinfo); + } + + return dataContainer; +} + +std::vector BaseSnapshot::collectSnapLink(const std::vector& linkfield) +{ + BaseSnapshot::LinkInfo linfo; + std::vector linkContainer; + for (auto* link : linkfield) + { + linfo.name = link->getName(); + linfo.value = link->getValueString(); + linfo.type = link->getValueTypeString(); + linkContainer.push_back(linfo); + } + + return linkContainer; +} + +bool BaseSnapshot::hasSnapParent(std::string& parentName) +{ + bool result = false; + + if(treeSnapshot.empty()) + { + return result; + } + + for(auto name : nodeList) + { + if(name == parentName) + { + result = true; + } + } + + return result; +} + + +std::shared_ptr BaseSnapshot::getSnapParent(std::shared_ptr& node, + std::string& parentName) +{ + if (!node) + { + return nullptr; + } + + if(node->name == parentName) + { + return node; + } + for (auto& child : node->childNode) + { + if(auto result = getSnapParent(child, parentName)) + { + return result; + } + } + return nullptr; +} } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h index aabed522a31..db34a61622f 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h @@ -20,7 +20,7 @@ * Contact information: contact@sofa-framework.org * ******************************************************************************/ #pragma once -// #include +#include #include #include @@ -40,47 +40,76 @@ class SOFA_CORE_API BaseSnapshot DataSnapshot dataSnapshot_; - std::vector snapshot; + //std::vector snapshot; public: struct DataInfo { std::string name; std::string type; std::string value; - std::string ownername; + std::string parentData; + + DataInfo() : name(), type(), value(), parentData() {} }; struct LinkInfo { std::string name; - std::string linkedpath; - std::string path; + std::string type; + std::string value; + LinkInfo() : name(), type(), value() {} }; - struct SparseDataSnapshot + struct SnapComponent //SparseDataSnapshot { + std::string name; std::vector dataContainer; std::vector linkContainer; + + SnapComponent() : name(""), dataContainer(), linkContainer() {} + + SnapComponent(const std::string& name) : name(name){} }; - SparseDataSnapshot SparseDataSnapshot_; + SnapComponent SnapComponent_; // SparseDataSnapshot SparseDataSnapshot_ - std::vector SparseSnapshot; + struct SnapNode + { + std::string name; + std::vector dataContainer; + std::vector linkContainer; + std::vector componentList; + std::vector> childNode; + + SnapNode() : name(""), dataContainer(), linkContainer(), componentList(), childNode() {} - std::vector ComponentSnapshot; + SnapNode(const std::string& name) : name(name) {} + }; - std::vector> NodeSnapshot; + SnapNode SnapNode_; + + std::vector nodeList; + std::vector> treeSnapshot; // here, it is the snapshot + public: - virtual void printSnapshot() = 0; - virtual void importSnapshot() = 0; - virtual void fillDataSnapshot(BaseData* dat) = 0 ; - virtual void fillSnapshot(DataSnapshot datasnap) = 0; - virtual void fillLinkSnapshot(BaseLink* link) = 0; - virtual void collectData(const std::vector& datafield, const std::vector& linkfield) = 0; - virtual void groupComponent() = 0; - virtual void putData(std::vector& datafield, std::vector& linkfield,BaseSnapshot::DataInfo& di) = 0; + virtual void importSnapshot(const std::string filename) = 0; + + + + std::vector collectSnapData(const std::vector& datafield); + std::vector collectSnapLink(const std::vector& linkfield); + bool hasSnapParent(std::string& parentName); + std::shared_ptr getSnapParent(std::shared_ptr& node, std::string& parentName); + + virtual std::shared_ptr createChildNode(const std::string& nodeName) = 0; + virtual void addChildToCurrentNode(std::shared_ptr child,SnapNode& snapnode) = 0 ; + + void addToSnap(Base& b, SnapNode& snapObj); + void addToSnap(Base& b, SnapComponent& snapObj); + virtual void exportTo(const std::string filename) = 0; + virtual void importFrom(std::string filename, BaseSnapshot::SnapNode& rootNode) = 0; BaseSnapshot(); virtual ~BaseSnapshot() = 0; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp index 7c42086c454..19d0747a793 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp @@ -39,10 +39,6 @@ JSONSnapshot::JSONSnapshot() {} JSONSnapshot::~JSONSnapshot() = default; -void JSONSnapshot::printSnapshot() -{ - std::cout << "printJSONSnapshot data : " << snapshot.size() << std::endl; -} void to_json(nlohmann::json& j, const BaseSnapshot::DataInfo& di ) { @@ -50,98 +46,82 @@ void to_json(nlohmann::json& j, const BaseSnapshot::DataInfo& di ) j["name"] = di.name; j["type"] = di.type; j["value"] = di.value; - j["ownername"] = di.ownername; } void to_json(nlohmann::json& j, const BaseSnapshot::LinkInfo& li ) { j.clear(); j["name"] = li.name; - j["linkedpath"] = li.linkedpath; - j["path"] = li.path; + j["type"] = li.type; + j["value"] = li.value; } -void to_json(nlohmann::json& j, const BaseSnapshot::SparseDataSnapshot& sds ) +void to_json(nlohmann::json& j, const BaseSnapshot::SnapComponent& sds ) { j.clear(); j["datas"] = sds.dataContainer; j["links"] = sds.linkContainer; } -void JSONSnapshot::collectData(const std::vector& datafield, const std::vector& linkfield) +void to_json(nlohmann::json& j, const BaseSnapshot::SnapNode& sn) { - SparseDataSnapshot_.dataContainer.clear(); - SparseDataSnapshot_.linkContainer.clear(); - DataInfo dinfo; - for (auto* data : datafield) - { - // std::cout << (*data) << std::endl; - - dinfo.name = data->getName(); - dinfo.type = data->getValueTypeString(); - dinfo.value = data->getValueString(); - // (*data).setValueString(dinfo.value); - // data->setValueString(dinfo.value); - - dinfo.ownername = (data->getOwner())->getName(); - SparseDataSnapshot_.dataContainer.push_back(dinfo); - } - LinkInfo linfo; - for (auto* link : linkfield) + j.clear(); + j["name"] = sn.name; + j["datas"] = sn.dataContainer; + j["links"] = sn.linkContainer; + j["componentList"] = sn.componentList; + + j["childNode"] = nlohmann::json::array(); + for (const auto& childPtr : sn.childNode) { - // std::cout << (*link) << std::endl; - linfo.name = link->getName(); - linfo.linkedpath = link->getLinkedPath(); - linfo.path = link->getPath(); - SparseDataSnapshot_.linkContainer.push_back(linfo); + if(childPtr) + { + j["childNode"].push_back(*childPtr); + } } - SparseSnapshot.push_back(SparseDataSnapshot_); } -nlohmann::json JSONSnapshot::nodeArray() -{ - nlohmann::json jNode = nlohmann::json::array(); - - NodeSnapshot.push_back(SparseSnapshot); - jNode.push_back(NodeSnapshot); - SparseSnapshot.clear(); - return jNode; +std::shared_ptr JSONSnapshot::createChildNode(const std::string& name) +{ + auto child = std::make_shared(); + child->name = name; + return child; } -void JSONSnapshot::groupComponent() +void JSONSnapshot::addChildToCurrentNode(std::shared_ptr child, BaseSnapshot::SnapNode& snapnode) { - NodeSnapshot.push_back(SparseSnapshot); - SparseSnapshot.clear(); + // snapnode.childNode.push_back(child); + // auto currentNode = getCurrentNode(); + // if (currentNode && child) + // currentNode->childNode.push_back(child); + std::cout << "wip" << std::endl; } + void JSONSnapshot::exportTo(const std::string filename) { - nlohmann::json root = nlohmann::json::object(); - for (size_t ni = 0; ni < NodeSnapshot.size(); ++ni) - { - const auto &components = NodeSnapshot[ni]; - nlohmann::json nodeJson = nlohmann::json::object(); + nlohmann::json j = nlohmann::json::array() ; - for (size_t ci = 0; ci < components.size(); ++ci) + for (const auto& nodePtr : treeSnapshot) + { + if (nodePtr) { - const auto &sds = components[ci]; - std::string compName; - compName = sds.dataContainer.front().ownername; - nodeJson[compName] = sds; + j.push_back(*nodePtr); } - root[ComponentSnapshot[ni]] = nodeJson; } std::ofstream file(filename); - file << root.dump(5); + file << j.dump(5); file.close(); } -void JSONSnapshot::importSnapshot() +void JSONSnapshot::importSnapshot(const std::string filename) { std::cout << "importSnapshot" << std::endl; + //importFrom(filename); + } @@ -156,58 +136,80 @@ void from_json(const nlohmann::json& j,BaseSnapshot::DataInfo& di ) void from_json(const nlohmann::json& j,BaseSnapshot::LinkInfo& li ) { j.at("name").get_to(li.name); - j.at("linkedpath").get_to(li.linkedpath); - j.at("path").get_to(li.path); + j.at("type").get_to(li.type); + j.at("value").get_to(li.value); } -void from_json(const nlohmann::json& j,BaseSnapshot::SparseDataSnapshot& sds ) +void from_json(const nlohmann::json& j,BaseSnapshot::SnapComponent& sds ) { j.at("datas").get_to(sds.dataContainer); j.at("links").get_to(sds.linkContainer); } -void JSONSnapshot::importFrom(const std::string filename, nlohmann::json& j) +void from_json(const nlohmann::json& j, BaseSnapshot::SnapNode& sn) { - std::ifstream file(filename); - file >> j; -} + // j.clear(); + j.at("name").get_to(sn.name); //j["name"] = sn.name; + j.at("datas").get_to(sn.dataContainer); //j["datas"] = sn.dataContainer; + j.at("links").get_to(sn.linkContainer); //j["links"] = sn.linkContainer; + j.at("componentList").get_to(sn.componentList); //j["componentList"] = sn.componentList; -void JSONSnapshot::putData(std::vector& datafield, std::vector& linkfield, BaseSnapshot::DataInfo& di) -{ - // idea -> while-loop with conditions like : while dataname are same, just set the data. if not - - std::cout << "hey" << std::endl; - + sn.childNode.clear(); + if (j.contains("childNode") && j["childNode"].is_array()) + { + for (const auto& childJson : j["childNode"]) + { + auto child = std::make_shared(); + childJson.get_to(*child); + sn.childNode.push_back(child); + } + } } - -void JSONSnapshot::fillDataSnapshot(BaseData* dat) +void JSONSnapshot::importFrom(const std::string filename, BaseSnapshot::SnapNode& rootNode) { - dataSnapshot_.dataContainer.push_back(dat); + std::cout << "importFrom" << std::endl; + std::ifstream file(filename); + if(file.is_open()) + { + nlohmann::json jfile; + file >> jfile; + file.close(); + + // Lines above would be useful for unit tests + + // for (auto& [key,value] : data.items()) + // { + // std::cout << "name : " << data.value("name","") << std::endl; + // std::cout << "key : " << key << std::endl; + // } + + // if(jfile.contains("componentList")) + // { + // std::cout << "componentList" << std::endl; + // for(auto& [componentkey,componentvalue] : jfile["componentList"].items()) + // { + + // std::cout << "Component : " << componentvalue["datas"][0].value("value","") << std::endl; + // std::cout << "Datas : " << std::endl; + // for(const auto& d : componentvalue["datas"]) + // { + // std::cout << " - " << d.value("name", "") << " [" << d.value("type", "") << "] = " << d.value("value", "") << std::endl; + // } + // std::cout << "Links : " << std::endl; + // for(const auto& l : componentvalue["links"]) + // { + // std::cout << " - " << l.value("name","") << ", value : "<>>(); + // std::cout << data.dump(2) << std::endl; + } } -void JSONSnapshot::fillSnapshot(DataSnapshot datasnap) -{ - snapshot.push_back(datasnap); -} -void JSONSnapshot::fillLinkSnapshot(BaseLink* link) -{ - dataSnapshot_.linkContainer.push_back(link); -} -// void JSONSnapshot::collectData(const std::vector& datafield, const std::vector& componentlinks ) -// { -// for (auto* data : datafield) -// { -// fillDataSnapshot(data); -// } - -// for(auto* link : componentlinks) -// { -// fillLinkSnapshot(link); -// } -// fillSnapshot(dataSnapshot_); -// } } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h index 7423d5b09d7..86bb3baf281 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h @@ -33,21 +33,15 @@ class SOFA_CORE_API JSONSnapshot : public BaseSnapshot { public: - void printSnapshot() override; //void exportSnapshot(const std::vector& datafield, const std::vector& linkfield) override; - void importSnapshot() override; - - void fillDataSnapshot(BaseData* dat) override; - void fillSnapshot(DataSnapshot datasnap) override; - void fillLinkSnapshot(BaseLink* link) override; - void collectData(const std::vector& datafield, const std::vector& linkfield) override; - void putData(std::vector& datafield, std::vector& linkfield, BaseSnapshot::DataInfo& di) override; - // std::vector getLinkField() const; - // std::vector getLinkField() const; - void groupComponent() override; - nlohmann::json nodeArray(); + void importSnapshot(const std::string filename) override; + + std::shared_ptr createChildNode(const std::string& nodeName) override; + void addChildToCurrentNode(std::shared_ptr child, BaseSnapshot::SnapNode& snapnode) override; + void exportTo(const std::string filename) override; - void importFrom(const std::string filename,nlohmann::json& j); + void importFrom(std::string filename, BaseSnapshot::SnapNode& rootNode) override; + JSONSnapshot(); ~JSONSnapshot(); diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp index 2afa89bcfa2..03cc4d48f57 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp @@ -48,30 +48,42 @@ #include #include using sofa::core::objectmodel::SnapshotType; +#include namespace sofa::simulation { -void SnapshotVisitor::processObject(core::objectmodel::BaseObject* obj) +void SnapshotVisitor::processObject(core::objectmodel::BaseObject* obj, std::string parentName) { - std::cout << "-" <getName() << std::endl; - obj->saveSnapshot(snapCont_); + + obj->saveSnapshot(snapCont_, parentName); } Visitor::Result SnapshotVisitor::processNodeTopDown(simulation::Node* node) { - std::cout << node->getName() << std::endl; - node->saveSnapshot(snapCont_); + auto* parent = node->getFirstParent(); + std::string parentName; + if(parent) + { + parentName = parent->getName(); + node->saveSnapshot(snapCont_,parentName); + } + else + { + parentName = "root"; + node->saveSnapshot(snapCont_,parentName); + } + for (simulation::Node::ObjectIterator it = node->object.begin(); it != node->object.end(); ++it) { - this->processObject(it->get()); - } - node->nodeSnapshot(snapCont_); + this->processObject(it->get(),node->getName()); + } + return RESULT_CONTINUE; } -void SnapshotVisitor::processNodeBottomUp(simulation::Node* /*node*/) +void SnapshotVisitor::processNodeBottomUp(simulation::Node* node) { } diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h index 7494305ea32..e6447318c96 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h @@ -26,6 +26,8 @@ #include #include #include +#include +#include namespace sofa::simulation @@ -36,10 +38,14 @@ class SOFA_SIMULATION_CORE_API SnapshotVisitor : public Visitor { protected: core::objectmodel::BaseSnapshot& snapCont_; + core::objectmodel::BaseSnapshot::SnapNode& snapNode_; + public: - SnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::BaseSnapshot& snapCont) : Visitor(eparams), snapCont_(snapCont) {} + SnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::BaseSnapshot& snapshot, core::objectmodel::BaseSnapshot::SnapNode& rootNode) : Visitor(eparams), snapCont_(snapshot), snapNode_(rootNode) + { + } - void processObject(core::objectmodel::BaseObject* obj); + void processObject(core::objectmodel::BaseObject* obj, std::string parentName); Result processNodeTopDown(simulation::Node* node) override; void processNodeBottomUp(simulation::Node* node) override; From 6d47405714d577768151cfe0ebf0cb3bc42ad703 Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Tue, 27 Jan 2026 17:57:05 +0100 Subject: [PATCH 12/57] [Snapshot] ADD files for loadSnapshot + CLEAN BaseSnapshot --- Sofa/framework/Core/CMakeLists.txt | 2 + .../Core/src/sofa/core/objectmodel/Base.cpp | 12 +-- .../Core/src/sofa/core/objectmodel/Base.h | 4 +- .../sofa/core/objectmodel/BaseSnapshot.cpp | 38 ++++--- .../src/sofa/core/objectmodel/BaseSnapshot.h | 48 +++------ .../sofa/core/objectmodel/JSONSnapshot.cpp | 100 +++++------------- .../src/sofa/core/objectmodel/JSONSnapshot.h | 12 +-- .../sofa/core/objectmodel/MemorySnapshot.cpp | 64 +++++++++++ .../sofa/core/objectmodel/MemorySnapshot.h | 50 +++++++++ .../sofa/core/objectmodel/SnapshotFactory.cpp | 4 +- .../sofa/core/objectmodel/SnapshotFactory.h | 4 +- Sofa/framework/Simulation/Core/CMakeLists.txt | 2 + .../sofa/simulation/LoadSnapshotVisitor.cpp | 1 + .../src/sofa/simulation/LoadSnapshotVisitor.h | 2 +- .../src/sofa/simulation/SnapshotVisitor.cpp | 17 +-- .../src/sofa/simulation/SnapshotVisitor.h | 4 +- 16 files changed, 205 insertions(+), 159 deletions(-) create mode 100644 Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp create mode 100644 Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.h diff --git a/Sofa/framework/Core/CMakeLists.txt b/Sofa/framework/Core/CMakeLists.txt index f6c0dea3656..8e58f72d0df 100644 --- a/Sofa/framework/Core/CMakeLists.txt +++ b/Sofa/framework/Core/CMakeLists.txt @@ -185,6 +185,7 @@ set(HEADER_FILES ${SRC_ROOT}/objectmodel/lifecycle/RemovedData.h ${SRC_ROOT}/objectmodel/lifecycle/RenamedData.h ${SRC_ROOT}/objectmodel/Link.h + ${SRC_ROOT}/objectmodel/MemorySnapshot.h ${SRC_ROOT}/objectmodel/MouseEvent.h ${SRC_ROOT}/objectmodel/SPtr.h ${SRC_ROOT}/objectmodel/SnapshotFactory.h @@ -335,6 +336,7 @@ set(SOURCE_FILES ${SRC_ROOT}/objectmodel/KeypressedEvent.cpp ${SRC_ROOT}/objectmodel/KeyreleasedEvent.cpp ${SRC_ROOT}/objectmodel/lifecycle/DeprecatedData.cpp + ${SRC_ROOT}/objectmodel/MemorySnapshot.cpp ${SRC_ROOT}/objectmodel/MouseEvent.cpp ${SRC_ROOT}/objectmodel/ScriptEvent.cpp ${SRC_ROOT}/objectmodel/SnapshotFactory.cpp diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index 9383d5c03fe..0d56eb87ead 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -689,14 +689,11 @@ void Base::saveSnapshot(BaseSnapshot& snap, std::string parent) auto snapObj = std::make_shared(); snapObj->name = this->getName(); snap.addToSnap(*this, *snapObj); - snap.nodeList.push_back(snapObj->name); - if(snap.hasSnapParent(parent)) { - std::cout << "getSnapParent" << std::endl; std::shared_ptr snapParent = snap.getSnapParent(snap.treeSnapshot[0],parent); - snapParent->childNode.push_back(snapObj); + snapParent->children.push_back(snapObj); } else { @@ -711,11 +708,11 @@ void Base::saveSnapshot(BaseSnapshot& snap, std::string parent) if(snap.hasSnapParent(parent)) { std::shared_ptr snapParent = snap.getSnapParent(snap.treeSnapshot[0],parent); - snapParent->componentList.push_back(*snapObj) ; + snapParent->components.push_back(*snapObj) ; } else { - snap.treeSnapshot[0]->componentList.push_back(*snapObj); + snap.treeSnapshot[0]->components.push_back(*snapObj); } } @@ -723,10 +720,11 @@ void Base::saveSnapshot(BaseSnapshot& snap, std::string parent) -void Base::loadSnapshot(BaseSnapshot& type) +void Base::loadSnapshot(BaseSnapshot& snap) { //type.importSnapshot(filename); std::cout << "load snapshot" << std::endl; + snap.addToSimulation(); } } // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h index 10532a0fdf5..6517838e3ac 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h @@ -378,9 +378,9 @@ public : // Snapshot_impl = impl; // } - void saveSnapshot(BaseSnapshot& type, std::string parent); + void saveSnapshot(BaseSnapshot& snap, std::string parent); - void loadSnapshot(BaseSnapshot& type); + void loadSnapshot(BaseSnapshot& snap); private : BaseSnapshot* Snapshot_impl; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp index 1a4fcc1ff07..9c7b10e4092 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp @@ -29,36 +29,33 @@ BaseSnapshot::BaseSnapshot() {} BaseSnapshot::~BaseSnapshot() = default; + +void BaseSnapshot::printSnapshot() +{ + std::cout << "Snapshot : " << std::endl; + for (auto element : treeSnapshot) + { + std::cout << element->name << std::endl; + } +} + + void BaseSnapshot::addToSnap(Base& b, SnapNode& snapObject) { std::vector objData = collectSnapData(b.getDataFields()); snapObject.dataContainer.insert(snapObject.dataContainer.end(),std::make_move_iterator(objData.begin()),std::make_move_iterator(objData.end())); - //snapObject.dataContainer.push_back(objData); std::vector objLink = collectSnapLink(b.getLinks()); snapObject.linkContainer.insert(snapObject.linkContainer.end(),std::make_move_iterator(objLink.begin()),std::make_move_iterator(objLink.end())); - //snapObject.linkContainer.push_back(objLink); - snapObject.name = b.getName(); - - // idea : change collectSnapData() parameter to take snapObject as argument. - // Maybe change/add a new struct to contains datas AND links (!= component) - // collectSnapData(b.getDataFields(), b.getLinks(), snapObject, isBool); - } void BaseSnapshot::addToSnap(Base& b, SnapComponent& snapObject) { - std::cout<< "snapcomponent" << std::endl; std::vector objData = collectSnapData(b.getDataFields()); snapObject.dataContainer.insert(snapObject.dataContainer.end(),std::make_move_iterator(objData.begin()),std::make_move_iterator(objData.end())); - //snapObject.dataContainer.push_back(objData); std::vector objLink = collectSnapLink(b.getLinks()); snapObject.linkContainer.insert(snapObject.linkContainer.end(),std::make_move_iterator(objLink.begin()),std::make_move_iterator(objLink.end())); - //snapObject.linkContainer.push_back(objLink); - snapObject.name = b.getName(); - - } @@ -74,7 +71,6 @@ std::vector BaseSnapshot::collectSnapData(const std::vec dinfo.value = data->getValueString(); dataContainer.push_back(dinfo); } - return dataContainer; } @@ -89,7 +85,6 @@ std::vector BaseSnapshot::collectSnapLink(const std::vec linfo.type = link->getValueTypeString(); linkContainer.push_back(linfo); } - return linkContainer; } @@ -127,7 +122,7 @@ std::shared_ptr BaseSnapshot::getSnapParent(std::shared_ return node; } - for (auto& child : node->childNode) + for (auto& child : node->children) { if(auto result = getSnapParent(child, parentName)) { @@ -137,4 +132,13 @@ std::shared_ptr BaseSnapshot::getSnapParent(std::shared_ return nullptr; } +void BaseSnapshot::addToSimulation() +{ + std::cout << "addToSimulation" << std::endl; + for (auto element : treeSnapshot) + { + std::cout << element->name << std::endl; + } +} + } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h index db34a61622f..827162a9763 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h @@ -30,26 +30,14 @@ class Base; class SOFA_CORE_API BaseSnapshot { -protected: - - struct DataSnapshot - { - std::vector dataContainer; - std::vector linkContainer; - }; - - DataSnapshot dataSnapshot_; - - //std::vector snapshot; public: struct DataInfo { std::string name; std::string type; std::string value; - std::string parentData; - DataInfo() : name(), type(), value(), parentData() {} + DataInfo() : name(), type(), value() {} }; struct LinkInfo @@ -60,7 +48,7 @@ class SOFA_CORE_API BaseSnapshot LinkInfo() : name(), type(), value() {} }; - struct SnapComponent //SparseDataSnapshot + struct SnapComponent { std::string name; std::vector dataContainer; @@ -71,50 +59,46 @@ class SOFA_CORE_API BaseSnapshot SnapComponent(const std::string& name) : name(name){} }; - SnapComponent SnapComponent_; // SparseDataSnapshot SparseDataSnapshot_ + struct SnapNode { std::string name; std::vector dataContainer; std::vector linkContainer; - std::vector componentList; - std::vector> childNode; + std::vector components; + std::vector> children; - SnapNode() : name(""), dataContainer(), linkContainer(), componentList(), childNode() {} + SnapNode() : name(""), dataContainer(), linkContainer(), components(), children() {} SnapNode(const std::string& name) : name(name) {} }; - SnapNode SnapNode_; + public : + SnapComponent SnapComponent_; + SnapNode SnapNode_; - std::vector nodeList; - std::vector> treeSnapshot; // here, it is the snapshot + std::vector nodeList; + std::vector> treeSnapshot; // here, it is the snapshot public: virtual void importSnapshot(const std::string filename) = 0; - - + void printSnapshot(); + void addToSnap(Base& b, SnapNode& snapObj); + void addToSnap(Base& b, SnapComponent& snapObj); std::vector collectSnapData(const std::vector& datafield); std::vector collectSnapLink(const std::vector& linkfield); bool hasSnapParent(std::string& parentName); std::shared_ptr getSnapParent(std::shared_ptr& node, std::string& parentName); - virtual std::shared_ptr createChildNode(const std::string& nodeName) = 0; - virtual void addChildToCurrentNode(std::shared_ptr child,SnapNode& snapnode) = 0 ; - - void addToSnap(Base& b, SnapNode& snapObj); - void addToSnap(Base& b, SnapComponent& snapObj); + void addToSimulation(); virtual void exportTo(const std::string filename) = 0; - virtual void importFrom(std::string filename, BaseSnapshot::SnapNode& rootNode) = 0; + virtual void importFrom(std::string filename) = 0; BaseSnapshot(); virtual ~BaseSnapshot() = 0; - - - }; } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp index 19d0747a793..b6323a6098b 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp @@ -69,39 +69,20 @@ void to_json(nlohmann::json& j, const BaseSnapshot::SnapNode& sn) j["name"] = sn.name; j["datas"] = sn.dataContainer; j["links"] = sn.linkContainer; - j["componentList"] = sn.componentList; + j["components"] = sn.components; - j["childNode"] = nlohmann::json::array(); - for (const auto& childPtr : sn.childNode) + j["children"] = nlohmann::json::array(); + for (const auto& childPtr : sn.children) { if(childPtr) { - j["childNode"].push_back(*childPtr); + j["children"].push_back(*childPtr); } } } - -std::shared_ptr JSONSnapshot::createChildNode(const std::string& name) -{ - auto child = std::make_shared(); - child->name = name; - return child; -} - -void JSONSnapshot::addChildToCurrentNode(std::shared_ptr child, BaseSnapshot::SnapNode& snapnode) -{ - // snapnode.childNode.push_back(child); - // auto currentNode = getCurrentNode(); - // if (currentNode && child) - // currentNode->childNode.push_back(child); - std::cout << "wip" << std::endl; -} - - void JSONSnapshot::exportTo(const std::string filename) { - nlohmann::json j = nlohmann::json::array() ; for (const auto& nodePtr : treeSnapshot) @@ -119,9 +100,7 @@ void JSONSnapshot::exportTo(const std::string filename) void JSONSnapshot::importSnapshot(const std::string filename) { - std::cout << "importSnapshot" << std::endl; - //importFrom(filename); - + std::cout << "importSnapshot" << std::endl; } @@ -148,65 +127,42 @@ void from_json(const nlohmann::json& j,BaseSnapshot::SnapComponent& sds ) void from_json(const nlohmann::json& j, BaseSnapshot::SnapNode& sn) { - // j.clear(); - j.at("name").get_to(sn.name); //j["name"] = sn.name; - j.at("datas").get_to(sn.dataContainer); //j["datas"] = sn.dataContainer; - j.at("links").get_to(sn.linkContainer); //j["links"] = sn.linkContainer; - j.at("componentList").get_to(sn.componentList); //j["componentList"] = sn.componentList; - - sn.childNode.clear(); - if (j.contains("childNode") && j["childNode"].is_array()) + j.at("name").get_to(sn.name); + j.at("datas").get_to(sn.dataContainer); + j.at("links").get_to(sn.linkContainer); + j.at("components").get_to(sn.components); + + sn.children.clear(); + if (j.contains("children") && j["children"].is_array()) { - for (const auto& childJson : j["childNode"]) + for (const auto& childJson : j["children"]) { auto child = std::make_shared(); childJson.get_to(*child); - sn.childNode.push_back(child); + sn.children.push_back(child); } } } -void JSONSnapshot::importFrom(const std::string filename, BaseSnapshot::SnapNode& rootNode) +void JSONSnapshot::importFrom(const std::string filename) { std::cout << "importFrom" << std::endl; std::ifstream file(filename); - if(file.is_open()) + nlohmann::json jfile; + file >> jfile; + file.close(); + + treeSnapshot.clear(); + + // std::cout << "root : " << jfile[0]["name"] << std::endl; + // std::cout << "children : " << jfile[0]["children"] << std::endl; + for (auto& [key,value] : jfile[0].items()) { - nlohmann::json jfile; - file >> jfile; - file.close(); - - // Lines above would be useful for unit tests - - // for (auto& [key,value] : data.items()) - // { - // std::cout << "name : " << data.value("name","") << std::endl; - // std::cout << "key : " << key << std::endl; - // } - - // if(jfile.contains("componentList")) - // { - // std::cout << "componentList" << std::endl; - // for(auto& [componentkey,componentvalue] : jfile["componentList"].items()) - // { - - // std::cout << "Component : " << componentvalue["datas"][0].value("value","") << std::endl; - // std::cout << "Datas : " << std::endl; - // for(const auto& d : componentvalue["datas"]) - // { - // std::cout << " - " << d.value("name", "") << " [" << d.value("type", "") << "] = " << d.value("value", "") << std::endl; - // } - // std::cout << "Links : " << std::endl; - // for(const auto& l : componentvalue["links"]) - // { - // std::cout << " - " << l.value("name","") << ", value : "<>>(); - // std::cout << data.dump(2) << std::endl; + std::cout << "TEST" << std::endl; } + + std::cout << "JSON imported successfully from: " << filename << std::endl; + } diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h index 86bb3baf281..4c73c393a9b 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h @@ -33,21 +33,11 @@ class SOFA_CORE_API JSONSnapshot : public BaseSnapshot { public: - //void exportSnapshot(const std::vector& datafield, const std::vector& linkfield) override; void importSnapshot(const std::string filename) override; - std::shared_ptr createChildNode(const std::string& nodeName) override; - void addChildToCurrentNode(std::shared_ptr child, BaseSnapshot::SnapNode& snapnode) override; - void exportTo(const std::string filename) override; - void importFrom(std::string filename, BaseSnapshot::SnapNode& rootNode) override; - + void importFrom(std::string filename) override; JSONSnapshot(); ~JSONSnapshot(); - - //nlohmann::json:: jNode = nlohmann::json::array(); - - - }; } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp new file mode 100644 index 00000000000..1d18ccff621 --- /dev/null +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp @@ -0,0 +1,64 @@ +/****************************************************************************** +* 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 +#include +#include +#include + +#include + + +namespace sofa::core::objectmodel +{ + + +MemorySnapshot::MemorySnapshot() +{} +MemorySnapshot::~MemorySnapshot() = default; + +void MemorySnapshot::exportTo(const std::string filename) +{ + std::cout << "exportTo" << std::endl; +} + +void MemorySnapshot::importSnapshot(const std::string filename) +{ + std::cout << "importSnapshot" << std::endl; + + +} + + +void MemorySnapshot::importFrom(const std::string filename) +{ + std::cout << "importFrom" << std::endl; + +} + + + + +} // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.h new file mode 100644 index 00000000000..41e06b29a1f --- /dev/null +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.h @@ -0,0 +1,50 @@ +/****************************************************************************** +* 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 * +******************************************************************************/ +#pragma once +#include +#include + + + + +namespace sofa::core::objectmodel +{ + +class SOFA_CORE_API MemorySnapshot : public BaseSnapshot +{ + +public: + //void exportSnapshot(const std::vector& datafield, const std::vector& linkfield) override; + void importSnapshot(const std::string filename) override; + + void exportTo(const std::string filename) override; + void importFrom(std::string filename) override; + + MemorySnapshot(); + ~MemorySnapshot(); + + //nlohmann::json:: jNode = nlohmann::json::array(); + + + +}; +} // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.cpp index 3b3761de9cb..5a81adb000a 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.cpp @@ -23,6 +23,7 @@ #include #include #include +#include @@ -35,7 +36,8 @@ std::unique_ptr createSnapshot(SnapshotType type) { case SnapshotType::JSON: return std::make_unique(); - + case SnapshotType::Memory: + return std::make_unique(); default: return nullptr; } diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.h b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.h index 70f1dc08e72..f890a68e5a8 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.h @@ -22,6 +22,7 @@ #pragma once #include // #include + #include namespace sofa::core::objectmodel @@ -30,7 +31,8 @@ class BaseSnapshot; enum class SnapshotType { JSON, - Print + Print, + Memory }; std::unique_ptr createSnapshot(SnapshotType type); diff --git a/Sofa/framework/Simulation/Core/CMakeLists.txt b/Sofa/framework/Simulation/Core/CMakeLists.txt index 7128ebce354..5edb0200f91 100644 --- a/Sofa/framework/Simulation/Core/CMakeLists.txt +++ b/Sofa/framework/Simulation/Core/CMakeLists.txt @@ -27,6 +27,7 @@ set(HEADER_FILES ${SRC_ROOT}/InitVisitor.h ${SRC_ROOT}/IntegrateBeginEvent.h ${SRC_ROOT}/IntegrateEndEvent.h + ${SRC_ROOT}/LoadSnapshotVisitor.h ${SRC_ROOT}/MechanicalOperations.h ${SRC_ROOT}/MechanicalVPrintVisitor.h ${SRC_ROOT}/MechanicalVisitor.h @@ -170,6 +171,7 @@ set(SOURCE_FILES ${SRC_ROOT}/InitVisitor.cpp ${SRC_ROOT}/IntegrateBeginEvent.cpp ${SRC_ROOT}/IntegrateEndEvent.cpp + ${SRC_ROOT}/LoadSnapshotVisitor.cpp ${SRC_ROOT}/MappingGraph.cpp ${SRC_ROOT}/MechanicalOperations.cpp ${SRC_ROOT}/MechanicalVPrintVisitor.cpp diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp index 62e7b68a3f5..412a04c04cc 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp @@ -60,6 +60,7 @@ void LoadSnapshotVisitor::processObject(core::objectmodel::BaseObject* obj) Visitor::Result LoadSnapshotVisitor::processNodeTopDown(simulation::Node* node) { + node->loadSnapshot(snapCont_); for (simulation::Node::ObjectIterator it = node->object.begin(); it != node->object.end(); ++it) { this->processObject(it->get()); diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.h index f7033fd8fb8..fc98b17a5d0 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.h @@ -37,7 +37,7 @@ class SOFA_SIMULATION_CORE_API LoadSnapshotVisitor : public Visitor protected: core::objectmodel::BaseSnapshot& snapCont_; public: - LoadSnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::BaseSnapshot& snapCont) : Visitor(eparams), snapCont_(snapCont) {} + LoadSnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::BaseSnapshot& snapshot) : Visitor(eparams), snapCont_(snapshot) {} void processObject(core::objectmodel::BaseObject* obj); diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp index 03cc4d48f57..38fd26dc83d 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp @@ -63,18 +63,9 @@ void SnapshotVisitor::processObject(core::objectmodel::BaseObject* obj, std::str Visitor::Result SnapshotVisitor::processNodeTopDown(simulation::Node* node) { auto* parent = node->getFirstParent(); - std::string parentName; - if(parent) - { - parentName = parent->getName(); - node->saveSnapshot(snapCont_,parentName); - } - else - { - parentName = "root"; - node->saveSnapshot(snapCont_,parentName); - } - + std::string parentName = parent ? parent->getName() : node->getName(); + node->saveSnapshot(snapCont_, parentName); + for (simulation::Node::ObjectIterator it = node->object.begin(); it != node->object.end(); ++it) { this->processObject(it->get(),node->getName()); @@ -83,7 +74,7 @@ Visitor::Result SnapshotVisitor::processNodeTopDown(simulation::Node* node) return RESULT_CONTINUE; } -void SnapshotVisitor::processNodeBottomUp(simulation::Node* node) +void SnapshotVisitor::processNodeBottomUp(simulation::Node* /*node*/) { } diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h index e6447318c96..687d3bd8782 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h @@ -38,10 +38,10 @@ class SOFA_SIMULATION_CORE_API SnapshotVisitor : public Visitor { protected: core::objectmodel::BaseSnapshot& snapCont_; - core::objectmodel::BaseSnapshot::SnapNode& snapNode_; + // core::objectmodel::BaseSnapshot::SnapNode& snapNode_; public: - SnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::BaseSnapshot& snapshot, core::objectmodel::BaseSnapshot::SnapNode& rootNode) : Visitor(eparams), snapCont_(snapshot), snapNode_(rootNode) + SnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::BaseSnapshot& snapshot) : Visitor(eparams), snapCont_(snapshot) { } From b0ad6c4713cf42c46721879c0edec7e0fec6d13d Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Wed, 28 Jan 2026 12:02:54 +0100 Subject: [PATCH 13/57] new design --- .../Core/src/sofa/core/objectmodel/Base.cpp | 80 +++++++----- .../Core/src/sofa/core/objectmodel/Base.h | 24 ++-- .../src/sofa/core/objectmodel/BaseNode.cpp | 14 +++ .../Core/src/sofa/core/objectmodel/BaseNode.h | 3 + .../sofa/core/objectmodel/BaseSnapshot.cpp | 114 +----------------- .../src/sofa/core/objectmodel/BaseSnapshot.h | 57 +++------ .../src/sofa/simulation/SnapshotVisitor.cpp | 48 +++++--- .../src/sofa/simulation/SnapshotVisitor.h | 10 +- 8 files changed, 130 insertions(+), 220 deletions(-) diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index 0d56eb87ead..018bee0e519 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -682,49 +682,69 @@ int Base::getInstanciationSourceFilePos() const return m_instanciationSourceFilePos; } -void Base::saveSnapshot(BaseSnapshot& snap, std::string parent) +void Base::saveDataIn(BaseSnapshot::SnapshotObject& snapshot) const { - if(this->getClassName() == "Node") + const auto& dataFields = this->getDataFields(); + + for (const auto& data : dataFields) { - auto snapObj = std::make_shared(); - snapObj->name = this->getName(); - snap.addToSnap(*this, *snapObj); - snap.nodeList.push_back(snapObj->name); - if(snap.hasSnapParent(parent)) - { - std::shared_ptr snapParent = snap.getSnapParent(snap.treeSnapshot[0],parent); - snapParent->children.push_back(snapObj); - } - else - { - snap.treeSnapshot.push_back(snapObj); - } - - } - else + BaseSnapshot::DataInfo dataInfo; + dataInfo.name = data->getName(); + dataInfo.type = data->getValueTypeString(); + dataInfo.value = data->getValueString(); + snapshot.m_dataContainer.push_back(dataInfo); + } +} + +void Base::saveLinksIn(BaseSnapshot::SnapshotObject& snapshot) const +{ + const auto& links = this->getLinks(); + + for (const auto& link : links) { - auto snapObj = std::make_shared(); - snap.addToSnap(*this, *snapObj); - if(snap.hasSnapParent(parent)) - { - std::shared_ptr snapParent = snap.getSnapParent(snap.treeSnapshot[0],parent); - snapParent->components.push_back(*snapObj) ; - } - else + BaseSnapshot::LinkInfo linkInfo; + linkInfo.name = link->getName(); + linkInfo.type = link->getValueTypeString(); + linkInfo.value = link->getValueString(); + snapshot.m_linkContainer.push_back(linkInfo); + } +} + +void Base::saveInternalStateIn(BaseSnapshot::SnapshotObject& snapshot) const +{} + +std::shared_ptr Base::createSnapshotObject(const std::vector>& parents) const +{ + auto object = std::make_shared(); + for (auto p : parents) + { + if (p) { - snap.treeSnapshot[0]->components.push_back(*snapObj); + p->components.push_back(*object); } - } + return object; +} + +std::shared_ptr Base::saveSnapshot(const std::vector>& parents) const +{ + const auto snapshotObject = createSnapshotObject(parent); + + snapshotObject->m_name = this->getName(); + saveDataIn(*snapshotObject); + saveLinksIn(*snapshotObject); + saveInternalStateIn(*snapshotObject); + + return snapshotObject; } -void Base::loadSnapshot(BaseSnapshot& snap) +void Base::loadSnapshot(BaseSnapshot& snapshot) { //type.importSnapshot(filename); std::cout << "load snapshot" << std::endl; - snap.addToSimulation(); + snapshot.addToSimulation(); } } // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h index 6517838e3ac..49789ed8da8 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h @@ -363,24 +363,14 @@ class SOFA_CORE_API Base : public IntrusiveObject ///@} + std::shared_ptr saveSnapshot(const std::vector>& parents) const; + void loadSnapshot(BaseSnapshot& snapshot); -public : - - // struct SnapshotContainer - // { - // std::string dataname; - - // std::string datavalue; - // }; - - // void setSnapshot(BaseSnapshot* impl) - // { - // Snapshot_impl = impl; - // } - - void saveSnapshot(BaseSnapshot& snap, std::string parent); - - void loadSnapshot(BaseSnapshot& snap); +protected: + void saveDataIn(BaseSnapshot::SnapshotObject& snapshot) const; + void saveLinksIn(BaseSnapshot::SnapshotObject& snapshot) const; + virtual void saveInternalStateIn(BaseSnapshot::SnapshotObject& snapshot) const; + virtual std::shared_ptr createSnapshotObject(const std::vector>& parents) const; private : BaseSnapshot* Snapshot_impl; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp index 5b6b0af4954..79814cdd979 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp @@ -63,6 +63,20 @@ core::visual::VisualLoop* BaseNode::getVisualLoop() const return this->getContext()->get(); } +std::shared_ptr +BaseNode::createSnapshotObject(const std::vector>& parents) const +{ + auto nodeObject = std::make_shared(); + for (auto p : parents) + { + if (p) + { + p->children.push_back(nodeObject); + } + } + return nodeObject; +} + /// Set the context of an object to this void BaseNode::setObjectContext(BaseComponent::SPtr obj) { diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.h index 2913373a309..bf827354d05 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.h @@ -128,6 +128,9 @@ class SOFA_CORE_API BaseNode : public virtual Base virtual core::collision::Pipeline* getCollisionPipeline() const; virtual core::visual::VisualLoop* getVisualLoop() const; +protected: + std::shared_ptr createSnapshotObject(const std::vector>& parents) const override; + private: virtual std::string internalGetPathName() const; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp index 9c7b10e4092..0979c49af06 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp @@ -29,116 +29,4 @@ BaseSnapshot::BaseSnapshot() {} BaseSnapshot::~BaseSnapshot() = default; - -void BaseSnapshot::printSnapshot() -{ - std::cout << "Snapshot : " << std::endl; - for (auto element : treeSnapshot) - { - std::cout << element->name << std::endl; - } -} - - -void BaseSnapshot::addToSnap(Base& b, SnapNode& snapObject) -{ - std::vector objData = collectSnapData(b.getDataFields()); - snapObject.dataContainer.insert(snapObject.dataContainer.end(),std::make_move_iterator(objData.begin()),std::make_move_iterator(objData.end())); - std::vector objLink = collectSnapLink(b.getLinks()); - snapObject.linkContainer.insert(snapObject.linkContainer.end(),std::make_move_iterator(objLink.begin()),std::make_move_iterator(objLink.end())); - snapObject.name = b.getName(); -} - -void BaseSnapshot::addToSnap(Base& b, SnapComponent& snapObject) -{ - std::vector objData = collectSnapData(b.getDataFields()); - snapObject.dataContainer.insert(snapObject.dataContainer.end(),std::make_move_iterator(objData.begin()),std::make_move_iterator(objData.end())); - std::vector objLink = collectSnapLink(b.getLinks()); - snapObject.linkContainer.insert(snapObject.linkContainer.end(),std::make_move_iterator(objLink.begin()),std::make_move_iterator(objLink.end())); - snapObject.name = b.getName(); -} - - - -std::vector BaseSnapshot::collectSnapData(const std::vector& datafield) -{ - BaseSnapshot::DataInfo dinfo; - std::vector dataContainer; - for (auto* data : datafield) - { - dinfo.name = data->getName(); - dinfo.type = data->getValueTypeString(); - dinfo.value = data->getValueString(); - dataContainer.push_back(dinfo); - } - return dataContainer; -} - -std::vector BaseSnapshot::collectSnapLink(const std::vector& linkfield) -{ - BaseSnapshot::LinkInfo linfo; - std::vector linkContainer; - for (auto* link : linkfield) - { - linfo.name = link->getName(); - linfo.value = link->getValueString(); - linfo.type = link->getValueTypeString(); - linkContainer.push_back(linfo); - } - return linkContainer; -} - -bool BaseSnapshot::hasSnapParent(std::string& parentName) -{ - bool result = false; - - if(treeSnapshot.empty()) - { - return result; - } - - for(auto name : nodeList) - { - if(name == parentName) - { - result = true; - } - } - - return result; -} - - -std::shared_ptr BaseSnapshot::getSnapParent(std::shared_ptr& node, - std::string& parentName) -{ - if (!node) - { - return nullptr; - } - - if(node->name == parentName) - { - return node; - } - - for (auto& child : node->children) - { - if(auto result = getSnapParent(child, parentName)) - { - return result; - } - } - return nullptr; -} - -void BaseSnapshot::addToSimulation() -{ - std::cout << "addToSimulation" << std::endl; - for (auto element : treeSnapshot) - { - std::cout << element->name << std::endl; - } -} - -} // namespace sofa::core::objectmodel \ No newline at end of file +} // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h index 827162a9763..d28ac404309 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h @@ -26,18 +26,15 @@ namespace sofa::core::objectmodel { -class Base; + class SOFA_CORE_API BaseSnapshot { - public: struct DataInfo { std::string name; std::string type; std::string value; - - DataInfo() : name(), type(), value() {} }; struct LinkInfo @@ -45,60 +42,38 @@ class SOFA_CORE_API BaseSnapshot std::string name; std::string type; std::string value; - LinkInfo() : name(), type(), value() {} }; - struct SnapComponent + struct SnapshotObject { - std::string name; - std::vector dataContainer; - std::vector linkContainer; - - SnapComponent() : name(""), dataContainer(), linkContainer() {} + std::string m_name; + std::vector m_dataContainer; + std::vector m_linkContainer; + void* m_internalState { nullptr }; - SnapComponent(const std::string& name) : name(name){} - }; + SnapshotObject() = default; + explicit SnapshotObject(const std::string& name) : m_name(name){} - + virtual ~SnapshotObject() = default; + }; - struct SnapNode + struct SnapNode : public SnapshotObject { - std::string name; - std::vector dataContainer; - std::vector linkContainer; - std::vector components; + std::vector components; std::vector> children; - SnapNode() : name(""), dataContainer(), linkContainer(), components(), children() {} - - SnapNode(const std::string& name) : name(name) {} + SnapNode() = default; + SnapNode(const std::string& name) : SnapshotObject(name) {} }; - public : - SnapComponent SnapComponent_; - SnapNode SnapNode_; - - std::vector nodeList; - std::vector> treeSnapshot; // here, it is the snapshot - + std::shared_ptr m_graphRoot { nullptr }; -public: virtual void importSnapshot(const std::string filename) = 0; - void printSnapshot(); - void addToSnap(Base& b, SnapNode& snapObj); - void addToSnap(Base& b, SnapComponent& snapObj); - std::vector collectSnapData(const std::vector& datafield); - std::vector collectSnapLink(const std::vector& linkfield); - bool hasSnapParent(std::string& parentName); - std::shared_ptr getSnapParent(std::shared_ptr& node, std::string& parentName); - - void addToSimulation(); - virtual void exportTo(const std::string filename) = 0; virtual void importFrom(std::string filename) = 0; BaseSnapshot(); virtual ~BaseSnapshot() = 0; }; -} // namespace sofa::core::objectmodel \ No newline at end of file +} // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp index 38fd26dc83d..698fa6b1acb 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp @@ -54,31 +54,51 @@ using sofa::core::objectmodel::SnapshotType; namespace sofa::simulation { -void SnapshotVisitor::processObject(core::objectmodel::BaseObject* obj, std::string parentName) +void SnapshotVisitor::processObject( + core::objectmodel::BaseObject* obj, + std::shared_ptr parent) { - - obj->saveSnapshot(snapCont_, parentName); + obj->saveSnapshot({parent}); } Visitor::Result SnapshotVisitor::processNodeTopDown(simulation::Node* node) -{ - auto* parent = node->getFirstParent(); - std::string parentName = parent ? parent->getName() : node->getName(); - node->saveSnapshot(snapCont_, parentName); +{ + const auto parents = node->getParents(); + + std::vector> snapshotParents; + for (auto* p : parents) + { + const auto it = m_snapshotNodeMap.find(p); + if (it != m_snapshotNodeMap.end()) + { + snapshotParents.push_back(it->second); + } + else + { + msg_error("SnapshotVisitor") << "Does it happen??"; + } + } + + auto snapshot = node->saveSnapshot(snapshotParents); + auto snapNode = std::dynamic_pointer_cast(snapshot); + if (snapNode) + { + m_snapshotNodeMap[node] = snapNode; + } - for (simulation::Node::ObjectIterator it = node->object.begin(); it != node->object.end(); ++it) + if (m_snapshotContainer.m_graphRoot == nullptr) //root node { - this->processObject(it->get(),node->getName()); + m_snapshotContainer.m_graphRoot = snapNode; + } + + for (const auto& it : node->object) + { + this->processObject(it.get(), snapNode); } return RESULT_CONTINUE; } -void SnapshotVisitor::processNodeBottomUp(simulation::Node* /*node*/) -{ -} - - } // namespace sofa::simulation diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h index 687d3bd8782..f29d6d1d682 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h @@ -37,18 +37,18 @@ namespace sofa::simulation class SOFA_SIMULATION_CORE_API SnapshotVisitor : public Visitor { protected: - core::objectmodel::BaseSnapshot& snapCont_; - // core::objectmodel::BaseSnapshot::SnapNode& snapNode_; + core::objectmodel::BaseSnapshot& m_snapshotContainer; + + std::unordered_map> m_snapshotNodeMap; public: - SnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::BaseSnapshot& snapshot) : Visitor(eparams), snapCont_(snapshot) + SnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::BaseSnapshot& snapshot) : Visitor(eparams), m_snapshotContainer(snapshot) { } - void processObject(core::objectmodel::BaseObject* obj, std::string parentName); + void processObject(core::objectmodel::BaseObject* obj, std::shared_ptr parent); Result processNodeTopDown(simulation::Node* node) override; - void processNodeBottomUp(simulation::Node* node) override; const char* getClassName() const override { return "SnapshotVisitor"; } }; From 2dde09837ac6beb02e47458c48a8755a3fb729ed Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Tue, 3 Feb 2026 09:27:58 +0100 Subject: [PATCH 14/57] [SNAPSHOT] FIX compilation + ADD unit tests --- Sofa/framework/Core/simutest/CMakeLists.txt | 1 + .../Core/simutest/objectmodel/Base_test.cpp | 53 ------- .../simutest/objectmodel/Snapshot_test.cpp | 134 +++++++++++++++++ .../Core/src/sofa/core/objectmodel/Base.cpp | 21 ++- .../Core/src/sofa/core/objectmodel/Base.h | 11 +- .../src/sofa/core/objectmodel/BaseNode.cpp | 10 +- .../Core/src/sofa/core/objectmodel/BaseNode.h | 5 +- .../sofa/core/objectmodel/BaseSnapshot.cpp | 10 ++ .../src/sofa/core/objectmodel/BaseSnapshot.h | 20 ++- .../sofa/core/objectmodel/JSONSnapshot.cpp | 139 ++++++++++-------- .../sofa/core/objectmodel/MemorySnapshot.cpp | 17 ++- .../sofa/core/objectmodel/SnapshotFactory.h | 2 +- .../sofa/simulation/LoadSnapshotVisitor.cpp | 4 +- .../src/sofa/simulation/SnapshotVisitor.cpp | 4 +- 14 files changed, 283 insertions(+), 148 deletions(-) create mode 100644 Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp diff --git a/Sofa/framework/Core/simutest/CMakeLists.txt b/Sofa/framework/Core/simutest/CMakeLists.txt index 5ec8342f6b6..6095de998c2 100644 --- a/Sofa/framework/Core/simutest/CMakeLists.txt +++ b/Sofa/framework/Core/simutest/CMakeLists.txt @@ -10,6 +10,7 @@ set(SOURCE_FILES objectmodel/BaseContext_test.cpp objectmodel/BaseLink_simutest.cpp objectmodel/PathResolver_simutest.cpp + objectmodel/Snapshot_test.cpp ) add_executable(${PROJECT_NAME} ${SOURCE_FILES}) diff --git a/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp index fddae9292ab..a02e32cb159 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp @@ -127,56 +127,3 @@ TEST_F(Base_test , testGetClassName) EXPECT_EQ(o.getTypeName(), "CustomBaseObject"); EXPECT_EQ(o.getClass()->className, "CustomBaseObject"); } - -TEST_F(Base_test, testSaveSnapshot) -{ - const std::string scene = R"( - - - - - - - - - - - - )"; - - SceneInstance c("xml", scene) ; - c.initScene() ; - - Node* root = c.root.get() ; - - // auto JSONSnapCont = createSnapshot(SnapshotType::JSON); - // auto visitor = SnapshotVisitor(nullptr,*JSONSnapCont); - // root->execute(visitor); - // JSONSnapCont->exportToJSON(); - - // std::vector vObj = root->getTreeObjects(); - - - - - - // for (auto* comp : vObj) - // { - // std::cout << comp->getPathName() << std::endl; - // comp->saveSnapshot(*JSONSnapCont); - - // } - - // std::vector> testcont = JSONSnapCont->getContainer(); - - // for (int j = 0; j< testcont.size(); j++) - // { - // std::cout << "Component n°" << j <. * +******************************************************************************* +* Authors: The SOFA Team and external contributors (see Authors.txt) * +* * +* Contact information: contact@sofa-framework.org * +******************************************************************************/ +#include +using sofa::core::objectmodel::Base ; +using sofa::core::objectmodel::ComponentState; + +#include +using sofa::testing::BaseSimulationTest ; +using sofa::simulation::Node ; + +#include +using sofa::core::objectmodel::BaseObject; + +#include +using sofa::core::objectmodel::SnapshotType; + +#include +using sofa::simulation::SnapshotVisitor; + +#include +using sofa::core::objectmodel::Data; + +#include +using sofa::core::objectmodel::BaseSnapshot; + +class TestComponent : public Base +{ +public: + + Data d_value; + + + TestComponent() + : d_value(initData(&d_value, 3.14f, "value", "test value")) + { + this->setName("pi"); + } + + void saveData(BaseSnapshot::SnapshotObject& snapshot) + { + this->saveDataIn(snapshot); + } + + + SOFA_CLASS(TestComponent,Base); +}; + +class Snapshot_test: public BaseSimulationTest +{ +public: + SceneInstance* c; + Node* node {nullptr}; + Snapshot_test() + { + std::stringstream scene ; + scene << "" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" ; + c = new SceneInstance("xml", scene.str()) ; + c->initScene() ; + const Node* root = c->root.get() ; + Base* b = sofa::core::PathResolver::FindBaseFromPath(root, "@/child1/child2"); + node = dynamic_cast(b); + } + ~Snapshot_test() override + { + delete c; + } +}; + +TEST_F(Snapshot_test, saveDataIn) +{ + TestComponent tcomponent; + + auto snapshot = std::make_shared(); + tcomponent.saveData(*snapshot); + for (auto& data : snapshot->m_dataContainer) + { + if(data.name == "name") + { + EXPECT_EQ(data.value, "pi"); + } + + if(data.name == "value") + { + EXPECT_EQ(data.value, "3.14"); + } + } +} + +TEST_F(Snapshot_test, saveSnapshot) +{ + TestComponent tcomponent; + + auto snapshot = std::make_shared(); + std::vector> snapshotParents; + snapshot = tcomponent.saveSnapshot(snapshotParents); + + EXPECT_EQ(snapshot->m_name, "pi"); + EXPECT_EQ(snapshot->m_dataContainer.size(), 6); + EXPECT_EQ(snapshot->m_dataContainer[0].name, "name"); + EXPECT_EQ(snapshot->m_dataContainer[0].value, "pi"); + EXPECT_EQ(snapshot->m_dataContainer[5].name, "value"); + EXPECT_EQ(snapshot->m_dataContainer[5].value, "3.14"); +} \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index 018bee0e519..8036b02455f 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -20,8 +20,9 @@ * Contact information: contact@sofa-framework.org * ******************************************************************************/ #define SOFA_CORE_OBJECTMODEL_BASE_CPP -#include +#include +#include #include #include #include @@ -685,7 +686,7 @@ int Base::getInstanciationSourceFilePos() const void Base::saveDataIn(BaseSnapshot::SnapshotObject& snapshot) const { const auto& dataFields = this->getDataFields(); - + for (const auto& data : dataFields) { BaseSnapshot::DataInfo dataInfo; @@ -710,10 +711,11 @@ void Base::saveLinksIn(BaseSnapshot::SnapshotObject& snapshot) const } } -void Base::saveInternalStateIn(BaseSnapshot::SnapshotObject& snapshot) const -{} +// void Base::saveInternalStateIn(BaseSnapshot::SnapshotObject& snapshot) const +// {} -std::shared_ptr Base::createSnapshotObject(const std::vector>& parents) const +std::shared_ptr +Base::createSnapshotObject(std::vector>& parents) const { auto object = std::make_shared(); for (auto p : parents) @@ -726,15 +728,13 @@ std::shared_ptr Base::createSnapshotObject(const s return object; } -std::shared_ptr Base::saveSnapshot(const std::vector>& parents) const +std::shared_ptr Base::saveSnapshot(std::vector>& parents) const { - const auto snapshotObject = createSnapshotObject(parent); - + const auto snapshotObject = createSnapshotObject(parents); snapshotObject->m_name = this->getName(); saveDataIn(*snapshotObject); saveLinksIn(*snapshotObject); - saveInternalStateIn(*snapshotObject); - + //saveInternalStateIn(*snapshotObject); return snapshotObject; } @@ -744,7 +744,6 @@ void Base::loadSnapshot(BaseSnapshot& snapshot) { //type.importSnapshot(filename); std::cout << "load snapshot" << std::endl; - snapshot.addToSimulation(); } } // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h index 49789ed8da8..01c71b0ffa6 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h @@ -41,9 +41,10 @@ #include #include -#include + #include +#include #define SOFA_BASE_CAST_IMPLEMENTATION(CLASSNAME) \ virtual const CLASSNAME* to##CLASSNAME() const override { return this; } \ @@ -52,7 +53,7 @@ virtual CLASSNAME* to##CLASSNAME() override { return this; } namespace sofa::core::objectmodel { -class BaseSnapshot; + /** * \brief Base class for everything @@ -363,14 +364,14 @@ class SOFA_CORE_API Base : public IntrusiveObject ///@} - std::shared_ptr saveSnapshot(const std::vector>& parents) const; + std::shared_ptr saveSnapshot(std::vector>& parents) const; void loadSnapshot(BaseSnapshot& snapshot); protected: void saveDataIn(BaseSnapshot::SnapshotObject& snapshot) const; void saveLinksIn(BaseSnapshot::SnapshotObject& snapshot) const; - virtual void saveInternalStateIn(BaseSnapshot::SnapshotObject& snapshot) const; - virtual std::shared_ptr createSnapshotObject(const std::vector>& parents) const; + //virtual void saveInternalStateIn(SnapshotObject& snapshot) const; + virtual std::shared_ptr createSnapshotObject(std::vector>& parents) const; private : BaseSnapshot* Snapshot_impl; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp index 79814cdd979..d2f2809b3d6 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp @@ -19,6 +19,7 @@ * * * Contact information: contact@sofa-framework.org * ******************************************************************************/ +#include #include #include #include @@ -63,10 +64,12 @@ core::visual::VisualLoop* BaseNode::getVisualLoop() const return this->getContext()->get(); } -std::shared_ptr -BaseNode::createSnapshotObject(const std::vector>& parents) const +// std::shared_ptr createSnapshotObject(const std::vector>& parents) + +std::shared_ptr +BaseNode::createSnapshotObject(std::vector>& parents) const { - auto nodeObject = std::make_shared(); + auto nodeObject = std::make_shared(); for (auto p : parents) { if (p) @@ -74,6 +77,7 @@ BaseNode::createSnapshotObject(const std::vectorchildren.push_back(nodeObject); } } + return nodeObject; } diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.h index bf827354d05..e40a5b5d25f 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.h @@ -24,10 +24,11 @@ #include #include #include - +#include namespace sofa::core::objectmodel { + /** * \brief Base class for simulation nodes. * @@ -129,7 +130,7 @@ class SOFA_CORE_API BaseNode : public virtual Base virtual core::visual::VisualLoop* getVisualLoop() const; protected: - std::shared_ptr createSnapshotObject(const std::vector>& parents) const override; + std::shared_ptr createSnapshotObject(std::vector>& parents) const ; private: virtual std::string internalGetPathName() const; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp index 0979c49af06..cc100c215aa 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp @@ -29,4 +29,14 @@ BaseSnapshot::BaseSnapshot() {} BaseSnapshot::~BaseSnapshot() = default; +void BaseSnapshot::printSnapshot() const +{ + std::cout << m_graphRoot->m_name << std::endl; + + for (auto& element : m_graphRoot->components) + { + std::cout << " Component name : " << element.m_name << std::endl; + } +} + } // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h index d28ac404309..a9517ab610f 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h @@ -20,14 +20,19 @@ * Contact information: contact@sofa-framework.org * ******************************************************************************/ #pragma once -#include -#include -#include +//#include +// #include +// #include +#include +#include +#include +#include +#include namespace sofa::core::objectmodel { -class SOFA_CORE_API BaseSnapshot +class SOFA_CORE_API BaseSnapshot { public: struct DataInfo @@ -49,7 +54,7 @@ class SOFA_CORE_API BaseSnapshot std::string m_name; std::vector m_dataContainer; std::vector m_linkContainer; - void* m_internalState { nullptr }; + //void* m_internalState { nullptr }; SnapshotObject() = default; explicit SnapshotObject(const std::string& name) : m_name(name){} @@ -64,6 +69,9 @@ class SOFA_CORE_API BaseSnapshot SnapNode() = default; SnapNode(const std::string& name) : SnapshotObject(name) {} + SnapNode(const SnapshotObject& obj) : SnapshotObject(obj) {} + + virtual ~SnapNode() noexcept = default; }; std::shared_ptr m_graphRoot { nullptr }; @@ -73,6 +81,8 @@ class SOFA_CORE_API BaseSnapshot virtual void exportTo(const std::string filename) = 0; virtual void importFrom(std::string filename) = 0; + void printSnapshot() const; + BaseSnapshot(); virtual ~BaseSnapshot() = 0; }; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp index b6323a6098b..57c7454940e 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp @@ -56,19 +56,20 @@ void to_json(nlohmann::json& j, const BaseSnapshot::LinkInfo& li ) j["value"] = li.value; } -void to_json(nlohmann::json& j, const BaseSnapshot::SnapComponent& sds ) +void to_json(nlohmann::json& j, const BaseSnapshot::SnapshotObject& so ) { j.clear(); - j["datas"] = sds.dataContainer; - j["links"] = sds.linkContainer; + j["name"] = so.m_name; + j["datas"] = so.m_dataContainer; + j["links"] = so.m_linkContainer; } void to_json(nlohmann::json& j, const BaseSnapshot::SnapNode& sn) { j.clear(); - j["name"] = sn.name; - j["datas"] = sn.dataContainer; - j["links"] = sn.linkContainer; + j["name"] = sn.m_name; + j["datas"] = sn.m_dataContainer; + j["links"] = sn.m_linkContainer; j["components"] = sn.components; j["children"] = nlohmann::json::array(); @@ -78,20 +79,37 @@ void to_json(nlohmann::json& j, const BaseSnapshot::SnapNode& sn) { j["children"].push_back(*childPtr); } + else + { + j["children"].push_back(nullptr); + } } } -void JSONSnapshot::exportTo(const std::string filename) +void to_json(nlohmann::json& j, const std::shared_ptr& sn) { - nlohmann::json j = nlohmann::json::array() ; - - for (const auto& nodePtr : treeSnapshot) + j.clear(); + j["name"] = sn->m_name; + j["datas"] = sn->m_dataContainer; + j["links"] = sn->m_linkContainer; + j["components"] = sn->components; + j["children"] = nlohmann::json::array(); + for (const auto& childPtr : sn->children) { - if (nodePtr) + if(childPtr) { - j.push_back(*nodePtr); + j["children"].push_back(*childPtr); + } + else + { + j["children"].push_back(nullptr); } } +} + +void JSONSnapshot::exportTo(const std::string filename) +{ + nlohmann::json j = *m_graphRoot ; std::ofstream file(filename); file << j.dump(5); @@ -104,62 +122,59 @@ void JSONSnapshot::importSnapshot(const std::string filename) } -void from_json(const nlohmann::json& j,BaseSnapshot::DataInfo& di ) -{ - j.at("name").get_to(di.name); - j.at("type").get_to(di.type); - j.at("value").get_to(di.value); +// void from_json(const nlohmann::json& j,BaseSnapshot::DataInfo& di ) +// { +// j.at("name").get_to(di.name); +// j.at("type").get_to(di.type); +// j.at("value").get_to(di.value); -} - -void from_json(const nlohmann::json& j,BaseSnapshot::LinkInfo& li ) -{ - j.at("name").get_to(li.name); - j.at("type").get_to(li.type); - j.at("value").get_to(li.value); -} - -void from_json(const nlohmann::json& j,BaseSnapshot::SnapComponent& sds ) -{ - j.at("datas").get_to(sds.dataContainer); - j.at("links").get_to(sds.linkContainer); -} - -void from_json(const nlohmann::json& j, BaseSnapshot::SnapNode& sn) -{ - j.at("name").get_to(sn.name); - j.at("datas").get_to(sn.dataContainer); - j.at("links").get_to(sn.linkContainer); - j.at("components").get_to(sn.components); - - sn.children.clear(); - if (j.contains("children") && j["children"].is_array()) - { - for (const auto& childJson : j["children"]) - { - auto child = std::make_shared(); - childJson.get_to(*child); - sn.children.push_back(child); - } - } -} +// } + +// void from_json(const nlohmann::json& j,BaseSnapshot::LinkInfo& li ) +// { +// j.at("name").get_to(li.name); +// j.at("type").get_to(li.type); +// j.at("value").get_to(li.value); +// } + +// void from_json(const nlohmann::json& j,BaseSnapshot::SnapshotObject& so ) +// { +// j.at("datas").get_to(so.m_dataContainer); +// j.at("links").get_to(so.m_linkContainer); +// } + +// void from_json(const nlohmann::json& j, BaseSnapshot::SnapNode& sn) +// { +// j.at("components").get_to(sn.components); + +// sn.children.clear(); +// if (j.contains("children") && j["children"].is_array()) +// { +// for (const auto& childJson : j["children"]) +// { +// auto child = std::make_shared(); +// childJson.get_to(*child); +// sn.children.push_back(child); +// } +// } +// } void JSONSnapshot::importFrom(const std::string filename) { - std::cout << "importFrom" << std::endl; - std::ifstream file(filename); - nlohmann::json jfile; - file >> jfile; - file.close(); + // std::cout << "importFrom" << std::endl; + // std::ifstream file(filename); + // nlohmann::json jfile; + // file >> jfile; + // file.close(); - treeSnapshot.clear(); + // treeSnapshot.clear(); - // std::cout << "root : " << jfile[0]["name"] << std::endl; - // std::cout << "children : " << jfile[0]["children"] << std::endl; - for (auto& [key,value] : jfile[0].items()) - { - std::cout << "TEST" << std::endl; - } + // // std::cout << "root : " << jfile[0]["name"] << std::endl; + // // std::cout << "children : " << jfile[0]["children"] << std::endl; + // for (auto& [key,value] : jfile[0].items()) + // { + // std::cout << "TEST" << std::endl; + // } std::cout << "JSON imported successfully from: " << filename << std::endl; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp index 1d18ccff621..44fb7eda313 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp @@ -42,16 +42,27 @@ MemorySnapshot::~MemorySnapshot() = default; void MemorySnapshot::exportTo(const std::string filename) { std::cout << "exportTo" << std::endl; + } void MemorySnapshot::importSnapshot(const std::string filename) { std::cout << "importSnapshot" << std::endl; - - + if(m_graphRoot != nullptr) + { + std::cout << m_graphRoot->m_name << std::endl; + + for (auto& element : m_graphRoot->components) + { + std::cout << " Component name : " << element.m_name << std::endl; + } + for (auto& element : m_graphRoot->children) + { + std::cout << " Child name : " << element->m_name << std::endl; + } + } } - void MemorySnapshot::importFrom(const std::string filename) { std::cout << "importFrom" << std::endl; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.h b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.h index f890a68e5a8..8fd835ec242 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.h @@ -20,7 +20,7 @@ * Contact information: contact@sofa-framework.org * ******************************************************************************/ #pragma once -#include +//#include // #include #include diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp index 412a04c04cc..c61a079c8fd 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp @@ -55,12 +55,12 @@ namespace sofa::simulation void LoadSnapshotVisitor::processObject(core::objectmodel::BaseObject* obj) { - obj->loadSnapshot(snapCont_); + //obj->loadSnapshot(snapCont_); } Visitor::Result LoadSnapshotVisitor::processNodeTopDown(simulation::Node* node) { - node->loadSnapshot(snapCont_); + //node->loadSnapshot(snapCont_); for (simulation::Node::ObjectIterator it = node->object.begin(); it != node->object.end(); ++it) { this->processObject(it->get()); diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp index 698fa6b1acb..ca5bcc3ad73 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp @@ -58,7 +58,9 @@ void SnapshotVisitor::processObject( core::objectmodel::BaseObject* obj, std::shared_ptr parent) { - obj->saveSnapshot({parent}); + std::vector> parents; + auto snapshot = obj->saveSnapshot(parents); + parent->components.push_back(*snapshot); } Visitor::Result SnapshotVisitor::processNodeTopDown(simulation::Node* node) From 4e6f9e4f2000e2b3717a3d762547668041be6b3d Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Mon, 9 Feb 2026 09:41:05 +0100 Subject: [PATCH 15/57] >[SNAPSHOT] ADD feature : loadSnapshot with read (wip) --- .../simutest/objectmodel/Snapshot_test.cpp | 2 +- .../simutest/objectmodel/Snapshot_test.py | 51 +++++++++++++++ .../Core/src/sofa/core/objectmodel/Base.cpp | 62 ++++++++++++++++++- .../Core/src/sofa/core/objectmodel/Base.h | 8 ++- .../src/sofa/core/objectmodel/BaseNode.cpp | 34 ++++++++-- .../Core/src/sofa/core/objectmodel/BaseNode.h | 4 +- .../src/sofa/core/objectmodel/BaseSnapshot.h | 14 ++--- .../sofa/core/objectmodel/JSONSnapshot.cpp | 8 +-- .../sofa/core/objectmodel/MemorySnapshot.cpp | 2 +- .../sofa/simulation/LoadSnapshotVisitor.cpp | 42 ++++++++++--- .../src/sofa/simulation/LoadSnapshotVisitor.h | 9 +-- .../src/sofa/simulation/SnapshotVisitor.cpp | 16 ++--- .../src/sofa/simulation/SnapshotVisitor.h | 4 +- 13 files changed, 208 insertions(+), 48 deletions(-) create mode 100644 Sofa/framework/Core/simutest/objectmodel/Snapshot_test.py diff --git a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp index 70465029d67..5a06c0a4577 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp @@ -122,7 +122,7 @@ TEST_F(Snapshot_test, saveSnapshot) TestComponent tcomponent; auto snapshot = std::make_shared(); - std::vector> snapshotParents; + std::vector> snapshotParents; snapshot = tcomponent.saveSnapshot(snapshotParents); EXPECT_EQ(snapshot->m_name, "pi"); diff --git a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.py b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.py new file mode 100644 index 00000000000..44a23a23374 --- /dev/null +++ b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.py @@ -0,0 +1,51 @@ +# Required import for python +import Sofa +import SofaRuntime + + +def main(): + # Make sure to load all necessary libraries + SofaRuntime.importPlugin("Sofa.Component.StateContainer") + + # Call the above function to create the scene graph + root = Sofa.Core.Node("root") + createScene(root) + + # Once defined, initialization of the scene graph + Sofa.Simulation.initRoot(root) + + # Run the simulation for 10 steps + for iteration in range(10): + print(f'Iteration #{iteration}') + Sofa.Simulation.animate(root, root.dt.value) + + print("Simulation made 10 time steps. Done") + + +# Function called when the scene graph is being created +def createScene(root): + + root.addObject('RequiredPlugin', name='Sofa.Component.StateContainer') + + # Scene must now include a AnimationLoop + root.addObject('DefaultAnimationLoop') + + # Add new nodes and objects in the scene + node1 = root.addChild("Node1") + node1.addObject("MechanicalObject", template="Rigid3d", position="0 0 0 0 0 0 1", showObject="1") + + node2 = root.addChild("Node2") + node2.addObject("EulerImplicitSolver") + node2.addObject("CGLinearSolver", iterations="100", tolerance="1e-3", threshold="1e-3") + node1.addChild(node2) + + node3 = root.addChild("Node3") + node3.addObject("MechanicalObject", template="Rigid3d", position="0 0 0 0 0 0 1", showObject="1") + node3.addChild(node2) + + return root + + +# Function used only if this script is called from a python environment +if __name__ == '__main__': + main() diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index 8036b02455f..99bdded3b4a 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -715,7 +715,7 @@ void Base::saveLinksIn(BaseSnapshot::SnapshotObject& snapshot) const // {} std::shared_ptr -Base::createSnapshotObject(std::vector>& parents) const +Base::createSnapshotObject(std::vector>& parents) const { auto object = std::make_shared(); for (auto p : parents) @@ -728,7 +728,7 @@ Base::createSnapshotObject(std::vector>& return object; } -std::shared_ptr Base::saveSnapshot(std::vector>& parents) const +std::shared_ptr Base::saveSnapshot(std::vector>& parents) const { const auto snapshotObject = createSnapshotObject(parents); snapshotObject->m_name = this->getName(); @@ -738,12 +738,68 @@ std::shared_ptr Base::saveSnapshot(std::vector +Base::findSnapshotObject(const std::shared_ptr& parents, const std::string objectname) +{ + std::cout << "Searching for snapshot object (base): " << objectname << std::endl; + for (auto p : parents->components) + { + if (p.m_name == objectname) + { + auto object = std::make_shared(p); + return object; + } + + } + return nullptr; +} -void Base::loadSnapshot(BaseSnapshot& snapshot) + +void Base::loadSnapshot(const std::shared_ptr& snapshotObject) { //type.importSnapshot(filename); std::cout << "load snapshot" << std::endl; + // a function to read data from the snapshot and store inside the component + for (const auto& dataInfo : snapshotObject->m_dataContainer) + { + std::cout << "Loading data field: " << dataInfo.name << std::endl; + // Find the corresponding data field in the component + auto dataField = this->findData(dataInfo.name); + //this->parseField(dataInfo.name, dataInfo.value); + + if (dataField) + { + std::cout << "=============" << std::endl; + std::cout << "dataField value before: " << dataField->getValueString() << std::endl; + + dataField->beginEditVoidPtr(); + dataField->read(dataInfo.value); + dataField->endEditVoidPtr(); + // dataField->update(); + std::cout << "dataField value after: " << dataField->getValueString() << std::endl; + } + } + + for (const auto& linkInfo : snapshotObject->m_linkContainer) + { + std::cout << "Loading link: " << linkInfo.name << std::endl; + // Find the corresponding link in the component + //this->parseField(linkInfo.name, linkInfo.value); + auto link = this->findLink(linkInfo.name); + std::cout << "link " << std::endl; + if (link) + { + std::cout << "link getpath" << std::endl; + auto path = link->getPath(); + std::cout << "linkInfo.value : " << linkInfo.value << std::endl; + link->parseString(linkInfo.value, &path); + std::cout << "link value before: " << link->getValueString() << std::endl; + link->read(path); + std::cout << "link value after: " << link->getValueString() << std::endl; + } + } + } } // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h index 01c71b0ffa6..93faa29926b 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h @@ -364,14 +364,16 @@ class SOFA_CORE_API Base : public IntrusiveObject ///@} - std::shared_ptr saveSnapshot(std::vector>& parents) const; - void loadSnapshot(BaseSnapshot& snapshot); + std::shared_ptr saveSnapshot(std::vector>& parents) const; + void loadSnapshot(const std::shared_ptr& snapshotObject); protected: void saveDataIn(BaseSnapshot::SnapshotObject& snapshot) const; void saveLinksIn(BaseSnapshot::SnapshotObject& snapshot) const; //virtual void saveInternalStateIn(SnapshotObject& snapshot) const; - virtual std::shared_ptr createSnapshotObject(std::vector>& parents) const; + virtual std::shared_ptr createSnapshotObject(std::vector>& parents) const; +public : + virtual std::shared_ptr findSnapshotObject(const std::shared_ptr& parents, const std::string objectname); private : BaseSnapshot* Snapshot_impl; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp index d2f2809b3d6..474c2783f55 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp @@ -64,12 +64,10 @@ core::visual::VisualLoop* BaseNode::getVisualLoop() const return this->getContext()->get(); } -// std::shared_ptr createSnapshotObject(const std::vector>& parents) - std::shared_ptr -BaseNode::createSnapshotObject(std::vector>& parents) const +BaseNode::createSnapshotObject(std::vector>& parents) const { - auto nodeObject = std::make_shared(); + auto nodeObject = std::make_shared(); for (auto p : parents) { if (p) @@ -81,6 +79,34 @@ BaseNode::createSnapshotObject(std::vector +BaseNode::findSnapshotObject( const std::shared_ptr& parents, const std::string objectname) +{ + std::cout << "Searching for snapshot object (node): " << objectname << std::endl; + std::cout << "Searching in parents: " << parents->m_name << std::endl; + if(parents->m_name == objectname) + { + return parents; + } + for (auto p : parents->children) + { + std::cout << "Searching in parents: " << p->m_name << std::endl; + if (p->m_name == objectname) + { + auto nodeObject = std::make_shared(*p); + return nodeObject; + } + else + { + auto childObject = findSnapshotObject(p, objectname); + if (childObject) + return childObject; + } + } + + return nullptr; +} + /// Set the context of an object to this void BaseNode::setObjectContext(BaseComponent::SPtr obj) { diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.h index e40a5b5d25f..9804e96d450 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.h @@ -130,7 +130,9 @@ class SOFA_CORE_API BaseNode : public virtual Base virtual core::visual::VisualLoop* getVisualLoop() const; protected: - std::shared_ptr createSnapshotObject(std::vector>& parents) const ; + std::shared_ptr createSnapshotObject(std::vector>& parents) const override; +public: + std::shared_ptr findSnapshotObject(const std::shared_ptr& parents, const std::string objectname) override; private: virtual std::string internalGetPathName() const; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h index a9517ab610f..d90cf0522f8 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h @@ -62,19 +62,19 @@ class SOFA_CORE_API BaseSnapshot virtual ~SnapshotObject() = default; }; - struct SnapNode : public SnapshotObject + struct SnapshotNode : public SnapshotObject { std::vector components; - std::vector> children; + std::vector> children; - SnapNode() = default; - SnapNode(const std::string& name) : SnapshotObject(name) {} - SnapNode(const SnapshotObject& obj) : SnapshotObject(obj) {} + SnapshotNode() = default; + SnapshotNode(const std::string& name) : SnapshotObject(name) {} + SnapshotNode(const SnapshotObject& obj) : SnapshotObject(obj) {} - virtual ~SnapNode() noexcept = default; + virtual ~SnapshotNode() noexcept = default; }; - std::shared_ptr m_graphRoot { nullptr }; + std::shared_ptr m_graphRoot { nullptr }; virtual void importSnapshot(const std::string filename) = 0; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp index 57c7454940e..79e106191aa 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp @@ -64,7 +64,7 @@ void to_json(nlohmann::json& j, const BaseSnapshot::SnapshotObject& so ) j["links"] = so.m_linkContainer; } -void to_json(nlohmann::json& j, const BaseSnapshot::SnapNode& sn) +void to_json(nlohmann::json& j, const BaseSnapshot::SnapshotNode& sn) { j.clear(); j["name"] = sn.m_name; @@ -86,7 +86,7 @@ void to_json(nlohmann::json& j, const BaseSnapshot::SnapNode& sn) } } -void to_json(nlohmann::json& j, const std::shared_ptr& sn) +void to_json(nlohmann::json& j, const std::shared_ptr& sn) { j.clear(); j["name"] = sn->m_name; @@ -143,7 +143,7 @@ void JSONSnapshot::importSnapshot(const std::string filename) // j.at("links").get_to(so.m_linkContainer); // } -// void from_json(const nlohmann::json& j, BaseSnapshot::SnapNode& sn) +// void from_json(const nlohmann::json& j, BaseSnapshot::SnapshotNode& sn) // { // j.at("components").get_to(sn.components); @@ -152,7 +152,7 @@ void JSONSnapshot::importSnapshot(const std::string filename) // { // for (const auto& childJson : j["children"]) // { -// auto child = std::make_shared(); +// auto child = std::make_shared(); // childJson.get_to(*child); // sn.children.push_back(child); // } diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp index 44fb7eda313..aa972b092bf 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp @@ -47,7 +47,7 @@ void MemorySnapshot::exportTo(const std::string filename) void MemorySnapshot::importSnapshot(const std::string filename) { - std::cout << "importSnapshot" << std::endl; + std::cout << "importSnapshot possible" << std::endl; if(m_graphRoot != nullptr) { std::cout << m_graphRoot->m_name << std::endl; diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp index c61a079c8fd..62fc415f13d 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp @@ -53,26 +53,48 @@ using sofa::core::objectmodel::SnapshotType; namespace sofa::simulation { -void LoadSnapshotVisitor::processObject(core::objectmodel::BaseObject* obj) +void LoadSnapshotVisitor::processObject( + core::objectmodel::BaseObject* obj, + std::shared_ptr parent +) { - //obj->loadSnapshot(snapCont_); + std::cout << "avant findSnapshotObjectBASE" << std::endl; + auto snapshotObject = obj->findSnapshotObject(parent, obj->getName()); + std::cout << "apres findSnapshotObjectBASE" << std::endl; + std::cout << "#######################" << std::endl; + std::cout << "snapshotObject name (object): " << snapshotObject->m_name << std::endl; + std::cout << "#######################" << std::endl; + obj->loadSnapshot(snapshotObject); } Visitor::Result LoadSnapshotVisitor::processNodeTopDown(simulation::Node* node) { - //node->loadSnapshot(snapCont_); + // find the snapshotObject in the snapshot in order to loadSnapshot + std::cout << "========================> NOUS SOMMES DANS LE NODE : " << node->getName() << std::endl; + std::cout << "avant findSnapshotObjectNODE" << std::endl; + auto snapshotObject = node->findSnapshotObject(m_snapshotContainer.m_graphRoot, node->getName()); + std::cout << "apres findSnapshotObjectNODE" << std::endl; + auto SnapshotNode = std::dynamic_pointer_cast(snapshotObject); + std::cout << "#########################" << std::endl; + std::cout << "snapshotObject name (node): " << SnapshotNode->m_name << std::endl; + for (auto element : SnapshotNode->components) + { + std::cout << "components name: " << element.m_name << std::endl; + } + for (auto child : SnapshotNode->children) + { + std::cout << "children name: " << child->m_name << std::endl; + } + std::cout << "#########################" << std::endl; + node->loadSnapshot(SnapshotNode); + for (simulation::Node::ObjectIterator it = node->object.begin(); it != node->object.end(); ++it) { - this->processObject(it->get()); - } + this->processObject(it->get(), SnapshotNode); + } return RESULT_CONTINUE; } -void LoadSnapshotVisitor::processNodeBottomUp(simulation::Node* /*node*/) -{ -} - - } // namespace sofa::simulation diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.h index fc98b17a5d0..2fe41a083fc 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.h @@ -35,14 +35,15 @@ namespace sofa::simulation class SOFA_SIMULATION_CORE_API LoadSnapshotVisitor : public Visitor { protected: - core::objectmodel::BaseSnapshot& snapCont_; + core::objectmodel::BaseSnapshot& m_snapshotContainer; + + std::unordered_map> m_snapshotNodeMap; public: - LoadSnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::BaseSnapshot& snapshot) : Visitor(eparams), snapCont_(snapshot) {} + LoadSnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::BaseSnapshot& snapshot) : Visitor(eparams), m_snapshotContainer(snapshot) {} - void processObject(core::objectmodel::BaseObject* obj); + void processObject(core::objectmodel::BaseObject* obj, std::shared_ptr parent); Result processNodeTopDown(simulation::Node* node) override; - void processNodeBottomUp(simulation::Node* node) override; const char* getClassName() const override { return "SnapshotVisitor"; } }; diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp index ca5bcc3ad73..1308609eea3 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp @@ -56,9 +56,9 @@ namespace sofa::simulation void SnapshotVisitor::processObject( core::objectmodel::BaseObject* obj, - std::shared_ptr parent) + std::shared_ptr parent) { - std::vector> parents; + std::vector> parents; auto snapshot = obj->saveSnapshot(parents); parent->components.push_back(*snapshot); } @@ -67,7 +67,7 @@ Visitor::Result SnapshotVisitor::processNodeTopDown(simulation::Node* node) { const auto parents = node->getParents(); - std::vector> snapshotParents; + std::vector> snapshotParents; for (auto* p : parents) { const auto it = m_snapshotNodeMap.find(p); @@ -82,20 +82,20 @@ Visitor::Result SnapshotVisitor::processNodeTopDown(simulation::Node* node) } auto snapshot = node->saveSnapshot(snapshotParents); - auto snapNode = std::dynamic_pointer_cast(snapshot); - if (snapNode) + auto SnapshotNode = std::dynamic_pointer_cast(snapshot); + if (SnapshotNode) { - m_snapshotNodeMap[node] = snapNode; + m_snapshotNodeMap[node] = SnapshotNode; } if (m_snapshotContainer.m_graphRoot == nullptr) //root node { - m_snapshotContainer.m_graphRoot = snapNode; + m_snapshotContainer.m_graphRoot = SnapshotNode; } for (const auto& it : node->object) { - this->processObject(it.get(), snapNode); + this->processObject(it.get(), SnapshotNode); } return RESULT_CONTINUE; diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h index f29d6d1d682..8fc6f7411cb 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h @@ -39,14 +39,14 @@ class SOFA_SIMULATION_CORE_API SnapshotVisitor : public Visitor protected: core::objectmodel::BaseSnapshot& m_snapshotContainer; - std::unordered_map> m_snapshotNodeMap; + std::unordered_map> m_snapshotNodeMap; public: SnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::BaseSnapshot& snapshot) : Visitor(eparams), m_snapshotContainer(snapshot) { } - void processObject(core::objectmodel::BaseObject* obj, std::shared_ptr parent); + void processObject(core::objectmodel::BaseObject* obj, std::shared_ptr parent); Result processNodeTopDown(simulation::Node* node) override; const char* getClassName() const override { return "SnapshotVisitor"; } From 75962c54fcc0db92845ececa2ba7cd2529bd557b Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Mon, 16 Feb 2026 11:41:19 +0100 Subject: [PATCH 16/57] [SNAPSHOT] CLEAN Update loadSnapshot --- .../simutest/objectmodel/Snapshot_test.cpp | 15 ++++ .../Core/src/sofa/core/objectmodel/Base.cpp | 75 ++++++++++--------- .../Core/src/sofa/core/objectmodel/BaseData.h | 2 + .../src/sofa/core/objectmodel/BaseNode.cpp | 3 - .../src/sofa/core/objectmodel/BaseSnapshot.h | 1 + .../Core/src/sofa/core/objectmodel/Data.h | 2 + .../sofa/simulation/LoadSnapshotVisitor.cpp | 22 +----- 7 files changed, 60 insertions(+), 60 deletions(-) diff --git a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp index 5a06c0a4577..1a2678e98e2 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp @@ -131,4 +131,19 @@ TEST_F(Snapshot_test, saveSnapshot) EXPECT_EQ(snapshot->m_dataContainer[0].value, "pi"); EXPECT_EQ(snapshot->m_dataContainer[5].name, "value"); EXPECT_EQ(snapshot->m_dataContainer[5].value, "3.14"); +} + +TEST_F(Snapshot_test, loadSnapshot) +{ + TestComponent tcomponent; + + auto snapshot = std::make_shared(); + std::vector> snapshotParents; + snapshot = tcomponent.saveSnapshot(snapshotParents); + + TestComponent tcomponent2; + tcomponent2.d_value.setValue(0.0f); + tcomponent2.loadSnapshot(snapshot); + + EXPECT_EQ(tcomponent2.d_value.getValue(), 3.14f); } \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index 99bdded3b4a..63a4362f919 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -738,10 +738,11 @@ std::shared_ptr Base::saveSnapshot(std::vector Base::findSnapshotObject(const std::shared_ptr& parents, const std::string objectname) { - std::cout << "Searching for snapshot object (base): " << objectname << std::endl; for (auto p : parents->components) { if (p.m_name == objectname) @@ -749,57 +750,57 @@ Base::findSnapshotObject(const std::shared_ptr& pare auto object = std::make_shared(p); return object; } - } - return nullptr; } void Base::loadSnapshot(const std::shared_ptr& snapshotObject) { - //type.importSnapshot(filename); - std::cout << "load snapshot" << std::endl; - // a function to read data from the snapshot and store inside the component + // const auto& dataFields = this->getDataFields(); + // for (const auto& data : dataFields) + // { + // auto* dataTest = dynamic_cast(data->getData()); + // if (dataTest) + // { + // auto value = dataTest->getValue(); + // std::cout << "name : " << value->getName() << std::endl; + // std::cout << "type : " << value->getValueTypeString() << std::endl; + // } + // } + + for (const auto& dataInfo : snapshotObject->m_dataContainer) { - std::cout << "Loading data field: " << dataInfo.name << std::endl; - // Find the corresponding data field in the component - auto dataField = this->findData(dataInfo.name); - //this->parseField(dataInfo.name, dataInfo.value); - - if (dataField) + std::cout << "dataType : " << dataInfo.type << std::endl; + if(dataInfo.name == "projectionMatrix" || dataInfo.name == "loadedPlugins") { - std::cout << "=============" << std::endl; - std::cout << "dataField value before: " << dataField->getValueString() << std::endl; - - dataField->beginEditVoidPtr(); - dataField->read(dataInfo.value); - dataField->endEditVoidPtr(); - // dataField->update(); - std::cout << "dataField value after: " << dataField->getValueString() << std::endl; + std::cout << "projectionMatrix or loadedPlugins found" << std::endl; } - } - - for (const auto& linkInfo : snapshotObject->m_linkContainer) - { - std::cout << "Loading link: " << linkInfo.name << std::endl; - // Find the corresponding link in the component - //this->parseField(linkInfo.name, linkInfo.value); - auto link = this->findLink(linkInfo.name); - std::cout << "link " << std::endl; - if (link) + else { - std::cout << "link getpath" << std::endl; - auto path = link->getPath(); - std::cout << "linkInfo.value : " << linkInfo.value << std::endl; - link->parseString(linkInfo.value, &path); - std::cout << "link value before: " << link->getValueString() << std::endl; - link->read(path); - std::cout << "link value after: " << link->getValueString() << std::endl; + this->parseField(dataInfo.name, dataInfo.value); } } + // for (const auto& linkInfo : snapshotObject->m_linkContainer) + // { + // // std::cout << "Loading link: " << linkInfo.name << std::endl; + // // Find the corresponding link in the component + // this->parseField(linkInfo.name, linkInfo.value); + // // auto link = this->findLink(linkInfo.name); + // // std::cout << "link " << std::endl; + // // if (link) + // // { + // // std::cout << "link getpath" << std::endl; + // // auto path = link->getPath(); + // // std::cout << "linkInfo.value : " << linkInfo.value << std::endl; + // // link->parseString(linkInfo.value, &path); + // // std::cout << "link value before: " << link->getValueString() << std::endl; + // // link->read(path); + // // std::cout << "link value after: " << link->getValueString() << std::endl; + // // } + // } } } // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseData.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseData.h index 0e3a4c7d894..343b7124b40 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseData.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseData.h @@ -317,6 +317,8 @@ class SOFA_CORE_API BaseData : public DDGNode virtual void* doBeginEditVoidPtr() = 0; virtual void doEndEditVoidPtr() = 0; virtual void doOnUpdate() {} + + }; /** A WriteAccessWithRawPtr is a RAII class, holding a reference to a given container diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp index 474c2783f55..3bc91522632 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp @@ -82,15 +82,12 @@ BaseNode::createSnapshotObject(std::vector BaseNode::findSnapshotObject( const std::shared_ptr& parents, const std::string objectname) { - std::cout << "Searching for snapshot object (node): " << objectname << std::endl; - std::cout << "Searching in parents: " << parents->m_name << std::endl; if(parents->m_name == objectname) { return parents; } for (auto p : parents->children) { - std::cout << "Searching in parents: " << p->m_name << std::endl; if (p->m_name == objectname) { auto nodeObject = std::make_shared(*p); diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h index d90cf0522f8..570b1b055eb 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h @@ -28,6 +28,7 @@ #include #include #include +#include namespace sofa::core::objectmodel { diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Data.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Data.h index 797c76f4cea..0103ffaa5e1 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Data.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Data.h @@ -236,6 +236,8 @@ class Data : public BaseData const void* doGetValueVoidPtr() const override { return &getValue(); } void* doBeginEditVoidPtr() override { return beginEdit(); } void doEndEditVoidPtr() override { endEdit(); } + + }; class EmptyData : public Data {}; diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp index 62fc415f13d..39b65163b07 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp @@ -58,36 +58,18 @@ void LoadSnapshotVisitor::processObject( std::shared_ptr parent ) { - std::cout << "avant findSnapshotObjectBASE" << std::endl; auto snapshotObject = obj->findSnapshotObject(parent, obj->getName()); - std::cout << "apres findSnapshotObjectBASE" << std::endl; - std::cout << "#######################" << std::endl; - std::cout << "snapshotObject name (object): " << snapshotObject->m_name << std::endl; - std::cout << "#######################" << std::endl; obj->loadSnapshot(snapshotObject); } Visitor::Result LoadSnapshotVisitor::processNodeTopDown(simulation::Node* node) { // find the snapshotObject in the snapshot in order to loadSnapshot - std::cout << "========================> NOUS SOMMES DANS LE NODE : " << node->getName() << std::endl; - std::cout << "avant findSnapshotObjectNODE" << std::endl; auto snapshotObject = node->findSnapshotObject(m_snapshotContainer.m_graphRoot, node->getName()); - std::cout << "apres findSnapshotObjectNODE" << std::endl; + auto SnapshotNode = std::dynamic_pointer_cast(snapshotObject); - std::cout << "#########################" << std::endl; - std::cout << "snapshotObject name (node): " << SnapshotNode->m_name << std::endl; - for (auto element : SnapshotNode->components) - { - std::cout << "components name: " << element.m_name << std::endl; - } - for (auto child : SnapshotNode->children) - { - std::cout << "children name: " << child->m_name << std::endl; - } - std::cout << "#########################" << std::endl; node->loadSnapshot(SnapshotNode); - + for (simulation::Node::ObjectIterator it = node->object.begin(); it != node->object.end(); ++it) { this->processObject(it->get(), SnapshotNode); From ca1c88a86fe60792224ec91aa425bacde30b03cc Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Tue, 24 Feb 2026 15:59:20 +0100 Subject: [PATCH 17/57] [SNAPSHOT] FIX nan problem --- .../fem/elastic/TetrahedronFEMForceField.inl | 3 +- .../Core/src/sofa/core/objectmodel/Base.cpp | 43 ++++++++++--------- .../src/sofa/core/objectmodel/BaseSnapshot.h | 12 +++++- .../sofa/core/objectmodel/MemorySnapshot.cpp | 26 +++++------ Sofa/framework/Type/CMakeLists.txt | 5 ++- 5 files changed, 51 insertions(+), 38 deletions(-) diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedronFEMForceField.inl b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedronFEMForceField.inl index 266ca6f8612..2a9a530720d 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedronFEMForceField.inl +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedronFEMForceField.inl @@ -758,7 +758,8 @@ inline void TetrahedronFEMForceField::computeRotationLarge( Transform // first vector on first edge // second vector in the plane of the two first edges // third vector orthogonal to first and second - + std::cout << " p size : " << p.size() << std::endl; + std::cout << " a : " << a << " b : " << b << " c : " << c << std::endl; const Coord edgex = (p[b]-p[a]).normalized(); Coord edgey = p[c]-p[a]; const Coord edgez = cross( edgex, edgey ).normalized(); diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index 63a4362f919..1bc8711cdc2 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -686,13 +686,22 @@ int Base::getInstanciationSourceFilePos() const void Base::saveDataIn(BaseSnapshot::SnapshotObject& snapshot) const { const auto& dataFields = this->getDataFields(); - + std::cout << "Type of dataFields : "<< this->getTypeName() << std::endl; for (const auto& data : dataFields) { + // std::cout << "data type : " << data->getValueTypeString() << std::endl; BaseSnapshot::DataInfo dataInfo; dataInfo.name = data->getName(); dataInfo.type = data->getValueTypeString(); dataInfo.value = data->getValueString(); + std::string replaceValue = "nan"; + std::string newValue = "0"; + std::size_t pos = dataInfo.value.find(replaceValue); + while (pos != std::string::npos) + { + dataInfo.value.replace(pos, replaceValue.length(),newValue); + pos = dataInfo.value.find(replaceValue, pos + newValue.length()); + } snapshot.m_dataContainer.push_back(dataInfo); } } @@ -703,6 +712,7 @@ void Base::saveLinksIn(BaseSnapshot::SnapshotObject& snapshot) const for (const auto& link : links) { + // std::cout << "link type : " << link->getValueTypeString() << std::endl; BaseSnapshot::LinkInfo linkInfo; linkInfo.name = link->getName(); linkInfo.type = link->getValueTypeString(); @@ -757,29 +767,20 @@ Base::findSnapshotObject(const std::shared_ptr& pare void Base::loadSnapshot(const std::shared_ptr& snapshotObject) { - // const auto& dataFields = this->getDataFields(); - // for (const auto& data : dataFields) - // { - // auto* dataTest = dynamic_cast(data->getData()); - // if (dataTest) - // { - // auto value = dataTest->getValue(); - // std::cout << "name : " << value->getName() << std::endl; - // std::cout << "type : " << value->getValueTypeString() << std::endl; - // } - // } - - for (const auto& dataInfo : snapshotObject->m_dataContainer) { - std::cout << "dataType : " << dataInfo.type << std::endl; - if(dataInfo.name == "projectionMatrix" || dataInfo.name == "loadedPlugins") + auto data = this->findData(dataInfo.name); + if (data) { - std::cout << "projectionMatrix or loadedPlugins found" << std::endl; - } - else - { - this->parseField(dataInfo.name, dataInfo.value); + if( dataInfo.name == "loadedPlugins"|| dataInfo.name == "filename" || dataInfo.name == "texturename") + { + std::cout << "projectionMatrix or loadedPlugins or filename or texturename or newField found" << std::endl; + } + else + { + data->read(dataInfo.value); + } + } } diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h index 570b1b055eb..607eab19b48 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h @@ -28,13 +28,23 @@ #include #include #include -#include + +#include namespace sofa::core::objectmodel { class SOFA_CORE_API BaseSnapshot { +private: + + +public: + + // Add containers which have all datas from a simulation in BaseData forms + std::vector> m_baseDataContainers; + + public: struct DataInfo { diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp index aa972b092bf..24b343615f2 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp @@ -47,20 +47,20 @@ void MemorySnapshot::exportTo(const std::string filename) void MemorySnapshot::importSnapshot(const std::string filename) { - std::cout << "importSnapshot possible" << std::endl; - if(m_graphRoot != nullptr) - { - std::cout << m_graphRoot->m_name << std::endl; + //std::cout << "importSnapshot possible" << std::endl; + // if(m_graphRoot != nullptr) + // { + // std::cout << m_graphRoot->m_name << std::endl; - for (auto& element : m_graphRoot->components) - { - std::cout << " Component name : " << element.m_name << std::endl; - } - for (auto& element : m_graphRoot->children) - { - std::cout << " Child name : " << element->m_name << std::endl; - } - } + // for (auto& element : m_graphRoot->components) + // { + // std::cout << " Component name : " << element.m_name << std::endl; + // } + // for (auto& element : m_graphRoot->children) + // { + // std::cout << " Child name : " << element->m_name << std::endl; + // } + // } } void MemorySnapshot::importFrom(const std::string filename) diff --git a/Sofa/framework/Type/CMakeLists.txt b/Sofa/framework/Type/CMakeLists.txt index ad991bb7e06..eed1db524f4 100644 --- a/Sofa/framework/Type/CMakeLists.txt +++ b/Sofa/framework/Type/CMakeLists.txt @@ -81,7 +81,7 @@ sofa_find_package(Sofa.Config REQUIRED) ## Boost (1.54.0 or higher) is now mandatory. set(BOOST_MIN_VERSION "1.54.0") set(Boost_NO_BOOST_CMAKE TRUE) -sofa_find_package(Boost ${BOOST_MIN_VERSION} QUIET) +sofa_find_package(Boost ${BOOST_MIN_VERSION} QUIET COMPONENTS serialization) if(NOT Boost_FOUND) if(WIN32) message(FATAL_ERROR "Boost (${BOOST_MIN_VERSION} or higher) is mandatory.\n" @@ -94,7 +94,7 @@ if(NOT Boost_FOUND) endif() endif() -sofa_find_package(Boost QUIET REQUIRED) +sofa_find_package(Boost QUIET REQUIRED COMPONENTS serialization) option(SOFA_USE_MIMALLOC "Use mimalloc to replace malloc (known to be more efficient, especially with MSVC)" OFF) if(SOFA_USE_MIMALLOC) @@ -105,6 +105,7 @@ add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) target_link_libraries(${PROJECT_NAME} PUBLIC Sofa.Config) target_link_libraries(${PROJECT_NAME} PUBLIC Boost::boost) +target_link_libraries(${PROJECT_NAME} PUBLIC Boost::serialization) if(mimalloc_FOUND) target_link_libraries(${PROJECT_NAME} PUBLIC mimalloc) From 7a946a9c6c3f17a3537d3b7d520b81ff547b1ca5 Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Wed, 25 Feb 2026 11:44:55 +0100 Subject: [PATCH 18/57] [Snapshot] Fix loadSnapshot for JSON --- .../fem/elastic/TetrahedronFEMForceField.inl | 3 + .../Core/src/sofa/core/objectmodel/Base.cpp | 7 +- .../src/sofa/core/objectmodel/BaseSnapshot.h | 37 +++- .../sofa/core/objectmodel/JSONSnapshot.cpp | 169 +++++++++++++----- 4 files changed, 161 insertions(+), 55 deletions(-) diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedronFEMForceField.inl b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedronFEMForceField.inl index 2a9a530720d..4a57b2043f7 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedronFEMForceField.inl +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedronFEMForceField.inl @@ -758,8 +758,11 @@ inline void TetrahedronFEMForceField::computeRotationLarge( Transform // first vector on first edge // second vector in the plane of the two first edges // third vector orthogonal to first and second + + // TODO : remove std::cout std::cout << " p size : " << p.size() << std::endl; std::cout << " a : " << a << " b : " << b << " c : " << c << std::endl; + const Coord edgex = (p[b]-p[a]).normalized(); Coord edgey = p[c]-p[a]; const Coord edgez = cross( edgex, edgey ).normalized(); diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index 1bc8711cdc2..c8fa7ae378b 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -772,15 +772,10 @@ void Base::loadSnapshot(const std::shared_ptr& sna auto data = this->findData(dataInfo.name); if (data) { - if( dataInfo.name == "loadedPlugins"|| dataInfo.name == "filename" || dataInfo.name == "texturename") - { - std::cout << "projectionMatrix or loadedPlugins or filename or texturename or newField found" << std::endl; - } - else + if( dataInfo.name != "loadedPlugins"&& dataInfo.name != "filename" && dataInfo.name != "texturename" && dataInfo.name != "pluginName") { data->read(dataInfo.value); } - } } diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h index 607eab19b48..ccd353a7acf 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h @@ -67,6 +67,23 @@ class SOFA_CORE_API BaseSnapshot std::vector m_linkContainer; //void* m_internalState { nullptr }; + + virtual void clear() + { + m_dataContainer.clear(); + m_linkContainer.clear(); + } + + void push_back(const DataInfo& data) + { + m_dataContainer.push_back(data); + } + + void push_back(const LinkInfo& link) + { + m_linkContainer.push_back(link); + } + SnapshotObject() = default; explicit SnapshotObject(const std::string& name) : m_name(name){} @@ -77,7 +94,25 @@ class SOFA_CORE_API BaseSnapshot { std::vector components; std::vector> children; - + + void clear() + { + components.clear(); + children.clear(); + m_dataContainer.clear(); + m_linkContainer.clear(); + } + + void push_back(const std::shared_ptr& child) + { + children.push_back(child); + } + + void push_back(const SnapshotObject& component) + { + components.push_back(component); + } + SnapshotNode() = default; SnapshotNode(const std::string& name) : SnapshotObject(name) {} SnapshotNode(const SnapshotObject& obj) : SnapshotObject(obj) {} diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp index 79e106191aa..f81f5c37fc4 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp @@ -122,62 +122,135 @@ void JSONSnapshot::importSnapshot(const std::string filename) } -// void from_json(const nlohmann::json& j,BaseSnapshot::DataInfo& di ) -// { -// j.at("name").get_to(di.name); -// j.at("type").get_to(di.type); -// j.at("value").get_to(di.value); +void from_json(const nlohmann::json& j, BaseSnapshot::DataInfo& di) +{ + di.name = j.value("name", ""); + di.type = j.value("type", ""); + di.value = j.value("value", ""); +} + +void from_json(const nlohmann::json& j, BaseSnapshot::LinkInfo& li) +{ + li.name = j.value("name", ""); + li.type = j.value("type", ""); + li.value = j.value("value", ""); +} + +void from_json(const nlohmann::json& j, BaseSnapshot::SnapshotObject& so) +{ + so.m_name = j.value("name", ""); -// } - -// void from_json(const nlohmann::json& j,BaseSnapshot::LinkInfo& li ) -// { -// j.at("name").get_to(li.name); -// j.at("type").get_to(li.type); -// j.at("value").get_to(li.value); -// } - -// void from_json(const nlohmann::json& j,BaseSnapshot::SnapshotObject& so ) -// { -// j.at("datas").get_to(so.m_dataContainer); -// j.at("links").get_to(so.m_linkContainer); -// } - -// void from_json(const nlohmann::json& j, BaseSnapshot::SnapshotNode& sn) -// { -// j.at("components").get_to(sn.components); - -// sn.children.clear(); -// if (j.contains("children") && j["children"].is_array()) -// { -// for (const auto& childJson : j["children"]) -// { -// auto child = std::make_shared(); -// childJson.get_to(*child); -// sn.children.push_back(child); -// } -// } -// } + if (j.contains("datas") && j["datas"].is_array()) + { + so.m_dataContainer.clear(); + for (const auto& dataJson : j["datas"]) + { + BaseSnapshot::DataInfo di; + from_json(dataJson, di); + so.m_dataContainer.push_back(di); + } + } + + if (j.contains("links") && j["links"].is_array()) + { + so.m_linkContainer.clear(); + for (const auto& linkJson : j["links"]) + { + BaseSnapshot::LinkInfo li; + from_json(linkJson, li); + so.m_linkContainer.push_back(li); + } + } +} -void JSONSnapshot::importFrom(const std::string filename) +void from_json(const nlohmann::json& j, BaseSnapshot::SnapshotNode& sn) { - // std::cout << "importFrom" << std::endl; - // std::ifstream file(filename); - // nlohmann::json jfile; - // file >> jfile; - // file.close(); + sn.m_name = j.value("name", ""); + + // Parser les données + if (j.contains("datas") && j["datas"].is_array()) + { + sn.m_dataContainer.clear(); + for (const auto& dataJson : j["datas"]) + { + BaseSnapshot::DataInfo di; + from_json(dataJson, di); + sn.m_dataContainer.push_back(di); + } + } + + // Parser les liens + if (j.contains("links") && j["links"].is_array()) + { + sn.m_linkContainer.clear(); + for (const auto& linkJson : j["links"]) + { + BaseSnapshot::LinkInfo li; + from_json(linkJson, li); + sn.m_linkContainer.push_back(li); + } + } - // treeSnapshot.clear(); + // Parser les composants + if (j.contains("components") && j["components"].is_array()) + { + sn.components.clear(); + for (const auto& compJson : j["components"]) + { + BaseSnapshot::SnapshotObject so; + from_json(compJson, so); + sn.components.push_back(so); + } + } - // // std::cout << "root : " << jfile[0]["name"] << std::endl; - // // std::cout << "children : " << jfile[0]["children"] << std::endl; - // for (auto& [key,value] : jfile[0].items()) - // { - // std::cout << "TEST" << std::endl; - // } + // Parser les enfants (récursivement) + sn.children.clear(); + if (j.contains("children") && j["children"].is_array()) + { + for (const auto& childJson : j["children"]) + { + if (!childJson.is_null()) + { + auto child = std::make_shared(); + from_json(childJson, *child); + sn.children.push_back(child); + } + } + } +} + +void JSONSnapshot::importFrom(const std::string filename) +{ + std::ifstream file(filename); + if (!file.is_open()) + { + std::cerr << "ERROR: Cannot open file " << filename << " for reading\n"; + return; + } + + nlohmann::json jsonRoot; + file >> jsonRoot; + file.close(); + + if (!m_graphRoot) + { + m_graphRoot = std::make_shared(); + } + + + if (jsonRoot.is_object() && !jsonRoot.empty()) + { + from_json(jsonRoot, *m_graphRoot); + } + else + { + std::cerr << "ERROR: Invalid JSON format in " << filename << "\n"; + return; + } std::cout << "JSON imported successfully from: " << filename << std::endl; + } From d931ccbe5a6600ac4c58045ff78e8a02323a3d75 Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Thu, 26 Feb 2026 11:40:43 +0100 Subject: [PATCH 19/57] remove comments --- .../Core/src/sofa/core/objectmodel/Base.cpp | 1 - .../src/sofa/core/objectmodel/MemorySnapshot.cpp | 16 ++-------------- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index c8fa7ae378b..c32538eec4f 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -686,7 +686,6 @@ int Base::getInstanciationSourceFilePos() const void Base::saveDataIn(BaseSnapshot::SnapshotObject& snapshot) const { const auto& dataFields = this->getDataFields(); - std::cout << "Type of dataFields : "<< this->getTypeName() << std::endl; for (const auto& data : dataFields) { // std::cout << "data type : " << data->getValueTypeString() << std::endl; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp index 24b343615f2..3fe6a66ab30 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp @@ -48,24 +48,12 @@ void MemorySnapshot::exportTo(const std::string filename) void MemorySnapshot::importSnapshot(const std::string filename) { //std::cout << "importSnapshot possible" << std::endl; - // if(m_graphRoot != nullptr) - // { - // std::cout << m_graphRoot->m_name << std::endl; - - // for (auto& element : m_graphRoot->components) - // { - // std::cout << " Component name : " << element.m_name << std::endl; - // } - // for (auto& element : m_graphRoot->children) - // { - // std::cout << " Child name : " << element->m_name << std::endl; - // } - // } + } void MemorySnapshot::importFrom(const std::string filename) { - std::cout << "importFrom" << std::endl; + //std::cout << "importFrom" << std::endl; } From 7aa1a698ef0632baad2c040aeb122a24a09e4b35 Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Fri, 27 Feb 2026 18:11:45 +0100 Subject: [PATCH 20/57] [Snapshot] Add unit tests + cleaning --- .../simutest/objectmodel/Snapshot_test.cpp | 124 ++++++++++++++++-- .../Core/src/sofa/core/objectmodel/Base.cpp | 28 ++-- .../Core/src/sofa/core/objectmodel/Base.h | 3 - .../src/sofa/core/objectmodel/BaseSnapshot.h | 11 -- .../sofa/core/objectmodel/JSONSnapshot.cpp | 4 - .../sofa/core/objectmodel/MemorySnapshot.h | 1 - .../sofa/simulation/LoadSnapshotVisitor.cpp | 1 - .../src/sofa/simulation/SnapshotVisitor.cpp | 6 +- 8 files changed, 125 insertions(+), 53 deletions(-) diff --git a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp index 1a2678e98e2..6c63d2752b7 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp @@ -38,9 +38,10 @@ using sofa::simulation::SnapshotVisitor; #include using sofa::core::objectmodel::Data; - -#include +using sofa::core::objectmodel::BaseLink; +using sofa::core::objectmodel::SingleLink ; using sofa::core::objectmodel::BaseSnapshot; +using sofa::core::objectmodel::BaseNode; class TestComponent : public Base { @@ -48,7 +49,6 @@ class TestComponent : public Base Data d_value; - TestComponent() : d_value(initData(&d_value, 3.14f, "value", "test value")) { @@ -60,13 +60,39 @@ class TestComponent : public Base this->saveDataIn(snapshot); } + void saveLinks(BaseSnapshot::SnapshotObject& snapshot) + { + this->saveLinksIn(snapshot); + } + + std::shared_ptr createSnapshotObjectTest(std::vector>& parents) const + { + + return this->createSnapshotObject(parents); + } SOFA_CLASS(TestComponent,Base); }; +class MockSnapshotTest : public BaseSnapshot +{ +public: + void importSnapshot(const std::string filename) override + {} + void exportTo(const std::string filename) override + {} + void importFrom(std::string filename) override + {} + + + MockSnapshotTest() {} + ~MockSnapshotTest() = default; +}; + class Snapshot_test: public BaseSimulationTest { public: + SceneInstance* c; Node* node {nullptr}; Snapshot_test() @@ -95,14 +121,19 @@ class Snapshot_test: public BaseSimulationTest { delete c; } + + }; + TEST_F(Snapshot_test, saveDataIn) { - TestComponent tcomponent; - + // TEST of saveDataIn method + // Check if the snapshot contains the component with expected data + + TestComponent tComponent; auto snapshot = std::make_shared(); - tcomponent.saveData(*snapshot); + tComponent.saveData(*snapshot); for (auto& data : snapshot->m_dataContainer) { if(data.name == "name") @@ -117,13 +148,83 @@ TEST_F(Snapshot_test, saveDataIn) } } +TEST_F(Snapshot_test, createSnapshotObject) +{ + // TEST of createSnapshotObject + // Check if createSnapshotObject can create a SnapshotObject + // To verify, A name and some data are added to the SnapshotObject + + TestComponent tComponent; + std::vector> snapshotParents; + auto snapshotObject = tComponent.createSnapshotObjectTest(snapshotParents); + + snapshotObject->m_name = "snapshotObject"; + tComponent.saveData(*snapshotObject); + + EXPECT_NE(snapshotObject, nullptr); + EXPECT_EQ(snapshotObject->m_name, "snapshotObject"); + + for (auto& data : snapshotObject->m_dataContainer) + { + if(data.name == "name") + { + EXPECT_EQ(data.value, "pi"); + } + + if(data.name == "value") + { + EXPECT_EQ(data.value, "3.14"); + } + } +} + +TEST_F(Snapshot_test, findSnapshotObject) +{ + // TEST of findSnapshotObject (Base version) + // + + MockSnapshotTest MockSnapshot; + + EXPECT_EQ(MockSnapshot.m_graphRoot, nullptr); + + MockSnapshot.m_graphRoot = std::make_shared("root"); + + auto snapshotObject1 = std::make_shared("SnapshotObject1"); + auto snapshotObject2 = std::make_shared("SnapshotObject2"); + + MockSnapshot.m_graphRoot->components.push_back(*snapshotObject1); + MockSnapshot.m_graphRoot->components.push_back(*snapshotObject2); + + TestComponent tComponent; + + auto expectedObject1 = tComponent.findSnapshotObject(MockSnapshot.m_graphRoot, "SnapshotObject1"); + auto expectedObject2 = tComponent.findSnapshotObject(MockSnapshot.m_graphRoot, "SnapshotObject2"); + + EXPECT_EQ(snapshotObject1->m_name, expectedObject1->m_name); + EXPECT_EQ(snapshotObject2->m_name, expectedObject2->m_name); + + Node mockNode; + + auto snapshotNode1 = std::make_shared("SnapshotNode1"); + auto snapshotNode2 = std::make_shared("SnapshotNode2"); + + MockSnapshot.m_graphRoot->children.push_back(snapshotNode1); + MockSnapshot.m_graphRoot->children.push_back(snapshotNode2); + + auto expectedNode1 = mockNode.findSnapshotObject(MockSnapshot.m_graphRoot,"SnapshotNode1"); + auto expectedNode2 = mockNode.findSnapshotObject(MockSnapshot.m_graphRoot,"SnapshotNode2"); + + EXPECT_EQ(snapshotNode1->m_name, expectedNode1->m_name); + EXPECT_EQ(snapshotNode2->m_name, expectedNode2->m_name); +} + TEST_F(Snapshot_test, saveSnapshot) { - TestComponent tcomponent; + TestComponent tComponent; auto snapshot = std::make_shared(); std::vector> snapshotParents; - snapshot = tcomponent.saveSnapshot(snapshotParents); + snapshot = tComponent.saveSnapshot(snapshotParents); EXPECT_EQ(snapshot->m_name, "pi"); EXPECT_EQ(snapshot->m_dataContainer.size(), 6); @@ -135,15 +236,16 @@ TEST_F(Snapshot_test, saveSnapshot) TEST_F(Snapshot_test, loadSnapshot) { - TestComponent tcomponent; + TestComponent tComponent; auto snapshot = std::make_shared(); std::vector> snapshotParents; - snapshot = tcomponent.saveSnapshot(snapshotParents); + snapshot = tComponent.saveSnapshot(snapshotParents); TestComponent tcomponent2; tcomponent2.d_value.setValue(0.0f); tcomponent2.loadSnapshot(snapshot); EXPECT_EQ(tcomponent2.d_value.getValue(), 3.14f); -} \ No newline at end of file +} + diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index c32538eec4f..45568d49730 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -688,11 +688,12 @@ void Base::saveDataIn(BaseSnapshot::SnapshotObject& snapshot) const const auto& dataFields = this->getDataFields(); for (const auto& data : dataFields) { - // std::cout << "data type : " << data->getValueTypeString() << std::endl; BaseSnapshot::DataInfo dataInfo; dataInfo.name = data->getName(); dataInfo.type = data->getValueTypeString(); dataInfo.value = data->getValueString(); + + // Wait PR#5976 to remove std::string replaceValue = "nan"; std::string newValue = "0"; std::size_t pos = dataInfo.value.find(replaceValue); @@ -701,6 +702,8 @@ void Base::saveDataIn(BaseSnapshot::SnapshotObject& snapshot) const dataInfo.value.replace(pos, replaceValue.length(),newValue); pos = dataInfo.value.find(replaceValue, pos + newValue.length()); } + // Wait PR#5976 to remove + snapshot.m_dataContainer.push_back(dataInfo); } } @@ -711,7 +714,6 @@ void Base::saveLinksIn(BaseSnapshot::SnapshotObject& snapshot) const for (const auto& link : links) { - // std::cout << "link type : " << link->getValueTypeString() << std::endl; BaseSnapshot::LinkInfo linkInfo; linkInfo.name = link->getName(); linkInfo.type = link->getValueTypeString(); @@ -780,21 +782,13 @@ void Base::loadSnapshot(const std::shared_ptr& sna // for (const auto& linkInfo : snapshotObject->m_linkContainer) // { - // // std::cout << "Loading link: " << linkInfo.name << std::endl; - // // Find the corresponding link in the component - // this->parseField(linkInfo.name, linkInfo.value); - // // auto link = this->findLink(linkInfo.name); - // // std::cout << "link " << std::endl; - // // if (link) - // // { - // // std::cout << "link getpath" << std::endl; - // // auto path = link->getPath(); - // // std::cout << "linkInfo.value : " << linkInfo.value << std::endl; - // // link->parseString(linkInfo.value, &path); - // // std::cout << "link value before: " << link->getValueString() << std::endl; - // // link->read(path); - // // std::cout << "link value after: " << link->getValueString() << std::endl; - // // } + // auto link = this->findLink(linkInfo.name); + // if (link) + // { + // std::cout << "link name : " << linkInfo.name << std::endl; + // std::cout << "link value : " << linkInfo.value << std::endl; + // link->read(linkInfo.value); + // } // } } diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h index 93faa29926b..833d9607ae4 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h @@ -375,9 +375,6 @@ class SOFA_CORE_API Base : public IntrusiveObject public : virtual std::shared_ptr findSnapshotObject(const std::shared_ptr& parents, const std::string objectname); -private : - BaseSnapshot* Snapshot_impl; - protected: /// List of fields (Data instances) VecData m_vecData; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h index ccd353a7acf..1f1244a048a 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h @@ -20,9 +20,6 @@ * Contact information: contact@sofa-framework.org * ******************************************************************************/ #pragma once -//#include -// #include -// #include #include #include #include @@ -36,14 +33,6 @@ namespace sofa::core::objectmodel class SOFA_CORE_API BaseSnapshot { -private: - - -public: - - // Add containers which have all datas from a simulation in BaseData forms - std::vector> m_baseDataContainers; - public: struct DataInfo diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp index f81f5c37fc4..c024b371073 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp @@ -167,7 +167,6 @@ void from_json(const nlohmann::json& j, BaseSnapshot::SnapshotNode& sn) { sn.m_name = j.value("name", ""); - // Parser les données if (j.contains("datas") && j["datas"].is_array()) { sn.m_dataContainer.clear(); @@ -179,7 +178,6 @@ void from_json(const nlohmann::json& j, BaseSnapshot::SnapshotNode& sn) } } - // Parser les liens if (j.contains("links") && j["links"].is_array()) { sn.m_linkContainer.clear(); @@ -191,7 +189,6 @@ void from_json(const nlohmann::json& j, BaseSnapshot::SnapshotNode& sn) } } - // Parser les composants if (j.contains("components") && j["components"].is_array()) { sn.components.clear(); @@ -203,7 +200,6 @@ void from_json(const nlohmann::json& j, BaseSnapshot::SnapshotNode& sn) } } - // Parser les enfants (récursivement) sn.children.clear(); if (j.contains("children") && j["children"].is_array()) { diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.h index 41e06b29a1f..ce5a9c94108 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.h @@ -33,7 +33,6 @@ class SOFA_CORE_API MemorySnapshot : public BaseSnapshot { public: - //void exportSnapshot(const std::vector& datafield, const std::vector& linkfield) override; void importSnapshot(const std::string filename) override; void exportTo(const std::string filename) override; diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp index 39b65163b07..a07ec40dfd8 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp @@ -64,7 +64,6 @@ void LoadSnapshotVisitor::processObject( Visitor::Result LoadSnapshotVisitor::processNodeTopDown(simulation::Node* node) { - // find the snapshotObject in the snapshot in order to loadSnapshot auto snapshotObject = node->findSnapshotObject(m_snapshotContainer.m_graphRoot, node->getName()); auto SnapshotNode = std::dynamic_pointer_cast(snapshotObject); diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp index 1308609eea3..30c1389f1d2 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp @@ -75,10 +75,6 @@ Visitor::Result SnapshotVisitor::processNodeTopDown(simulation::Node* node) { snapshotParents.push_back(it->second); } - else - { - msg_error("SnapshotVisitor") << "Does it happen??"; - } } auto snapshot = node->saveSnapshot(snapshotParents); @@ -88,7 +84,7 @@ Visitor::Result SnapshotVisitor::processNodeTopDown(simulation::Node* node) m_snapshotNodeMap[node] = SnapshotNode; } - if (m_snapshotContainer.m_graphRoot == nullptr) //root node + if (m_snapshotContainer.m_graphRoot == nullptr) { m_snapshotContainer.m_graphRoot = SnapshotNode; } From 45821a77829277c048a3987f323cac91bb1c8acd Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Mon, 2 Mar 2026 14:13:47 +0100 Subject: [PATCH 21/57] update and clean findSnapshotObject_test --- .../simutest/objectmodel/Snapshot_test.cpp | 40 ++++++------------- .../Core/src/sofa/core/objectmodel/Base.cpp | 10 +++-- .../src/sofa/core/objectmodel/BaseNode.cpp | 6 ++- 3 files changed, 23 insertions(+), 33 deletions(-) diff --git a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp index 6c63d2752b7..dbd5ae82105 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp @@ -180,42 +180,26 @@ TEST_F(Snapshot_test, createSnapshotObject) TEST_F(Snapshot_test, findSnapshotObject) { - // TEST of findSnapshotObject (Base version) - // - - MockSnapshotTest MockSnapshot; - - EXPECT_EQ(MockSnapshot.m_graphRoot, nullptr); - - MockSnapshot.m_graphRoot = std::make_shared("root"); - - auto snapshotObject1 = std::make_shared("SnapshotObject1"); - auto snapshotObject2 = std::make_shared("SnapshotObject2"); - - MockSnapshot.m_graphRoot->components.push_back(*snapshotObject1); - MockSnapshot.m_graphRoot->components.push_back(*snapshotObject2); + // TEST of findSnapshotObject + // Check if findSnapshotObject can find the SnapshotObject in a Snapshot + // with the component's name + TestComponent tComponent; - auto expectedObject1 = tComponent.findSnapshotObject(MockSnapshot.m_graphRoot, "SnapshotObject1"); - auto expectedObject2 = tComponent.findSnapshotObject(MockSnapshot.m_graphRoot, "SnapshotObject2"); - - EXPECT_EQ(snapshotObject1->m_name, expectedObject1->m_name); - EXPECT_EQ(snapshotObject2->m_name, expectedObject2->m_name); + auto snapshotNode = std::make_shared("root"); + std::vector> snapshotParents; + snapshotParents.push_back(snapshotNode); - Node mockNode; + auto snapshot = tComponent.saveSnapshot(snapshotParents); + snapshotNode->components.push_back(*snapshot); - auto snapshotNode1 = std::make_shared("SnapshotNode1"); - auto snapshotNode2 = std::make_shared("SnapshotNode2"); + auto expectedObject = tComponent.findSnapshotObject(snapshotNode, "pi"); - MockSnapshot.m_graphRoot->children.push_back(snapshotNode1); - MockSnapshot.m_graphRoot->children.push_back(snapshotNode2); + EXPECT_NE(expectedObject, nullptr); - auto expectedNode1 = mockNode.findSnapshotObject(MockSnapshot.m_graphRoot,"SnapshotNode1"); - auto expectedNode2 = mockNode.findSnapshotObject(MockSnapshot.m_graphRoot,"SnapshotNode2"); + EXPECT_EQ(tComponent.getName(), expectedObject->m_name); - EXPECT_EQ(snapshotNode1->m_name, expectedNode1->m_name); - EXPECT_EQ(snapshotNode2->m_name, expectedNode2->m_name); } TEST_F(Snapshot_test, saveSnapshot) diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index 45568d49730..b70981805be 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -758,11 +758,15 @@ Base::findSnapshotObject(const std::shared_ptr& pare { if (p.m_name == objectname) { - auto object = std::make_shared(p); - return object; + auto snapshotObject = std::make_shared(p); + return snapshotObject; } } - return nullptr; + msg_error("findSnapshotObject") << "SnapshotObject "<< objectname << " not found"; + auto defaultObject = std::make_shared(); + defaultObject->m_name = "Unknown object"; + + return defaultObject; } diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp index 3bc91522632..8e2d63d40ab 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp @@ -100,8 +100,10 @@ BaseNode::findSnapshotObject( const std::shared_ptr& return childObject; } } - - return nullptr; + msg_error("findSnapshotNode") << "SnapshotNode "<< objectname << " not found"; + auto defaultObject = std::make_shared(); + defaultObject->m_name = "Unknown node"; + return defaultObject; } /// Set the context of an object to this From df5ef4d5d972f3dd48bb64358e62558a0cc9f072 Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Tue, 3 Mar 2026 15:47:03 +0100 Subject: [PATCH 22/57] Add unit test (JSONSnapshot) --- .../simutest/objectmodel/Snapshot_test.cpp | 132 ++++++++++++++---- .../Core/src/sofa/core/objectmodel/Base.cpp | 1 - testfile.json | 41 ++++++ 3 files changed, 147 insertions(+), 27 deletions(-) create mode 100644 testfile.json diff --git a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp index dbd5ae82105..2b8848fa542 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp @@ -36,6 +36,9 @@ using sofa::core::objectmodel::SnapshotType; #include using sofa::simulation::SnapshotVisitor; +#include +using sofa::simulation::LoadSnapshotVisitor; + #include using sofa::core::objectmodel::Data; using sofa::core::objectmodel::BaseLink; @@ -43,6 +46,10 @@ using sofa::core::objectmodel::SingleLink ; using sofa::core::objectmodel::BaseSnapshot; using sofa::core::objectmodel::BaseNode; +#include +#include + + class TestComponent : public Base { public: @@ -71,22 +78,48 @@ class TestComponent : public Base return this->createSnapshotObject(parents); } - SOFA_CLASS(TestComponent,Base); + //SOFA_CLASS(TestComponent,Base); }; class MockSnapshotTest : public BaseSnapshot { public: void importSnapshot(const std::string filename) override - {} + { + SOFA_UNUSED(filename); + } void exportTo(const std::string filename) override - {} + { + SOFA_UNUSED(filename); + } void importFrom(std::string filename) override - {} + { + SOFA_UNUSED(filename); + } MockSnapshotTest() {} ~MockSnapshotTest() = default; + + void setupSnapshot() + { + this->m_graphRoot = std::make_shared("root"); + auto snapshotObject0 = std::make_shared("snapshotObject0"); + this->m_graphRoot->components.push_back(*snapshotObject0); + + auto snapshotNode1 = std::make_shared("snapshotNode1"); + auto snapshotNode2 = std::make_shared("snapshotNode2"); + + auto snapshotObject1 = std::make_shared("snapshotObject1"); + auto snapshotObject2 = std::make_shared("snapshotObject2"); + + snapshotNode1->components.push_back(*snapshotObject1); + snapshotNode2->components.push_back(*snapshotObject2); + + snapshotNode1->children.push_back(snapshotNode2); + + this->m_graphRoot->children.push_back(snapshotNode1); + } }; class Snapshot_test: public BaseSimulationTest @@ -95,28 +128,7 @@ class Snapshot_test: public BaseSimulationTest SceneInstance* c; Node* node {nullptr}; - Snapshot_test() - { - std::stringstream scene ; - scene << "" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" ; - c = new SceneInstance("xml", scene.str()) ; - c->initScene() ; - const Node* root = c->root.get() ; - Base* b = sofa::core::PathResolver::FindBaseFromPath(root, "@/child1/child2"); - node = dynamic_cast(b); - } + Snapshot_test() {} ~Snapshot_test() override { delete c; @@ -204,6 +216,8 @@ TEST_F(Snapshot_test, findSnapshotObject) TEST_F(Snapshot_test, saveSnapshot) { + // Test of saveSnapshot + TestComponent tComponent; auto snapshot = std::make_shared(); @@ -220,6 +234,8 @@ TEST_F(Snapshot_test, saveSnapshot) TEST_F(Snapshot_test, loadSnapshot) { + // Test of loadSnapshot + TestComponent tComponent; auto snapshot = std::make_shared(); @@ -233,3 +249,67 @@ TEST_F(Snapshot_test, loadSnapshot) EXPECT_EQ(tcomponent2.d_value.getValue(), 3.14f); } +TEST_F(Snapshot_test, BaseSnapshot) +{ + // Test of BaseSnapshot + // Test the structure and the behavior of a snapshot + + MockSnapshotTest MockSnapshot; + MockSnapshot.setupSnapshot(); + + EXPECT_EQ(MockSnapshot.m_graphRoot->m_name,"root"); + EXPECT_EQ(MockSnapshot.m_graphRoot->components[0].m_name,"snapshotObject0"); + EXPECT_EQ(MockSnapshot.m_graphRoot->children[0]->m_name,"snapshotNode1"); + EXPECT_EQ(MockSnapshot.m_graphRoot->children[0]->components[0].m_name,"snapshotObject1"); + EXPECT_EQ(MockSnapshot.m_graphRoot->children[0]->children[0]->m_name,"snapshotNode2"); + EXPECT_EQ(MockSnapshot.m_graphRoot->children[0]->children[0]->components[0].m_name,"snapshotObject2"); + +} + +TEST_F(Snapshot_test, JSONSnapshot) +{ + // TEST JSONSnapshot + // Test the behavior of the export and the import with JSON + + auto JsonSnapshotTest = createSnapshot(SnapshotType::JSON); + + const std::string scene = R"( + + + + + + + + + + )"; + + SceneInstance c("xml", scene) ; + c.initScene() ; + + Node* root = c.root.get() ; + + std::string path = std::filesystem::temp_directory_path() / "testfile.json"; + auto visitor = SnapshotVisitor(nullptr, *JsonSnapshotTest); + root->execute(visitor); + JsonSnapshotTest->exportTo(path); + EXPECT_NE(JsonSnapshotTest->m_graphRoot,nullptr); + std::cout << "JsonSnapshotTest : " << JsonSnapshotTest->m_graphRoot->m_name << std::endl; + + std::ifstream checkFile(path); + EXPECT_TRUE(checkFile.good()); + checkFile.close(); + + auto JsonSnapshotTest2 = createSnapshot(SnapshotType::JSON); + JsonSnapshotTest2->importFrom(path); + EXPECT_NE(JsonSnapshotTest2->m_graphRoot,nullptr); + + EXPECT_EQ(JsonSnapshotTest2->m_graphRoot->m_name,"Root"); + EXPECT_EQ(JsonSnapshotTest2->m_graphRoot->components[0].m_name,"Sofa.Component.StateContainer"); + EXPECT_EQ(JsonSnapshotTest2->m_graphRoot->components[1].m_name,"DefaultAnimationLoop1"); + EXPECT_EQ(JsonSnapshotTest2->m_graphRoot->components[2].m_name,"DefaultVisualManagerLoop1"); + EXPECT_EQ(JsonSnapshotTest2->m_graphRoot->children[0]->m_name,"child1"); + EXPECT_EQ(JsonSnapshotTest2->m_graphRoot->children[0]->components[0].m_name,"MechanicalObject1"); + +} \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index b70981805be..4cc419422d2 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -702,7 +702,6 @@ void Base::saveDataIn(BaseSnapshot::SnapshotObject& snapshot) const dataInfo.value.replace(pos, replaceValue.length(),newValue); pos = dataInfo.value.find(replaceValue, pos + newValue.length()); } - // Wait PR#5976 to remove snapshot.m_dataContainer.push_back(dataInfo); } diff --git a/testfile.json b/testfile.json new file mode 100644 index 00000000000..7fec0652566 --- /dev/null +++ b/testfile.json @@ -0,0 +1,41 @@ +{ + "children": [ + { + "children": [ + { + "children": [], + "components": [ + { + "datas": [], + "links": [], + "name": "snapshotObject2" + } + ], + "datas": [], + "links": [], + "name": "snapshotNode2" + } + ], + "components": [ + { + "datas": [], + "links": [], + "name": "snapshotObject1" + } + ], + "datas": [], + "links": [], + "name": "snapshotNode1" + } + ], + "components": [ + { + "datas": [], + "links": [], + "name": "snapshotObject0" + } + ], + "datas": [], + "links": [], + "name": "root" +} \ No newline at end of file From 32ccf0578ccdfaa247a42508a365d9e38a59314a Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Tue, 3 Mar 2026 16:37:59 +0100 Subject: [PATCH 23/57] cleaning - include --- .../simutest/objectmodel/Snapshot_test.py | 51 ------------------- .../sofa/core/objectmodel/JSONSnapshot.cpp | 13 ----- .../src/sofa/core/objectmodel/JSONSnapshot.h | 2 - .../sofa/core/objectmodel/MemorySnapshot.cpp | 20 ++------ .../sofa/core/objectmodel/MemorySnapshot.h | 8 --- .../sofa/core/objectmodel/SnapshotFactory.cpp | 3 -- .../sofa/core/objectmodel/SnapshotFactory.h | 3 -- .../sofa/simulation/LoadSnapshotVisitor.cpp | 25 --------- .../src/sofa/simulation/LoadSnapshotVisitor.h | 8 +-- .../src/sofa/simulation/SnapshotVisitor.cpp | 24 --------- .../src/sofa/simulation/SnapshotVisitor.h | 6 +-- 11 files changed, 6 insertions(+), 157 deletions(-) delete mode 100644 Sofa/framework/Core/simutest/objectmodel/Snapshot_test.py diff --git a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.py b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.py deleted file mode 100644 index 44a23a23374..00000000000 --- a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.py +++ /dev/null @@ -1,51 +0,0 @@ -# Required import for python -import Sofa -import SofaRuntime - - -def main(): - # Make sure to load all necessary libraries - SofaRuntime.importPlugin("Sofa.Component.StateContainer") - - # Call the above function to create the scene graph - root = Sofa.Core.Node("root") - createScene(root) - - # Once defined, initialization of the scene graph - Sofa.Simulation.initRoot(root) - - # Run the simulation for 10 steps - for iteration in range(10): - print(f'Iteration #{iteration}') - Sofa.Simulation.animate(root, root.dt.value) - - print("Simulation made 10 time steps. Done") - - -# Function called when the scene graph is being created -def createScene(root): - - root.addObject('RequiredPlugin', name='Sofa.Component.StateContainer') - - # Scene must now include a AnimationLoop - root.addObject('DefaultAnimationLoop') - - # Add new nodes and objects in the scene - node1 = root.addChild("Node1") - node1.addObject("MechanicalObject", template="Rigid3d", position="0 0 0 0 0 0 1", showObject="1") - - node2 = root.addChild("Node2") - node2.addObject("EulerImplicitSolver") - node2.addObject("CGLinearSolver", iterations="100", tolerance="1e-3", threshold="1e-3") - node1.addChild(node2) - - node3 = root.addChild("Node3") - node3.addObject("MechanicalObject", template="Rigid3d", position="0 0 0 0 0 0 1", showObject="1") - node3.addChild(node2) - - return root - - -# Function used only if this script is called from a python environment -if __name__ == '__main__': - main() diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp index c024b371073..bf1e6ef3391 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp @@ -20,26 +20,19 @@ * Contact information: contact@sofa-framework.org * ******************************************************************************/ #include -#include - #include #include #include #include #include -#include - - namespace sofa::core::objectmodel { - JSONSnapshot::JSONSnapshot() {} JSONSnapshot::~JSONSnapshot() = default; - void to_json(nlohmann::json& j, const BaseSnapshot::DataInfo& di ) { j.clear(); @@ -233,7 +226,6 @@ void JSONSnapshot::importFrom(const std::string filename) m_graphRoot = std::make_shared(); } - if (jsonRoot.is_object() && !jsonRoot.empty()) { from_json(jsonRoot, *m_graphRoot); @@ -245,11 +237,6 @@ void JSONSnapshot::importFrom(const std::string filename) } std::cout << "JSON imported successfully from: " << filename << std::endl; - - } - - - } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h index 4c73c393a9b..8385f7971a5 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h @@ -24,8 +24,6 @@ #include #include - - namespace sofa::core::objectmodel { diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp index 3fe6a66ab30..b6ce02d93c3 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp @@ -20,44 +20,32 @@ * Contact information: contact@sofa-framework.org * ******************************************************************************/ #include -#include - +#include #include #include #include #include -#include - -#include - namespace sofa::core::objectmodel { - MemorySnapshot::MemorySnapshot() {} MemorySnapshot::~MemorySnapshot() = default; void MemorySnapshot::exportTo(const std::string filename) { - std::cout << "exportTo" << std::endl; - + SOFA_UNUSED(filename); } void MemorySnapshot::importSnapshot(const std::string filename) { - //std::cout << "importSnapshot possible" << std::endl; - + SOFA_UNUSED(filename); } void MemorySnapshot::importFrom(const std::string filename) { - //std::cout << "importFrom" << std::endl; - + SOFA_UNUSED(filename); } - - - } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.h index ce5a9c94108..d81bb39318b 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.h @@ -23,9 +23,6 @@ #include #include - - - namespace sofa::core::objectmodel { @@ -34,16 +31,11 @@ class SOFA_CORE_API MemorySnapshot : public BaseSnapshot public: void importSnapshot(const std::string filename) override; - void exportTo(const std::string filename) override; void importFrom(std::string filename) override; MemorySnapshot(); ~MemorySnapshot(); - //nlohmann::json:: jNode = nlohmann::json::array(); - - - }; } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.cpp index 5a81adb000a..3da025bfc9e 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.cpp @@ -21,12 +21,9 @@ ******************************************************************************/ #pragma once #include -#include #include #include - - namespace sofa::core::objectmodel { diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.h b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.h index 8fd835ec242..da73e966da4 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.h @@ -20,9 +20,6 @@ * Contact information: contact@sofa-framework.org * ******************************************************************************/ #pragma once -//#include -// #include - #include namespace sofa::core::objectmodel diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp index a07ec40dfd8..059712293b8 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp @@ -22,34 +22,9 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -//#include -#include -#include -// #include -#include #include using sofa::core::objectmodel::SnapshotType; - namespace sofa::simulation { diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.h index 2fe41a083fc..133cb572083 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.h @@ -19,25 +19,19 @@ * * * Contact information: contact@sofa-framework.org * ******************************************************************************/ - - +#include #include #include #include -#include -#include - namespace sofa::simulation { - class SOFA_SIMULATION_CORE_API LoadSnapshotVisitor : public Visitor { protected: core::objectmodel::BaseSnapshot& m_snapshotContainer; - std::unordered_map> m_snapshotNodeMap; public: LoadSnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::BaseSnapshot& snapshot) : Visitor(eparams), m_snapshotContainer(snapshot) {} diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp index 30c1389f1d2..fad0a7f5c97 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp @@ -22,30 +22,6 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -//#include -#include -#include -// #include -#include #include using sofa::core::objectmodel::SnapshotType; #include diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h index 8fc6f7411cb..d11efff7a25 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h @@ -19,17 +19,13 @@ * * * Contact information: contact@sofa-framework.org * ******************************************************************************/ - - +#include #include #include #include -#include -#include #include #include - namespace sofa::simulation { From 8ffb12f6fd46cd631943042813fe489beb240099 Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Tue, 3 Mar 2026 16:44:49 +0100 Subject: [PATCH 24/57] Renaming SnapshotVisitor to SaveSnapshotVisitor --- Sofa/framework/Core/simutest/objectmodel/Base_test.cpp | 4 ++-- Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp | 6 +++--- Sofa/framework/Simulation/Core/CMakeLists.txt | 4 ++-- .../Core/src/sofa/simulation/LoadSnapshotVisitor.h | 2 +- .../{SnapshotVisitor.cpp => SaveSnapshotVisitor.cpp} | 6 +++--- .../simulation/{SnapshotVisitor.h => SaveSnapshotVisitor.h} | 6 +++--- 6 files changed, 14 insertions(+), 14 deletions(-) rename Sofa/framework/Simulation/Core/src/sofa/simulation/{SnapshotVisitor.cpp => SaveSnapshotVisitor.cpp} (94%) rename Sofa/framework/Simulation/Core/src/sofa/simulation/{SnapshotVisitor.h => SaveSnapshotVisitor.h} (88%) diff --git a/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp index a02e32cb159..05acfefa0d8 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp @@ -39,8 +39,8 @@ using sofa::defaulttype::Vec3Types; #include using sofa::core::objectmodel::SnapshotType; -#include -using sofa::simulation::SnapshotVisitor; +#include +using sofa::simulation::SaveSnapshotVisitor; namespace customns { diff --git a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp index 2b8848fa542..19564bbe6cf 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp @@ -33,8 +33,8 @@ using sofa::core::objectmodel::BaseObject; #include using sofa::core::objectmodel::SnapshotType; -#include -using sofa::simulation::SnapshotVisitor; +#include +using sofa::simulation::SaveSnapshotVisitor; #include using sofa::simulation::LoadSnapshotVisitor; @@ -291,7 +291,7 @@ TEST_F(Snapshot_test, JSONSnapshot) Node* root = c.root.get() ; std::string path = std::filesystem::temp_directory_path() / "testfile.json"; - auto visitor = SnapshotVisitor(nullptr, *JsonSnapshotTest); + auto visitor = SaveSnapshotVisitor(nullptr, *JsonSnapshotTest); root->execute(visitor); JsonSnapshotTest->exportTo(path); EXPECT_NE(JsonSnapshotTest->m_graphRoot,nullptr); diff --git a/Sofa/framework/Simulation/Core/CMakeLists.txt b/Sofa/framework/Simulation/Core/CMakeLists.txt index 5edb0200f91..162fdc4b391 100644 --- a/Sofa/framework/Simulation/Core/CMakeLists.txt +++ b/Sofa/framework/Simulation/Core/CMakeLists.txt @@ -45,7 +45,7 @@ set(HEADER_FILES ${SRC_ROOT}/SceneLoaderFactory.h ${SRC_ROOT}/Simulation.h ${SRC_ROOT}/SimulationLoop.h - ${SRC_ROOT}/SnapshotVisitor.h + ${SRC_ROOT}/SaveSnapshotVisitor.h ${SRC_ROOT}/SolveVisitor.h ${SRC_ROOT}/StateChangeVisitor.h ${SRC_ROOT}/TopologyChangeVisitor.h @@ -190,7 +190,7 @@ set(SOURCE_FILES ${SRC_ROOT}/SceneCheckRegistry.cpp ${SRC_ROOT}/SceneCheckMainRegistry.cpp ${SRC_ROOT}/Simulation.cpp - ${SRC_ROOT}/SnapshotVisitor.cpp + ${SRC_ROOT}/SaveSnapshotVisitor.cpp ${SRC_ROOT}/SolveVisitor.cpp ${SRC_ROOT}/StateChangeVisitor.cpp ${SRC_ROOT}/TopologyChangeVisitor.cpp diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.h index 133cb572083..e48a754bcc2 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.h @@ -38,7 +38,7 @@ class SOFA_SIMULATION_CORE_API LoadSnapshotVisitor : public Visitor void processObject(core::objectmodel::BaseObject* obj, std::shared_ptr parent); Result processNodeTopDown(simulation::Node* node) override; - const char* getClassName() const override { return "SnapshotVisitor"; } + const char* getClassName() const override { return "LoadSnapshotVisitor"; } }; diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.cpp similarity index 94% rename from Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp rename to Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.cpp index fad0a7f5c97..8acf2540cab 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.cpp @@ -19,7 +19,7 @@ * * * Contact information: contact@sofa-framework.org * ******************************************************************************/ -#include +#include #include #include #include @@ -30,7 +30,7 @@ using sofa::core::objectmodel::SnapshotType; namespace sofa::simulation { -void SnapshotVisitor::processObject( +void SaveSnapshotVisitor::processObject( core::objectmodel::BaseObject* obj, std::shared_ptr parent) { @@ -39,7 +39,7 @@ void SnapshotVisitor::processObject( parent->components.push_back(*snapshot); } -Visitor::Result SnapshotVisitor::processNodeTopDown(simulation::Node* node) +Visitor::Result SaveSnapshotVisitor::processNodeTopDown(simulation::Node* node) { const auto parents = node->getParents(); diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.h similarity index 88% rename from Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h rename to Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.h index d11efff7a25..02e77a62258 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotVisitor.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.h @@ -30,7 +30,7 @@ namespace sofa::simulation { -class SOFA_SIMULATION_CORE_API SnapshotVisitor : public Visitor +class SOFA_SIMULATION_CORE_API SaveSnapshotVisitor : public Visitor { protected: core::objectmodel::BaseSnapshot& m_snapshotContainer; @@ -38,14 +38,14 @@ class SOFA_SIMULATION_CORE_API SnapshotVisitor : public Visitor std::unordered_map> m_snapshotNodeMap; public: - SnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::BaseSnapshot& snapshot) : Visitor(eparams), m_snapshotContainer(snapshot) + SaveSnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::BaseSnapshot& snapshot) : Visitor(eparams), m_snapshotContainer(snapshot) { } void processObject(core::objectmodel::BaseObject* obj, std::shared_ptr parent); Result processNodeTopDown(simulation::Node* node) override; - const char* getClassName() const override { return "SnapshotVisitor"; } + const char* getClassName() const override { return "SaveSnapshotVisitor"; } }; From ae8b609536277718149c7524a190319e10c997b6 Mon Sep 17 00:00:00 2001 From: Lucas-TJ Date: Thu, 5 Mar 2026 16:33:05 +0100 Subject: [PATCH 25/57] remove Boost serialization --- Sofa/framework/Type/CMakeLists.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Sofa/framework/Type/CMakeLists.txt b/Sofa/framework/Type/CMakeLists.txt index eed1db524f4..ad991bb7e06 100644 --- a/Sofa/framework/Type/CMakeLists.txt +++ b/Sofa/framework/Type/CMakeLists.txt @@ -81,7 +81,7 @@ sofa_find_package(Sofa.Config REQUIRED) ## Boost (1.54.0 or higher) is now mandatory. set(BOOST_MIN_VERSION "1.54.0") set(Boost_NO_BOOST_CMAKE TRUE) -sofa_find_package(Boost ${BOOST_MIN_VERSION} QUIET COMPONENTS serialization) +sofa_find_package(Boost ${BOOST_MIN_VERSION} QUIET) if(NOT Boost_FOUND) if(WIN32) message(FATAL_ERROR "Boost (${BOOST_MIN_VERSION} or higher) is mandatory.\n" @@ -94,7 +94,7 @@ if(NOT Boost_FOUND) endif() endif() -sofa_find_package(Boost QUIET REQUIRED COMPONENTS serialization) +sofa_find_package(Boost QUIET REQUIRED) option(SOFA_USE_MIMALLOC "Use mimalloc to replace malloc (known to be more efficient, especially with MSVC)" OFF) if(SOFA_USE_MIMALLOC) @@ -105,7 +105,6 @@ add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) target_link_libraries(${PROJECT_NAME} PUBLIC Sofa.Config) target_link_libraries(${PROJECT_NAME} PUBLIC Boost::boost) -target_link_libraries(${PROJECT_NAME} PUBLIC Boost::serialization) if(mimalloc_FOUND) target_link_libraries(${PROJECT_NAME} PUBLIC mimalloc) From 306f78c6d5a49f2c5e44a913d99d66f603f9b55a Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Mon, 9 Mar 2026 10:29:47 +0100 Subject: [PATCH 26/57] split snapshotVisitors (LoadDataSnapshotVisitor and LoadLinkSnapshotVisitor) --- .../simutest/objectmodel/Snapshot_test.cpp | 104 ++++++++++++++---- .../Core/src/sofa/core/objectmodel/Base.cpp | 57 ++++++---- .../Core/src/sofa/core/objectmodel/Base.h | 5 +- .../sofa/core/objectmodel/BaseComponent.cpp | 8 ++ .../src/sofa/core/objectmodel/BaseNode.cpp | 7 +- .../Core/src/sofa/core/objectmodel/BaseNode.h | 2 +- .../sofa/core/objectmodel/BaseSnapshot.cpp | 15 +-- .../src/sofa/core/objectmodel/BaseSnapshot.h | 16 +-- .../sofa/core/objectmodel/JSONSnapshot.cpp | 11 +- .../src/sofa/core/objectmodel/JSONSnapshot.h | 1 - .../sofa/core/objectmodel/MemorySnapshot.cpp | 8 -- .../sofa/core/objectmodel/MemorySnapshot.h | 1 - Sofa/framework/Simulation/Core/CMakeLists.txt | 6 +- ...isitor.cpp => LoadDataSnapshotVisitor.cpp} | 20 ++-- .../sofa/simulation/LoadDataSnapshotVisitor.h | 45 ++++++++ .../simulation/LoadLinkSnapshotVisitor.cpp | 54 +++++++++ ...hotVisitor.h => LoadLinkSnapshotVisitor.h} | 9 +- .../sofa/simulation/SaveSnapshotVisitor.cpp | 6 +- .../Tutorials/Basic/TutorialBasicPendulum.scn | 4 +- 19 files changed, 261 insertions(+), 118 deletions(-) rename Sofa/framework/Simulation/Core/src/sofa/simulation/{LoadSnapshotVisitor.cpp => LoadDataSnapshotVisitor.cpp} (77%) create mode 100644 Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.h create mode 100644 Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.cpp rename Sofa/framework/Simulation/Core/src/sofa/simulation/{LoadSnapshotVisitor.h => LoadLinkSnapshotVisitor.h} (81%) diff --git a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp index 19564bbe6cf..7fea5869116 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp @@ -20,6 +20,8 @@ * Contact information: contact@sofa-framework.org * ******************************************************************************/ #include + +#include "gtest/gtest.h" using sofa::core::objectmodel::Base ; using sofa::core::objectmodel::ComponentState; @@ -36,8 +38,11 @@ using sofa::core::objectmodel::SnapshotType; #include using sofa::simulation::SaveSnapshotVisitor; -#include -using sofa::simulation::LoadSnapshotVisitor; +#include +using sofa::simulation::LoadDataSnapshotVisitor; + +#include +using sofa::simulation::LoadLinkSnapshotVisitor; #include using sofa::core::objectmodel::Data; @@ -52,8 +57,11 @@ using sofa::core::objectmodel::BaseNode; class TestComponent : public Base { + public: + SOFA_CLASS(TestComponent,Base); + Data d_value; TestComponent() @@ -78,16 +86,11 @@ class TestComponent : public Base return this->createSnapshotObject(parents); } - //SOFA_CLASS(TestComponent,Base); }; class MockSnapshotTest : public BaseSnapshot { public: - void importSnapshot(const std::string filename) override - { - SOFA_UNUSED(filename); - } void exportTo(const std::string filename) override { SOFA_UNUSED(filename); @@ -249,23 +252,6 @@ TEST_F(Snapshot_test, loadSnapshot) EXPECT_EQ(tcomponent2.d_value.getValue(), 3.14f); } -TEST_F(Snapshot_test, BaseSnapshot) -{ - // Test of BaseSnapshot - // Test the structure and the behavior of a snapshot - - MockSnapshotTest MockSnapshot; - MockSnapshot.setupSnapshot(); - - EXPECT_EQ(MockSnapshot.m_graphRoot->m_name,"root"); - EXPECT_EQ(MockSnapshot.m_graphRoot->components[0].m_name,"snapshotObject0"); - EXPECT_EQ(MockSnapshot.m_graphRoot->children[0]->m_name,"snapshotNode1"); - EXPECT_EQ(MockSnapshot.m_graphRoot->children[0]->components[0].m_name,"snapshotObject1"); - EXPECT_EQ(MockSnapshot.m_graphRoot->children[0]->children[0]->m_name,"snapshotNode2"); - EXPECT_EQ(MockSnapshot.m_graphRoot->children[0]->children[0]->components[0].m_name,"snapshotObject2"); - -} - TEST_F(Snapshot_test, JSONSnapshot) { // TEST JSONSnapshot @@ -312,4 +298,74 @@ TEST_F(Snapshot_test, JSONSnapshot) EXPECT_EQ(JsonSnapshotTest2->m_graphRoot->children[0]->m_name,"child1"); EXPECT_EQ(JsonSnapshotTest2->m_graphRoot->children[0]->components[0].m_name,"MechanicalObject1"); +} + +TEST_F(Snapshot_test, LoadLinkVisitor) +{ + auto JsonSnapshotTest = createSnapshot(SnapshotType::JSON); + + // const std::string scene = R"( + // + // + // + // + // + // + // + // + // + // )"; + + const std::string scene = R"( + + + + + + + + + + + + + + + + + + + + + + + + + + + )"; + + SceneInstance c("xml", scene) ; + c.initScene() ; + + Node* root = c.root.get() ; + + std::string path = std::filesystem::temp_directory_path() / "testfile.json"; + auto visitor = SaveSnapshotVisitor(nullptr, *JsonSnapshotTest); + root->execute(visitor); + JsonSnapshotTest->exportTo(path); + EXPECT_NE(JsonSnapshotTest->m_graphRoot,nullptr); + std::cout << "JsonSnapshotTest : " << JsonSnapshotTest->m_graphRoot->m_name << std::endl; + + std::ifstream checkFile(path); + EXPECT_TRUE(checkFile.good()); + checkFile.close(); + + auto loadvisitor = LoadDataSnapshotVisitor(nullptr, *JsonSnapshotTest); + root->execute(loadvisitor); + auto loadlinkvisitor = LoadLinkSnapshotVisitor(nullptr, *JsonSnapshotTest); + root->execute(loadlinkvisitor); + EXPECT_NE(JsonSnapshotTest->m_graphRoot,nullptr); } \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index 4cc419422d2..c2a2424a79c 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -685,8 +685,7 @@ int Base::getInstanciationSourceFilePos() const void Base::saveDataIn(BaseSnapshot::SnapshotObject& snapshot) const { - const auto& dataFields = this->getDataFields(); - for (const auto& data : dataFields) + for (const auto& dataFields = this->getDataFields(); const auto& data : dataFields) { BaseSnapshot::DataInfo dataInfo; dataInfo.name = data->getName(); @@ -709,14 +708,23 @@ void Base::saveDataIn(BaseSnapshot::SnapshotObject& snapshot) const void Base::saveLinksIn(BaseSnapshot::SnapshotObject& snapshot) const { - const auto& links = this->getLinks(); - - for (const auto& link : links) + for (const auto& links = this->getLinks(); const auto& link : links) { BaseSnapshot::LinkInfo linkInfo; linkInfo.name = link->getName(); linkInfo.type = link->getValueTypeString(); linkInfo.value = link->getValueString(); + // linkInfo.value = link->getLinkedPath(); + // linkInfo.value = link->getPath(); + + std::string replaceValue = "//"; + std::size_t pos = linkInfo.value.find(replaceValue); + while (pos != std::string::npos) + { + linkInfo.value.replace(pos, replaceValue.length(), ""); + pos = linkInfo.value.find(replaceValue, pos); + } + snapshot.m_linkContainer.push_back(linkInfo); } } @@ -728,7 +736,7 @@ std::shared_ptr Base::createSnapshotObject(std::vector>& parents) const { auto object = std::make_shared(); - for (auto p : parents) + for (const auto& p : parents) { if (p) { @@ -751,9 +759,9 @@ std::shared_ptr Base::saveSnapshot(std::vector -Base::findSnapshotObject(const std::shared_ptr& parents, const std::string objectname) +Base::findSnapshotObject(const std::shared_ptr& parents, const std::string& objectname) { - for (auto p : parents->components) + for (const auto& p : parents->components) { if (p.m_name == objectname) { @@ -769,12 +777,11 @@ Base::findSnapshotObject(const std::shared_ptr& pare } -void Base::loadSnapshot(const std::shared_ptr& snapshotObject) +void Base::loadDataSnapshot(const std::shared_ptr& snapshotObject) const { for (const auto& dataInfo : snapshotObject->m_dataContainer) { - auto data = this->findData(dataInfo.name); - if (data) + if (const auto data = this->findData(dataInfo.name)) { if( dataInfo.name != "loadedPlugins"&& dataInfo.name != "filename" && dataInfo.name != "texturename" && dataInfo.name != "pluginName") { @@ -782,18 +789,24 @@ void Base::loadSnapshot(const std::shared_ptr& sna } } } +} - // for (const auto& linkInfo : snapshotObject->m_linkContainer) - // { - // auto link = this->findLink(linkInfo.name); - // if (link) - // { - // std::cout << "link name : " << linkInfo.name << std::endl; - // std::cout << "link value : " << linkInfo.value << std::endl; - // link->read(linkInfo.value); - // } - // } -} +void Base::loadLinkSnapshot(const std::shared_ptr& snapshotObject) const +{ + for (const auto& linkInfo : snapshotObject->m_linkContainer) + { + if (const auto link = this->findLink(linkInfo.name)) + { + if(linkInfo.name != "odeSolver" && linkInfo.name != "linearSolver") + { + std::cout << "===========link name : " << linkInfo.name << std::endl; + std::cout << "===========link value : " << linkInfo.value << std::endl; + link->read(linkInfo.value); + } + + } + } +} } // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h index 833d9607ae4..1f2bdc21b12 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h @@ -365,7 +365,8 @@ class SOFA_CORE_API Base : public IntrusiveObject ///@} std::shared_ptr saveSnapshot(std::vector>& parents) const; - void loadSnapshot(const std::shared_ptr& snapshotObject); + void loadDataSnapshot(const std::shared_ptr& snapshotObject) const; + void loadLinkSnapshot(const std::shared_ptr& snapshotObject) const; protected: void saveDataIn(BaseSnapshot::SnapshotObject& snapshot) const; @@ -373,7 +374,7 @@ class SOFA_CORE_API Base : public IntrusiveObject //virtual void saveInternalStateIn(SnapshotObject& snapshot) const; virtual std::shared_ptr createSnapshotObject(std::vector>& parents) const; public : - virtual std::shared_ptr findSnapshotObject(const std::shared_ptr& parents, const std::string objectname); + virtual std::shared_ptr findSnapshotObject(const std::shared_ptr& parents, const std::string& objectname); protected: /// List of fields (Data instances) diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseComponent.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseComponent.cpp index 827aa9659bb..6d55bfb6d8e 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseComponent.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseComponent.cpp @@ -178,9 +178,17 @@ void BaseComponent::setSrc(const std::string &valueString, const BaseComponent * Base* BaseComponent::findLinkDestClass(const BaseClass* destType, const std::string& path, const BaseLink* link) { if (this->getContext() == BaseContext::getDefault()) + { + std::cout << "if BaseObject::findLinkDestClass" << std::endl; + std::cout << path << std::endl; return nullptr; + } else + { + std::cout << "else BaseObject::findLinkDestClass" << std::endl; + std::cout << path << std::endl; return this->getContext()->findLinkDestClass(destType, path, link); + } } diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp index 8e2d63d40ab..59b17c08f47 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp @@ -80,13 +80,13 @@ BaseNode::createSnapshotObject(std::vector -BaseNode::findSnapshotObject( const std::shared_ptr& parents, const std::string objectname) +BaseNode::findSnapshotObject( const std::shared_ptr& parents, const std::string& objectname) { if(parents->m_name == objectname) { return parents; } - for (auto p : parents->children) + for (const auto& p : parents->children) { if (p->m_name == objectname) { @@ -95,8 +95,7 @@ BaseNode::findSnapshotObject( const std::shared_ptr& } else { - auto childObject = findSnapshotObject(p, objectname); - if (childObject) + if (auto childObject = findSnapshotObject(p, objectname)) return childObject; } } diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.h index 9804e96d450..4a6668d018c 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.h @@ -132,7 +132,7 @@ class SOFA_CORE_API BaseNode : public virtual Base protected: std::shared_ptr createSnapshotObject(std::vector>& parents) const override; public: - std::shared_ptr findSnapshotObject(const std::shared_ptr& parents, const std::string objectname) override; + std::shared_ptr findSnapshotObject(const std::shared_ptr& parents, const std::string& objectname) override; private: virtual std::string internalGetPathName() const; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp index cc100c215aa..821aad1a013 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp @@ -20,23 +20,10 @@ * Contact information: contact@sofa-framework.org * ******************************************************************************/ #include -#include "BaseSnapshot.h" namespace sofa::core::objectmodel { -BaseSnapshot::BaseSnapshot() -{} +BaseSnapshot::BaseSnapshot() = default; BaseSnapshot::~BaseSnapshot() = default; - -void BaseSnapshot::printSnapshot() const -{ - std::cout << m_graphRoot->m_name << std::endl; - - for (auto& element : m_graphRoot->components) - { - std::cout << " Component name : " << element.m_name << std::endl; - } -} - } // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h index 1f1244a048a..7d017cd6717 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h @@ -21,9 +21,9 @@ ******************************************************************************/ #pragma once #include +#include #include #include -#include #include #include @@ -74,7 +74,7 @@ class SOFA_CORE_API BaseSnapshot } SnapshotObject() = default; - explicit SnapshotObject(const std::string& name) : m_name(name){} + explicit SnapshotObject(std::string name) : m_name(std::move(name)){} virtual ~SnapshotObject() = default; }; @@ -84,7 +84,7 @@ class SOFA_CORE_API BaseSnapshot std::vector components; std::vector> children; - void clear() + void clear() override { components.clear(); children.clear(); @@ -103,21 +103,17 @@ class SOFA_CORE_API BaseSnapshot } SnapshotNode() = default; - SnapshotNode(const std::string& name) : SnapshotObject(name) {} - SnapshotNode(const SnapshotObject& obj) : SnapshotObject(obj) {} + explicit SnapshotNode(const std::string& name) : SnapshotObject(name) {} + explicit SnapshotNode(const SnapshotObject& obj) : SnapshotObject(obj) {} - virtual ~SnapshotNode() noexcept = default; + ~SnapshotNode() noexcept override = default; }; std::shared_ptr m_graphRoot { nullptr }; - virtual void importSnapshot(const std::string filename) = 0; - virtual void exportTo(const std::string filename) = 0; virtual void importFrom(std::string filename) = 0; - void printSnapshot() const; - BaseSnapshot(); virtual ~BaseSnapshot() = 0; }; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp index bf1e6ef3391..63b7ba82619 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp @@ -22,15 +22,12 @@ #include #include #include -#include #include -#include namespace sofa::core::objectmodel { -JSONSnapshot::JSONSnapshot() -{} +JSONSnapshot::JSONSnapshot() = default; JSONSnapshot::~JSONSnapshot() = default; void to_json(nlohmann::json& j, const BaseSnapshot::DataInfo& di ) @@ -109,12 +106,6 @@ void JSONSnapshot::exportTo(const std::string filename) file.close(); } -void JSONSnapshot::importSnapshot(const std::string filename) -{ - std::cout << "importSnapshot" << std::endl; -} - - void from_json(const nlohmann::json& j, BaseSnapshot::DataInfo& di) { di.name = j.value("name", ""); diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h index 8385f7971a5..5e69ab3ed13 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h @@ -31,7 +31,6 @@ class SOFA_CORE_API JSONSnapshot : public BaseSnapshot { public: - void importSnapshot(const std::string filename) override; void exportTo(const std::string filename) override; void importFrom(std::string filename) override; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp index b6ce02d93c3..dfff79435c4 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp @@ -20,11 +20,8 @@ * Contact information: contact@sofa-framework.org * ******************************************************************************/ #include -#include #include #include -#include -#include namespace sofa::core::objectmodel { @@ -38,11 +35,6 @@ void MemorySnapshot::exportTo(const std::string filename) SOFA_UNUSED(filename); } -void MemorySnapshot::importSnapshot(const std::string filename) -{ - SOFA_UNUSED(filename); -} - void MemorySnapshot::importFrom(const std::string filename) { SOFA_UNUSED(filename); diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.h index d81bb39318b..f064f2c82f8 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.h @@ -30,7 +30,6 @@ class SOFA_CORE_API MemorySnapshot : public BaseSnapshot { public: - void importSnapshot(const std::string filename) override; void exportTo(const std::string filename) override; void importFrom(std::string filename) override; diff --git a/Sofa/framework/Simulation/Core/CMakeLists.txt b/Sofa/framework/Simulation/Core/CMakeLists.txt index 162fdc4b391..df57bcc5059 100644 --- a/Sofa/framework/Simulation/Core/CMakeLists.txt +++ b/Sofa/framework/Simulation/Core/CMakeLists.txt @@ -27,7 +27,8 @@ set(HEADER_FILES ${SRC_ROOT}/InitVisitor.h ${SRC_ROOT}/IntegrateBeginEvent.h ${SRC_ROOT}/IntegrateEndEvent.h - ${SRC_ROOT}/LoadSnapshotVisitor.h + ${SRC_ROOT}/LoadDataSnapshotVisitor.h + ${SRC_ROOT}/LoadLinkSnapshotVisitor.h ${SRC_ROOT}/MechanicalOperations.h ${SRC_ROOT}/MechanicalVPrintVisitor.h ${SRC_ROOT}/MechanicalVisitor.h @@ -171,7 +172,8 @@ set(SOURCE_FILES ${SRC_ROOT}/InitVisitor.cpp ${SRC_ROOT}/IntegrateBeginEvent.cpp ${SRC_ROOT}/IntegrateEndEvent.cpp - ${SRC_ROOT}/LoadSnapshotVisitor.cpp + ${SRC_ROOT}/LoadDataSnapshotVisitor.cpp + ${SRC_ROOT}/LoadLinkSnapshotVisitor.cpp ${SRC_ROOT}/MappingGraph.cpp ${SRC_ROOT}/MechanicalOperations.cpp ${SRC_ROOT}/MechanicalVPrintVisitor.cpp diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.cpp similarity index 77% rename from Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp rename to Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.cpp index 059712293b8..37889e4b594 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.cpp @@ -19,7 +19,7 @@ * * * Contact information: contact@sofa-framework.org * ******************************************************************************/ -#include +#include #include #include #include @@ -28,22 +28,22 @@ using sofa::core::objectmodel::SnapshotType; namespace sofa::simulation { -void LoadSnapshotVisitor::processObject( +void LoadDataSnapshotVisitor::processObject( core::objectmodel::BaseObject* obj, - std::shared_ptr parent + const std::shared_ptr& parent ) { auto snapshotObject = obj->findSnapshotObject(parent, obj->getName()); - obj->loadSnapshot(snapshotObject); + obj->loadDataSnapshot(snapshotObject); } -Visitor::Result LoadSnapshotVisitor::processNodeTopDown(simulation::Node* node) -{ - auto snapshotObject = node->findSnapshotObject(m_snapshotContainer.m_graphRoot, node->getName()); - - auto SnapshotNode = std::dynamic_pointer_cast(snapshotObject); - node->loadSnapshot(SnapshotNode); +Visitor::Result LoadDataSnapshotVisitor::processNodeTopDown(simulation::Node* node) +{ + const auto snapshotObject = node->findSnapshotObject(m_snapshotContainer.m_graphRoot, node->getName()); + const auto SnapshotNode = std::dynamic_pointer_cast(snapshotObject); + node->loadDataSnapshot(SnapshotNode); + std::cout << "test object.getSize : " << node->object.getSize() << std::endl; for (simulation::Node::ObjectIterator it = node->object.begin(); it != node->object.end(); ++it) { this->processObject(it->get(), SnapshotNode); diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.h new file mode 100644 index 00000000000..0126fc18f72 --- /dev/null +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.h @@ -0,0 +1,45 @@ +/****************************************************************************** +* 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 * +******************************************************************************/ +#pragma once +#include +#include + +namespace sofa::simulation +{ + +class SOFA_SIMULATION_CORE_API LoadDataSnapshotVisitor : public Visitor +{ +protected: + core::objectmodel::BaseSnapshot& m_snapshotContainer; + +public: + LoadDataSnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::BaseSnapshot& snapshot) : Visitor(eparams), m_snapshotContainer(snapshot) {} + + void processObject(core::objectmodel::BaseObject* obj, const std::shared_ptr& parent); + + Result processNodeTopDown(simulation::Node* node) override; + const char* getClassName() const override { return "LoadDataSnapshotVisitor"; } + +}; + +} // namespace sofa::simulation + diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.cpp new file mode 100644 index 00000000000..51adddf3226 --- /dev/null +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.cpp @@ -0,0 +1,54 @@ +/****************************************************************************** +* 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 +using sofa::core::objectmodel::SnapshotType; + +namespace sofa::simulation +{ + +void LoadLinkSnapshotVisitor::processObject( + core::objectmodel::BaseObject* obj, + const std::shared_ptr& parent +) +{ + const auto snapshotObject = obj->findSnapshotObject(parent, obj->getName()); + obj->loadLinkSnapshot(snapshotObject); +} + +Visitor::Result LoadLinkSnapshotVisitor::processNodeTopDown(simulation::Node* node) +{ + const auto snapshotObject = node->findSnapshotObject(m_snapshotContainer.m_graphRoot, node->getName()); + const auto SnapshotNode = std::dynamic_pointer_cast(snapshotObject); + node->loadLinkSnapshot(SnapshotNode); + + for (simulation::Node::ObjectIterator it = node->object.begin(); it != node->object.end(); ++it) + { + this->processObject(it->get(), SnapshotNode); + } + return RESULT_CONTINUE; +} + +} // namespace sofa::simulation + diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.h similarity index 81% rename from Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.h rename to Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.h index e48a754bcc2..c17241ba8fd 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.h @@ -19,6 +19,7 @@ * * * Contact information: contact@sofa-framework.org * ******************************************************************************/ +#pragma once #include #include #include @@ -27,18 +28,18 @@ namespace sofa::simulation { -class SOFA_SIMULATION_CORE_API LoadSnapshotVisitor : public Visitor +class SOFA_SIMULATION_CORE_API LoadLinkSnapshotVisitor : public Visitor { protected: core::objectmodel::BaseSnapshot& m_snapshotContainer; public: - LoadSnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::BaseSnapshot& snapshot) : Visitor(eparams), m_snapshotContainer(snapshot) {} + LoadLinkSnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::BaseSnapshot& snapshot) : Visitor(eparams), m_snapshotContainer(snapshot) {} - void processObject(core::objectmodel::BaseObject* obj, std::shared_ptr parent); + void processObject(core::objectmodel::BaseObject* obj, const std::shared_ptr& parent); Result processNodeTopDown(simulation::Node* node) override; - const char* getClassName() const override { return "LoadSnapshotVisitor"; } + const char* getClassName() const override { return "LoadLinkSnapshotVisitor"; } }; diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.cpp index 8acf2540cab..84bdf0cc531 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.cpp @@ -35,7 +35,7 @@ void SaveSnapshotVisitor::processObject( std::shared_ptr parent) { std::vector> parents; - auto snapshot = obj->saveSnapshot(parents); + const auto snapshot = obj->saveSnapshot(parents); parent->components.push_back(*snapshot); } @@ -53,8 +53,8 @@ Visitor::Result SaveSnapshotVisitor::processNodeTopDown(simulation::Node* node) } } - auto snapshot = node->saveSnapshot(snapshotParents); - auto SnapshotNode = std::dynamic_pointer_cast(snapshot); + const auto snapshot = node->saveSnapshot(snapshotParents); + const auto SnapshotNode = std::dynamic_pointer_cast(snapshot); if (SnapshotNode) { m_snapshotNodeMap[node] = SnapshotNode; diff --git a/examples/Tutorials/Basic/TutorialBasicPendulum.scn b/examples/Tutorials/Basic/TutorialBasicPendulum.scn index ba50111ce2e..3488f8e33b9 100644 --- a/examples/Tutorials/Basic/TutorialBasicPendulum.scn +++ b/examples/Tutorials/Basic/TutorialBasicPendulum.scn @@ -13,8 +13,8 @@ - - + + Date: Mon, 16 Mar 2026 11:47:48 +0100 Subject: [PATCH 27/57] fix in a test --- Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp index 7fea5869116..a251a2df46c 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp @@ -247,7 +247,7 @@ TEST_F(Snapshot_test, loadSnapshot) TestComponent tcomponent2; tcomponent2.d_value.setValue(0.0f); - tcomponent2.loadSnapshot(snapshot); + tcomponent2.loadDataSnapshot(snapshot); EXPECT_EQ(tcomponent2.d_value.getValue(), 3.14f); } From fd6c83e683212e9418c06fae55345ad73c62bbe7 Mon Sep 17 00:00:00 2001 From: Lucas-TJ Date: Thu, 19 Mar 2026 17:21:27 +0100 Subject: [PATCH 28/57] update 19/03 --- .../Core/src/sofa/core/objectmodel/Base.cpp | 43 ++++++++++++++----- .../sofa/core/objectmodel/BaseComponent.cpp | 4 -- .../src/sofa/core/objectmodel/BaseNode.cpp | 24 ++++------- .../simulation/LoadDataSnapshotVisitor.cpp | 4 +- 4 files changed, 45 insertions(+), 30 deletions(-) diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index c2a2424a79c..32128e86977 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -717,13 +717,13 @@ void Base::saveLinksIn(BaseSnapshot::SnapshotObject& snapshot) const // linkInfo.value = link->getLinkedPath(); // linkInfo.value = link->getPath(); - std::string replaceValue = "//"; - std::size_t pos = linkInfo.value.find(replaceValue); - while (pos != std::string::npos) - { - linkInfo.value.replace(pos, replaceValue.length(), ""); - pos = linkInfo.value.find(replaceValue, pos); - } + // std::string replaceValue = "//"; + // std::size_t pos = linkInfo.value.find(replaceValue); + // while (pos != std::string::npos) + // { + // linkInfo.value.replace(pos, replaceValue.length(), ""); + // pos = linkInfo.value.find(replaceValue, pos); + // } snapshot.m_linkContainer.push_back(linkInfo); } @@ -793,15 +793,38 @@ void Base::loadDataSnapshot(const std::shared_ptr& void Base::loadLinkSnapshot(const std::shared_ptr& snapshotObject) const { + //if ( this->getClassName() != "Node") for (const auto& linkInfo : snapshotObject->m_linkContainer) { if (const auto link = this->findLink(linkInfo.name)) { if(linkInfo.name != "odeSolver" && linkInfo.name != "linearSolver") { - std::cout << "===========link name : " << linkInfo.name << std::endl; - std::cout << "===========link value : " << linkInfo.value << std::endl; - link->read(linkInfo.value); + // std::cout << "===========link name : " << linkInfo.name << std::endl; + // std::cout << "===========link value : " << linkInfo.value << std::endl; + + // link->read(linkInfo.value); + + // Idea : Compare links in the snapshot and in the simulation, and change/add targets to the link + std::vector newSublinks = helper::split(linkInfo.value, ' '); + std::vector currentSublinks = helper::split(link->getValueString(), ' '); + + for (const auto& subLink : newSublinks) + { + Base* obj = PathResolver::FindBaseFromClassAndPath(link->getOwner(), link->getDestClass(), subLink); + auto it = std::ranges::find(currentSublinks, subLink); + if (it != currentSublinks.end()) { + // subLink is in currentSublinks + const size_t index = std::distance(currentSublinks.begin(), it); + link->set(obj,index); + } + else { + // subLink is not in currentSublinks + link->add(obj,subLink); + } + } + + } } diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseComponent.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseComponent.cpp index 6d55bfb6d8e..b632cf093c6 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseComponent.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseComponent.cpp @@ -179,14 +179,10 @@ Base* BaseComponent::findLinkDestClass(const BaseClass* destType, const std::str { if (this->getContext() == BaseContext::getDefault()) { - std::cout << "if BaseObject::findLinkDestClass" << std::endl; - std::cout << path << std::endl; return nullptr; } else { - std::cout << "else BaseObject::findLinkDestClass" << std::endl; - std::cout << path << std::endl; return this->getContext()->findLinkDestClass(destType, path, link); } } diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp index 59b17c08f47..256b325ec3a 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp @@ -82,27 +82,21 @@ BaseNode::createSnapshotObject(std::vector BaseNode::findSnapshotObject( const std::shared_ptr& parents, const std::string& objectname) { + if (!parents) return nullptr; + if(parents->m_name == objectname) { return parents; } - for (const auto& p : parents->children) + + for (const auto& child : parents->children) { - if (p->m_name == objectname) - { - auto nodeObject = std::make_shared(*p); - return nodeObject; - } - else - { - if (auto childObject = findSnapshotObject(p, objectname)) - return childObject; - } + if (auto result = this->findSnapshotObject(child, objectname)) + return result; + } - msg_error("findSnapshotNode") << "SnapshotNode "<< objectname << " not found"; - auto defaultObject = std::make_shared(); - defaultObject->m_name = "Unknown node"; - return defaultObject; + + return nullptr; } /// Set the context of an object to this diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.cpp index 37889e4b594..057fba578e3 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.cpp @@ -40,7 +40,9 @@ void LoadDataSnapshotVisitor::processObject( Visitor::Result LoadDataSnapshotVisitor::processNodeTopDown(simulation::Node* node) { const auto snapshotObject = node->findSnapshotObject(m_snapshotContainer.m_graphRoot, node->getName()); - + if (!snapshotObject) + msg_error("findSnapshotNode") << "SnapshotNode "<< node->getName() << " not found in "; + std::string nodeName = node->getName(); const auto SnapshotNode = std::dynamic_pointer_cast(snapshotObject); node->loadDataSnapshot(SnapshotNode); std::cout << "test object.getSize : " << node->object.getSize() << std::endl; From 18512b0a1e610b3160b5b19492d25d26eeb44b4f Mon Sep 17 00:00:00 2001 From: Lucas-TJ Date: Thu, 19 Mar 2026 17:40:02 +0100 Subject: [PATCH 29/57] rename BaseSnapshot to Snapshot --- Sofa/framework/Core/CMakeLists.txt | 4 +- .../simutest/objectmodel/Snapshot_test.cpp | 38 +++++++++---------- .../Core/src/sofa/core/objectmodel/Base.cpp | 32 ++++++++-------- .../Core/src/sofa/core/objectmodel/Base.h | 16 ++++---- .../src/sofa/core/objectmodel/BaseNode.cpp | 12 +++--- .../Core/src/sofa/core/objectmodel/BaseNode.h | 6 +-- .../sofa/core/objectmodel/JSONSnapshot.cpp | 32 ++++++++-------- .../src/sofa/core/objectmodel/JSONSnapshot.h | 4 +- .../sofa/core/objectmodel/MemorySnapshot.h | 4 +- .../{BaseSnapshot.cpp => Snapshot.cpp} | 6 +-- .../{BaseSnapshot.h => Snapshot.h} | 10 ++--- .../sofa/core/objectmodel/SnapshotFactory.cpp | 2 +- .../sofa/core/objectmodel/SnapshotFactory.h | 4 +- .../simulation/LoadDataSnapshotVisitor.cpp | 4 +- .../sofa/simulation/LoadDataSnapshotVisitor.h | 6 +-- .../simulation/LoadLinkSnapshotVisitor.cpp | 4 +- .../sofa/simulation/LoadLinkSnapshotVisitor.h | 6 +-- .../sofa/simulation/SaveSnapshotVisitor.cpp | 8 ++-- .../src/sofa/simulation/SaveSnapshotVisitor.h | 8 ++-- 19 files changed, 103 insertions(+), 103 deletions(-) rename Sofa/framework/Core/src/sofa/core/objectmodel/{BaseSnapshot.cpp => Snapshot.cpp} (93%) rename Sofa/framework/Core/src/sofa/core/objectmodel/{BaseSnapshot.h => Snapshot.h} (94%) diff --git a/Sofa/framework/Core/CMakeLists.txt b/Sofa/framework/Core/CMakeLists.txt index 8e58f72d0df..8c073a7bccd 100644 --- a/Sofa/framework/Core/CMakeLists.txt +++ b/Sofa/framework/Core/CMakeLists.txt @@ -159,7 +159,7 @@ set(HEADER_FILES ${SRC_ROOT}/objectmodel/BaseLink.h ${SRC_ROOT}/objectmodel/BaseNode.h ${SRC_ROOT}/objectmodel/BaseObjectDescription.h - ${SRC_ROOT}/objectmodel/BaseSnapshot.h + ${SRC_ROOT}/objectmodel/Snapshot.h ${SRC_ROOT}/objectmodel/ClassInfo.h ${SRC_ROOT}/objectmodel/ComponentState.h ${SRC_ROOT}/objectmodel/ConfigurationSetting.h @@ -313,7 +313,7 @@ set(SOURCE_FILES ${SRC_ROOT}/objectmodel/BaseLink.cpp ${SRC_ROOT}/objectmodel/BaseNode.cpp ${SRC_ROOT}/objectmodel/BaseObjectDescription.cpp - ${SRC_ROOT}/objectmodel/BaseSnapshot.cpp + ${SRC_ROOT}/objectmodel/Snapshot.cpp ${SRC_ROOT}/objectmodel/ClassInfo.cpp ${SRC_ROOT}/objectmodel/ComponentState.cpp ${SRC_ROOT}/objectmodel/ConfigurationSetting.cpp diff --git a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp index a251a2df46c..30f5afd468d 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp @@ -48,7 +48,7 @@ using sofa::simulation::LoadLinkSnapshotVisitor; using sofa::core::objectmodel::Data; using sofa::core::objectmodel::BaseLink; using sofa::core::objectmodel::SingleLink ; -using sofa::core::objectmodel::BaseSnapshot; +using sofa::core::objectmodel::Snapshot; using sofa::core::objectmodel::BaseNode; #include @@ -70,17 +70,17 @@ class TestComponent : public Base this->setName("pi"); } - void saveData(BaseSnapshot::SnapshotObject& snapshot) + void saveData(Snapshot::SnapshotObject& snapshot) { this->saveDataIn(snapshot); } - void saveLinks(BaseSnapshot::SnapshotObject& snapshot) + void saveLinks(Snapshot::SnapshotObject& snapshot) { this->saveLinksIn(snapshot); } - std::shared_ptr createSnapshotObjectTest(std::vector>& parents) const + std::shared_ptr createSnapshotObjectTest(std::vector>& parents) const { return this->createSnapshotObject(parents); @@ -88,7 +88,7 @@ class TestComponent : public Base }; -class MockSnapshotTest : public BaseSnapshot +class MockSnapshotTest : public Snapshot { public: void exportTo(const std::string filename) override @@ -106,15 +106,15 @@ class MockSnapshotTest : public BaseSnapshot void setupSnapshot() { - this->m_graphRoot = std::make_shared("root"); - auto snapshotObject0 = std::make_shared("snapshotObject0"); + this->m_graphRoot = std::make_shared("root"); + auto snapshotObject0 = std::make_shared("snapshotObject0"); this->m_graphRoot->components.push_back(*snapshotObject0); - auto snapshotNode1 = std::make_shared("snapshotNode1"); - auto snapshotNode2 = std::make_shared("snapshotNode2"); + auto snapshotNode1 = std::make_shared("snapshotNode1"); + auto snapshotNode2 = std::make_shared("snapshotNode2"); - auto snapshotObject1 = std::make_shared("snapshotObject1"); - auto snapshotObject2 = std::make_shared("snapshotObject2"); + auto snapshotObject1 = std::make_shared("snapshotObject1"); + auto snapshotObject2 = std::make_shared("snapshotObject2"); snapshotNode1->components.push_back(*snapshotObject1); snapshotNode2->components.push_back(*snapshotObject2); @@ -147,7 +147,7 @@ TEST_F(Snapshot_test, saveDataIn) // Check if the snapshot contains the component with expected data TestComponent tComponent; - auto snapshot = std::make_shared(); + auto snapshot = std::make_shared(); tComponent.saveData(*snapshot); for (auto& data : snapshot->m_dataContainer) { @@ -170,7 +170,7 @@ TEST_F(Snapshot_test, createSnapshotObject) // To verify, A name and some data are added to the SnapshotObject TestComponent tComponent; - std::vector> snapshotParents; + std::vector> snapshotParents; auto snapshotObject = tComponent.createSnapshotObjectTest(snapshotParents); snapshotObject->m_name = "snapshotObject"; @@ -202,8 +202,8 @@ TEST_F(Snapshot_test, findSnapshotObject) TestComponent tComponent; - auto snapshotNode = std::make_shared("root"); - std::vector> snapshotParents; + auto snapshotNode = std::make_shared("root"); + std::vector> snapshotParents; snapshotParents.push_back(snapshotNode); auto snapshot = tComponent.saveSnapshot(snapshotParents); @@ -223,8 +223,8 @@ TEST_F(Snapshot_test, saveSnapshot) TestComponent tComponent; - auto snapshot = std::make_shared(); - std::vector> snapshotParents; + auto snapshot = std::make_shared(); + std::vector> snapshotParents; snapshot = tComponent.saveSnapshot(snapshotParents); EXPECT_EQ(snapshot->m_name, "pi"); @@ -241,8 +241,8 @@ TEST_F(Snapshot_test, loadSnapshot) TestComponent tComponent; - auto snapshot = std::make_shared(); - std::vector> snapshotParents; + auto snapshot = std::make_shared(); + std::vector> snapshotParents; snapshot = tComponent.saveSnapshot(snapshotParents); TestComponent tcomponent2; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index 32128e86977..88540b7238d 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -22,7 +22,7 @@ #define SOFA_CORE_OBJECTMODEL_BASE_CPP #include -#include +#include #include #include #include @@ -683,11 +683,11 @@ int Base::getInstanciationSourceFilePos() const return m_instanciationSourceFilePos; } -void Base::saveDataIn(BaseSnapshot::SnapshotObject& snapshot) const +void Base::saveDataIn(Snapshot::SnapshotObject& snapshot) const { for (const auto& dataFields = this->getDataFields(); const auto& data : dataFields) { - BaseSnapshot::DataInfo dataInfo; + Snapshot::DataInfo dataInfo; dataInfo.name = data->getName(); dataInfo.type = data->getValueTypeString(); dataInfo.value = data->getValueString(); @@ -706,11 +706,11 @@ void Base::saveDataIn(BaseSnapshot::SnapshotObject& snapshot) const } } -void Base::saveLinksIn(BaseSnapshot::SnapshotObject& snapshot) const +void Base::saveLinksIn(Snapshot::SnapshotObject& snapshot) const { for (const auto& links = this->getLinks(); const auto& link : links) { - BaseSnapshot::LinkInfo linkInfo; + Snapshot::LinkInfo linkInfo; linkInfo.name = link->getName(); linkInfo.type = link->getValueTypeString(); linkInfo.value = link->getValueString(); @@ -729,13 +729,13 @@ void Base::saveLinksIn(BaseSnapshot::SnapshotObject& snapshot) const } } -// void Base::saveInternalStateIn(BaseSnapshot::SnapshotObject& snapshot) const +// void Base::saveInternalStateIn(Snapshot::SnapshotObject& snapshot) const // {} -std::shared_ptr -Base::createSnapshotObject(std::vector>& parents) const +std::shared_ptr +Base::createSnapshotObject(std::vector>& parents) const { - auto object = std::make_shared(); + auto object = std::make_shared(); for (const auto& p : parents) { if (p) @@ -746,7 +746,7 @@ Base::createSnapshotObject(std::vector Base::saveSnapshot(std::vector>& parents) const +std::shared_ptr Base::saveSnapshot(std::vector>& parents) const { const auto snapshotObject = createSnapshotObject(parents); snapshotObject->m_name = this->getName(); @@ -758,26 +758,26 @@ std::shared_ptr Base::saveSnapshot(std::vector -Base::findSnapshotObject(const std::shared_ptr& parents, const std::string& objectname) +std::shared_ptr +Base::findSnapshotObject(const std::shared_ptr& parents, const std::string& objectname) { for (const auto& p : parents->components) { if (p.m_name == objectname) { - auto snapshotObject = std::make_shared(p); + auto snapshotObject = std::make_shared(p); return snapshotObject; } } msg_error("findSnapshotObject") << "SnapshotObject "<< objectname << " not found"; - auto defaultObject = std::make_shared(); + auto defaultObject = std::make_shared(); defaultObject->m_name = "Unknown object"; return defaultObject; } -void Base::loadDataSnapshot(const std::shared_ptr& snapshotObject) const +void Base::loadDataSnapshot(const std::shared_ptr& snapshotObject) const { for (const auto& dataInfo : snapshotObject->m_dataContainer) { @@ -791,7 +791,7 @@ void Base::loadDataSnapshot(const std::shared_ptr& } } -void Base::loadLinkSnapshot(const std::shared_ptr& snapshotObject) const +void Base::loadLinkSnapshot(const std::shared_ptr& snapshotObject) const { //if ( this->getClassName() != "Node") for (const auto& linkInfo : snapshotObject->m_linkContainer) diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h index 1f2bdc21b12..66f96d82e7c 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h @@ -44,7 +44,7 @@ #include -#include +#include #define SOFA_BASE_CAST_IMPLEMENTATION(CLASSNAME) \ virtual const CLASSNAME* to##CLASSNAME() const override { return this; } \ @@ -364,17 +364,17 @@ class SOFA_CORE_API Base : public IntrusiveObject ///@} - std::shared_ptr saveSnapshot(std::vector>& parents) const; - void loadDataSnapshot(const std::shared_ptr& snapshotObject) const; - void loadLinkSnapshot(const std::shared_ptr& snapshotObject) const; + std::shared_ptr saveSnapshot(std::vector>& parents) const; + void loadDataSnapshot(const std::shared_ptr& snapshotObject) const; + void loadLinkSnapshot(const std::shared_ptr& snapshotObject) const; protected: - void saveDataIn(BaseSnapshot::SnapshotObject& snapshot) const; - void saveLinksIn(BaseSnapshot::SnapshotObject& snapshot) const; + void saveDataIn(Snapshot::SnapshotObject& snapshot) const; + void saveLinksIn(Snapshot::SnapshotObject& snapshot) const; //virtual void saveInternalStateIn(SnapshotObject& snapshot) const; - virtual std::shared_ptr createSnapshotObject(std::vector>& parents) const; + virtual std::shared_ptr createSnapshotObject(std::vector>& parents) const; public : - virtual std::shared_ptr findSnapshotObject(const std::shared_ptr& parents, const std::string& objectname); + virtual std::shared_ptr findSnapshotObject(const std::shared_ptr& parents, const std::string& objectname); protected: /// List of fields (Data instances) diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp index 256b325ec3a..774b9fdf85a 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp @@ -19,7 +19,7 @@ * * * Contact information: contact@sofa-framework.org * ******************************************************************************/ -#include +#include #include #include #include @@ -64,10 +64,10 @@ core::visual::VisualLoop* BaseNode::getVisualLoop() const return this->getContext()->get(); } -std::shared_ptr -BaseNode::createSnapshotObject(std::vector>& parents) const +std::shared_ptr +BaseNode::createSnapshotObject(std::vector>& parents) const { - auto nodeObject = std::make_shared(); + auto nodeObject = std::make_shared(); for (auto p : parents) { if (p) @@ -79,8 +79,8 @@ BaseNode::createSnapshotObject(std::vector -BaseNode::findSnapshotObject( const std::shared_ptr& parents, const std::string& objectname) +std::shared_ptr +BaseNode::findSnapshotObject( const std::shared_ptr& parents, const std::string& objectname) { if (!parents) return nullptr; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.h index 4a6668d018c..9c2bf3c27b2 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.h @@ -24,7 +24,7 @@ #include #include #include -#include +#include namespace sofa::core::objectmodel { @@ -130,9 +130,9 @@ class SOFA_CORE_API BaseNode : public virtual Base virtual core::visual::VisualLoop* getVisualLoop() const; protected: - std::shared_ptr createSnapshotObject(std::vector>& parents) const override; + std::shared_ptr createSnapshotObject(std::vector>& parents) const override; public: - std::shared_ptr findSnapshotObject(const std::shared_ptr& parents, const std::string& objectname) override; + std::shared_ptr findSnapshotObject(const std::shared_ptr& parents, const std::string& objectname) override; private: virtual std::string internalGetPathName() const; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp index 63b7ba82619..4259043b7a3 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp @@ -30,7 +30,7 @@ namespace sofa::core::objectmodel JSONSnapshot::JSONSnapshot() = default; JSONSnapshot::~JSONSnapshot() = default; -void to_json(nlohmann::json& j, const BaseSnapshot::DataInfo& di ) +void to_json(nlohmann::json& j, const Snapshot::DataInfo& di ) { j.clear(); j["name"] = di.name; @@ -38,7 +38,7 @@ void to_json(nlohmann::json& j, const BaseSnapshot::DataInfo& di ) j["value"] = di.value; } -void to_json(nlohmann::json& j, const BaseSnapshot::LinkInfo& li ) +void to_json(nlohmann::json& j, const Snapshot::LinkInfo& li ) { j.clear(); j["name"] = li.name; @@ -46,7 +46,7 @@ void to_json(nlohmann::json& j, const BaseSnapshot::LinkInfo& li ) j["value"] = li.value; } -void to_json(nlohmann::json& j, const BaseSnapshot::SnapshotObject& so ) +void to_json(nlohmann::json& j, const Snapshot::SnapshotObject& so ) { j.clear(); j["name"] = so.m_name; @@ -54,7 +54,7 @@ void to_json(nlohmann::json& j, const BaseSnapshot::SnapshotObject& so ) j["links"] = so.m_linkContainer; } -void to_json(nlohmann::json& j, const BaseSnapshot::SnapshotNode& sn) +void to_json(nlohmann::json& j, const Snapshot::SnapshotNode& sn) { j.clear(); j["name"] = sn.m_name; @@ -76,7 +76,7 @@ void to_json(nlohmann::json& j, const BaseSnapshot::SnapshotNode& sn) } } -void to_json(nlohmann::json& j, const std::shared_ptr& sn) +void to_json(nlohmann::json& j, const std::shared_ptr& sn) { j.clear(); j["name"] = sn->m_name; @@ -106,21 +106,21 @@ void JSONSnapshot::exportTo(const std::string filename) file.close(); } -void from_json(const nlohmann::json& j, BaseSnapshot::DataInfo& di) +void from_json(const nlohmann::json& j, Snapshot::DataInfo& di) { di.name = j.value("name", ""); di.type = j.value("type", ""); di.value = j.value("value", ""); } -void from_json(const nlohmann::json& j, BaseSnapshot::LinkInfo& li) +void from_json(const nlohmann::json& j, Snapshot::LinkInfo& li) { li.name = j.value("name", ""); li.type = j.value("type", ""); li.value = j.value("value", ""); } -void from_json(const nlohmann::json& j, BaseSnapshot::SnapshotObject& so) +void from_json(const nlohmann::json& j, Snapshot::SnapshotObject& so) { so.m_name = j.value("name", ""); @@ -129,7 +129,7 @@ void from_json(const nlohmann::json& j, BaseSnapshot::SnapshotObject& so) so.m_dataContainer.clear(); for (const auto& dataJson : j["datas"]) { - BaseSnapshot::DataInfo di; + Snapshot::DataInfo di; from_json(dataJson, di); so.m_dataContainer.push_back(di); } @@ -140,14 +140,14 @@ void from_json(const nlohmann::json& j, BaseSnapshot::SnapshotObject& so) so.m_linkContainer.clear(); for (const auto& linkJson : j["links"]) { - BaseSnapshot::LinkInfo li; + Snapshot::LinkInfo li; from_json(linkJson, li); so.m_linkContainer.push_back(li); } } } -void from_json(const nlohmann::json& j, BaseSnapshot::SnapshotNode& sn) +void from_json(const nlohmann::json& j, Snapshot::SnapshotNode& sn) { sn.m_name = j.value("name", ""); @@ -156,7 +156,7 @@ void from_json(const nlohmann::json& j, BaseSnapshot::SnapshotNode& sn) sn.m_dataContainer.clear(); for (const auto& dataJson : j["datas"]) { - BaseSnapshot::DataInfo di; + Snapshot::DataInfo di; from_json(dataJson, di); sn.m_dataContainer.push_back(di); } @@ -167,7 +167,7 @@ void from_json(const nlohmann::json& j, BaseSnapshot::SnapshotNode& sn) sn.m_linkContainer.clear(); for (const auto& linkJson : j["links"]) { - BaseSnapshot::LinkInfo li; + Snapshot::LinkInfo li; from_json(linkJson, li); sn.m_linkContainer.push_back(li); } @@ -178,7 +178,7 @@ void from_json(const nlohmann::json& j, BaseSnapshot::SnapshotNode& sn) sn.components.clear(); for (const auto& compJson : j["components"]) { - BaseSnapshot::SnapshotObject so; + Snapshot::SnapshotObject so; from_json(compJson, so); sn.components.push_back(so); } @@ -191,7 +191,7 @@ void from_json(const nlohmann::json& j, BaseSnapshot::SnapshotNode& sn) { if (!childJson.is_null()) { - auto child = std::make_shared(); + auto child = std::make_shared(); from_json(childJson, *child); sn.children.push_back(child); } @@ -214,7 +214,7 @@ void JSONSnapshot::importFrom(const std::string filename) if (!m_graphRoot) { - m_graphRoot = std::make_shared(); + m_graphRoot = std::make_shared(); } if (jsonRoot.is_object() && !jsonRoot.empty()) diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h index 5e69ab3ed13..4d9fd050149 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h @@ -21,13 +21,13 @@ ******************************************************************************/ #pragma once #include -#include +#include #include namespace sofa::core::objectmodel { -class SOFA_CORE_API JSONSnapshot : public BaseSnapshot +class SOFA_CORE_API JSONSnapshot : public Snapshot { public: diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.h index f064f2c82f8..d8b1146b90f 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.h @@ -21,12 +21,12 @@ ******************************************************************************/ #pragma once #include -#include +#include namespace sofa::core::objectmodel { -class SOFA_CORE_API MemorySnapshot : public BaseSnapshot +class SOFA_CORE_API MemorySnapshot : public Snapshot { public: diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.cpp similarity index 93% rename from Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp rename to Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.cpp index 821aad1a013..1447e0d9636 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.cpp @@ -19,11 +19,11 @@ * * * Contact information: contact@sofa-framework.org * ******************************************************************************/ -#include +#include namespace sofa::core::objectmodel { -BaseSnapshot::BaseSnapshot() = default; -BaseSnapshot::~BaseSnapshot() = default; +Snapshot::Snapshot() = default; +Snapshot::~Snapshot() = default; } // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.h similarity index 94% rename from Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h rename to Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.h index 7d017cd6717..4812d0ea8b3 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseSnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.h @@ -31,7 +31,7 @@ namespace sofa::core::objectmodel { -class SOFA_CORE_API BaseSnapshot +class SOFA_CORE_API Snapshot { public: @@ -111,10 +111,10 @@ class SOFA_CORE_API BaseSnapshot std::shared_ptr m_graphRoot { nullptr }; - virtual void exportTo(const std::string filename) = 0; - virtual void importFrom(std::string filename) = 0; + // virtual void exportTo(const std::string filename) = 0; + // virtual void importFrom(std::string filename) = 0; - BaseSnapshot(); - virtual ~BaseSnapshot() = 0; + Snapshot(); + virtual ~Snapshot(); }; } // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.cpp index 3da025bfc9e..97b863ef70c 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.cpp @@ -27,7 +27,7 @@ namespace sofa::core::objectmodel { -std::unique_ptr createSnapshot(SnapshotType type) +std::unique_ptr createSnapshot(SnapshotType type) { switch (type) { diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.h b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.h index da73e966da4..8df1daf1867 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.h @@ -24,13 +24,13 @@ namespace sofa::core::objectmodel { -class BaseSnapshot; +class Snapshot; enum class SnapshotType { JSON, Print, Memory }; -std::unique_ptr createSnapshot(SnapshotType type); +std::unique_ptr createSnapshot(SnapshotType type); } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.cpp index 057fba578e3..3561d53cf4c 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.cpp @@ -30,7 +30,7 @@ namespace sofa::simulation void LoadDataSnapshotVisitor::processObject( core::objectmodel::BaseObject* obj, - const std::shared_ptr& parent + const std::shared_ptr& parent ) { auto snapshotObject = obj->findSnapshotObject(parent, obj->getName()); @@ -43,7 +43,7 @@ Visitor::Result LoadDataSnapshotVisitor::processNodeTopDown(simulation::Node* no if (!snapshotObject) msg_error("findSnapshotNode") << "SnapshotNode "<< node->getName() << " not found in "; std::string nodeName = node->getName(); - const auto SnapshotNode = std::dynamic_pointer_cast(snapshotObject); + const auto SnapshotNode = std::dynamic_pointer_cast(snapshotObject); node->loadDataSnapshot(SnapshotNode); std::cout << "test object.getSize : " << node->object.getSize() << std::endl; for (simulation::Node::ObjectIterator it = node->object.begin(); it != node->object.end(); ++it) diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.h index 0126fc18f72..62055566d39 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.h @@ -29,12 +29,12 @@ namespace sofa::simulation class SOFA_SIMULATION_CORE_API LoadDataSnapshotVisitor : public Visitor { protected: - core::objectmodel::BaseSnapshot& m_snapshotContainer; + core::objectmodel::Snapshot& m_snapshotContainer; public: - LoadDataSnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::BaseSnapshot& snapshot) : Visitor(eparams), m_snapshotContainer(snapshot) {} + LoadDataSnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::Snapshot& snapshot) : Visitor(eparams), m_snapshotContainer(snapshot) {} - void processObject(core::objectmodel::BaseObject* obj, const std::shared_ptr& parent); + void processObject(core::objectmodel::BaseObject* obj, const std::shared_ptr& parent); Result processNodeTopDown(simulation::Node* node) override; const char* getClassName() const override { return "LoadDataSnapshotVisitor"; } diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.cpp index 51adddf3226..52d5cae4509 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.cpp @@ -30,7 +30,7 @@ namespace sofa::simulation void LoadLinkSnapshotVisitor::processObject( core::objectmodel::BaseObject* obj, - const std::shared_ptr& parent + const std::shared_ptr& parent ) { const auto snapshotObject = obj->findSnapshotObject(parent, obj->getName()); @@ -40,7 +40,7 @@ void LoadLinkSnapshotVisitor::processObject( Visitor::Result LoadLinkSnapshotVisitor::processNodeTopDown(simulation::Node* node) { const auto snapshotObject = node->findSnapshotObject(m_snapshotContainer.m_graphRoot, node->getName()); - const auto SnapshotNode = std::dynamic_pointer_cast(snapshotObject); + const auto SnapshotNode = std::dynamic_pointer_cast(snapshotObject); node->loadLinkSnapshot(SnapshotNode); for (simulation::Node::ObjectIterator it = node->object.begin(); it != node->object.end(); ++it) diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.h index c17241ba8fd..a3ccf23aea8 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.h @@ -31,12 +31,12 @@ namespace sofa::simulation class SOFA_SIMULATION_CORE_API LoadLinkSnapshotVisitor : public Visitor { protected: - core::objectmodel::BaseSnapshot& m_snapshotContainer; + core::objectmodel::Snapshot& m_snapshotContainer; public: - LoadLinkSnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::BaseSnapshot& snapshot) : Visitor(eparams), m_snapshotContainer(snapshot) {} + LoadLinkSnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::Snapshot& snapshot) : Visitor(eparams), m_snapshotContainer(snapshot) {} - void processObject(core::objectmodel::BaseObject* obj, const std::shared_ptr& parent); + void processObject(core::objectmodel::BaseObject* obj, const std::shared_ptr& parent); Result processNodeTopDown(simulation::Node* node) override; const char* getClassName() const override { return "LoadLinkSnapshotVisitor"; } diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.cpp index 84bdf0cc531..4f56f0675fa 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.cpp @@ -32,9 +32,9 @@ namespace sofa::simulation void SaveSnapshotVisitor::processObject( core::objectmodel::BaseObject* obj, - std::shared_ptr parent) + std::shared_ptr parent) { - std::vector> parents; + std::vector> parents; const auto snapshot = obj->saveSnapshot(parents); parent->components.push_back(*snapshot); } @@ -43,7 +43,7 @@ Visitor::Result SaveSnapshotVisitor::processNodeTopDown(simulation::Node* node) { const auto parents = node->getParents(); - std::vector> snapshotParents; + std::vector> snapshotParents; for (auto* p : parents) { const auto it = m_snapshotNodeMap.find(p); @@ -54,7 +54,7 @@ Visitor::Result SaveSnapshotVisitor::processNodeTopDown(simulation::Node* node) } const auto snapshot = node->saveSnapshot(snapshotParents); - const auto SnapshotNode = std::dynamic_pointer_cast(snapshot); + const auto SnapshotNode = std::dynamic_pointer_cast(snapshot); if (SnapshotNode) { m_snapshotNodeMap[node] = SnapshotNode; diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.h index 02e77a62258..67296e07130 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.h @@ -33,16 +33,16 @@ namespace sofa::simulation class SOFA_SIMULATION_CORE_API SaveSnapshotVisitor : public Visitor { protected: - core::objectmodel::BaseSnapshot& m_snapshotContainer; + core::objectmodel::Snapshot& m_snapshotContainer; - std::unordered_map> m_snapshotNodeMap; + std::unordered_map> m_snapshotNodeMap; public: - SaveSnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::BaseSnapshot& snapshot) : Visitor(eparams), m_snapshotContainer(snapshot) + SaveSnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::Snapshot& snapshot) : Visitor(eparams), m_snapshotContainer(snapshot) { } - void processObject(core::objectmodel::BaseObject* obj, std::shared_ptr parent); + void processObject(core::objectmodel::BaseObject* obj, std::shared_ptr parent); Result processNodeTopDown(simulation::Node* node) override; const char* getClassName() const override { return "SaveSnapshotVisitor"; } From 56d9c4fdc164308d66905f80317ca19c0e356952 Mon Sep 17 00:00:00 2001 From: Lucas-TJ Date: Fri, 20 Mar 2026 11:39:24 +0100 Subject: [PATCH 30/57] Refactoring the API of snapshot (Snapshot, SnapshotJSONExporter and SnapshotManager) --- Sofa/framework/Core/CMakeLists.txt | 10 +- .../Core/simutest/objectmodel/Base_test.cpp | 3 - .../simutest/objectmodel/Snapshot_test.cpp | 93 ++++++++----------- .../Core/src/sofa/core/objectmodel/Base.h | 2 - .../src/sofa/core/objectmodel/JSONSnapshot.h | 40 -------- .../Core/src/sofa/core/objectmodel/Snapshot.h | 10 +- .../sofa/core/objectmodel/SnapshotFactory.cpp | 43 --------- ...NSnapshot.cpp => SnapshotJSONExporter.cpp} | 18 ++-- ...emorySnapshot.h => SnapshotJSONExporter.h} | 14 +-- ...MemorySnapshot.cpp => SnapshotManager.cpp} | 14 +-- .../{SnapshotFactory.h => SnapshotManager.h} | 11 +-- .../simulation/LoadDataSnapshotVisitor.cpp | 3 - .../simulation/LoadLinkSnapshotVisitor.cpp | 2 - .../sofa/simulation/SaveSnapshotVisitor.cpp | 2 - 14 files changed, 64 insertions(+), 201 deletions(-) delete mode 100644 Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h delete mode 100644 Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.cpp rename Sofa/framework/Core/src/sofa/core/objectmodel/{JSONSnapshot.cpp => SnapshotJSONExporter.cpp} (93%) rename Sofa/framework/Core/src/sofa/core/objectmodel/{MemorySnapshot.h => SnapshotJSONExporter.h} (89%) rename Sofa/framework/Core/src/sofa/core/objectmodel/{MemorySnapshot.cpp => SnapshotManager.cpp} (85%) rename Sofa/framework/Core/src/sofa/core/objectmodel/{SnapshotFactory.h => SnapshotManager.h} (91%) diff --git a/Sofa/framework/Core/CMakeLists.txt b/Sofa/framework/Core/CMakeLists.txt index 8c073a7bccd..65dcdda7cf4 100644 --- a/Sofa/framework/Core/CMakeLists.txt +++ b/Sofa/framework/Core/CMakeLists.txt @@ -178,17 +178,16 @@ set(HEADER_FILES ${SRC_ROOT}/objectmodel/HapticDeviceEvent.h ${SRC_ROOT}/objectmodel/IdleEvent.h ${SRC_ROOT}/objectmodel/JoystickEvent.h - ${SRC_ROOT}/objectmodel/JSONSnapshot.h + ${SRC_ROOT}/objectmodel/SnapshotJSONExporter.h ${SRC_ROOT}/objectmodel/KeypressedEvent.h ${SRC_ROOT}/objectmodel/KeyreleasedEvent.h ${SRC_ROOT}/objectmodel/lifecycle/DeprecatedData.h ${SRC_ROOT}/objectmodel/lifecycle/RemovedData.h ${SRC_ROOT}/objectmodel/lifecycle/RenamedData.h ${SRC_ROOT}/objectmodel/Link.h - ${SRC_ROOT}/objectmodel/MemorySnapshot.h + ${SRC_ROOT}/objectmodel/SnapshotManager.h ${SRC_ROOT}/objectmodel/MouseEvent.h ${SRC_ROOT}/objectmodel/SPtr.h - ${SRC_ROOT}/objectmodel/SnapshotFactory.h ${SRC_ROOT}/objectmodel/ScriptEvent.h ${SRC_ROOT}/objectmodel/TypeOfInsertion.h ${SRC_ROOT}/objectmodel/Tag.h @@ -332,14 +331,13 @@ set(SOURCE_FILES ${SRC_ROOT}/objectmodel/HapticDeviceEvent.cpp ${SRC_ROOT}/objectmodel/IdleEvent.cpp ${SRC_ROOT}/objectmodel/JoystickEvent.cpp - ${SRC_ROOT}/objectmodel/JSONSnapshot.cpp + ${SRC_ROOT}/objectmodel/SnapshotJSONExporter.cpp ${SRC_ROOT}/objectmodel/KeypressedEvent.cpp ${SRC_ROOT}/objectmodel/KeyreleasedEvent.cpp ${SRC_ROOT}/objectmodel/lifecycle/DeprecatedData.cpp - ${SRC_ROOT}/objectmodel/MemorySnapshot.cpp + ${SRC_ROOT}/objectmodel/SnapshotManager.cpp ${SRC_ROOT}/objectmodel/MouseEvent.cpp ${SRC_ROOT}/objectmodel/ScriptEvent.cpp - ${SRC_ROOT}/objectmodel/SnapshotFactory.cpp ${SRC_ROOT}/objectmodel/Tag.cpp ${SRC_ROOT}/objectmodel/TagSet.cpp ${SRC_ROOT}/topology/BaseMeshTopology.cpp diff --git a/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp index 05acfefa0d8..4802c593704 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Base_test.cpp @@ -36,9 +36,6 @@ using sofa::defaulttype::Rigid3Types; #include using sofa::defaulttype::Vec3Types; -#include -using sofa::core::objectmodel::SnapshotType; - #include using sofa::simulation::SaveSnapshotVisitor; diff --git a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp index 30f5afd468d..70f1085bfc7 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp @@ -32,9 +32,6 @@ using sofa::simulation::Node ; #include using sofa::core::objectmodel::BaseObject; -#include -using sofa::core::objectmodel::SnapshotType; - #include using sofa::simulation::SaveSnapshotVisitor; @@ -91,16 +88,6 @@ class TestComponent : public Base class MockSnapshotTest : public Snapshot { public: - void exportTo(const std::string filename) override - { - SOFA_UNUSED(filename); - } - void importFrom(std::string filename) override - { - SOFA_UNUSED(filename); - } - - MockSnapshotTest() {} ~MockSnapshotTest() = default; @@ -252,12 +239,12 @@ TEST_F(Snapshot_test, loadSnapshot) EXPECT_EQ(tcomponent2.d_value.getValue(), 3.14f); } -TEST_F(Snapshot_test, JSONSnapshot) +TEST_F(Snapshot_test, SnapshotJSONExporter) { - // TEST JSONSnapshot + // TEST SnapshotJSONExporter // Test the behavior of the export and the import with JSON - auto JsonSnapshotTest = createSnapshot(SnapshotType::JSON); + // auto SnapshotJSONExporterTest = createSnapshot(SnapshotType::JSON); const std::string scene = R"( @@ -277,32 +264,32 @@ TEST_F(Snapshot_test, JSONSnapshot) Node* root = c.root.get() ; std::string path = std::filesystem::temp_directory_path() / "testfile.json"; - auto visitor = SaveSnapshotVisitor(nullptr, *JsonSnapshotTest); - root->execute(visitor); - JsonSnapshotTest->exportTo(path); - EXPECT_NE(JsonSnapshotTest->m_graphRoot,nullptr); - std::cout << "JsonSnapshotTest : " << JsonSnapshotTest->m_graphRoot->m_name << std::endl; - - std::ifstream checkFile(path); - EXPECT_TRUE(checkFile.good()); - checkFile.close(); - - auto JsonSnapshotTest2 = createSnapshot(SnapshotType::JSON); - JsonSnapshotTest2->importFrom(path); - EXPECT_NE(JsonSnapshotTest2->m_graphRoot,nullptr); - - EXPECT_EQ(JsonSnapshotTest2->m_graphRoot->m_name,"Root"); - EXPECT_EQ(JsonSnapshotTest2->m_graphRoot->components[0].m_name,"Sofa.Component.StateContainer"); - EXPECT_EQ(JsonSnapshotTest2->m_graphRoot->components[1].m_name,"DefaultAnimationLoop1"); - EXPECT_EQ(JsonSnapshotTest2->m_graphRoot->components[2].m_name,"DefaultVisualManagerLoop1"); - EXPECT_EQ(JsonSnapshotTest2->m_graphRoot->children[0]->m_name,"child1"); - EXPECT_EQ(JsonSnapshotTest2->m_graphRoot->children[0]->components[0].m_name,"MechanicalObject1"); + // auto visitor = SaveSnapshotVisitor(nullptr, *SnapshotJSONExporterTest); + // root->execute(visitor); + // SnapshotJSONExporterTest->exportTo(path); + // EXPECT_NE(SnapshotJSONExporterTest->m_graphRoot,nullptr); + // std::cout << "SnapshotJSONExporterTest : " << SnapshotJSONExporterTest->m_graphRoot->m_name << std::endl; + // + // std::ifstream checkFile(path); + // EXPECT_TRUE(checkFile.good()); + // checkFile.close(); + // + // // auto SnapshotJSONExporterTest2 = createSnapshot(SnapshotType::JSON); + // SnapshotJSONExporterTest2->importFrom(path); + // EXPECT_NE(SnapshotJSONExporterTest2->m_graphRoot,nullptr); + // + // EXPECT_EQ(SnapshotJSONExporterTest2->m_graphRoot->m_name,"Root"); + // EXPECT_EQ(SnapshotJSONExporterTest2->m_graphRoot->components[0].m_name,"Sofa.Component.StateContainer"); + // EXPECT_EQ(SnapshotJSONExporterTest2->m_graphRoot->components[1].m_name,"DefaultAnimationLoop1"); + // EXPECT_EQ(SnapshotJSONExporterTest2->m_graphRoot->components[2].m_name,"DefaultVisualManagerLoop1"); + // EXPECT_EQ(SnapshotJSONExporterTest2->m_graphRoot->children[0]->m_name,"child1"); + // EXPECT_EQ(SnapshotJSONExporterTest2->m_graphRoot->children[0]->components[0].m_name,"MechanicalObject1"); } TEST_F(Snapshot_test, LoadLinkVisitor) { - auto JsonSnapshotTest = createSnapshot(SnapshotType::JSON); + // auto SnapshotJSONExporterTest = createSnapshot(SnapshotType::JSON); // const std::string scene = R"( // @@ -352,20 +339,20 @@ TEST_F(Snapshot_test, LoadLinkVisitor) Node* root = c.root.get() ; - std::string path = std::filesystem::temp_directory_path() / "testfile.json"; - auto visitor = SaveSnapshotVisitor(nullptr, *JsonSnapshotTest); - root->execute(visitor); - JsonSnapshotTest->exportTo(path); - EXPECT_NE(JsonSnapshotTest->m_graphRoot,nullptr); - std::cout << "JsonSnapshotTest : " << JsonSnapshotTest->m_graphRoot->m_name << std::endl; - - std::ifstream checkFile(path); - EXPECT_TRUE(checkFile.good()); - checkFile.close(); - - auto loadvisitor = LoadDataSnapshotVisitor(nullptr, *JsonSnapshotTest); - root->execute(loadvisitor); - auto loadlinkvisitor = LoadLinkSnapshotVisitor(nullptr, *JsonSnapshotTest); - root->execute(loadlinkvisitor); - EXPECT_NE(JsonSnapshotTest->m_graphRoot,nullptr); + // std::string path = std::filesystem::temp_directory_path() / "testfile.json"; + // auto visitor = SaveSnapshotVisitor(nullptr, *SnapshotJSONExporterTest); + // root->execute(visitor); + // SnapshotJSONExporterTest->exportTo(path); + // EXPECT_NE(SnapshotJSONExporterTest->m_graphRoot,nullptr); + // std::cout << "SnapshotJSONExporterTest : " << SnapshotJSONExporterTest->m_graphRoot->m_name << std::endl; + // + // std::ifstream checkFile(path); + // EXPECT_TRUE(checkFile.good()); + // checkFile.close(); + // + // auto loadvisitor = LoadDataSnapshotVisitor(nullptr, *SnapshotJSONExporterTest); + // root->execute(loadvisitor); + // auto loadlinkvisitor = LoadLinkSnapshotVisitor(nullptr, *SnapshotJSONExporterTest); + // root->execute(loadlinkvisitor); + // EXPECT_NE(SnapshotJSONExporterTest->m_graphRoot,nullptr); } \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h index 66f96d82e7c..087a9c97e0f 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h @@ -42,8 +42,6 @@ #include -#include - #include #define SOFA_BASE_CAST_IMPLEMENTATION(CLASSNAME) \ diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h deleted file mode 100644 index 4d9fd050149..00000000000 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.h +++ /dev/null @@ -1,40 +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 * -******************************************************************************/ -#pragma once -#include -#include -#include - -namespace sofa::core::objectmodel -{ - -class SOFA_CORE_API JSONSnapshot : public Snapshot -{ - -public: - - void exportTo(const std::string filename) override; - void importFrom(std::string filename) override; - JSONSnapshot(); - ~JSONSnapshot(); -}; -} // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.h index 4812d0ea8b3..588ec77e117 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.h @@ -31,6 +31,13 @@ namespace sofa::core::objectmodel { +/** +* \brief Class for snapshot +* +* This class contains the structure for a snapshot of a simulation in SOFA. +* The snapshot contains datas and links, and keep to shape of a scene graph +*/ + class SOFA_CORE_API Snapshot { @@ -111,9 +118,6 @@ class SOFA_CORE_API Snapshot std::shared_ptr m_graphRoot { nullptr }; - // virtual void exportTo(const std::string filename) = 0; - // virtual void importFrom(std::string filename) = 0; - Snapshot(); virtual ~Snapshot(); }; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.cpp deleted file mode 100644 index 97b863ef70c..00000000000 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.cpp +++ /dev/null @@ -1,43 +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 * -******************************************************************************/ -#pragma once -#include -#include -#include - -namespace sofa::core::objectmodel -{ - -std::unique_ptr createSnapshot(SnapshotType type) -{ - switch (type) - { - case SnapshotType::JSON: - return std::make_unique(); - case SnapshotType::Memory: - return std::make_unique(); - default: - return nullptr; - } -} - -} // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp similarity index 93% rename from Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp rename to Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp index 4259043b7a3..66f9f603b4a 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/JSONSnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp @@ -19,7 +19,8 @@ * * * Contact information: contact@sofa-framework.org * ******************************************************************************/ -#include +#include +#include #include #include #include @@ -27,9 +28,6 @@ namespace sofa::core::objectmodel { -JSONSnapshot::JSONSnapshot() = default; -JSONSnapshot::~JSONSnapshot() = default; - void to_json(nlohmann::json& j, const Snapshot::DataInfo& di ) { j.clear(); @@ -97,9 +95,9 @@ void to_json(nlohmann::json& j, const std::shared_ptr& s } } -void JSONSnapshot::exportTo(const std::string filename) +void exportTo(Snapshot& snapshot, const std::string& filename) { - nlohmann::json j = *m_graphRoot ; + nlohmann::json j = snapshot.m_graphRoot ; std::ofstream file(filename); file << j.dump(5); @@ -199,7 +197,7 @@ void from_json(const nlohmann::json& j, Snapshot::SnapshotNode& sn) } } -void JSONSnapshot::importFrom(const std::string filename) +void importFrom(Snapshot& snapshot, const std::string& filename) { std::ifstream file(filename); if (!file.is_open()) @@ -212,14 +210,14 @@ void JSONSnapshot::importFrom(const std::string filename) file >> jsonRoot; file.close(); - if (!m_graphRoot) + if (!snapshot.m_graphRoot) { - m_graphRoot = std::make_shared(); + snapshot.m_graphRoot = std::make_shared(); } if (jsonRoot.is_object() && !jsonRoot.empty()) { - from_json(jsonRoot, *m_graphRoot); + from_json(jsonRoot, *snapshot.m_graphRoot); } else { diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h similarity index 89% rename from Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.h rename to Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h index d8b1146b90f..3db8483f9a7 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h @@ -25,16 +25,6 @@ namespace sofa::core::objectmodel { - -class SOFA_CORE_API MemorySnapshot : public Snapshot -{ - -public: - void exportTo(const std::string filename) override; - void importFrom(std::string filename) override; - - MemorySnapshot(); - ~MemorySnapshot(); - -}; + void exportTo(Snapshot& snapshot, const std::string& filename); + void importFrom(Snapshot& snapshot, const std::string& filename); } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.cpp similarity index 85% rename from Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp rename to Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.cpp index dfff79435c4..2a93c72cad0 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/MemorySnapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.cpp @@ -19,25 +19,13 @@ * * * Contact information: contact@sofa-framework.org * ******************************************************************************/ -#include +#include #include #include namespace sofa::core::objectmodel { -MemorySnapshot::MemorySnapshot() -{} -MemorySnapshot::~MemorySnapshot() = default; -void MemorySnapshot::exportTo(const std::string filename) -{ - SOFA_UNUSED(filename); -} - -void MemorySnapshot::importFrom(const std::string filename) -{ - SOFA_UNUSED(filename); -} } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.h b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.h similarity index 91% rename from Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.h rename to Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.h index 8df1daf1867..bfcf48bdccb 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotFactory.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.h @@ -20,17 +20,10 @@ * Contact information: contact@sofa-framework.org * ******************************************************************************/ #pragma once -#include +#include +#include namespace sofa::core::objectmodel { -class Snapshot; -enum class SnapshotType -{ - JSON, - Print, - Memory -}; -std::unique_ptr createSnapshot(SnapshotType type); } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.cpp index 3561d53cf4c..b9519eeba90 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.cpp @@ -22,8 +22,6 @@ #include #include #include -#include -using sofa::core::objectmodel::SnapshotType; namespace sofa::simulation { @@ -45,7 +43,6 @@ Visitor::Result LoadDataSnapshotVisitor::processNodeTopDown(simulation::Node* no std::string nodeName = node->getName(); const auto SnapshotNode = std::dynamic_pointer_cast(snapshotObject); node->loadDataSnapshot(SnapshotNode); - std::cout << "test object.getSize : " << node->object.getSize() << std::endl; for (simulation::Node::ObjectIterator it = node->object.begin(); it != node->object.end(); ++it) { this->processObject(it->get(), SnapshotNode); diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.cpp index 52d5cae4509..7219d94df54 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.cpp @@ -22,8 +22,6 @@ #include #include #include -#include -using sofa::core::objectmodel::SnapshotType; namespace sofa::simulation { diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.cpp index 4f56f0675fa..975d213df35 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.cpp @@ -22,8 +22,6 @@ #include #include #include -#include -using sofa::core::objectmodel::SnapshotType; #include From f22857ffe2dd646d7eb0f9d58f4b662ba20473e8 Mon Sep 17 00:00:00 2001 From: Lucas-TJ Date: Mon, 23 Mar 2026 17:12:44 +0100 Subject: [PATCH 31/57] Fix loadDataSnapshot and update SnapshotManager --- .../simutest/objectmodel/Snapshot_test.cpp | 116 +++++------------- .../Core/src/sofa/core/objectmodel/Base.cpp | 68 +++++----- .../Core/src/sofa/core/objectmodel/BaseLink.h | 2 + .../Core/src/sofa/core/objectmodel/Link.h | 2 +- .../Core/src/sofa/core/objectmodel/Snapshot.h | 2 + .../core/objectmodel/SnapshotJSONExporter.cpp | 18 +++ .../sofa/core/objectmodel/SnapshotManager.cpp | 22 ++++ .../sofa/core/objectmodel/SnapshotManager.h | 12 ++ 8 files changed, 123 insertions(+), 119 deletions(-) diff --git a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp index 70f1085bfc7..a0a4b46f060 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp @@ -21,6 +21,7 @@ ******************************************************************************/ #include +#include "../../src/sofa/core/objectmodel/Base.h" #include "gtest/gtest.h" using sofa::core::objectmodel::Base ; using sofa::core::objectmodel::ComponentState; @@ -32,6 +33,9 @@ using sofa::simulation::Node ; #include using sofa::core::objectmodel::BaseObject; +#include +using sofa::core::objectmodel::Snapshot; + #include using sofa::simulation::SaveSnapshotVisitor; @@ -41,6 +45,8 @@ using sofa::simulation::LoadDataSnapshotVisitor; #include using sofa::simulation::LoadLinkSnapshotVisitor; +#include + #include using sofa::core::objectmodel::Data; using sofa::core::objectmodel::BaseLink; @@ -51,7 +57,6 @@ using sofa::core::objectmodel::BaseNode; #include #include - class TestComponent : public Base { @@ -85,33 +90,6 @@ class TestComponent : public Base }; -class MockSnapshotTest : public Snapshot -{ -public: - MockSnapshotTest() {} - ~MockSnapshotTest() = default; - - void setupSnapshot() - { - this->m_graphRoot = std::make_shared("root"); - auto snapshotObject0 = std::make_shared("snapshotObject0"); - this->m_graphRoot->components.push_back(*snapshotObject0); - - auto snapshotNode1 = std::make_shared("snapshotNode1"); - auto snapshotNode2 = std::make_shared("snapshotNode2"); - - auto snapshotObject1 = std::make_shared("snapshotObject1"); - auto snapshotObject2 = std::make_shared("snapshotObject2"); - - snapshotNode1->components.push_back(*snapshotObject1); - snapshotNode2->components.push_back(*snapshotObject2); - - snapshotNode1->children.push_back(snapshotNode2); - - this->m_graphRoot->children.push_back(snapshotNode1); - } -}; - class Snapshot_test: public BaseSimulationTest { public: @@ -124,7 +102,6 @@ class Snapshot_test: public BaseSimulationTest delete c; } - }; @@ -185,7 +162,6 @@ TEST_F(Snapshot_test, findSnapshotObject) // TEST of findSnapshotObject // Check if findSnapshotObject can find the SnapshotObject in a Snapshot // with the component's name - TestComponent tComponent; @@ -244,8 +220,6 @@ TEST_F(Snapshot_test, SnapshotJSONExporter) // TEST SnapshotJSONExporter // Test the behavior of the export and the import with JSON - // auto SnapshotJSONExporterTest = createSnapshot(SnapshotType::JSON); - const std::string scene = R"( @@ -263,46 +237,35 @@ TEST_F(Snapshot_test, SnapshotJSONExporter) Node* root = c.root.get() ; - std::string path = std::filesystem::temp_directory_path() / "testfile.json"; - // auto visitor = SaveSnapshotVisitor(nullptr, *SnapshotJSONExporterTest); - // root->execute(visitor); - // SnapshotJSONExporterTest->exportTo(path); - // EXPECT_NE(SnapshotJSONExporterTest->m_graphRoot,nullptr); - // std::cout << "SnapshotJSONExporterTest : " << SnapshotJSONExporterTest->m_graphRoot->m_name << std::endl; - // - // std::ifstream checkFile(path); - // EXPECT_TRUE(checkFile.good()); - // checkFile.close(); - // - // // auto SnapshotJSONExporterTest2 = createSnapshot(SnapshotType::JSON); - // SnapshotJSONExporterTest2->importFrom(path); - // EXPECT_NE(SnapshotJSONExporterTest2->m_graphRoot,nullptr); - // - // EXPECT_EQ(SnapshotJSONExporterTest2->m_graphRoot->m_name,"Root"); - // EXPECT_EQ(SnapshotJSONExporterTest2->m_graphRoot->components[0].m_name,"Sofa.Component.StateContainer"); - // EXPECT_EQ(SnapshotJSONExporterTest2->m_graphRoot->components[1].m_name,"DefaultAnimationLoop1"); - // EXPECT_EQ(SnapshotJSONExporterTest2->m_graphRoot->components[2].m_name,"DefaultVisualManagerLoop1"); - // EXPECT_EQ(SnapshotJSONExporterTest2->m_graphRoot->children[0]->m_name,"child1"); - // EXPECT_EQ(SnapshotJSONExporterTest2->m_graphRoot->children[0]->components[0].m_name,"MechanicalObject1"); + std::filesystem::path path = std::filesystem::temp_directory_path() / "test_file.json"; + auto m_snapshot = std::make_shared(); + + auto visitor = SaveSnapshotVisitor(nullptr, *m_snapshot); + root->execute(visitor); + + exportTo(*m_snapshot,path); + std::ifstream checkFile(path); + EXPECT_TRUE(checkFile.good()); + checkFile.close(); + + auto m_snapshot_import = std::make_shared(); + importFrom(*m_snapshot_import, path); + + EXPECT_NE(m_snapshot_import->m_graphRoot,nullptr); + + EXPECT_EQ(m_snapshot_import->m_graphRoot->m_name,"Root"); + EXPECT_EQ(m_snapshot_import->m_graphRoot->components[0].m_name,"Sofa.Component.StateContainer"); + EXPECT_EQ(m_snapshot_import->m_graphRoot->components[1].m_name,"DefaultAnimationLoop1"); + EXPECT_EQ(m_snapshot_import->m_graphRoot->components[2].m_name,"DefaultVisualManagerLoop1"); + EXPECT_EQ(m_snapshot_import->m_graphRoot->children[0]->m_name,"child1"); + EXPECT_EQ(m_snapshot_import->m_graphRoot->children[0]->components[0].m_name,"MechanicalObject1"); + + std::filesystem::remove(path); } -TEST_F(Snapshot_test, LoadLinkVisitor) +TEST_F(Snapshot_test, Regression) { - // auto SnapshotJSONExporterTest = createSnapshot(SnapshotType::JSON); - - // const std::string scene = R"( - // - // - // - // - // - // - // - // - // - // )"; - const std::string scene = R"( @@ -339,20 +302,5 @@ TEST_F(Snapshot_test, LoadLinkVisitor) Node* root = c.root.get() ; - // std::string path = std::filesystem::temp_directory_path() / "testfile.json"; - // auto visitor = SaveSnapshotVisitor(nullptr, *SnapshotJSONExporterTest); - // root->execute(visitor); - // SnapshotJSONExporterTest->exportTo(path); - // EXPECT_NE(SnapshotJSONExporterTest->m_graphRoot,nullptr); - // std::cout << "SnapshotJSONExporterTest : " << SnapshotJSONExporterTest->m_graphRoot->m_name << std::endl; - // - // std::ifstream checkFile(path); - // EXPECT_TRUE(checkFile.good()); - // checkFile.close(); - // - // auto loadvisitor = LoadDataSnapshotVisitor(nullptr, *SnapshotJSONExporterTest); - // root->execute(loadvisitor); - // auto loadlinkvisitor = LoadLinkSnapshotVisitor(nullptr, *SnapshotJSONExporterTest); - // root->execute(loadlinkvisitor); - // EXPECT_NE(SnapshotJSONExporterTest->m_graphRoot,nullptr); + } \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index 88540b7238d..7cbabb17534 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -717,13 +717,13 @@ void Base::saveLinksIn(Snapshot::SnapshotObject& snapshot) const // linkInfo.value = link->getLinkedPath(); // linkInfo.value = link->getPath(); - // std::string replaceValue = "//"; - // std::size_t pos = linkInfo.value.find(replaceValue); - // while (pos != std::string::npos) - // { - // linkInfo.value.replace(pos, replaceValue.length(), ""); - // pos = linkInfo.value.find(replaceValue, pos); - // } + std::string replaceValue = "//"; + std::size_t pos = linkInfo.value.find(replaceValue); + while (pos != std::string::npos) + { + linkInfo.value.replace(pos, replaceValue.length(), ""); + pos = linkInfo.value.find(replaceValue, pos); + } snapshot.m_linkContainer.push_back(linkInfo); } @@ -783,10 +783,17 @@ void Base::loadDataSnapshot(const std::shared_ptr& sna { if (const auto data = this->findData(dataInfo.name)) { - if( dataInfo.name != "loadedPlugins"&& dataInfo.name != "filename" && dataInfo.name != "texturename" && dataInfo.name != "pluginName") - { - data->read(dataInfo.value); + // If dataInfo.value is a vector like '["Value1", "Value2" ... "Value_i"]' + if (dataInfo.value[0] == '[' && dataInfo.value.back() == ']') { + std::string dataValueStr = dataInfo.value; + dataValueStr.erase(std::remove(dataValueStr.begin(), dataValueStr.end(), '['), dataValueStr.end()); + dataValueStr.erase(std::remove(dataValueStr.begin(), dataValueStr.end(), ']'), dataValueStr.end()); + dataValueStr.erase(std::remove(dataValueStr.begin(), dataValueStr.end(), '"'), dataValueStr.end()); + dataValueStr.erase(std::remove(dataValueStr.begin(), dataValueStr.end(), ','), dataValueStr.end()); + data->read(dataValueStr); } + else + data->read(dataInfo.value); } } } @@ -798,35 +805,28 @@ void Base::loadLinkSnapshot(const std::shared_ptr& sna { if (const auto link = this->findLink(linkInfo.name)) { - if(linkInfo.name != "odeSolver" && linkInfo.name != "linearSolver") - { - // std::cout << "===========link name : " << linkInfo.name << std::endl; - // std::cout << "===========link value : " << linkInfo.value << std::endl; - - // link->read(linkInfo.value); + // std::cout << "===========link name : " << linkInfo.name << std::endl; + // std::cout << "===========link value : " << linkInfo.value << std::endl; - // Idea : Compare links in the snapshot and in the simulation, and change/add targets to the link - std::vector newSublinks = helper::split(linkInfo.value, ' '); - std::vector currentSublinks = helper::split(link->getValueString(), ' '); + // link->read(linkInfo.value); - for (const auto& subLink : newSublinks) + // Idea : Compare links in the snapshot and in the simulation, and change/add targets to the link + std::vector newSublinks = helper::split(linkInfo.value, ' '); + for (const auto& newSublink : newSublinks) + { + auto obj = PathResolver::FindBaseFromPath(link->getOwner(), newSublink); + bool checkedPath = PathResolver::CheckPath(obj,link->getDestClass(),newSublink); + if (!checkedPath) { - Base* obj = PathResolver::FindBaseFromClassAndPath(link->getOwner(), link->getDestClass(), subLink); - auto it = std::ranges::find(currentSublinks, subLink); - if (it != currentSublinks.end()) { - // subLink is in currentSublinks - const size_t index = std::distance(currentSublinks.begin(), it); - link->set(obj,index); - } - else { - // subLink is not in currentSublinks - link->add(obj,subLink); - } + link->add(obj, newSublink); } - - } - + // How to detect if a link is depracted ? + // for (const auto& oldLink : ) + // { + // if (std::ranges::find(newSublinks,oldLink) == newSublinks.end()) + // link->removePath(oldLink); + // } } } } diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.h index d5c71fc6d57..57c5e561344 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.h @@ -175,6 +175,8 @@ class SOFA_CORE_API BaseLink /// Change the link's target at the provided index. bool set(Base* baseptr, size_t index=0) { return _doSet_(baseptr, index); } + virtual bool removePath(const std::string& path) = 0; + protected: virtual bool _doSet_(Base* target, const size_t index=0) = 0; virtual Base* _doGetOwner_() const = 0 ; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Link.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Link.h index b1519d4bc89..88aa5fb8266 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Link.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Link.h @@ -427,7 +427,7 @@ class TLink : public BaseLink return true; } - bool removePath(const std::string& path) + bool removePath(const std::string& path) override { if (path.empty()) return false; const std::size_t n = m_value.size(); diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.h index 588ec77e117..b6c13b66044 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.h @@ -121,4 +121,6 @@ class SOFA_CORE_API Snapshot Snapshot(); virtual ~Snapshot(); }; + + } // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp index 66f9f603b4a..4ca0e451d9b 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp @@ -28,6 +28,8 @@ namespace sofa::core::objectmodel { + + void to_json(nlohmann::json& j, const Snapshot::DataInfo& di ) { j.clear(); @@ -228,4 +230,20 @@ void importFrom(Snapshot& snapshot, const std::string& filename) std::cout << "JSON imported successfully from: " << filename << std::endl; } + +std::string to_String(const std::string& filename) +{ + std::ifstream file(filename); + if (!file.is_open()) + { + msg_error("SnapshotJSONExporter") << "ERROR: Cannot open file " << filename << " for reading\n"; + return ""; + } + + nlohmann::json jsonRoot; + file >> jsonRoot; + file.close(); + return to_string(jsonRoot); +} + } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.cpp index 2a93c72cad0..0b210e3fe0e 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.cpp @@ -26,6 +26,28 @@ namespace sofa::core::objectmodel { +SnapshotManager::SnapshotManager() = default; +SnapshotManager::~SnapshotManager() = default; + +void SnapshotManager::AddRecentFile(const std::string& path, std::vector& recentFiles, int maxFiles) +{ + recentFiles.erase( + std::remove(recentFiles.begin(), recentFiles.end(), path), + recentFiles.end() + ); + //recentFiles.insert(recentFiles.begin(), path); + recentFiles.push_back(path); + if (recentFiles.size() > maxFiles) + recentFiles.resize(maxFiles); +} + +void SnapshotManager::AddRecentSnapshot(std::map>& recentSnapshots, std::shared_ptr snapshot, double snapshotTime, int maxSnapshots) +{ + static int index = 0; + recentSnapshots["Memory_Snapshot " + std::to_string(index++) + " at " + std::to_string(snapshotTime)] = snapshot; + if (recentSnapshots.size() > maxSnapshots) + recentSnapshots.erase(recentSnapshots.begin()); +} } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.h b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.h index bfcf48bdccb..be7b75c5064 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.h @@ -25,5 +25,17 @@ namespace sofa::core::objectmodel { +class SnapshotManager +{ +public: + SnapshotManager(); + ~SnapshotManager(); + + std::vector recentSnapshotFiles; + std::map> recentSnapshots; + + static void AddRecentFile(const std::string& path, std::vector& recentFiles, int maxFiles = 10); + static void AddRecentSnapshot(std::map>& recentSnapshots, std::shared_ptr snapshot, double snapshotTime, int maxSnapshots = 10); +}; } // namespace sofa::core::objectmodel \ No newline at end of file From 8bbdb8baf5515e244226684deb72edc39bb58038 Mon Sep 17 00:00:00 2001 From: Lucas-TJ Date: Thu, 9 Apr 2026 14:42:46 +0200 Subject: [PATCH 32/57] update Snapshot and JSONExporter --- .../simutest/objectmodel/Snapshot_test.cpp | 80 +++++++------------ .../Core/src/sofa/core/objectmodel/Base.cpp | 24 ++---- .../src/sofa/core/objectmodel/Snapshot.cpp | 4 + .../Core/src/sofa/core/objectmodel/Snapshot.h | 3 +- .../core/objectmodel/SnapshotJSONExporter.cpp | 8 +- .../core/objectmodel/SnapshotJSONExporter.h | 2 + 6 files changed, 49 insertions(+), 72 deletions(-) diff --git a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp index a0a4b46f060..0ef7ea05d84 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp @@ -21,7 +21,6 @@ ******************************************************************************/ #include -#include "../../src/sofa/core/objectmodel/Base.h" #include "gtest/gtest.h" using sofa::core::objectmodel::Base ; using sofa::core::objectmodel::ComponentState; @@ -61,9 +60,6 @@ class TestComponent : public Base { public: - - SOFA_CLASS(TestComponent,Base); - Data d_value; TestComponent() @@ -93,15 +89,8 @@ class TestComponent : public Base class Snapshot_test: public BaseSimulationTest { public: - - SceneInstance* c; - Node* node {nullptr}; Snapshot_test() {} - ~Snapshot_test() override - { - delete c; - } - + ~Snapshot_test() override {} }; @@ -127,6 +116,32 @@ TEST_F(Snapshot_test, saveDataIn) } } +TEST_F(Snapshot_test, saveLinkIn) +{ + // TEST of saveLinksIn method + // Check if the snapshot contains the component with expected data + TestComponent tComponent; + auto snapshot = std::make_shared(); + + tComponent.saveLinks(*snapshot); + for (auto& link : snapshot->m_linkContainer) + { + if (link.name == "name") + { + EXPECT_EQ(link.value, "@./"); + } + if (link.name == "slaves") + { + EXPECT_EQ(link.value, ""); + } + if (link.name == "master") + { + EXPECT_EQ(link.value, ""); + } + + } +} + TEST_F(Snapshot_test, createSnapshotObject) { // TEST of createSnapshotObject @@ -263,44 +278,3 @@ TEST_F(Snapshot_test, SnapshotJSONExporter) std::filesystem::remove(path); } - -TEST_F(Snapshot_test, Regression) -{ - const std::string scene = R"( - - - - - - - - - - - - - - - - - - - - - - - - - - - )"; - - SceneInstance c("xml", scene) ; - c.initScene() ; - - Node* root = c.root.get() ; - - -} \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index 7cbabb17534..a5a5eb5fe94 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -692,16 +692,6 @@ void Base::saveDataIn(Snapshot::SnapshotObject& snapshot) const dataInfo.type = data->getValueTypeString(); dataInfo.value = data->getValueString(); - // Wait PR#5976 to remove - std::string replaceValue = "nan"; - std::string newValue = "0"; - std::size_t pos = dataInfo.value.find(replaceValue); - while (pos != std::string::npos) - { - dataInfo.value.replace(pos, replaceValue.length(),newValue); - pos = dataInfo.value.find(replaceValue, pos + newValue.length()); - } - snapshot.m_dataContainer.push_back(dataInfo); } } @@ -714,8 +704,6 @@ void Base::saveLinksIn(Snapshot::SnapshotObject& snapshot) const linkInfo.name = link->getName(); linkInfo.type = link->getValueTypeString(); linkInfo.value = link->getValueString(); - // linkInfo.value = link->getLinkedPath(); - // linkInfo.value = link->getPath(); std::string replaceValue = "//"; std::size_t pos = linkInfo.value.find(replaceValue); @@ -792,15 +780,19 @@ void Base::loadDataSnapshot(const std::shared_ptr& sna dataValueStr.erase(std::remove(dataValueStr.begin(), dataValueStr.end(), ','), dataValueStr.end()); data->read(dataValueStr); } - else - data->read(dataInfo.value); + else { + // std::cout << "Object ? " << this->getName() << ", data : " << dataInfo.name << std::endl; + if(data->read(dataInfo.value) == 0) + std::cout << "[" << this->getName() << "] " <<"read is false for " << dataInfo.name << " : " << dataInfo.value << std::endl; + + } + } } } void Base::loadLinkSnapshot(const std::shared_ptr& snapshotObject) const { - //if ( this->getClassName() != "Node") for (const auto& linkInfo : snapshotObject->m_linkContainer) { if (const auto link = this->findLink(linkInfo.name)) @@ -821,7 +813,7 @@ void Base::loadLinkSnapshot(const std::shared_ptr& sna link->add(obj, newSublink); } } - // How to detect if a link is depracted ? + // How do I detect if a link is useless ? // for (const auto& oldLink : ) // { // if (std::ranges::find(newSublinks,oldLink) == newSublinks.end()) diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.cpp index 1447e0d9636..4e7911aae3f 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.cpp @@ -26,4 +26,8 @@ namespace sofa::core::objectmodel Snapshot::Snapshot() = default; Snapshot::~Snapshot() = default; + +std::size_t Snapshot::getNumberChildren() { + return m_graphRoot->children.size(); +} } // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.h index b6c13b66044..d089b7bed1d 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.h @@ -116,7 +116,8 @@ class SOFA_CORE_API Snapshot ~SnapshotNode() noexcept override = default; }; - std::shared_ptr m_graphRoot { nullptr }; + std::shared_ptr m_graphRoot {nullptr}; + std::size_t getNumberChildren(); Snapshot(); virtual ~Snapshot(); diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp index 4ca0e451d9b..79fc0ca0989 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp @@ -230,8 +230,7 @@ void importFrom(Snapshot& snapshot, const std::string& filename) std::cout << "JSON imported successfully from: " << filename << std::endl; } - -std::string to_String(const std::string& filename) +std::string file_To_String(const std::string& filename) { std::ifstream file(filename); if (!file.is_open()) @@ -246,4 +245,9 @@ std::string to_String(const std::string& filename) return to_string(jsonRoot); } +std::string snapshot_To_String(const Snapshot& snapshot) +{ + nlohmann::json j = snapshot.m_graphRoot ; + return to_string(j); +} } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h index 3db8483f9a7..0a6e932f81a 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h @@ -27,4 +27,6 @@ namespace sofa::core::objectmodel { void exportTo(Snapshot& snapshot, const std::string& filename); void importFrom(Snapshot& snapshot, const std::string& filename); + std::string file_To_String(const std::string& filename); + std::string snapshot_To_String(const Snapshot& snapshot); } // namespace sofa::core::objectmodel \ No newline at end of file From a29f82698db56513bb1f361ecd0e95a58e8629ef Mon Sep 17 00:00:00 2001 From: Lucas-TJ Date: Tue, 5 May 2026 09:19:30 +0200 Subject: [PATCH 33/57] update Snapshot and JSONExporter --- .../Core/src/sofa/core/objectmodel/Base.cpp | 27 ++++-- .../Core/src/sofa/core/objectmodel/Base.h | 5 +- .../src/sofa/core/objectmodel/Snapshot.cpp | 3 - .../Core/src/sofa/core/objectmodel/Snapshot.h | 7 +- .../core/objectmodel/SnapshotJSONExporter.cpp | 87 ++++++++++++++++++- .../core/objectmodel/SnapshotJSONExporter.h | 4 + .../sofa/core/objectmodel/SnapshotManager.cpp | 6 +- .../sofa/core/objectmodel/SnapshotManager.h | 3 +- .../simulation/LoadDataSnapshotVisitor.cpp | 5 +- .../simulation/LoadLinkSnapshotVisitor.cpp | 1 - .../sofa/simulation/SaveSnapshotVisitor.cpp | 2 - .../src/sofa/simulation/SaveSnapshotVisitor.h | 3 - 12 files changed, 119 insertions(+), 34 deletions(-) diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index a5a5eb5fe94..5d6e1ebf9b3 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -683,6 +683,7 @@ int Base::getInstanciationSourceFilePos() const return m_instanciationSourceFilePos; } +/// Save datas in a SnapshotObject void Base::saveDataIn(Snapshot::SnapshotObject& snapshot) const { for (const auto& dataFields = this->getDataFields(); const auto& data : dataFields) @@ -696,6 +697,7 @@ void Base::saveDataIn(Snapshot::SnapshotObject& snapshot) const } } +/// Save links in a SnapshotObject void Base::saveLinksIn(Snapshot::SnapshotObject& snapshot) const { for (const auto& links = this->getLinks(); const auto& link : links) @@ -705,6 +707,7 @@ void Base::saveLinksIn(Snapshot::SnapshotObject& snapshot) const linkInfo.type = link->getValueTypeString(); linkInfo.value = link->getValueString(); + // Think about it std::string replaceValue = "//"; std::size_t pos = linkInfo.value.find(replaceValue); while (pos != std::string::npos) @@ -717,9 +720,11 @@ void Base::saveLinksIn(Snapshot::SnapshotObject& snapshot) const } } -// void Base::saveInternalStateIn(Snapshot::SnapshotObject& snapshot) const -// {} +void Base::saveInternalStateIn(Snapshot::SnapshotObject& snapshot) const { + SOFA_UNUSED(snapshot); +} +/// Create a SnapshotObject from the component to save in the snapshot std::shared_ptr Base::createSnapshotObject(std::vector>& parents) const { @@ -734,18 +739,19 @@ Base::createSnapshotObject(std::vector>& return object; } +/// Save the component in the snapshot std::shared_ptr Base::saveSnapshot(std::vector>& parents) const { const auto snapshotObject = createSnapshotObject(parents); snapshotObject->m_name = this->getName(); saveDataIn(*snapshotObject); saveLinksIn(*snapshotObject); - //saveInternalStateIn(*snapshotObject); + saveInternalStateIn(*snapshotObject); return snapshotObject; } - +/// Find the SnapshotObject in the graph with the object's name std::shared_ptr Base::findSnapshotObject(const std::shared_ptr& parents, const std::string& objectname) { @@ -764,7 +770,12 @@ Base::findSnapshotObject(const std::shared_ptr& parents, return defaultObject; } +void Base::loadInternalStateFrom(const Snapshot::SnapshotObject& snapshot) const +{ + SOFA_UNUSED(snapshot); +} +/// Load datas from the snapshot to the scene void Base::loadDataSnapshot(const std::shared_ptr& snapshotObject) const { for (const auto& dataInfo : snapshotObject->m_dataContainer) @@ -781,8 +792,7 @@ void Base::loadDataSnapshot(const std::shared_ptr& sna data->read(dataValueStr); } else { - // std::cout << "Object ? " << this->getName() << ", data : " << dataInfo.name << std::endl; - if(data->read(dataInfo.value) == 0) + if(data->read(dataInfo.value) == 0 ) std::cout << "[" << this->getName() << "] " <<"read is false for " << dataInfo.name << " : " << dataInfo.value << std::endl; } @@ -791,15 +801,13 @@ void Base::loadDataSnapshot(const std::shared_ptr& sna } } +/// Load links from the snapshot to the scene void Base::loadLinkSnapshot(const std::shared_ptr& snapshotObject) const { for (const auto& linkInfo : snapshotObject->m_linkContainer) { if (const auto link = this->findLink(linkInfo.name)) { - // std::cout << "===========link name : " << linkInfo.name << std::endl; - // std::cout << "===========link value : " << linkInfo.value << std::endl; - // link->read(linkInfo.value); // Idea : Compare links in the snapshot and in the simulation, and change/add targets to the link @@ -813,6 +821,7 @@ void Base::loadLinkSnapshot(const std::shared_ptr& sna link->add(obj, newSublink); } } + // How do I detect if a link is useless ? // for (const auto& oldLink : ) // { diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h index 087a9c97e0f..248bfe63582 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h @@ -369,11 +369,12 @@ class SOFA_CORE_API Base : public IntrusiveObject protected: void saveDataIn(Snapshot::SnapshotObject& snapshot) const; void saveLinksIn(Snapshot::SnapshotObject& snapshot) const; - //virtual void saveInternalStateIn(SnapshotObject& snapshot) const; + virtual std::shared_ptr createSnapshotObject(std::vector>& parents) const; public : virtual std::shared_ptr findSnapshotObject(const std::shared_ptr& parents, const std::string& objectname); - + virtual void saveInternalStateIn(Snapshot::SnapshotObject& snapshot) const; + virtual void loadInternalStateFrom(const Snapshot::SnapshotObject& snapshot) const; protected: /// List of fields (Data instances) VecData m_vecData; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.cpp index 4e7911aae3f..a28a3897eee 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.cpp @@ -27,7 +27,4 @@ namespace sofa::core::objectmodel Snapshot::Snapshot() = default; Snapshot::~Snapshot() = default; -std::size_t Snapshot::getNumberChildren() { - return m_graphRoot->children.size(); -} } // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.h index d089b7bed1d..360088aedd8 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.h @@ -35,7 +35,7 @@ namespace sofa::core::objectmodel * \brief Class for snapshot * * This class contains the structure for a snapshot of a simulation in SOFA. -* The snapshot contains datas and links, and keep to shape of a scene graph +* The snapshot contains datas and links, and keep the shape of a scene graph */ class SOFA_CORE_API Snapshot @@ -61,7 +61,7 @@ class SOFA_CORE_API Snapshot std::string m_name; std::vector m_dataContainer; std::vector m_linkContainer; - //void* m_internalState { nullptr }; + void* m_internalState { nullptr }; virtual void clear() @@ -117,11 +117,10 @@ class SOFA_CORE_API Snapshot }; std::shared_ptr m_graphRoot {nullptr}; - std::size_t getNumberChildren(); Snapshot(); virtual ~Snapshot(); -}; +}; } // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp index 79fc0ca0989..3f333e8a131 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp @@ -25,6 +25,8 @@ #include #include + + namespace sofa::core::objectmodel { @@ -198,7 +200,7 @@ void from_json(const nlohmann::json& j, Snapshot::SnapshotNode& sn) } } } - + void importFrom(Snapshot& snapshot, const std::string& filename) { std::ifstream file(filename); @@ -250,4 +252,87 @@ std::string snapshot_To_String(const Snapshot& snapshot) nlohmann::json j = snapshot.m_graphRoot ; return to_string(j); } + +void exportTo(std::map>& snapshots, const std::string& filename) +{ + std::ofstream file(filename); + + nlohmann::json j_all = nlohmann::json::array(); + + for (const auto& snapshotJson : snapshots) + { + j_all.push_back(snapshotJson.second->m_graphRoot); + } + file << j_all.dump(5); + file.close(); +} + +void importFrom(std::map>& snapshots, const std::string& filename) +{ + std::ifstream file(filename); + + if (!file.is_open()) + { + std::cerr << "ERROR: Cannot open file " << filename << " for reading\n"; + return; + } + + nlohmann::json j_all = nlohmann::json::array(); + file >> j_all; + file.close(); + + snapshots.clear(); + + int index = 0; + + for (const auto& snapshotJson : j_all) + { + auto snapshot = std::make_shared(); + + from_json(snapshotJson, *snapshot->m_graphRoot); + + std::string id; + + if (snapshot->m_graphRoot) + id = snapshot->m_graphRoot->m_name; + + if (id.empty()) + id="snapshot_"+ std::to_string(index++); + snapshot->m_graphRoot->m_name = id; + snapshots[id] = snapshot; + } +} + +void separateSnapshots(const std::string& filename, SnapshotManager& snapshotManager) +{ + std::ifstream file(filename); + + nlohmann::json jSnapshot; + + if (!file.is_open()) + { + msg_error("SnapshotJSONExporter") << "ERROR: Cannot open file " << filename << " for reading\n"; + return; + } + + file >> jSnapshot; + file.close(); + + for (const auto& snapshotJson : jSnapshot) + { + auto snapshot = std::make_shared(); + snapshot->m_graphRoot = std::make_shared(); + from_json(snapshotJson, *snapshot->m_graphRoot); + std::string snapshotTime = "0"; + for (const auto& data : snapshot->m_graphRoot->m_dataContainer) + { + if (data.name == "time") + snapshotTime = data.value; + } + + snapshotManager.AddRecentSnapshot(snapshotManager.recentSnapshots,snapshot, std::stod(snapshotTime)); + } + +} + } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h index 0a6e932f81a..d8fd4f6d4f2 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h @@ -22,6 +22,7 @@ #pragma once #include #include +#include namespace sofa::core::objectmodel { @@ -29,4 +30,7 @@ namespace sofa::core::objectmodel void importFrom(Snapshot& snapshot, const std::string& filename); std::string file_To_String(const std::string& filename); std::string snapshot_To_String(const Snapshot& snapshot); + void exportTo(std::map>& snapshots, const std::string& filename); + void importFrom(std::map>& snapshots, const std::string& filename); + void separateSnapshots(const std::string& filename, SnapshotManager& snapshotManager); } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.cpp index 0b210e3fe0e..28a82141040 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.cpp @@ -36,18 +36,16 @@ void SnapshotManager::AddRecentFile(const std::string& path, std::vector maxFiles) recentFiles.resize(maxFiles); } -void SnapshotManager::AddRecentSnapshot(std::map>& recentSnapshots, std::shared_ptr snapshot, double snapshotTime, int maxSnapshots) +void SnapshotManager::AddRecentSnapshot(std::map>& recentSnapshots, std::shared_ptr snapshot, double snapshotTime) { static int index = 0; recentSnapshots["Memory_Snapshot " + std::to_string(index++) + " at " + std::to_string(snapshotTime)] = snapshot; - if (recentSnapshots.size() > maxSnapshots) - recentSnapshots.erase(recentSnapshots.begin()); + } } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.h b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.h index be7b75c5064..01b626ebb98 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.h @@ -34,8 +34,9 @@ class SnapshotManager std::vector recentSnapshotFiles; std::map> recentSnapshots; + static void AddRecentFile(const std::string& path, std::vector& recentFiles, int maxFiles = 10); - static void AddRecentSnapshot(std::map>& recentSnapshots, std::shared_ptr snapshot, double snapshotTime, int maxSnapshots = 10); + static void AddRecentSnapshot(std::map>& recentSnapshots, std::shared_ptr snapshot, double snapshotTime ); }; } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.cpp index b9519eeba90..632076be85b 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.cpp @@ -33,6 +33,7 @@ void LoadDataSnapshotVisitor::processObject( { auto snapshotObject = obj->findSnapshotObject(parent, obj->getName()); obj->loadDataSnapshot(snapshotObject); + obj->loadInternalStateFrom(*snapshotObject); } Visitor::Result LoadDataSnapshotVisitor::processNodeTopDown(simulation::Node* node) @@ -40,7 +41,6 @@ Visitor::Result LoadDataSnapshotVisitor::processNodeTopDown(simulation::Node* no const auto snapshotObject = node->findSnapshotObject(m_snapshotContainer.m_graphRoot, node->getName()); if (!snapshotObject) msg_error("findSnapshotNode") << "SnapshotNode "<< node->getName() << " not found in "; - std::string nodeName = node->getName(); const auto SnapshotNode = std::dynamic_pointer_cast(snapshotObject); node->loadDataSnapshot(SnapshotNode); for (simulation::Node::ObjectIterator it = node->object.begin(); it != node->object.end(); ++it) @@ -51,6 +51,3 @@ Visitor::Result LoadDataSnapshotVisitor::processNodeTopDown(simulation::Node* no } } // namespace sofa::simulation - - - diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.cpp index 7219d94df54..f4f24800303 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.cpp @@ -20,7 +20,6 @@ * Contact information: contact@sofa-framework.org * ******************************************************************************/ #include -#include #include namespace sofa::simulation diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.cpp index 975d213df35..4e6c0e98412 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.cpp @@ -20,9 +20,7 @@ * Contact information: contact@sofa-framework.org * ******************************************************************************/ #include -#include #include -#include namespace sofa::simulation diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.h index 67296e07130..1aa4716753f 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SaveSnapshotVisitor.h @@ -20,10 +20,7 @@ * Contact information: contact@sofa-framework.org * ******************************************************************************/ #include -#include #include -#include -#include #include namespace sofa::simulation From 624be72144371fd0072b348eff5c4c0708461ea2 Mon Sep 17 00:00:00 2001 From: Lucas-TJ Date: Thu, 7 May 2026 16:28:00 +0200 Subject: [PATCH 34/57] update load data and link + clean --- .../fem/elastic/TetrahedronFEMForceField.inl | 4 -- .../Core/src/sofa/core/objectmodel/Base.cpp | 48 ++++++++----------- .../sofa/core/objectmodel/BaseComponent.cpp | 4 -- .../src/sofa/core/objectmodel/BaseNode.cpp | 3 +- testfile.json | 41 ---------------- 5 files changed, 21 insertions(+), 79 deletions(-) delete mode 100644 testfile.json diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedronFEMForceField.inl b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedronFEMForceField.inl index 4a57b2043f7..266ca6f8612 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedronFEMForceField.inl +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedronFEMForceField.inl @@ -759,10 +759,6 @@ inline void TetrahedronFEMForceField::computeRotationLarge( Transform // second vector in the plane of the two first edges // third vector orthogonal to first and second - // TODO : remove std::cout - std::cout << " p size : " << p.size() << std::endl; - std::cout << " a : " << a << " b : " << b << " c : " << c << std::endl; - const Coord edgex = (p[b]-p[a]).normalized(); Coord edgey = p[c]-p[a]; const Coord edgez = cross( edgex, edgey ).normalized(); diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index 5d6e1ebf9b3..40c413da89e 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -22,7 +22,6 @@ #define SOFA_CORE_OBJECTMODEL_BASE_CPP #include -#include #include #include #include @@ -38,6 +37,8 @@ using sofa::helper::logging::Message ; #include using sofa::helper::getClosestMatch; +#include + #include #include #include @@ -782,21 +783,8 @@ void Base::loadDataSnapshot(const std::shared_ptr& sna { if (const auto data = this->findData(dataInfo.name)) { - // If dataInfo.value is a vector like '["Value1", "Value2" ... "Value_i"]' - if (dataInfo.value[0] == '[' && dataInfo.value.back() == ']') { - std::string dataValueStr = dataInfo.value; - dataValueStr.erase(std::remove(dataValueStr.begin(), dataValueStr.end(), '['), dataValueStr.end()); - dataValueStr.erase(std::remove(dataValueStr.begin(), dataValueStr.end(), ']'), dataValueStr.end()); - dataValueStr.erase(std::remove(dataValueStr.begin(), dataValueStr.end(), '"'), dataValueStr.end()); - dataValueStr.erase(std::remove(dataValueStr.begin(), dataValueStr.end(), ','), dataValueStr.end()); - data->read(dataValueStr); - } - else { - if(data->read(dataInfo.value) == 0 ) - std::cout << "[" << this->getName() << "] " <<"read is false for " << dataInfo.name << " : " << dataInfo.value << std::endl; - - } - + if(data->read(dataInfo.value) == 0 ) + msg_error() << "Failed to read " << dataInfo.name << " : " << dataInfo.value; } } } @@ -804,32 +792,36 @@ void Base::loadDataSnapshot(const std::shared_ptr& sna /// Load links from the snapshot to the scene void Base::loadLinkSnapshot(const std::shared_ptr& snapshotObject) const { + std::vector linksFromSnapshot; + for (const auto& linkInfo : snapshotObject->m_linkContainer) { if (const auto link = this->findLink(linkInfo.name)) { - // link->read(linkInfo.value); - // Idea : Compare links in the snapshot and in the simulation, and change/add targets to the link std::vector newSublinks = helper::split(linkInfo.value, ' '); for (const auto& newSublink : newSublinks) { auto obj = PathResolver::FindBaseFromPath(link->getOwner(), newSublink); - bool checkedPath = PathResolver::CheckPath(obj,link->getDestClass(),newSublink); - if (!checkedPath) + if ( obj != nullptr) { - link->add(obj, newSublink); + linksFromSnapshot.push_back(obj); } } - - // How do I detect if a link is useless ? - // for (const auto& oldLink : ) - // { - // if (std::ranges::find(newSublinks,oldLink) == newSublinks.end()) - // link->removePath(oldLink); - // } + std::size_t i = 0; + for (const auto& linkFromSnapshot : linksFromSnapshot) + { + std::string linkName = linkFromSnapshot->getName(); + Base* linkedBase = link->getLinkedBase(i); + if (linkedBase != linkFromSnapshot || linkedBase != nullptr) + link->add(linkFromSnapshot,linkName); + else + link->remove(linkedBase); + i+=1; + } } } + } } // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseComponent.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseComponent.cpp index b632cf093c6..827aa9659bb 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseComponent.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseComponent.cpp @@ -178,13 +178,9 @@ void BaseComponent::setSrc(const std::string &valueString, const BaseComponent * Base* BaseComponent::findLinkDestClass(const BaseClass* destType, const std::string& path, const BaseLink* link) { if (this->getContext() == BaseContext::getDefault()) - { return nullptr; - } else - { return this->getContext()->findLinkDestClass(destType, path, link); - } } diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp index 774b9fdf85a..2c4d082967d 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.cpp @@ -19,14 +19,13 @@ * * * Contact information: contact@sofa-framework.org * ******************************************************************************/ -#include #include #include #include #include #include #include - +#include namespace sofa::core::objectmodel { diff --git a/testfile.json b/testfile.json deleted file mode 100644 index 7fec0652566..00000000000 --- a/testfile.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "children": [ - { - "children": [ - { - "children": [], - "components": [ - { - "datas": [], - "links": [], - "name": "snapshotObject2" - } - ], - "datas": [], - "links": [], - "name": "snapshotNode2" - } - ], - "components": [ - { - "datas": [], - "links": [], - "name": "snapshotObject1" - } - ], - "datas": [], - "links": [], - "name": "snapshotNode1" - } - ], - "components": [ - { - "datas": [], - "links": [], - "name": "snapshotObject0" - } - ], - "datas": [], - "links": [], - "name": "root" -} \ No newline at end of file From aeaab5984455a9b637d8bf611f0711da242c982b Mon Sep 17 00:00:00 2001 From: Lucas-TJ Date: Mon, 11 May 2026 14:42:22 +0200 Subject: [PATCH 35/57] update LoadSnapshotVisitor --- .../Core/src/sofa/core/objectmodel/Base.cpp | 20 +++---- Sofa/framework/Simulation/Core/CMakeLists.txt | 2 + .../sofa/simulation/LoadSnapshotVisitor.cpp | 55 +++++++++++++++++++ .../src/sofa/simulation/LoadSnapshotVisitor.h | 45 +++++++++++++++ 4 files changed, 112 insertions(+), 10 deletions(-) create mode 100644 Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp create mode 100644 Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.h diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index 40c413da89e..933f4776446 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -809,16 +809,16 @@ void Base::loadLinkSnapshot(const std::shared_ptr& sna } } std::size_t i = 0; - for (const auto& linkFromSnapshot : linksFromSnapshot) - { - std::string linkName = linkFromSnapshot->getName(); - Base* linkedBase = link->getLinkedBase(i); - if (linkedBase != linkFromSnapshot || linkedBase != nullptr) - link->add(linkFromSnapshot,linkName); - else - link->remove(linkedBase); - i+=1; - } + // for (const auto& linkFromSnapshot : linksFromSnapshot) + // { + // std::string linkName = linkFromSnapshot->getName(); + // Base* linkedBase = link->getLinkedBase(i); + // if (linkedBase != linkFromSnapshot || linkedBase != nullptr) + // link->add(linkFromSnapshot,linkName); + // else + // link->remove(linkedBase); + // i+=1; + // } } } diff --git a/Sofa/framework/Simulation/Core/CMakeLists.txt b/Sofa/framework/Simulation/Core/CMakeLists.txt index bd7f741d610..63af1b4a06b 100644 --- a/Sofa/framework/Simulation/Core/CMakeLists.txt +++ b/Sofa/framework/Simulation/Core/CMakeLists.txt @@ -27,6 +27,7 @@ set(HEADER_FILES ${SRC_ROOT}/InitVisitor.h ${SRC_ROOT}/IntegrateBeginEvent.h ${SRC_ROOT}/IntegrateEndEvent.h + ${SRC_ROOT}/LoadSnapshotVisitor.h ${SRC_ROOT}/LoadDataSnapshotVisitor.h ${SRC_ROOT}/LoadLinkSnapshotVisitor.h ${SRC_ROOT}/MechanicalOperations.h @@ -171,6 +172,7 @@ set(SOURCE_FILES ${SRC_ROOT}/InitVisitor.cpp ${SRC_ROOT}/IntegrateBeginEvent.cpp ${SRC_ROOT}/IntegrateEndEvent.cpp + ${SRC_ROOT}/LoadSnapshotVisitor.cpp ${SRC_ROOT}/LoadDataSnapshotVisitor.cpp ${SRC_ROOT}/LoadLinkSnapshotVisitor.cpp ${SRC_ROOT}/MappingGraph.cpp diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp new file mode 100644 index 00000000000..8dcf3350027 --- /dev/null +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp @@ -0,0 +1,55 @@ +/****************************************************************************** +* 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 + +namespace sofa::simulation +{ + +void LoadSnapshotVisitor::processObject( + core::objectmodel::BaseObject* obj, + const std::shared_ptr& parent +) +{ + auto snapshotObject = obj->findSnapshotObject(parent, obj->getName()); + obj->loadDataSnapshot(snapshotObject); + obj->loadLinkSnapshot(snapshotObject); + // obj->loadInternalStateFrom(*snapshotObject); +} + +Visitor::Result LoadSnapshotVisitor::processNodeTopDown(simulation::Node* node) +{ + const auto snapshotObject = node->findSnapshotObject(m_snapshotContainer.m_graphRoot, node->getName()); + if (!snapshotObject) + msg_error("findSnapshotNode") << "SnapshotNode "<< node->getName() << " not found in "; + const auto SnapshotNode = std::dynamic_pointer_cast(snapshotObject); + node->loadDataSnapshot(SnapshotNode); + node->loadLinkSnapshot(SnapshotNode); + for (simulation::Node::ObjectIterator it = node->object.begin(); it != node->object.end(); ++it) + { + this->processObject(it->get(), SnapshotNode); + } + return RESULT_CONTINUE; +} + +} // namespace sofa::simulation diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.h new file mode 100644 index 00000000000..fe0e2154c67 --- /dev/null +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.h @@ -0,0 +1,45 @@ +/****************************************************************************** +* 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 * +******************************************************************************/ +#pragma once +#include +#include + +namespace sofa::simulation +{ + +class SOFA_SIMULATION_CORE_API LoadSnapshotVisitor : public Visitor +{ +protected: + core::objectmodel::Snapshot& m_snapshotContainer; + +public: + LoadSnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::Snapshot& snapshot) : Visitor(eparams), m_snapshotContainer(snapshot) {} + + void processObject(core::objectmodel::BaseObject* obj, const std::shared_ptr& parent); + + Result processNodeTopDown(simulation::Node* node) override; + const char* getClassName() const override { return "LoadDataSnapshotVisitor"; } + +}; + +} // namespace sofa::simulation + From 59ae206644c959c387d8e7d5770c64e981a9a515 Mon Sep 17 00:00:00 2001 From: Lucas-TJ Date: Mon, 11 May 2026 16:54:23 +0200 Subject: [PATCH 36/57] clean --- Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp | 2 +- .../Core/src/sofa/simulation/LoadSnapshotVisitor.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index 933f4776446..174ccad22eb 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -784,7 +784,7 @@ void Base::loadDataSnapshot(const std::shared_ptr& sna if (const auto data = this->findData(dataInfo.name)) { if(data->read(dataInfo.value) == 0 ) - msg_error() << "Failed to read " << dataInfo.name << " : " << dataInfo.value; + msg_error("LoadSnapshot") << "Failed to read " << dataInfo.name << " from the snapshot: " << dataInfo.value; } } } diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp index 8dcf3350027..4f816142a86 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp @@ -33,7 +33,7 @@ void LoadSnapshotVisitor::processObject( { auto snapshotObject = obj->findSnapshotObject(parent, obj->getName()); obj->loadDataSnapshot(snapshotObject); - obj->loadLinkSnapshot(snapshotObject); + // obj->loadLinkSnapshot(snapshotObject); // obj->loadInternalStateFrom(*snapshotObject); } @@ -44,7 +44,7 @@ Visitor::Result LoadSnapshotVisitor::processNodeTopDown(simulation::Node* node) msg_error("findSnapshotNode") << "SnapshotNode "<< node->getName() << " not found in "; const auto SnapshotNode = std::dynamic_pointer_cast(snapshotObject); node->loadDataSnapshot(SnapshotNode); - node->loadLinkSnapshot(SnapshotNode); + // node->loadLinkSnapshot(SnapshotNode); for (simulation::Node::ObjectIterator it = node->object.begin(); it != node->object.end(); ++it) { this->processObject(it->get(), SnapshotNode); From f134ba586b2b3f77ef249243a0147574009c6e17 Mon Sep 17 00:00:00 2001 From: Lucas-TJ Date: Thu, 21 May 2026 11:26:04 +0200 Subject: [PATCH 37/57] update --- .../Core/simutest/objectmodel/Snapshot_test.cpp | 3 ++- .../Core/src/sofa/core/objectmodel/Base.cpp | 8 -------- .../Core/src/sofa/core/objectmodel/Base.h | 16 ++++++++++++++++ .../Core/src/sofa/core/objectmodel/Snapshot.h | 2 +- .../sofa/core/objectmodel/SnapshotJSONExporter.h | 15 +++++++++++++++ .../src/sofa/core/objectmodel/SnapshotManager.h | 6 ++++++ 6 files changed, 40 insertions(+), 10 deletions(-) diff --git a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp index 0ef7ea05d84..ad702c76dfc 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp @@ -49,7 +49,7 @@ using sofa::simulation::LoadLinkSnapshotVisitor; #include using sofa::core::objectmodel::Data; using sofa::core::objectmodel::BaseLink; -using sofa::core::objectmodel::SingleLink ; +using sofa::core::objectmodel::SingleLink; using sofa::core::objectmodel::Snapshot; using sofa::core::objectmodel::BaseNode; @@ -120,6 +120,7 @@ TEST_F(Snapshot_test, saveLinkIn) { // TEST of saveLinksIn method // Check if the snapshot contains the component with expected data + TestComponent tComponent; auto snapshot = std::make_shared(); diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index 174ccad22eb..3059b6ac00f 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -684,7 +684,6 @@ int Base::getInstanciationSourceFilePos() const return m_instanciationSourceFilePos; } -/// Save datas in a SnapshotObject void Base::saveDataIn(Snapshot::SnapshotObject& snapshot) const { for (const auto& dataFields = this->getDataFields(); const auto& data : dataFields) @@ -698,7 +697,6 @@ void Base::saveDataIn(Snapshot::SnapshotObject& snapshot) const } } -/// Save links in a SnapshotObject void Base::saveLinksIn(Snapshot::SnapshotObject& snapshot) const { for (const auto& links = this->getLinks(); const auto& link : links) @@ -708,7 +706,6 @@ void Base::saveLinksIn(Snapshot::SnapshotObject& snapshot) const linkInfo.type = link->getValueTypeString(); linkInfo.value = link->getValueString(); - // Think about it std::string replaceValue = "//"; std::size_t pos = linkInfo.value.find(replaceValue); while (pos != std::string::npos) @@ -725,7 +722,6 @@ void Base::saveInternalStateIn(Snapshot::SnapshotObject& snapshot) const { SOFA_UNUSED(snapshot); } -/// Create a SnapshotObject from the component to save in the snapshot std::shared_ptr Base::createSnapshotObject(std::vector>& parents) const { @@ -740,7 +736,6 @@ Base::createSnapshotObject(std::vector>& return object; } -/// Save the component in the snapshot std::shared_ptr Base::saveSnapshot(std::vector>& parents) const { const auto snapshotObject = createSnapshotObject(parents); @@ -752,7 +747,6 @@ std::shared_ptr Base::saveSnapshot(std::vector Base::findSnapshotObject(const std::shared_ptr& parents, const std::string& objectname) { @@ -776,7 +770,6 @@ void Base::loadInternalStateFrom(const Snapshot::SnapshotObject& snapshot) const SOFA_UNUSED(snapshot); } -/// Load datas from the snapshot to the scene void Base::loadDataSnapshot(const std::shared_ptr& snapshotObject) const { for (const auto& dataInfo : snapshotObject->m_dataContainer) @@ -789,7 +782,6 @@ void Base::loadDataSnapshot(const std::shared_ptr& sna } } -/// Load links from the snapshot to the scene void Base::loadLinkSnapshot(const std::shared_ptr& snapshotObject) const { std::vector linksFromSnapshot; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h index 248bfe63582..5d8c4eba240 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h @@ -362,18 +362,34 @@ class SOFA_CORE_API Base : public IntrusiveObject ///@} + /// Save a SnapshotObject full of data and link into the snapshot std::shared_ptr saveSnapshot(std::vector>& parents) const; + + /// Load data from the snapshot to the scene void loadDataSnapshot(const std::shared_ptr& snapshotObject) const; + + /// Load link from the snapshot to the scene void loadLinkSnapshot(const std::shared_ptr& snapshotObject) const; protected: + + /// Save data from an object to the SnapshotObject void saveDataIn(Snapshot::SnapshotObject& snapshot) const; + + /// Save link from an object to the SnapshotObject void saveLinksIn(Snapshot::SnapshotObject& snapshot) const; + /// Create a SnapshotObject that will contain data and link virtual std::shared_ptr createSnapshotObject(std::vector>& parents) const; public : + + /// Find a SnapshotObject corresponding to the object from the scene virtual std::shared_ptr findSnapshotObject(const std::shared_ptr& parents, const std::string& objectname); + + /// Save Internal State to the SnapshotObject virtual void saveInternalStateIn(Snapshot::SnapshotObject& snapshot) const; + + ///Load Internal State from a snapshot to the scene virtual void loadInternalStateFrom(const Snapshot::SnapshotObject& snapshot) const; protected: /// List of fields (Data instances) diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.h index 360088aedd8..9c04f642d1b 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.h @@ -35,7 +35,7 @@ namespace sofa::core::objectmodel * \brief Class for snapshot * * This class contains the structure for a snapshot of a simulation in SOFA. -* The snapshot contains datas and links, and keep the shape of a scene graph +* The snapshot contains data and link, and keep the shape of a scene graph */ class SOFA_CORE_API Snapshot diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h index d8fd4f6d4f2..809bef9b4ad 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h @@ -26,11 +26,26 @@ namespace sofa::core::objectmodel { + + /// Export a single Snapshot to a JSON file void exportTo(Snapshot& snapshot, const std::string& filename); + + /// Import a single Snapshot from a JSON file void importFrom(Snapshot& snapshot, const std::string& filename); + + /// Read a JSON file and returns its content as a string std::string file_To_String(const std::string& filename); + + /// Serialize a Snapshot to a JSON string std::string snapshot_To_String(const Snapshot& snapshot); + + /// Export a collection of Snapshots to a single JSON file void exportTo(std::map>& snapshots, const std::string& filename); + + /// Import a collection of Snapshots from a single JSON file void importFrom(std::map>& snapshots, const std::string& filename); + + /// Parses a multi-snapshot JSON file and registers each snapshot with a SnapshotManager void separateSnapshots(const std::string& filename, SnapshotManager& snapshotManager); + } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.h b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.h index 01b626ebb98..55cd95ff871 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.h @@ -25,6 +25,12 @@ namespace sofa::core::objectmodel { + +/** +* \brief Snapshot Class for a container of snapshot +* +* This class contains methods and elements that will help to manage snapshot in memory. +*/ class SnapshotManager { public: From 6aade44d03c945e1a77dc476cb6cb49f493e124d Mon Sep 17 00:00:00 2001 From: Lucas-TJ Date: Thu, 21 May 2026 13:42:26 +0200 Subject: [PATCH 38/57] update --- .../TetrahedralCorotationalFEMForceField.h | 31 +++++++++++++++++-- examples/Demos/liver.scn | 10 +++--- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedralCorotationalFEMForceField.h b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedralCorotationalFEMForceField.h index d5116e2f8ea..df65c009020 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedralCorotationalFEMForceField.h +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedralCorotationalFEMForceField.h @@ -113,14 +113,41 @@ class TetrahedralCorotationalFEMForceField : public BaseLinearElasticityFEMForce } /// Output stream - inline friend std::ostream& operator<< ( std::ostream& os, const TetrahedronInformation& /*tri*/ ) + inline friend std::ostream& operator<< ( std::ostream& os, const TetrahedronInformation& tri ) { + // MaterialStiffness (MatrixSym or Mat — has operator<< in SOFA) + os << tri.materialMatrix << " "; + + // StrainDisplacementTransposed (Mat type — has operator<< in SOFA) + os << tri.strainDisplacementTransposedMatrix << " "; + + // fixed_array + for (int i = 0; i < 4; ++i) + os << tri.rotatedInitialElements[i] << " "; + + // Mat<4, 4, Real> + os << tri.elemShapeFun << " "; + + // Transformation (Mat<3,3,Real> — has operator<< in SOFA) + os << tri.rotation << " "; + + // Transformation + os << tri.initialTransformation << " "; return os; } /// Input stream - inline friend std::istream& operator>> ( std::istream& in, TetrahedronInformation& /*tri*/ ) + inline friend std::istream& operator>> ( std::istream& in, TetrahedronInformation& tri ) { + in >> tri.materialMatrix; + in >> tri.strainDisplacementTransposedMatrix; + + for (int i = 0; i < 4; ++i) + in >> tri.rotatedInitialElements[i]; + + in >> tri.elemShapeFun; + in >> tri.rotation; + in >> tri.initialTransformation; return in; } }; diff --git a/examples/Demos/liver.scn b/examples/Demos/liver.scn index 6b93edffdef..eddef65ad19 100644 --- a/examples/Demos/liver.scn +++ b/examples/Demos/liver.scn @@ -19,30 +19,30 @@ - + - + - + - + - + From 1c08261f46cf2a84231885ce9d464933fe1b97cd Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Mon, 22 Dec 2025 16:39:09 +0100 Subject: [PATCH 39/57] cleaning add functions --- .../sofa/core/objectmodel/BaseComponent.cpp | 2 +- .../Core/src/sofa/core/objectmodel/BaseLink.h | 2 + .../Core/src/sofa/core/objectmodel/Link.h | 52 ++++++++++--------- .../Core/src/sofa/simulation/Node.cpp | 4 +- 4 files changed, 33 insertions(+), 27 deletions(-) diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseComponent.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseComponent.cpp index 827aa9659bb..fb2b16f2d8f 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseComponent.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseComponent.cpp @@ -225,7 +225,7 @@ void BaseComponent::addSlave(BaseComponent::SPtr s) if (previous == this) return; if (previous) previous->l_slaves.remove(s); - l_slaves.add(s); + l_slaves.add(s.get()); if (previous) this->getContext()->notifyMoveSlave(previous.get(), this, s.get()); else diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.h index 57c5e561344..9a92d15deb2 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.h @@ -171,6 +171,7 @@ class SOFA_CORE_API BaseLink /// Add a new target to the link. bool add(Base* baseptr, const std::string& path) { return _doAdd_(baseptr, path); } + bool add(Base* baseptr) { return _doAdd_(baseptr); } /// Change the link's target at the provided index. bool set(Base* baseptr, size_t index=0) { return _doSet_(baseptr, index); } @@ -183,6 +184,7 @@ class SOFA_CORE_API BaseLink virtual void _doSetOwner_(Base* owner) = 0; virtual Base* _doGet_(const size_t=0) const = 0; virtual bool _doAdd_(Base* target, const std::string&) = 0; + virtual bool _doAdd_(Base*) = 0; virtual void _doClear_() = 0; virtual std::string _doGetLinkedPath_(const size_t=0) const = 0; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Link.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Link.h index 88aa5fb8266..f29386c3e9e 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Link.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Link.h @@ -377,27 +377,6 @@ class TLink : public BaseLink return true; } - bool add(DestPtr v) - { - if (!v) - return false; - const std::size_t index = TraitsContainer::add(m_value,v); - updateCounter(); - added(v, index); - return true; - } - - bool add(DestPtr v, const std::string& path) - { - if (!v && path.empty()) - return false; - std::size_t index = TraitsContainer::add(m_value,v); - TraitsValueType::setPath(m_value[index],path); - updateCounter(); - added(v, index); - return true; - } - bool addPath(const std::string& path) { if (path.empty()) @@ -503,7 +482,32 @@ class TLink : public BaseLink } /// TLink:adding accepts nullptr (for a not yet resolved link). - return TLink::add(destptr, path); + std::size_t index = TraitsContainer::add(m_value, destptr); + TraitsValueType::setPath(m_value[index], path); + updateCounter(); + added(destptr, index); + return true; + } + + bool _doAdd_(Base* baseptr) override + { + /// If the pointer is null and the path empty we do nothing + if(!baseptr) + return false; + + /// Downcast the pointer to a compatible type and + /// If the types are not compatible with the Link we returns false + auto destptr = castTo(baseptr); + if(!destptr) + { + return false; + } + + /// TLink:adding accepts nullptr (for a not yet resolved link). + const std::size_t index = TraitsContainer::add(m_value, destptr); + updateCounter(); + added(destptr, index); + return true;; } /// Returns false on type mismatch @@ -577,7 +581,7 @@ class MultiLink : public TLink& init, DestPtr val) : Inherit(init), m_validator(nullptr) { - if (val) this->add(val); + if (val) this->_doAdd_(sofa::core::castToBase(TraitsDestPtr::get(val))); } virtual ~MultiLink() @@ -654,7 +658,7 @@ class SingleLink : public TLink& init, DestPtr val) : Inherit(init), m_validator(nullptr) { - if (val) this->add(val); + if (val) this->_doAdd_(sofa::core::castToBase(TraitsDestPtr::get(val))); } virtual ~SingleLink() diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.cpp index bcc0dd329fa..97bc1e887c6 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.cpp @@ -628,7 +628,7 @@ bool Node::doAddObject(sofa::core::objectmodel::BaseComponent::SPtr sobj, sofa:: { this->setObjectContext(sobj); if(insertionLocation == sofa::core::objectmodel::TypeOfInsertion::AtEnd) - object.add(sobj); + object.add(sobj.get()); else object.addBegin(sobj); @@ -1175,7 +1175,7 @@ void Node::doAddChild(BaseNode::SPtr node) { const Node::SPtr dagnode = sofa::core::objectmodel::SPtr_static_cast(node); setDirtyDescendancy(); - child.add(dagnode); + child.add(dagnode.get()); dagnode->l_parents.add(this); dagnode->l_parents.updateLinks(); // to fix load-time unresolved links } From 4e418d914018e6488cdc1e3400ae9e78b86f0401 Mon Sep 17 00:00:00 2001 From: Lucas-TJ Date: Thu, 21 May 2026 17:46:58 +0200 Subject: [PATCH 40/57] fix Output stream and Input stream for TetrahedronInformation --- Sofa/framework/Core/src/sofa/core/objectmodel/Link.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Link.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Link.h index f29386c3e9e..bc8061ac8d6 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Link.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Link.h @@ -387,11 +387,11 @@ class TLink : public BaseLink return add(ptr, path); } - bool remove(DestPtr v) + bool _doRemove_(Base* target) override { - if (!v) + if (!target) return false; - return removeAt(TraitsContainer::find(m_value,v)); + return removeAt(TraitsContainer::find(m_value,castTo(target))); } bool removeAt(std::size_t index) @@ -406,7 +406,7 @@ class TLink : public BaseLink return true; } - bool removePath(const std::string& path) override + bool removePath(const std::string& path) { if (path.empty()) return false; const std::size_t n = m_value.size(); From 22d5eacc997ffc501143289b7911f1788b7a34e4 Mon Sep 17 00:00:00 2001 From: Lucas-TJ Date: Thu, 21 May 2026 15:07:01 +0200 Subject: [PATCH 41/57] fix conflict --- .../Core/src/sofa/core/objectmodel/BaseComponent.cpp | 4 ++-- Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.h | 3 ++- Sofa/framework/Simulation/Core/src/sofa/simulation/Node.cpp | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseComponent.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseComponent.cpp index fb2b16f2d8f..25ce7a02211 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseComponent.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseComponent.cpp @@ -224,7 +224,7 @@ void BaseComponent::addSlave(BaseComponent::SPtr s) const BaseComponent::SPtr previous = s->getMaster(); if (previous == this) return; if (previous) - previous->l_slaves.remove(s); + previous->l_slaves.remove(s.get()); l_slaves.add(s.get()); if (previous) this->getContext()->notifyMoveSlave(previous.get(), this, s.get()); @@ -234,7 +234,7 @@ void BaseComponent::addSlave(BaseComponent::SPtr s) void BaseComponent::removeSlave(BaseComponent::SPtr s) { - if (l_slaves.remove(s)) + if (l_slaves.remove(s.get())) { this->getContext()->notifyRemoveSlave(this, s.get()); } diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.h index 9a92d15deb2..4c7c879f97b 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.h @@ -176,7 +176,7 @@ class SOFA_CORE_API BaseLink /// Change the link's target at the provided index. bool set(Base* baseptr, size_t index=0) { return _doSet_(baseptr, index); } - virtual bool removePath(const std::string& path) = 0; + bool remove(Base* baseptr) {return _doRemove_(baseptr); } protected: virtual bool _doSet_(Base* target, const size_t index=0) = 0; @@ -187,6 +187,7 @@ class SOFA_CORE_API BaseLink virtual bool _doAdd_(Base*) = 0; virtual void _doClear_() = 0; virtual std::string _doGetLinkedPath_(const size_t=0) const = 0; + virtual bool _doRemove_(Base* target) = 0; unsigned int m_flags; std::string m_name; diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.cpp index 97bc1e887c6..4e76301bdec 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/Node.cpp @@ -647,7 +647,7 @@ bool Node::doRemoveObject(sofa::core::objectmodel::BaseComponent::SPtr sobj) dmsg_warning_when(sobj == nullptr) << "Trying to remove a nullptr object"; this->clearObjectContext(sobj); - object.remove(sobj); + object.remove(sobj.get()); sofa::core::objectmodel::BaseComponent* obj = sobj.get(); if(obj != nullptr && !obj->removeInNode( this ) ) @@ -1185,7 +1185,7 @@ void Node::doRemoveChild(BaseNode::SPtr node) { const Node::SPtr dagnode = sofa::core::objectmodel::SPtr_static_cast(node); setDirtyDescendancy(); - child.remove(dagnode); + child.remove(dagnode.get()); dagnode->l_parents.remove(this); } From ebf7d4d1c77d03a38b686a1a95a758c9b76d00ec Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Thu, 28 May 2026 14:27:09 +0200 Subject: [PATCH 42/57] remove spaces from MultipleObjectsTwoCubes.scn --- .../Collision/MultipleObjectsTwoCubes.scn | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/examples/Tutorials/Collision/MultipleObjectsTwoCubes.scn b/examples/Tutorials/Collision/MultipleObjectsTwoCubes.scn index 8ab98c70dff..ec48437afbf 100644 --- a/examples/Tutorials/Collision/MultipleObjectsTwoCubes.scn +++ b/examples/Tutorials/Collision/MultipleObjectsTwoCubes.scn @@ -25,31 +25,31 @@ - - - - - - + + + + + + - + - - - - - - + + + + + + - - - + + + - - - + + + From 21364b8c8d9d37cc6ba3f7519a399f9d9db1ffaf Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Mon, 1 Jun 2026 10:44:44 +0200 Subject: [PATCH 43/57] update 01/06 - work in TriangleCollisionModel --- .../geometry/TriangleCollisionModel.h | 32 +++++++++++++++++++ .../geometry/TriangleCollisionModel.inl | 14 ++++++++ .../Core/src/sofa/core/objectmodel/Base.cpp | 3 +- .../Core/src/sofa/core/objectmodel/Base.h | 2 +- .../sofa/simulation/LoadSnapshotVisitor.cpp | 26 ++++++++++----- examples/Demos/collisionMultiple.scn | 6 ++-- .../Collision/ModelizationTriangleBased.scn | 14 ++++---- 7 files changed, 77 insertions(+), 20 deletions(-) diff --git a/Sofa/Component/Collision/Geometry/src/sofa/component/collision/geometry/TriangleCollisionModel.h b/Sofa/Component/Collision/Geometry/src/sofa/component/collision/geometry/TriangleCollisionModel.h index 712c6db49f6..430ee5ad80f 100644 --- a/Sofa/Component/Collision/Geometry/src/sofa/component/collision/geometry/TriangleCollisionModel.h +++ b/Sofa/Component/Collision/Geometry/src/sofa/component/collision/geometry/TriangleCollisionModel.h @@ -28,6 +28,7 @@ #include #include #include +#include namespace sofa::component::collision::geometry { @@ -193,6 +194,37 @@ class TriangleCollisionModel : public core::CollisionModel const VecDeriv& getNormals() const { return m_normals; } int getTriangleFlags(sofa::core::topology::BaseMeshTopology::TriangleID i); + void saveInternalStateIn(sofa::core::objectmodel::Snapshot::SnapshotObject& snapshot) const override + { + sofa::core::objectmodel::Snapshot::DataInfo dataInfo; + + std::stringstream ss; + this->m_triangles->write(ss); + // this->m_internalTriangles.write(ss); + dataInfo.name = "m_internalTriangles"; + dataInfo.type = "vector"; + dataInfo.value = ss.str(); + + snapshot.m_dataContainer.push_back(dataInfo); + } + + void loadInternalStateFrom(const core::objectmodel::Snapshot::SnapshotObject &snapshot) override + { + std::cout << "load 1" << std::endl; + for (const auto& dataInfo : snapshot.m_dataContainer) + { + if (dataInfo.name == "m_internalTriangles") + { + std::stringstream ss(dataInfo.value); + // Find a way to modify m_triangles... + this->m_triangles->read(ss); + // this->m_internalTriangles.read(ss); + // const_cast(m_triangles)->read(ss); + } + } + std::cout << "load 2" << std::endl; + } + Deriv velocity(sofa::Index index)const; diff --git a/Sofa/Component/Collision/Geometry/src/sofa/component/collision/geometry/TriangleCollisionModel.inl b/Sofa/Component/Collision/Geometry/src/sofa/component/collision/geometry/TriangleCollisionModel.inl index f2bc2b681ef..7056a25a387 100644 --- a/Sofa/Component/Collision/Geometry/src/sofa/component/collision/geometry/TriangleCollisionModel.inl +++ b/Sofa/Component/Collision/Geometry/src/sofa/component/collision/geometry/TriangleCollisionModel.inl @@ -247,6 +247,20 @@ void TriangleCollisionModel::computeBoundingTree(int maxDepth) const type::Vec3& pt1 = x[t.p1Index()]; const type::Vec3& pt2 = x[t.p2Index()]; const type::Vec3& pt3 = x[t.p3Index()]; + // std::cout << "x = " << x << std::endl; + // std::cout << "t is valid ? " << t.valid() << std::endl; + // std::cout << "t.p1Index() = " << t.p1Index() << std::endl; + // std::cout << "x size = " << x.size() << std::endl; + // std::cout << "pt1 = " << pt1 << " pt2 = " << pt2 << " pt3 = " << pt3 << std::endl; + // std::cout << "m_triangles ? " << (*(this->m_triangles)) << std::endl ; + // std::cout << "size m_triangles ? " << this->m_triangles->size()<< std::endl; + // std::cout << "size m_normals ? " << this->m_normals.size() << std::endl; + + // std::stringstream ss; + // this->m_triangles->write(ss); + // std::string str = ss.str(); + // std::cout << str << std::endl; + for (int c = 0; c < 3; c++) { diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index 3059b6ac00f..650789fe3da 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -765,9 +765,10 @@ Base::findSnapshotObject(const std::shared_ptr& parents, return defaultObject; } -void Base::loadInternalStateFrom(const Snapshot::SnapshotObject& snapshot) const +void Base::loadInternalStateFrom(const Snapshot::SnapshotObject& snapshot) { SOFA_UNUSED(snapshot); + } void Base::loadDataSnapshot(const std::shared_ptr& snapshotObject) const diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h index 5d8c4eba240..aa3a1d52a1a 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h @@ -390,7 +390,7 @@ public : virtual void saveInternalStateIn(Snapshot::SnapshotObject& snapshot) const; ///Load Internal State from a snapshot to the scene - virtual void loadInternalStateFrom(const Snapshot::SnapshotObject& snapshot) const; + virtual void loadInternalStateFrom(const Snapshot::SnapshotObject& snapshot) ; protected: /// List of fields (Data instances) VecData m_vecData; diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp index 4f816142a86..9317fb241d7 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp @@ -32,9 +32,15 @@ void LoadSnapshotVisitor::processObject( ) { auto snapshotObject = obj->findSnapshotObject(parent, obj->getName()); - obj->loadDataSnapshot(snapshotObject); - // obj->loadLinkSnapshot(snapshotObject); - // obj->loadInternalStateFrom(*snapshotObject); + if (!snapshotObject) + msg_error("findSnapshotObject") << "SnapshotObject " << obj->getName() << " not found in "; + else + { + obj->loadDataSnapshot(snapshotObject); + // obj->loadLinkSnapshot(snapshotObject); + obj->loadInternalStateFrom(*snapshotObject); + } + } Visitor::Result LoadSnapshotVisitor::processNodeTopDown(simulation::Node* node) @@ -42,13 +48,17 @@ Visitor::Result LoadSnapshotVisitor::processNodeTopDown(simulation::Node* node) const auto snapshotObject = node->findSnapshotObject(m_snapshotContainer.m_graphRoot, node->getName()); if (!snapshotObject) msg_error("findSnapshotNode") << "SnapshotNode "<< node->getName() << " not found in "; - const auto SnapshotNode = std::dynamic_pointer_cast(snapshotObject); - node->loadDataSnapshot(SnapshotNode); - // node->loadLinkSnapshot(SnapshotNode); - for (simulation::Node::ObjectIterator it = node->object.begin(); it != node->object.end(); ++it) + else { - this->processObject(it->get(), SnapshotNode); + const auto SnapshotNode = std::dynamic_pointer_cast(snapshotObject); + node->loadDataSnapshot(SnapshotNode); + // node->loadLinkSnapshot(SnapshotNode); + for (simulation::Node::ObjectIterator it = node->object.begin(); it != node->object.end(); ++it) + { + this->processObject(it->get(), SnapshotNode); + } } + return RESULT_CONTINUE; } diff --git a/examples/Demos/collisionMultiple.scn b/examples/Demos/collisionMultiple.scn index cd2ea9d47cd..fbee01a00fd 100644 --- a/examples/Demos/collisionMultiple.scn +++ b/examples/Demos/collisionMultiple.scn @@ -32,7 +32,7 @@ - + @@ -54,7 +54,7 @@ - + @@ -76,7 +76,7 @@ - + diff --git a/examples/Tutorials/Collision/ModelizationTriangleBased.scn b/examples/Tutorials/Collision/ModelizationTriangleBased.scn index b7d60e6dc42..ea42ae12083 100644 --- a/examples/Tutorials/Collision/ModelizationTriangleBased.scn +++ b/examples/Tutorials/Collision/ModelizationTriangleBased.scn @@ -24,19 +24,19 @@ - + - - - + + + - - - + + + From 882812667c373f54114de41ebef1e2e4f825d7dd Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Tue, 9 Jun 2026 10:02:59 +0200 Subject: [PATCH 44/57] update 09/06 - internal state loading TriangleCollisionModel --- .../geometry/TriangleCollisionModel.h | 25 +++++++++++-------- .../Core/src/sofa/core/objectmodel/Base.cpp | 2 +- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/Sofa/Component/Collision/Geometry/src/sofa/component/collision/geometry/TriangleCollisionModel.h b/Sofa/Component/Collision/Geometry/src/sofa/component/collision/geometry/TriangleCollisionModel.h index 430ee5ad80f..03f36a94453 100644 --- a/Sofa/Component/Collision/Geometry/src/sofa/component/collision/geometry/TriangleCollisionModel.h +++ b/Sofa/Component/Collision/Geometry/src/sofa/component/collision/geometry/TriangleCollisionModel.h @@ -200,29 +200,34 @@ class TriangleCollisionModel : public core::CollisionModel std::stringstream ss; this->m_triangles->write(ss); - // this->m_internalTriangles.write(ss); - dataInfo.name = "m_internalTriangles"; + + dataInfo.name = "m_triangles"; dataInfo.type = "vector"; dataInfo.value = ss.str(); snapshot.m_dataContainer.push_back(dataInfo); + } void loadInternalStateFrom(const core::objectmodel::Snapshot::SnapshotObject &snapshot) override { - std::cout << "load 1" << std::endl; for (const auto& dataInfo : snapshot.m_dataContainer) { - if (dataInfo.name == "m_internalTriangles") + if (dataInfo.name == "m_triangles") { - std::stringstream ss(dataInfo.value); - // Find a way to modify m_triangles... - this->m_triangles->read(ss); - // this->m_internalTriangles.read(ss); - // const_cast(m_triangles)->read(ss); + // std::stringstream ss(dataInfo.value); + // std::istringstream iss(dataInfo.value); + // this->m_internalTriangles.read(iss); + // m_triangles = &m_internalTriangles; + // m_needsUpdate = true; + + m_triangles = &m_topology->getTriangles(); + resize(m_topology->getNbTriangles()); + updateNormals(); + } + } - std::cout << "load 2" << std::endl; } Deriv velocity(sofa::Index index)const; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index 650789fe3da..0065238aa97 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -778,7 +778,7 @@ void Base::loadDataSnapshot(const std::shared_ptr& sna if (const auto data = this->findData(dataInfo.name)) { if(data->read(dataInfo.value) == 0 ) - msg_error("LoadSnapshot") << "Failed to read " << dataInfo.name << " from the snapshot: " << dataInfo.value; + msg_error("LoadSnapshot") << "Failed to read " << dataInfo.name << " in " << this->getName() << " from the snapshot " << dataInfo.value; } } } From d57985e0c2f5765906d5724dbe862d44e3e870c8 Mon Sep 17 00:00:00 2001 From: Lucas Burel Date: Mon, 15 Jun 2026 10:07:55 +0200 Subject: [PATCH 45/57] update 15/06 --- .../Core/src/sofa/simulation/LoadSnapshotVisitor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp index 9317fb241d7..ca2e55b7e03 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp @@ -33,7 +33,7 @@ void LoadSnapshotVisitor::processObject( { auto snapshotObject = obj->findSnapshotObject(parent, obj->getName()); if (!snapshotObject) - msg_error("findSnapshotObject") << "SnapshotObject " << obj->getName() << " not found in "; + msg_error("findSnapshotObject") << "SnapshotObject " << obj->getName() << " not found"; else { obj->loadDataSnapshot(snapshotObject); @@ -47,7 +47,7 @@ Visitor::Result LoadSnapshotVisitor::processNodeTopDown(simulation::Node* node) { const auto snapshotObject = node->findSnapshotObject(m_snapshotContainer.m_graphRoot, node->getName()); if (!snapshotObject) - msg_error("findSnapshotNode") << "SnapshotNode "<< node->getName() << " not found in "; + msg_error("findSnapshotNode") << "SnapshotNode "<< node->getName() << " not found"; else { const auto SnapshotNode = std::dynamic_pointer_cast(snapshotObject); From 1299e85dd09add0b551995bd8122600992b59277 Mon Sep 17 00:00:00 2001 From: Lucas-TJ Date: Mon, 15 Jun 2026 15:50:55 +0200 Subject: [PATCH 46/57] clean Snapshot API --- Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp | 2 +- .../Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp | 4 ++-- .../Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp index ad702c76dfc..a7802104aa1 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp @@ -259,7 +259,7 @@ TEST_F(Snapshot_test, SnapshotJSONExporter) auto visitor = SaveSnapshotVisitor(nullptr, *m_snapshot); root->execute(visitor); - exportTo(*m_snapshot,path); + exportToJSON(*m_snapshot,path); std::ifstream checkFile(path); EXPECT_TRUE(checkFile.good()); diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp index 3f333e8a131..6467bbf269e 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp @@ -99,7 +99,7 @@ void to_json(nlohmann::json& j, const std::shared_ptr& s } } -void exportTo(Snapshot& snapshot, const std::string& filename) +void exportToJSON(Snapshot& snapshot, const std::string& filename) { nlohmann::json j = snapshot.m_graphRoot ; @@ -253,7 +253,7 @@ std::string snapshot_To_String(const Snapshot& snapshot) return to_string(j); } -void exportTo(std::map>& snapshots, const std::string& filename) +void exportToJSON(std::map>& snapshots, const std::string& filename) { std::ofstream file(filename); diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h index 809bef9b4ad..9e002251104 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h @@ -28,7 +28,7 @@ namespace sofa::core::objectmodel { /// Export a single Snapshot to a JSON file - void exportTo(Snapshot& snapshot, const std::string& filename); + void exportToJSON(Snapshot& snapshot, const std::string& filename); /// Import a single Snapshot from a JSON file void importFrom(Snapshot& snapshot, const std::string& filename); @@ -40,7 +40,7 @@ namespace sofa::core::objectmodel std::string snapshot_To_String(const Snapshot& snapshot); /// Export a collection of Snapshots to a single JSON file - void exportTo(std::map>& snapshots, const std::string& filename); + void exportToJSON(std::map>& snapshots, const std::string& filename); /// Import a collection of Snapshots from a single JSON file void importFrom(std::map>& snapshots, const std::string& filename); From ffadade44c7692f862abb5b29cc487f0b4899106 Mon Sep 17 00:00:00 2001 From: Lucas-TJ Date: Wed, 17 Jun 2026 17:02:09 +0200 Subject: [PATCH 47/57] update wip loadLink --- .../simutest/objectmodel/Snapshot_test.cpp | 73 ++++++++++++++++++- .../Core/src/sofa/core/objectmodel/Base.cpp | 38 ++-------- .../src/sofa/core/objectmodel/BaseLink.cpp | 33 +++++++++ .../Core/src/sofa/core/objectmodel/BaseLink.h | 2 + .../sofa/simulation/LoadSnapshotVisitor.cpp | 4 +- 5 files changed, 114 insertions(+), 36 deletions(-) diff --git a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp index a7802104aa1..e09c9754e41 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp @@ -19,6 +19,8 @@ * * * Contact information: contact@sofa-framework.org * ******************************************************************************/ +#include +#include #include #include "gtest/gtest.h" @@ -29,8 +31,8 @@ using sofa::core::objectmodel::ComponentState; using sofa::testing::BaseSimulationTest ; using sofa::simulation::Node ; -#include -using sofa::core::objectmodel::BaseObject; +#include +using sofa::core::objectmodel::BaseComponent; #include using sofa::core::objectmodel::Snapshot; @@ -62,7 +64,7 @@ class TestComponent : public Base public: Data d_value; - TestComponent() + TestComponent() : d_value(initData(&d_value, 3.14f, "value", "test value")) { this->setName("pi"); @@ -86,6 +88,25 @@ class TestComponent : public Base }; +class TestComponentA : public BaseComponent +{ +public: + SOFA_CLASS(TestComponentA, BaseComponent); + + Data d_value; + sofa::MultiLink l_target; + + // SingleLink l_target; + + TestComponentA() + : d_value(initData(&d_value, 3.14f, "value", "test value")) + , l_target(initLink("target","target test")) + { + this->setName("pi"); + } + +}; + class Snapshot_test: public BaseSimulationTest { public: @@ -139,7 +160,6 @@ TEST_F(Snapshot_test, saveLinkIn) { EXPECT_EQ(link.value, ""); } - } } @@ -231,6 +251,51 @@ TEST_F(Snapshot_test, loadSnapshot) EXPECT_EQ(tcomponent2.d_value.getValue(), 3.14f); } +TEST_F(Snapshot_test, loadLinkSnapshot) +{ + /// Test of loadLinkSnapshot + /// wip + TestComponentA Component1; + Component1.setName("Component1"); + TestComponentA Component2; + TestComponentA* ptr; + ptr = &Component2; + Component2.setName("Component2"); + TestComponentA Component3; + Component3.setName("Component3"); + + + auto snapshotNode = std::make_shared("root"); + std::vector> snapshotParents; + snapshotParents.push_back(snapshotNode); + + std::cout << "Component1 l_target value : " <(); + snapshotObject1 = Component1.saveSnapshot(snapshotParents); + + ptr = &Component3; + Component1.l_target.add(ptr); + + std::cout << "Component1 l_target value : " <& sna } } -void Base::loadLinkSnapshot(const std::shared_ptr& snapshotObject) const -{ - std::vector linksFromSnapshot; +void Base::loadLinkSnapshot(const std::shared_ptr& snapshotObject) const { + /// wip + for (const auto& linkInfo : snapshotObject->m_linkContainer) { + if (const auto link = this->findLink(linkInfo.name)) { - for (const auto& linkInfo : snapshotObject->m_linkContainer) - { - if (const auto link = this->findLink(linkInfo.name)) - { - - std::vector newSublinks = helper::split(linkInfo.value, ' '); - for (const auto& newSublink : newSublinks) - { - auto obj = PathResolver::FindBaseFromPath(link->getOwner(), newSublink); - if ( obj != nullptr) - { - linksFromSnapshot.push_back(obj); - } - } - std::size_t i = 0; - // for (const auto& linkFromSnapshot : linksFromSnapshot) - // { - // std::string linkName = linkFromSnapshot->getName(); - // Base* linkedBase = link->getLinkedBase(i); - // if (linkedBase != linkFromSnapshot || linkedBase != nullptr) - // link->add(linkFromSnapshot,linkName); - // else - // link->remove(linkedBase); - // i+=1; - // } + if (link->readFromSnapshot(linkInfo.value) == 0 ) + msg_error("LoadSnapshot") << "Failed to read " << linkInfo.name << " in " << this->getName() << " from the snapshot " << linkInfo.value; } } - } -} // namespace sofa::core::objectmodel + +}// namespace sofa::core::objectmodel namespace sofa::helper::logging diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.cpp index c056c2ef233..995ddf664dc 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.cpp @@ -323,6 +323,39 @@ bool BaseLink::read( const std::string& str ) return ok; } +/// wip : idea -> compare str with the actual simulation. If a link is an extra link, add it (create new object ?) +/// If a link (from the scene) is not necessary anymore, it will be remove naturally +bool BaseLink::readFromSnapshot( const std::string& str ) +{ + if (str.empty()) + return true; + + const auto owner = getOwner(); + if (owner == nullptr) + return false; + + std::vector linkPaths; + std::istringstream istr(str); + std::string linkString; + + while (istr >> linkString) + { + if (!linkString.empty() && linkString[0] == '@') + linkPaths.push_back(linkString); + } + + for (const auto& linkPath : linkPaths) { + std::cout << linkPath << std::endl; + Base *ptr = PathResolver::FindBaseFromClassAndPath(owner, getDestClass(), linkPath); + if (ptr == nullptr) { + msg_warning(owner) << "readFromSnapshot: could not resolve link path " << linkPath << "\" for link " << getName() << ". Skipping."; + /// Create a new object ? + /// this->add(ptr); + } + } + return true; +} + std::string BaseLink::getLinkedPath(const std::size_t index) const { if(index >= getSize()) diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.h index 4c7c879f97b..d8b229c9e91 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.h @@ -134,6 +134,8 @@ class SOFA_CORE_API BaseLink /// Read the command line bool read( const std::string& str ); + bool readFromSnapshot( const std::string& str ); + /// Update pointers in case the pointed-to objects have appeared /// @return false if there are broken links bool updateLinks(); diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp index ca2e55b7e03..069af116c33 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp @@ -37,7 +37,7 @@ void LoadSnapshotVisitor::processObject( else { obj->loadDataSnapshot(snapshotObject); - // obj->loadLinkSnapshot(snapshotObject); + obj->loadLinkSnapshot(snapshotObject); obj->loadInternalStateFrom(*snapshotObject); } @@ -52,7 +52,7 @@ Visitor::Result LoadSnapshotVisitor::processNodeTopDown(simulation::Node* node) { const auto SnapshotNode = std::dynamic_pointer_cast(snapshotObject); node->loadDataSnapshot(SnapshotNode); - // node->loadLinkSnapshot(SnapshotNode); + node->loadLinkSnapshot(SnapshotNode); for (simulation::Node::ObjectIterator it = node->object.begin(); it != node->object.end(); ++it) { this->processObject(it->get(), SnapshotNode); From 91fc73f567e098664ccba99c87511761193b8623 Mon Sep 17 00:00:00 2001 From: Lucas-TJ Date: Tue, 23 Jun 2026 11:41:24 +0200 Subject: [PATCH 48/57] Update unit tests and fix loadLinkSnapshot --- .../geometry/TriangleCollisionModel.h | 9 +- .../fem/elastic/TetrahedronFEMForceField.h | 6 + .../simutest/objectmodel/Snapshot_test.cpp | 284 +++++++++++------- .../Core/src/sofa/core/objectmodel/Base.cpp | 7 +- .../src/sofa/core/objectmodel/BaseLink.cpp | 73 ++++- .../sofa/simulation/LoadSnapshotVisitor.cpp | 2 - .../Simulation/Graph/test/Link_test.cpp | 2 + 7 files changed, 246 insertions(+), 137 deletions(-) diff --git a/Sofa/Component/Collision/Geometry/src/sofa/component/collision/geometry/TriangleCollisionModel.h b/Sofa/Component/Collision/Geometry/src/sofa/component/collision/geometry/TriangleCollisionModel.h index 03f36a94453..80a541cc26c 100644 --- a/Sofa/Component/Collision/Geometry/src/sofa/component/collision/geometry/TriangleCollisionModel.h +++ b/Sofa/Component/Collision/Geometry/src/sofa/component/collision/geometry/TriangleCollisionModel.h @@ -211,20 +211,15 @@ class TriangleCollisionModel : public core::CollisionModel void loadInternalStateFrom(const core::objectmodel::Snapshot::SnapshotObject &snapshot) override { + m_needsUpdate = true; + for (const auto& dataInfo : snapshot.m_dataContainer) { if (dataInfo.name == "m_triangles") { - // std::stringstream ss(dataInfo.value); - // std::istringstream iss(dataInfo.value); - // this->m_internalTriangles.read(iss); - // m_triangles = &m_internalTriangles; - // m_needsUpdate = true; - m_triangles = &m_topology->getTriangles(); resize(m_topology->getNbTriangles()); updateNormals(); - } } diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedronFEMForceField.h b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedronFEMForceField.h index 8f9b3992c4b..e3171614c6b 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedronFEMForceField.h +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedronFEMForceField.h @@ -290,6 +290,12 @@ class TetrahedronFEMForceField : public BaseLinearElasticityFEMForceFieldl_topology->getTetrahedra()); + } + protected: void computeStrainDisplacement( StrainDisplacement &J, Coord a, Coord b, Coord c, Coord d ); Real peudo_determinant_for_coef ( const type::Mat<2, 3, Real>& M ); diff --git a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp index e09c9754e41..0528f188962 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp @@ -52,20 +52,24 @@ using sofa::simulation::LoadLinkSnapshotVisitor; using sofa::core::objectmodel::Data; using sofa::core::objectmodel::BaseLink; using sofa::core::objectmodel::SingleLink; +using sofa::core::objectmodel::MultiLink; using sofa::core::objectmodel::Snapshot; using sofa::core::objectmodel::BaseNode; #include #include -class TestComponent : public Base +class TestComponent : public BaseComponent { - public: + SOFA_CLASS(TestComponent, BaseComponent); + Data d_value; - + sofa::MultiLink l_target; + TestComponent() : d_value(initData(&d_value, 3.14f, "value", "test value")) + , l_target(initLink("target","target test")) { this->setName("pi"); } @@ -82,27 +86,8 @@ class TestComponent : public Base std::shared_ptr createSnapshotObjectTest(std::vector>& parents) const { - - return this->createSnapshotObject(parents); - } -}; - -class TestComponentA : public BaseComponent -{ -public: - SOFA_CLASS(TestComponentA, BaseComponent); - - Data d_value; - sofa::MultiLink l_target; - - // SingleLink l_target; - - TestComponentA() - : d_value(initData(&d_value, 3.14f, "value", "test value")) - , l_target(initLink("target","target test")) - { - this->setName("pi"); + return this->createSnapshotObject(parents); } }; @@ -114,15 +99,22 @@ class Snapshot_test: public BaseSimulationTest ~Snapshot_test() override {} }; - +/** + * @brief Test of saveDataIn + * + * This test verifies that saveDataIn save data correctly in a SnapshotObject. + * + * Test steps: + * 1. Create a component (Component) and a snapshot + * 2. Save component's data in the snapshot + * 3. Check if the snapshot contains the component with expected data + * + */ TEST_F(Snapshot_test, saveDataIn) { - // TEST of saveDataIn method - // Check if the snapshot contains the component with expected data - - TestComponent tComponent; + TestComponent Component; auto snapshot = std::make_shared(); - tComponent.saveData(*snapshot); + Component.saveData(*snapshot); for (auto& data : snapshot->m_dataContainer) { if(data.name == "name") @@ -137,10 +129,19 @@ TEST_F(Snapshot_test, saveDataIn) } } +/** + * @brief Test of saveLinksIn + * + * This test verifies that saveLinksIn save links correctly in a SnapshotObject. + * + * Test steps: + * 1. Create a component (Component) and a snapshot + * 2. Save component's links in the snapshot + * 3. Check if the snapshot contains the component with expected links + * + */ TEST_F(Snapshot_test, saveLinkIn) { - // TEST of saveLinksIn method - // Check if the snapshot contains the component with expected data TestComponent tComponent; auto snapshot = std::make_shared(); @@ -163,22 +164,30 @@ TEST_F(Snapshot_test, saveLinkIn) } } +/** + * @brief Test of createSnapshotObject + * + * This test verifies that createSnapshotObject can find the SnapshotObject in a Snapshot with the component's name. + * + * Test steps: + * 1. Create a component (Component) + * 2. Create a SnapshotObject with the function createSnapshotObject + * 3. Save Component's data in the SnapshotObject + * 4. Verify if every data is correctly saved in the SnapshotObject + * + */ TEST_F(Snapshot_test, createSnapshotObject) { - // TEST of createSnapshotObject - // Check if createSnapshotObject can create a SnapshotObject - // To verify, A name and some data are added to the SnapshotObject + TestComponent Component; - TestComponent tComponent; std::vector> snapshotParents; - auto snapshotObject = tComponent.createSnapshotObjectTest(snapshotParents); + auto snapshotObject = Component.createSnapshotObjectTest(snapshotParents); snapshotObject->m_name = "snapshotObject"; - tComponent.saveData(*snapshotObject); + Component.saveData(*snapshotObject); EXPECT_NE(snapshotObject, nullptr); EXPECT_EQ(snapshotObject->m_name, "snapshotObject"); - for (auto& data : snapshotObject->m_dataContainer) { if(data.name == "name") @@ -193,114 +202,163 @@ TEST_F(Snapshot_test, createSnapshotObject) } } +/** + * @brief Test of findSnapshotObject + * + * This test verifies that findSnapshotObject can find the SnapshotObject in a Snapshot with the component's name. + * + * Test steps: + * 1. Create a component (Component) and a graph of with a SnapshotNode + * 2. Save Component in the SnapshotNode (as a SnapshotObject) + * 3. Use findSnapshotObject to find the SnapshotObject corresponding to Component + * 4. Verify if the SnapshotObject has been correctly found + * + */ TEST_F(Snapshot_test, findSnapshotObject) { - // TEST of findSnapshotObject - // Check if findSnapshotObject can find the SnapshotObject in a Snapshot - // with the component's name - - TestComponent tComponent; - + TestComponent Component; auto snapshotNode = std::make_shared("root"); std::vector> snapshotParents; - snapshotParents.push_back(snapshotNode); + snapshotParents.push_back(snapshotNode); - auto snapshot = tComponent.saveSnapshot(snapshotParents); + auto snapshot = Component.saveSnapshot(snapshotParents); snapshotNode->components.push_back(*snapshot); - auto expectedObject = tComponent.findSnapshotObject(snapshotNode, "pi"); + auto expectedObject = Component.findSnapshotObject(snapshotNode, "pi"); EXPECT_NE(expectedObject, nullptr); - - EXPECT_EQ(tComponent.getName(), expectedObject->m_name); - + EXPECT_EQ(Component.getName(), expectedObject->m_name); } +/** + * @brief Test of saveSnapshot + * + * This test verifies that saveSnapshot save the data to a previously saved snapshot. + * + * Test steps: + * 1. Create a component (Component) and a snapshot + * 2. Save Component1's data in the snapshot + * 3. Verify if the snapshot contains all the data from Component1 + * + */ TEST_F(Snapshot_test, saveSnapshot) { - // Test of saveSnapshot - - TestComponent tComponent; - + TestComponent Component; auto snapshot = std::make_shared(); std::vector> snapshotParents; - snapshot = tComponent.saveSnapshot(snapshotParents); + + snapshot = Component.saveSnapshot(snapshotParents); EXPECT_EQ(snapshot->m_name, "pi"); - EXPECT_EQ(snapshot->m_dataContainer.size(), 6); + EXPECT_EQ(snapshot->m_dataContainer.size(), 7); EXPECT_EQ(snapshot->m_dataContainer[0].name, "name"); EXPECT_EQ(snapshot->m_dataContainer[0].value, "pi"); - EXPECT_EQ(snapshot->m_dataContainer[5].name, "value"); - EXPECT_EQ(snapshot->m_dataContainer[5].value, "3.14"); + EXPECT_EQ(snapshot->m_dataContainer.back().name, "value"); + EXPECT_EQ(snapshot->m_dataContainer.back().value, "3.14"); + EXPECT_EQ(snapshot->m_linkContainer[0].name, "context"); + EXPECT_EQ(snapshot->m_linkContainer[0].value, "@./"); + EXPECT_EQ(snapshot->m_linkContainer.back().name, "target"); + EXPECT_EQ(snapshot->m_linkContainer.back().value, ""); + } -TEST_F(Snapshot_test, loadSnapshot) +/** + * @brief Test of loadDataSnapshot + * + * This test verifies that loadLinkSnapshot restores the state of data to a previously saved snapshot + * + * Test steps: + * 1. Create a component (Component1) and a snapshot + * 2. Save Component1's data in the snapshot + * 3. Create another component (Component2) and change the data d_value + * 4. Load Component1's data into Component2 with loadDataSnapshot + * 5. Verify if Component2 has same value as Component1 + * + */ +TEST_F(Snapshot_test, loadDataSnapshot) { - // Test of loadSnapshot - - TestComponent tComponent; - + TestComponent Component1; auto snapshot = std::make_shared(); std::vector> snapshotParents; - snapshot = tComponent.saveSnapshot(snapshotParents); - TestComponent tcomponent2; - tcomponent2.d_value.setValue(0.0f); - tcomponent2.loadDataSnapshot(snapshot); + snapshot = Component1.saveSnapshot(snapshotParents); - EXPECT_EQ(tcomponent2.d_value.getValue(), 3.14f); + TestComponent Component2; + Component2.d_value.setValue(0.0f); + Component2.loadDataSnapshot(snapshot); + + EXPECT_EQ(Component2.d_value.getValue(), 3.14f); } +/** + * @brief Test of loadLinkSnapshot + * + * This test verifies that loadLinkSnapshot restores the state of a link to a previously saved snapshot. + * First, it set up a graph "root" with 3 components: Component1, Component2 and Component3 + * Each component holds a multi-link l_target pointing to other components + * + * Test steps: + * 1. Add Component2 to Component1's l_target link. + * 2. Save a snapshot of Component1 (l_target points to @Component2 only). + * 3. Add Component3 to Component1's l_target link. + * 4. Verify that l_target now points to both @Component2 and@Component3. + * 5. Restore Component1 from the snapshot. + * 6. Verify that l_target is back to pointing to @Component2 only, + * confirming that it @Component3 was correctly removed by loadLinkSnapshot. + * + */ TEST_F(Snapshot_test, loadLinkSnapshot) { - /// Test of loadLinkSnapshot - /// wip - TestComponentA Component1; - Component1.setName("Component1"); - TestComponentA Component2; - TestComponentA* ptr; - ptr = &Component2; - Component2.setName("Component2"); - TestComponentA Component3; - Component3.setName("Component3"); - + const SceneInstance scene("root"); + auto Component1 = sofa::core::objectmodel::New(); + Component1->setName("Component1"); + auto Component2 = sofa::core::objectmodel::New(); + Component2->setName("Component2"); + auto Component3 = sofa::core::objectmodel::New(); + Component3->setName("Component3"); + scene.root->addObject(Component1); + scene.root->addObject(Component2); + scene.root->addObject(Component3); auto snapshotNode = std::make_shared("root"); std::vector> snapshotParents; snapshotParents.push_back(snapshotNode); - std::cout << "Component1 l_target value : " <l_target.add(ptr); - std::cout << "Component1 l_target value : " <l_target.getValueString(), "@Component2"); auto snapshotObject1 = std::make_shared(); - snapshotObject1 = Component1.saveSnapshot(snapshotParents); + snapshotObject1 = Component1->saveSnapshot(snapshotParents); - ptr = &Component3; - Component1.l_target.add(ptr); + ptr = Component3.get(); + Component1->l_target.add(ptr); - std::cout << "Component1 l_target value : " <l_target.getValueString(), "@Component2 @Component3"); - Component1.loadLinkSnapshot(snapshotObject1); - - std::cout << "Component1 l_target value : " <loadLinkSnapshot(snapshotObject1); + EXPECT_EQ(Component1->l_target.getValueString(), "@Component2"); } +/** + * @brief Test of SnapshotJSONExporter + * + * This test verifies the behavior of the export and the import with SnapshotJSONExporter + * + * Test steps: + * 1. Init the scene + * 2. Create a snapshot (snapshot) + * 3. Run SaveSnapshotVisitor to save the state in m_snapshot + * 4. Export m_snapshot to a JSON file and check if the file is valid + * 5. Create another snapshot (snapshot_import) + * 6. Import the JSON file in snapshot_import + * 7. Compare m_snapshot and snapshot_import + * + */ TEST_F(Snapshot_test, SnapshotJSONExporter) { - // TEST SnapshotJSONExporter - // Test the behavior of the export and the import with JSON - const std::string scene = R"( @@ -319,28 +377,30 @@ TEST_F(Snapshot_test, SnapshotJSONExporter) Node* root = c.root.get() ; std::filesystem::path path = std::filesystem::temp_directory_path() / "test_file.json"; - auto m_snapshot = std::make_shared(); + auto snapshot = std::make_shared(); - auto visitor = SaveSnapshotVisitor(nullptr, *m_snapshot); + auto visitor = SaveSnapshotVisitor(nullptr, *snapshot); root->execute(visitor); - exportToJSON(*m_snapshot,path); + exportToJSON(*snapshot,path); std::ifstream checkFile(path); EXPECT_TRUE(checkFile.good()); checkFile.close(); - auto m_snapshot_import = std::make_shared(); - importFrom(*m_snapshot_import, path); + auto snapshot_import = std::make_shared(); + importFrom(*snapshot_import, path); - EXPECT_NE(m_snapshot_import->m_graphRoot,nullptr); + EXPECT_NE(snapshot_import->m_graphRoot,nullptr); - EXPECT_EQ(m_snapshot_import->m_graphRoot->m_name,"Root"); - EXPECT_EQ(m_snapshot_import->m_graphRoot->components[0].m_name,"Sofa.Component.StateContainer"); - EXPECT_EQ(m_snapshot_import->m_graphRoot->components[1].m_name,"DefaultAnimationLoop1"); - EXPECT_EQ(m_snapshot_import->m_graphRoot->components[2].m_name,"DefaultVisualManagerLoop1"); - EXPECT_EQ(m_snapshot_import->m_graphRoot->children[0]->m_name,"child1"); - EXPECT_EQ(m_snapshot_import->m_graphRoot->children[0]->components[0].m_name,"MechanicalObject1"); + EXPECT_EQ(snapshot_import->m_graphRoot->m_name,"Root"); + EXPECT_EQ(snapshot_import->m_graphRoot->components[0].m_name,"Sofa.Component.StateContainer"); + EXPECT_EQ(snapshot_import->m_graphRoot->components[1].m_name,"DefaultAnimationLoop1"); + EXPECT_EQ(snapshot_import->m_graphRoot->components[2].m_name,"DefaultVisualManagerLoop1"); + EXPECT_EQ(snapshot_import->m_graphRoot->children[0]->m_name,"child1"); + EXPECT_EQ(snapshot_import->m_graphRoot->children[0]->components[0].m_name,"MechanicalObject1"); std::filesystem::remove(path); } + + diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index 8717581bc6c..f36bf764987 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -765,7 +765,7 @@ Base::findSnapshotObject(const std::shared_ptr& parents, return defaultObject; } -void Base::loadInternalStateFrom(const Snapshot::SnapshotObject& snapshot) +void Base::loadInternalStateFrom(const Snapshot::SnapshotObject& snapshot) { SOFA_UNUSED(snapshot); @@ -778,18 +778,17 @@ void Base::loadDataSnapshot(const std::shared_ptr& sna if (const auto data = this->findData(dataInfo.name)) { if(data->read(dataInfo.value) == 0 ) - msg_error("LoadSnapshot") << "Failed to read " << dataInfo.name << " in " << this->getName() << " from the snapshot " << dataInfo.value; + msg_error("LoadDataSnapshot") << "Failed to read " << dataInfo.name << " in " << this->getName() << " from the snapshot " << dataInfo.value; } } } void Base::loadLinkSnapshot(const std::shared_ptr& snapshotObject) const { - /// wip for (const auto& linkInfo : snapshotObject->m_linkContainer) { if (const auto link = this->findLink(linkInfo.name)) { if (link->readFromSnapshot(linkInfo.value) == 0 ) - msg_error("LoadSnapshot") << "Failed to read " << linkInfo.name << " in " << this->getName() << " from the snapshot " << linkInfo.value; + msg_error("LoadLinkSnapshot") << "Failed to read " << linkInfo.name << " in " << this->getName() << " from the snapshot " << linkInfo.value; } } } diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.cpp index 995ddf664dc..ab34d560c71 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.cpp @@ -323,10 +323,11 @@ bool BaseLink::read( const std::string& str ) return ok; } -/// wip : idea -> compare str with the actual simulation. If a link is an extra link, add it (create new object ?) -/// If a link (from the scene) is not necessary anymore, it will be remove naturally bool BaseLink::readFromSnapshot( const std::string& str ) { + this->updateLinks(); + bool result = true; + if (str.empty()) return true; @@ -334,26 +335,74 @@ bool BaseLink::readFromSnapshot( const std::string& str ) if (owner == nullptr) return false; - std::vector linkPaths; + /// From the snapshot + std::vector linkPathsFromSnapshot; std::istringstream istr(str); std::string linkString; while (istr >> linkString) { if (!linkString.empty() && linkString[0] == '@') - linkPaths.push_back(linkString); + linkPathsFromSnapshot.push_back(linkString); + } + + /// From the link + std::vector linkPathsFromLink; + + std::string linkPath = this->getValueString(); + + std::string replaceValue = "//"; + std::size_t pos = linkPath.find(replaceValue); + while (pos != std::string::npos) + { + linkPath.replace(pos, replaceValue.length(), ""); + pos = linkPath.find(replaceValue, pos); } - for (const auto& linkPath : linkPaths) { - std::cout << linkPath << std::endl; - Base *ptr = PathResolver::FindBaseFromClassAndPath(owner, getDestClass(), linkPath); - if (ptr == nullptr) { - msg_warning(owner) << "readFromSnapshot: could not resolve link path " << linkPath << "\" for link " << getName() << ". Skipping."; - /// Create a new object ? - /// this->add(ptr); + std::istringstream istrLink(linkPath); + std::string linkStringBis; + + while (istrLink >> linkStringBis) + { + if (!linkStringBis.empty() && linkStringBis[0] == '@') + linkPathsFromLink.push_back(linkStringBis); + } + + std::set mixedLink; + mixedLink.insert(linkPathsFromSnapshot.begin(), linkPathsFromSnapshot.end()); + mixedLink.insert(linkPathsFromLink.begin(), linkPathsFromLink.end()); + + for (const auto& linkPath : mixedLink) + { + bool inLinkPathsFromSnapshot = std::find(linkPathsFromSnapshot.begin(), linkPathsFromSnapshot.end(), linkPath) != linkPathsFromSnapshot.end(); + bool inLinkPathsFromLink = std::find(linkPathsFromLink.begin(), linkPathsFromLink.end(), linkPath) != linkPathsFromLink.end(); + + if (inLinkPathsFromLink && inLinkPathsFromSnapshot) + { + result = true; + } + else if (inLinkPathsFromLink) + { + Base *ptr = PathResolver::FindBaseFromClassAndPath(owner, getDestClass(), linkPath); + if (ptr == nullptr) + { + msg_warning(owner) << "readFromSnapshot: could not resolve link path " << linkPath << "\" for link " << getName() << ". Skipping."; + result = false; + } + this->remove(ptr); + } + else if (inLinkPathsFromSnapshot) + { + Base *ptr = PathResolver::FindBaseFromClassAndPath(owner, getDestClass(), linkPath); + if (ptr == nullptr) + { + msg_warning(owner) << "readFromSnapshot: could not resolve link path " << linkPath << "\" for link " << getName() << ". Skipping."; + result = false; + } + this->add(ptr); } } - return true; + return result; } std::string BaseLink::getLinkedPath(const std::size_t index) const diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp index 069af116c33..f5eca27d842 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp @@ -40,7 +40,6 @@ void LoadSnapshotVisitor::processObject( obj->loadLinkSnapshot(snapshotObject); obj->loadInternalStateFrom(*snapshotObject); } - } Visitor::Result LoadSnapshotVisitor::processNodeTopDown(simulation::Node* node) @@ -58,7 +57,6 @@ Visitor::Result LoadSnapshotVisitor::processNodeTopDown(simulation::Node* node) this->processObject(it->get(), SnapshotNode); } } - return RESULT_CONTINUE; } diff --git a/Sofa/framework/Simulation/Graph/test/Link_test.cpp b/Sofa/framework/Simulation/Graph/test/Link_test.cpp index 3d904bfa8ef..a47bbb0a698 100644 --- a/Sofa/framework/Simulation/Graph/test/Link_test.cpp +++ b/Sofa/framework/Simulation/Graph/test/Link_test.cpp @@ -19,6 +19,8 @@ * * * Contact information: contact@sofa-framework.org * ******************************************************************************/ +#include +#include #include using sofa::testing::BaseSimulationTest ; From 0c103cd0c6132be40ff718c324598e50b50b263c Mon Sep 17 00:00:00 2001 From: Lucas-TJ Date: Fri, 26 Jun 2026 10:43:25 +0200 Subject: [PATCH 49/57] clean comments --- .../collision/geometry/TriangleCollisionModel.inl | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/Sofa/Component/Collision/Geometry/src/sofa/component/collision/geometry/TriangleCollisionModel.inl b/Sofa/Component/Collision/Geometry/src/sofa/component/collision/geometry/TriangleCollisionModel.inl index 7056a25a387..f2bc2b681ef 100644 --- a/Sofa/Component/Collision/Geometry/src/sofa/component/collision/geometry/TriangleCollisionModel.inl +++ b/Sofa/Component/Collision/Geometry/src/sofa/component/collision/geometry/TriangleCollisionModel.inl @@ -247,20 +247,6 @@ void TriangleCollisionModel::computeBoundingTree(int maxDepth) const type::Vec3& pt1 = x[t.p1Index()]; const type::Vec3& pt2 = x[t.p2Index()]; const type::Vec3& pt3 = x[t.p3Index()]; - // std::cout << "x = " << x << std::endl; - // std::cout << "t is valid ? " << t.valid() << std::endl; - // std::cout << "t.p1Index() = " << t.p1Index() << std::endl; - // std::cout << "x size = " << x.size() << std::endl; - // std::cout << "pt1 = " << pt1 << " pt2 = " << pt2 << " pt3 = " << pt3 << std::endl; - // std::cout << "m_triangles ? " << (*(this->m_triangles)) << std::endl ; - // std::cout << "size m_triangles ? " << this->m_triangles->size()<< std::endl; - // std::cout << "size m_normals ? " << this->m_normals.size() << std::endl; - - // std::stringstream ss; - // this->m_triangles->write(ss); - // std::string str = ss.str(); - // std::cout << str << std::endl; - for (int c = 0; c < 3; c++) { From d715b5072ac26462778372f07a82ef307ec651ab Mon Sep 17 00:00:00 2001 From: Lucas-TJ Date: Thu, 2 Jul 2026 16:33:30 +0200 Subject: [PATCH 50/57] remove LoadDataSnapshotVisitor and LoadLinkSnapshotVisitor --- .../simutest/objectmodel/Snapshot_test.cpp | 6 --- Sofa/framework/Simulation/Core/CMakeLists.txt | 4 -- .../simulation/LoadDataSnapshotVisitor.cpp | 53 ------------------- .../sofa/simulation/LoadDataSnapshotVisitor.h | 45 ---------------- .../simulation/LoadLinkSnapshotVisitor.cpp | 51 ------------------ .../sofa/simulation/LoadLinkSnapshotVisitor.h | 47 ---------------- 6 files changed, 206 deletions(-) delete mode 100644 Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.cpp delete mode 100644 Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.h delete mode 100644 Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.cpp delete mode 100644 Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.h diff --git a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp index 0528f188962..5a0184f23e7 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp @@ -40,12 +40,6 @@ using sofa::core::objectmodel::Snapshot; #include using sofa::simulation::SaveSnapshotVisitor; -#include -using sofa::simulation::LoadDataSnapshotVisitor; - -#include -using sofa::simulation::LoadLinkSnapshotVisitor; - #include #include diff --git a/Sofa/framework/Simulation/Core/CMakeLists.txt b/Sofa/framework/Simulation/Core/CMakeLists.txt index 07d548c48e8..21be119265e 100644 --- a/Sofa/framework/Simulation/Core/CMakeLists.txt +++ b/Sofa/framework/Simulation/Core/CMakeLists.txt @@ -28,8 +28,6 @@ set(HEADER_FILES ${SRC_ROOT}/IntegrateBeginEvent.h ${SRC_ROOT}/IntegrateEndEvent.h ${SRC_ROOT}/LoadSnapshotVisitor.h - ${SRC_ROOT}/LoadDataSnapshotVisitor.h - ${SRC_ROOT}/LoadLinkSnapshotVisitor.h ${SRC_ROOT}/MechanicalOperations.h ${SRC_ROOT}/MechanicalVPrintVisitor.h ${SRC_ROOT}/MechanicalVisitor.h @@ -184,8 +182,6 @@ set(SOURCE_FILES ${SRC_ROOT}/IntegrateBeginEvent.cpp ${SRC_ROOT}/IntegrateEndEvent.cpp ${SRC_ROOT}/LoadSnapshotVisitor.cpp - ${SRC_ROOT}/LoadDataSnapshotVisitor.cpp - ${SRC_ROOT}/LoadLinkSnapshotVisitor.cpp ${SRC_ROOT}/MappingGraph.cpp ${SRC_ROOT}/MappingGraphMechanicalOperations.cpp ${SRC_ROOT}/MechanicalOperations.cpp diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.cpp deleted file mode 100644 index 632076be85b..00000000000 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.cpp +++ /dev/null @@ -1,53 +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 - -namespace sofa::simulation -{ - -void LoadDataSnapshotVisitor::processObject( - core::objectmodel::BaseObject* obj, - const std::shared_ptr& parent -) -{ - auto snapshotObject = obj->findSnapshotObject(parent, obj->getName()); - obj->loadDataSnapshot(snapshotObject); - obj->loadInternalStateFrom(*snapshotObject); -} - -Visitor::Result LoadDataSnapshotVisitor::processNodeTopDown(simulation::Node* node) -{ - const auto snapshotObject = node->findSnapshotObject(m_snapshotContainer.m_graphRoot, node->getName()); - if (!snapshotObject) - msg_error("findSnapshotNode") << "SnapshotNode "<< node->getName() << " not found in "; - const auto SnapshotNode = std::dynamic_pointer_cast(snapshotObject); - node->loadDataSnapshot(SnapshotNode); - for (simulation::Node::ObjectIterator it = node->object.begin(); it != node->object.end(); ++it) - { - this->processObject(it->get(), SnapshotNode); - } - return RESULT_CONTINUE; -} - -} // namespace sofa::simulation diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.h deleted file mode 100644 index 62055566d39..00000000000 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadDataSnapshotVisitor.h +++ /dev/null @@ -1,45 +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 * -******************************************************************************/ -#pragma once -#include -#include - -namespace sofa::simulation -{ - -class SOFA_SIMULATION_CORE_API LoadDataSnapshotVisitor : public Visitor -{ -protected: - core::objectmodel::Snapshot& m_snapshotContainer; - -public: - LoadDataSnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::Snapshot& snapshot) : Visitor(eparams), m_snapshotContainer(snapshot) {} - - void processObject(core::objectmodel::BaseObject* obj, const std::shared_ptr& parent); - - Result processNodeTopDown(simulation::Node* node) override; - const char* getClassName() const override { return "LoadDataSnapshotVisitor"; } - -}; - -} // namespace sofa::simulation - diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.cpp deleted file mode 100644 index f4f24800303..00000000000 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.cpp +++ /dev/null @@ -1,51 +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 -{ - -void LoadLinkSnapshotVisitor::processObject( - core::objectmodel::BaseObject* obj, - const std::shared_ptr& parent -) -{ - const auto snapshotObject = obj->findSnapshotObject(parent, obj->getName()); - obj->loadLinkSnapshot(snapshotObject); -} - -Visitor::Result LoadLinkSnapshotVisitor::processNodeTopDown(simulation::Node* node) -{ - const auto snapshotObject = node->findSnapshotObject(m_snapshotContainer.m_graphRoot, node->getName()); - const auto SnapshotNode = std::dynamic_pointer_cast(snapshotObject); - node->loadLinkSnapshot(SnapshotNode); - - for (simulation::Node::ObjectIterator it = node->object.begin(); it != node->object.end(); ++it) - { - this->processObject(it->get(), SnapshotNode); - } - return RESULT_CONTINUE; -} - -} // namespace sofa::simulation - diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.h deleted file mode 100644 index a3ccf23aea8..00000000000 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadLinkSnapshotVisitor.h +++ /dev/null @@ -1,47 +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 * -******************************************************************************/ -#pragma once -#include -#include -#include -#include - -namespace sofa::simulation -{ - -class SOFA_SIMULATION_CORE_API LoadLinkSnapshotVisitor : public Visitor -{ -protected: - core::objectmodel::Snapshot& m_snapshotContainer; - -public: - LoadLinkSnapshotVisitor(const sofa::core::ExecParams* eparams, core::objectmodel::Snapshot& snapshot) : Visitor(eparams), m_snapshotContainer(snapshot) {} - - void processObject(core::objectmodel::BaseObject* obj, const std::shared_ptr& parent); - - Result processNodeTopDown(simulation::Node* node) override; - const char* getClassName() const override { return "LoadLinkSnapshotVisitor"; } - -}; - -} // namespace sofa::simulation - From f7e3e0a6c9d865a03816d6a42fc2a3d2217bbb75 Mon Sep 17 00:00:00 2001 From: Lucas-TJ Date: Thu, 2 Jul 2026 16:37:06 +0200 Subject: [PATCH 51/57] clean std::cout --- .../Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp index 6467bbf269e..918013bdab0 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp @@ -229,7 +229,7 @@ void importFrom(Snapshot& snapshot, const std::string& filename) return; } - std::cout << "JSON imported successfully from: " << filename << std::endl; + msg_info("SnapshotJSONExporter") << "JSON imported successfully from: " << filename; } std::string file_To_String(const std::string& filename) From b5bac441263b4af57dacd8e3bb177f4b7428bb0a Mon Sep 17 00:00:00 2001 From: Lucas-TJ Date: Fri, 3 Jul 2026 16:44:22 +0200 Subject: [PATCH 52/57] fix & clean --- .../simutest/objectmodel/Snapshot_test.cpp | 3 +-- .../Core/src/sofa/core/objectmodel/Base.cpp | 19 +++++++------------ .../src/sofa/core/objectmodel/BaseLink.cpp | 11 +++-------- .../core/objectmodel/SnapshotJSONExporter.cpp | 17 ++++++++++------- .../sofa/core/objectmodel/SnapshotManager.h | 4 ++-- 5 files changed, 23 insertions(+), 31 deletions(-) diff --git a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp index 5a0184f23e7..cfbe65825a7 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp @@ -356,7 +356,7 @@ TEST_F(Snapshot_test, SnapshotJSONExporter) const std::string scene = R"( - + @@ -388,7 +388,6 @@ TEST_F(Snapshot_test, SnapshotJSONExporter) EXPECT_NE(snapshot_import->m_graphRoot,nullptr); EXPECT_EQ(snapshot_import->m_graphRoot->m_name,"Root"); - EXPECT_EQ(snapshot_import->m_graphRoot->components[0].m_name,"Sofa.Component.StateContainer"); EXPECT_EQ(snapshot_import->m_graphRoot->components[1].m_name,"DefaultAnimationLoop1"); EXPECT_EQ(snapshot_import->m_graphRoot->components[2].m_name,"DefaultVisualManagerLoop1"); EXPECT_EQ(snapshot_import->m_graphRoot->children[0]->m_name,"child1"); diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index f36bf764987..3512d3f8ba0 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -706,14 +706,8 @@ void Base::saveLinksIn(Snapshot::SnapshotObject& snapshot) const linkInfo.type = link->getValueTypeString(); linkInfo.value = link->getValueString(); - std::string replaceValue = "//"; - std::size_t pos = linkInfo.value.find(replaceValue); - while (pos != std::string::npos) - { - linkInfo.value.replace(pos, replaceValue.length(), ""); - pos = linkInfo.value.find(replaceValue, pos); - } - + std::string search = "//"; + sofa::helper::replaceAll(linkInfo.value, search,""); snapshot.m_linkContainer.push_back(linkInfo); } } @@ -758,7 +752,7 @@ Base::findSnapshotObject(const std::shared_ptr& parents, return snapshotObject; } } - msg_error("findSnapshotObject") << "SnapshotObject "<< objectname << " not found"; + msg_error() << "SnapshotObject "<< objectname << " not found"; auto defaultObject = std::make_shared(); defaultObject->m_name = "Unknown object"; @@ -778,17 +772,18 @@ void Base::loadDataSnapshot(const std::shared_ptr& sna if (const auto data = this->findData(dataInfo.name)) { if(data->read(dataInfo.value) == 0 ) - msg_error("LoadDataSnapshot") << "Failed to read " << dataInfo.name << " in " << this->getName() << " from the snapshot " << dataInfo.value; + msg_error() << "Failed to read " << dataInfo.name << " in " << this->getName() << " from the snapshot " << dataInfo.value; } } } -void Base::loadLinkSnapshot(const std::shared_ptr& snapshotObject) const { +void Base::loadLinkSnapshot(const std::shared_ptr& snapshotObject) const +{ for (const auto& linkInfo : snapshotObject->m_linkContainer) { if (const auto link = this->findLink(linkInfo.name)) { if (link->readFromSnapshot(linkInfo.value) == 0 ) - msg_error("LoadLinkSnapshot") << "Failed to read " << linkInfo.name << " in " << this->getName() << " from the snapshot " << linkInfo.value; + msg_error() << "Failed to read " << linkInfo.name << " in " << this->getName() << " from the snapshot " << linkInfo.value; } } } diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.cpp index ab34d560c71..09304bfe439 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.cpp @@ -351,14 +351,9 @@ bool BaseLink::readFromSnapshot( const std::string& str ) std::string linkPath = this->getValueString(); - std::string replaceValue = "//"; - std::size_t pos = linkPath.find(replaceValue); - while (pos != std::string::npos) - { - linkPath.replace(pos, replaceValue.length(), ""); - pos = linkPath.find(replaceValue, pos); - } - + std::string search = "//"; + sofa::helper::replaceAll(linkPath, search,""); + std::istringstream istrLink(linkPath); std::string linkStringBis; diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp index 918013bdab0..99b678f58a9 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp @@ -24,8 +24,11 @@ #include #include #include +#include +using sofa::helper::logging::MessageDispatcher ; +using sofa::helper::logging::Message ; - +#define ERROR_LOG_SIZE 100 namespace sofa::core::objectmodel { @@ -206,7 +209,7 @@ void importFrom(Snapshot& snapshot, const std::string& filename) std::ifstream file(filename); if (!file.is_open()) { - std::cerr << "ERROR: Cannot open file " << filename << " for reading\n"; + msg_error("SnapshotJSONExporter") << "ERROR: Cannot open file " << filename << " for reading"; return; } @@ -225,7 +228,7 @@ void importFrom(Snapshot& snapshot, const std::string& filename) } else { - std::cerr << "ERROR: Invalid JSON format in " << filename << "\n"; + msg_error("SnapshotJSONExporter") << "Invalid JSON format in " << filename ; return; } @@ -237,7 +240,7 @@ std::string file_To_String(const std::string& filename) std::ifstream file(filename); if (!file.is_open()) { - msg_error("SnapshotJSONExporter") << "ERROR: Cannot open file " << filename << " for reading\n"; + msg_error("SnapshotJSONExporter") << "Cannot open file " << filename << " for reading"; return ""; } @@ -273,7 +276,7 @@ void importFrom(std::map>& snapshots, con if (!file.is_open()) { - std::cerr << "ERROR: Cannot open file " << filename << " for reading\n"; + msg_error("SnapshotJSONExporter") << "Cannot open file " << filename << " for reading"; return; } @@ -311,7 +314,7 @@ void separateSnapshots(const std::string& filename, SnapshotManager& snapshotMan if (!file.is_open()) { - msg_error("SnapshotJSONExporter") << "ERROR: Cannot open file " << filename << " for reading\n"; + msg_error("SnapshotJSONExporter") << "Cannot open file " << filename << " for reading"; return; } @@ -330,7 +333,7 @@ void separateSnapshots(const std::string& filename, SnapshotManager& snapshotMan snapshotTime = data.value; } - snapshotManager.AddRecentSnapshot(snapshotManager.recentSnapshots,snapshot, std::stod(snapshotTime)); + snapshotManager.AddRecentSnapshot(snapshotManager.m_recentSnapshots,snapshot, std::stod(snapshotTime)); } } diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.h b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.h index 55cd95ff871..9de86b1b5bf 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.h @@ -37,8 +37,8 @@ class SnapshotManager SnapshotManager(); ~SnapshotManager(); - std::vector recentSnapshotFiles; - std::map> recentSnapshots; + std::vector m_recentSnapshotFiles; + std::map> m_recentSnapshots; static void AddRecentFile(const std::string& path, std::vector& recentFiles, int maxFiles = 10); From 1e19e717fe0d69da7df068d45382e12a9768f0d1 Mon Sep 17 00:00:00 2001 From: Lucas-TJ Date: Mon, 6 Jul 2026 11:57:14 +0200 Subject: [PATCH 53/57] fix & clean --- .../simutest/objectmodel/Snapshot_test.cpp | 26 +++++++------------ .../Core/src/sofa/core/objectmodel/Base.cpp | 3 ++- .../Core/src/sofa/core/objectmodel/BaseLink.h | 1 + .../Core/src/sofa/core/objectmodel/BaseNode.h | 4 +++ .../Core/src/sofa/core/objectmodel/Snapshot.h | 1 - .../core/objectmodel/SnapshotJSONExporter.cpp | 4 +-- .../core/objectmodel/SnapshotJSONExporter.h | 4 +-- .../sofa/core/objectmodel/SnapshotManager.h | 4 +-- .../sofa/simulation/LoadSnapshotVisitor.cpp | 9 +++---- 9 files changed, 26 insertions(+), 30 deletions(-) diff --git a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp index cfbe65825a7..f5af64820dc 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp @@ -62,10 +62,10 @@ class TestComponent : public BaseComponent sofa::MultiLink l_target; TestComponent() - : d_value(initData(&d_value, 3.14f, "value", "test value")) + : d_value(initData(&d_value, 3.14f, "pi", "test value")) , l_target(initLink("target","target test")) { - this->setName("pi"); + this->setName("TestComponent"); } void saveData(Snapshot::SnapshotObject& snapshot) @@ -111,12 +111,11 @@ TEST_F(Snapshot_test, saveDataIn) Component.saveData(*snapshot); for (auto& data : snapshot->m_dataContainer) { - if(data.name == "name") + if (data.name == "name") { - EXPECT_EQ(data.value, "pi"); + EXPECT_EQ(data.value, "TestComponent"); } - - if(data.name == "value") + if(data.name == "pi") { EXPECT_EQ(data.value, "3.14"); } @@ -184,12 +183,7 @@ TEST_F(Snapshot_test, createSnapshotObject) EXPECT_EQ(snapshotObject->m_name, "snapshotObject"); for (auto& data : snapshotObject->m_dataContainer) { - if(data.name == "name") - { - EXPECT_EQ(data.value, "pi"); - } - - if(data.name == "value") + if(data.name == "pi") { EXPECT_EQ(data.value, "3.14"); } @@ -218,7 +212,7 @@ TEST_F(Snapshot_test, findSnapshotObject) auto snapshot = Component.saveSnapshot(snapshotParents); snapshotNode->components.push_back(*snapshot); - auto expectedObject = Component.findSnapshotObject(snapshotNode, "pi"); + auto expectedObject = Component.findSnapshotObject(snapshotNode, "TestComponent"); EXPECT_NE(expectedObject, nullptr); EXPECT_EQ(Component.getName(), expectedObject->m_name); @@ -243,11 +237,11 @@ TEST_F(Snapshot_test, saveSnapshot) snapshot = Component.saveSnapshot(snapshotParents); - EXPECT_EQ(snapshot->m_name, "pi"); + EXPECT_EQ(snapshot->m_name, "TestComponent"); EXPECT_EQ(snapshot->m_dataContainer.size(), 7); EXPECT_EQ(snapshot->m_dataContainer[0].name, "name"); - EXPECT_EQ(snapshot->m_dataContainer[0].value, "pi"); - EXPECT_EQ(snapshot->m_dataContainer.back().name, "value"); + EXPECT_EQ(snapshot->m_dataContainer[0].value, "TestComponent"); + EXPECT_EQ(snapshot->m_dataContainer.back().name, "pi"); EXPECT_EQ(snapshot->m_dataContainer.back().value, "3.14"); EXPECT_EQ(snapshot->m_linkContainer[0].name, "context"); EXPECT_EQ(snapshot->m_linkContainer[0].value, "@./"); diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index 3512d3f8ba0..80ac272ddd7 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -712,7 +712,8 @@ void Base::saveLinksIn(Snapshot::SnapshotObject& snapshot) const } } -void Base::saveInternalStateIn(Snapshot::SnapshotObject& snapshot) const { +void Base::saveInternalStateIn(Snapshot::SnapshotObject& snapshot) const +{ SOFA_UNUSED(snapshot); } diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.h index d8b229c9e91..cbedb7f3e2b 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseLink.h @@ -134,6 +134,7 @@ class SOFA_CORE_API BaseLink /// Read the command line bool read( const std::string& str ); + /// Read the command line from a snapshot bool readFromSnapshot( const std::string& str ); /// Update pointers in case the pointed-to objects have appeared diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.h b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.h index 9c2bf3c27b2..e9f5c4a416b 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/BaseNode.h @@ -130,8 +130,12 @@ class SOFA_CORE_API BaseNode : public virtual Base virtual core::visual::VisualLoop* getVisualLoop() const; protected: + + /// Create a SnapshotObject that will contain data and link std::shared_ptr createSnapshotObject(std::vector>& parents) const override; public: + + /// Find a SnapshotObject corresponding to the object from the scene std::shared_ptr findSnapshotObject(const std::shared_ptr& parents, const std::string& objectname) override; private: diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.h index 9c04f642d1b..a3505ddd706 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Snapshot.h @@ -37,7 +37,6 @@ namespace sofa::core::objectmodel * This class contains the structure for a snapshot of a simulation in SOFA. * The snapshot contains data and link, and keep the shape of a scene graph */ - class SOFA_CORE_API Snapshot { diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp index 99b678f58a9..4eb5de6d844 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp @@ -235,7 +235,7 @@ void importFrom(Snapshot& snapshot, const std::string& filename) msg_info("SnapshotJSONExporter") << "JSON imported successfully from: " << filename; } -std::string file_To_String(const std::string& filename) +std::string fileToString(const std::string& filename) { std::ifstream file(filename); if (!file.is_open()) @@ -250,7 +250,7 @@ std::string file_To_String(const std::string& filename) return to_string(jsonRoot); } -std::string snapshot_To_String(const Snapshot& snapshot) +std::string snapshotToString(const Snapshot& snapshot) { nlohmann::json j = snapshot.m_graphRoot ; return to_string(j); diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h index 9e002251104..df0efff1819 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h @@ -34,10 +34,10 @@ namespace sofa::core::objectmodel void importFrom(Snapshot& snapshot, const std::string& filename); /// Read a JSON file and returns its content as a string - std::string file_To_String(const std::string& filename); + std::string fileToString(const std::string& filename); /// Serialize a Snapshot to a JSON string - std::string snapshot_To_String(const Snapshot& snapshot); + std::string snapshotToString(const Snapshot& snapshot); /// Export a collection of Snapshots to a single JSON file void exportToJSON(std::map>& snapshots, const std::string& filename); diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.h b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.h index 9de86b1b5bf..25671c35273 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.h @@ -41,8 +41,8 @@ class SnapshotManager std::map> m_recentSnapshots; - static void AddRecentFile(const std::string& path, std::vector& recentFiles, int maxFiles = 10); - static void AddRecentSnapshot(std::map>& recentSnapshots, std::shared_ptr snapshot, double snapshotTime ); + void AddRecentFile(const std::string& path, std::vector& recentFiles, int maxFiles = 10); + void AddRecentSnapshot(std::map>& recentSnapshots, std::shared_ptr snapshot, double snapshotTime ); }; } // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp index f5eca27d842..57c6c7e98e7 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp @@ -22,6 +22,7 @@ #include #include #include +#include namespace sofa::simulation { @@ -32,9 +33,7 @@ void LoadSnapshotVisitor::processObject( ) { auto snapshotObject = obj->findSnapshotObject(parent, obj->getName()); - if (!snapshotObject) - msg_error("findSnapshotObject") << "SnapshotObject " << obj->getName() << " not found"; - else + if (snapshotObject) { obj->loadDataSnapshot(snapshotObject); obj->loadLinkSnapshot(snapshotObject); @@ -45,9 +44,7 @@ void LoadSnapshotVisitor::processObject( Visitor::Result LoadSnapshotVisitor::processNodeTopDown(simulation::Node* node) { const auto snapshotObject = node->findSnapshotObject(m_snapshotContainer.m_graphRoot, node->getName()); - if (!snapshotObject) - msg_error("findSnapshotNode") << "SnapshotNode "<< node->getName() << " not found"; - else + if (snapshotObject) { const auto SnapshotNode = std::dynamic_pointer_cast(snapshotObject); node->loadDataSnapshot(SnapshotNode); From 4b11efabc9f9b1513459d21d99f2e0d25ec5d36e Mon Sep 17 00:00:00 2001 From: Lucas-TJ Date: Tue, 7 Jul 2026 17:08:10 +0200 Subject: [PATCH 54/57] Modifications to SnapshotManager class --- Sofa/framework/Core/CMakeLists.txt | 2 - .../core/objectmodel/SnapshotJSONExporter.cpp | 34 +--- .../core/objectmodel/SnapshotJSONExporter.h | 6 +- .../sofa/core/objectmodel/SnapshotManager.cpp | 51 ------ .../sofa/core/objectmodel/SnapshotManager.h | 48 ------ Sofa/framework/Simulation/Core/CMakeLists.txt | 3 + .../src/sofa/simulation/SnapshotManager.cpp | 145 ++++++++++++++++++ .../src/sofa/simulation/SnapshotManager.h | 84 ++++++++++ 8 files changed, 234 insertions(+), 139 deletions(-) delete mode 100644 Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.cpp delete mode 100644 Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.h create mode 100644 Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotManager.cpp create mode 100644 Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotManager.h diff --git a/Sofa/framework/Core/CMakeLists.txt b/Sofa/framework/Core/CMakeLists.txt index 613b45e02be..439e7724da2 100644 --- a/Sofa/framework/Core/CMakeLists.txt +++ b/Sofa/framework/Core/CMakeLists.txt @@ -186,7 +186,6 @@ set(HEADER_FILES ${SRC_ROOT}/objectmodel/lifecycle/RemovedData.h ${SRC_ROOT}/objectmodel/lifecycle/RenamedData.h ${SRC_ROOT}/objectmodel/Link.h - ${SRC_ROOT}/objectmodel/SnapshotManager.h ${SRC_ROOT}/objectmodel/MouseEvent.h ${SRC_ROOT}/objectmodel/SPtr.h ${SRC_ROOT}/objectmodel/ScriptEvent.h @@ -336,7 +335,6 @@ set(SOURCE_FILES ${SRC_ROOT}/objectmodel/KeypressedEvent.cpp ${SRC_ROOT}/objectmodel/KeyreleasedEvent.cpp ${SRC_ROOT}/objectmodel/lifecycle/DeprecatedData.cpp - ${SRC_ROOT}/objectmodel/SnapshotManager.cpp ${SRC_ROOT}/objectmodel/MouseEvent.cpp ${SRC_ROOT}/objectmodel/ScriptEvent.cpp ${SRC_ROOT}/objectmodel/Tag.cpp diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp index 4eb5de6d844..a64ebaaae8d 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.cpp @@ -306,36 +306,4 @@ void importFrom(std::map>& snapshots, con } } -void separateSnapshots(const std::string& filename, SnapshotManager& snapshotManager) -{ - std::ifstream file(filename); - - nlohmann::json jSnapshot; - - if (!file.is_open()) - { - msg_error("SnapshotJSONExporter") << "Cannot open file " << filename << " for reading"; - return; - } - - file >> jSnapshot; - file.close(); - - for (const auto& snapshotJson : jSnapshot) - { - auto snapshot = std::make_shared(); - snapshot->m_graphRoot = std::make_shared(); - from_json(snapshotJson, *snapshot->m_graphRoot); - std::string snapshotTime = "0"; - for (const auto& data : snapshot->m_graphRoot->m_dataContainer) - { - if (data.name == "time") - snapshotTime = data.value; - } - - snapshotManager.AddRecentSnapshot(snapshotManager.m_recentSnapshots,snapshot, std::stod(snapshotTime)); - } - -} - -} // namespace sofa::core::objectmodel \ No newline at end of file +} // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h index df0efff1819..679375ba4b9 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h @@ -22,7 +22,6 @@ #pragma once #include #include -#include namespace sofa::core::objectmodel { @@ -45,7 +44,4 @@ namespace sofa::core::objectmodel /// Import a collection of Snapshots from a single JSON file void importFrom(std::map>& snapshots, const std::string& filename); - /// Parses a multi-snapshot JSON file and registers each snapshot with a SnapshotManager - void separateSnapshots(const std::string& filename, SnapshotManager& snapshotManager); - -} // namespace sofa::core::objectmodel \ No newline at end of file +} // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.cpp deleted file mode 100644 index 28a82141040..00000000000 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.cpp +++ /dev/null @@ -1,51 +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 - -namespace sofa::core::objectmodel -{ - -SnapshotManager::SnapshotManager() = default; - -SnapshotManager::~SnapshotManager() = default; - -void SnapshotManager::AddRecentFile(const std::string& path, std::vector& recentFiles, int maxFiles) -{ - recentFiles.erase( - std::remove(recentFiles.begin(), recentFiles.end(), path), - recentFiles.end() - ); - recentFiles.push_back(path); - if (recentFiles.size() > maxFiles) - recentFiles.resize(maxFiles); -} - -void SnapshotManager::AddRecentSnapshot(std::map>& recentSnapshots, std::shared_ptr snapshot, double snapshotTime) -{ - static int index = 0; - recentSnapshots["Memory_Snapshot " + std::to_string(index++) + " at " + std::to_string(snapshotTime)] = snapshot; - -} - -} // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.h b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.h deleted file mode 100644 index 25671c35273..00000000000 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotManager.h +++ /dev/null @@ -1,48 +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 * -******************************************************************************/ -#pragma once -#include -#include - -namespace sofa::core::objectmodel -{ - -/** -* \brief Snapshot Class for a container of snapshot -* -* This class contains methods and elements that will help to manage snapshot in memory. -*/ -class SnapshotManager -{ -public: - SnapshotManager(); - ~SnapshotManager(); - - std::vector m_recentSnapshotFiles; - std::map> m_recentSnapshots; - - - void AddRecentFile(const std::string& path, std::vector& recentFiles, int maxFiles = 10); - void AddRecentSnapshot(std::map>& recentSnapshots, std::shared_ptr snapshot, double snapshotTime ); - -}; -} // namespace sofa::core::objectmodel \ No newline at end of file diff --git a/Sofa/framework/Simulation/Core/CMakeLists.txt b/Sofa/framework/Simulation/Core/CMakeLists.txt index 21be119265e..5a825de3ffe 100644 --- a/Sofa/framework/Simulation/Core/CMakeLists.txt +++ b/Sofa/framework/Simulation/Core/CMakeLists.txt @@ -46,6 +46,7 @@ set(HEADER_FILES ${SRC_ROOT}/Simulation.h ${SRC_ROOT}/SimulationLoop.h ${SRC_ROOT}/SaveSnapshotVisitor.h + ${SRC_ROOT}/SnapshotManager.h ${SRC_ROOT}/SolveVisitor.h ${SRC_ROOT}/StateChangeVisitor.h ${SRC_ROOT}/TopologyChangeVisitor.h @@ -202,6 +203,7 @@ set(SOURCE_FILES ${SRC_ROOT}/SceneCheckMainRegistry.cpp ${SRC_ROOT}/Simulation.cpp ${SRC_ROOT}/SaveSnapshotVisitor.cpp + ${SRC_ROOT}/SnapshotManager.cpp ${SRC_ROOT}/SolveVisitor.cpp ${SRC_ROOT}/StateChangeVisitor.cpp ${SRC_ROOT}/TopologyChangeVisitor.cpp @@ -326,6 +328,7 @@ sofa_find_package(Sofa.Core REQUIRED) add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES}) target_link_libraries(${PROJECT_NAME} PUBLIC Sofa.Core) +target_link_libraries(${PROJECT_NAME} PRIVATE nlohmann_json::nlohmann_json) target_include_directories(${PROJECT_NAME} PUBLIC $ diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotManager.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotManager.cpp new file mode 100644 index 00000000000..5e525c84217 --- /dev/null +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotManager.cpp @@ -0,0 +1,145 @@ +/****************************************************************************** +* 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 +#include +#include +#include +#include +#include +using sofa::helper::system::FileSystem; + + + +namespace sofa::simulation +{ + +SnapshotManager::SnapshotManager() = default; + +SnapshotManager::~SnapshotManager() = default; + +void SnapshotManager::addRecentFile(const std::string& path) +{ + m_recentSnapshotsFromFiles.erase(std::remove(m_recentSnapshotsFromFiles.begin(), m_recentSnapshotsFromFiles.end(), path), m_recentSnapshotsFromFiles.end()); + m_recentSnapshotsFromFiles.push_back(path); +} + +void SnapshotManager::addRecentSnapshot(std::shared_ptr snapshot, + double snapshotTime) +{ + static int index = 0; + m_recentSnapshotsFromMemory["Memory_Snapshot " + std::to_string(index++) + " at " + std::to_string(snapshotTime)] = std::move(snapshot); +} + +void SnapshotManager::doMemorySave(sofa::core::sptr& groot) +{ + auto snapshot = std::make_shared(); + auto visitor = SaveSnapshotVisitor(nullptr, *snapshot); + groot->execute(visitor); + addRecentSnapshot(snapshot, groot->getTime()); +} + +void SnapshotManager::doMemoryLoad(sofa::core::sptr& groot) +{ + if (m_recentSnapshotsFromMemory.empty()) + { + msg_warning("MemoryLoad") << "No Snapshot in memory"; + return; + } + + const auto& snapshot = m_recentSnapshotsFromMemory.rbegin()->second; + auto visitor = LoadSnapshotVisitor(nullptr, *snapshot); + groot->execute(visitor); +} + +void SnapshotManager::doSaveTo(sofa::core::sptr& groot,std::string savePath, bool isGroup) +{ + auto m_snapshot = std::make_shared(); + auto visitor = SaveSnapshotVisitor(nullptr,*m_snapshot); + groot->execute(visitor); + + + std::string FileExtension = FileSystem::getExtension(savePath); + if (FileExtension == "json" && !isGroup) + exportToJSON(*m_snapshot,savePath); + else if (FileExtension == "json" && isGroup) + exportToJSON(m_recentSnapshotsFromMemory,savePath); + else + msg_error("SaveSnapshot") << "Snapshot " << savePath << " not supported"; + + addRecentFile(savePath); + msg_info("SaveSnapshot") << "Snapshot " << savePath << " saved"; +} + +void SnapshotManager::doLoadTo(sofa::core::sptr& groot, std::string outPath) +{ + auto m_snapshot = std::make_shared(); + if (FileSystem::exists(outPath)) + { + importFrom(*m_snapshot,outPath); + auto visitor = LoadSnapshotVisitor(nullptr,*m_snapshot); + groot->execute(visitor); + } + addRecentFile(outPath); + msg_info("LoadSnapshot") << "Snapshot " << outPath << " loaded"; +} + +void SnapshotManager::doLoadToGroup(const std::string& filename) +{ + if (!FileSystem::exists(filename)) + return; + + std::ifstream file(filename); + + nlohmann::json jSnapshot; + + if (!file.is_open()) + { + msg_error("SnapshotJSONExporter") << "Cannot open file " << filename << " for reading"; + return; + } + + file >> jSnapshot; + file.close(); + + for (const auto& snapshotJson : jSnapshot) + { + auto snapshot = std::make_shared(); + snapshot->m_graphRoot = std::make_shared(); + sofa::core::objectmodel::from_json(snapshotJson, *snapshot->m_graphRoot); + std::string snapshotTime = "0"; + for (const auto& data : snapshot->m_graphRoot->m_dataContainer) + { + if (data.name == "time") + snapshotTime = data.value; + } + + addRecentSnapshot(snapshot, std::stod(snapshotTime)); + } + + msg_info("LoadSnapshot") << "Snapshot " << filename << " loaded"; +} + +} // namespace sofa::simulation diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotManager.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotManager.h new file mode 100644 index 00000000000..64077d63e66 --- /dev/null +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotManager.h @@ -0,0 +1,84 @@ +/****************************************************************************** +* 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 * +******************************************************************************/ +#pragma once + +#include +#include +#include +#include + +#include +#include +#include +#include + + +namespace sofa::simulation +{ + +/** + * \brief Snapshot container and memory save/load helper. + * + * Actually, this class: + * - Store snapshots (from files or memory) + * - Do save/load in memory + * - Do save/load in a file + * + */ +class SOFA_SIMULATION_CORE_API SnapshotManager +{ +public: + SnapshotManager(); + ~SnapshotManager(); + + /// Container of snapshot from Files + std::vector m_recentSnapshotsFromFiles; + + /// Container of snapshot from Memory + std::map> m_recentSnapshotsFromMemory; + + /// Store every snapshot from files in m_recentSnapshotsFromFiles and sort them by filename + void addRecentFile(const std::string& path); + + /// Store every snapshot in memory in m_recentSnapshotsFromMemory and sort them by simulation time + void addRecentSnapshot(std::shared_ptr snapshot, + double snapshotTime); + + /// Save and store a Snapshot in memory + void doMemorySave(sofa::core::sptr& groot); + + /// Load a snapshot from memory + void doMemoryLoad(sofa::core::sptr& groot); + + /// Save and store a Snapshot to a file (or Save and store a group of Snapshot to a file when isGroup is true) + void doSaveTo(sofa::core::sptr& groot,std::string savePath, bool isGroup); + + /// Load a snapshot from a file + void doLoadTo(sofa::core::sptr& groot, std::string outPath); + + /// Load a group of snapshots from a file + void doLoadToGroup(const std::string& filename); + + +}; + +} // namespace sofa::simulation From 83408b52f4aae526e4af8ac728f4d693ee684324 Mon Sep 17 00:00:00 2001 From: Lucas-TJ Date: Wed, 8 Jul 2026 10:37:31 +0200 Subject: [PATCH 55/57] clean base.h and fix windows compilation --- .../simutest/objectmodel/Snapshot_test.cpp | 31 +++++-- .../Core/src/sofa/core/objectmodel/Base.cpp | 82 +++++++++++-------- .../Core/src/sofa/core/objectmodel/Base.h | 23 ++---- .../sofa/simulation/LoadSnapshotVisitor.cpp | 10 ++- 4 files changed, 85 insertions(+), 61 deletions(-) diff --git a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp index f5af64820dc..d770723feab 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp @@ -70,12 +70,30 @@ class TestComponent : public BaseComponent void saveData(Snapshot::SnapshotObject& snapshot) { - this->saveDataIn(snapshot); + for (const auto& dataFields = this->getDataFields(); const auto& data : dataFields) + { + Snapshot::DataInfo dataInfo; + dataInfo.name = data->getName(); + dataInfo.type = data->getValueTypeString(); + dataInfo.value = data->getValueString(); + + snapshot.m_dataContainer.push_back(dataInfo); + } } void saveLinks(Snapshot::SnapshotObject& snapshot) { - this->saveLinksIn(snapshot); + for (const auto& links = this->getLinks(); const auto& link : links) + { + Snapshot::LinkInfo linkInfo; + linkInfo.name = link->getName(); + linkInfo.type = link->getValueTypeString(); + linkInfo.value = link->getValueString(); + + std::string search = "//"; + sofa::helper::replaceAll(linkInfo.value, search,""); + snapshot.m_linkContainer.push_back(linkInfo); + } } std::shared_ptr createSnapshotObjectTest(std::vector>& parents) const @@ -273,7 +291,7 @@ TEST_F(Snapshot_test, loadDataSnapshot) TestComponent Component2; Component2.d_value.setValue(0.0f); - Component2.loadDataSnapshot(snapshot); + Component2.loadSnapshot(snapshot); EXPECT_EQ(Component2.d_value.getValue(), 3.14f); } @@ -325,7 +343,7 @@ TEST_F(Snapshot_test, loadLinkSnapshot) EXPECT_EQ(Component1->l_target.getValueString(), "@Component2 @Component3"); - Component1->loadLinkSnapshot(snapshotObject1); + Component1->loadSnapshot(snapshotObject1); EXPECT_EQ(Component1->l_target.getValueString(), "@Component2"); } @@ -370,14 +388,14 @@ TEST_F(Snapshot_test, SnapshotJSONExporter) auto visitor = SaveSnapshotVisitor(nullptr, *snapshot); root->execute(visitor); - exportToJSON(*snapshot,path); + exportToJSON(*snapshot, path.string()); std::ifstream checkFile(path); EXPECT_TRUE(checkFile.good()); checkFile.close(); auto snapshot_import = std::make_shared(); - importFrom(*snapshot_import, path); + importFrom(*snapshot_import, path.string()); EXPECT_NE(snapshot_import->m_graphRoot,nullptr); @@ -390,4 +408,3 @@ TEST_F(Snapshot_test, SnapshotJSONExporter) std::filesystem::remove(path); } - diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp index 80ac272ddd7..3ce613fbbcb 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.cpp @@ -684,34 +684,6 @@ int Base::getInstanciationSourceFilePos() const return m_instanciationSourceFilePos; } -void Base::saveDataIn(Snapshot::SnapshotObject& snapshot) const -{ - for (const auto& dataFields = this->getDataFields(); const auto& data : dataFields) - { - Snapshot::DataInfo dataInfo; - dataInfo.name = data->getName(); - dataInfo.type = data->getValueTypeString(); - dataInfo.value = data->getValueString(); - - snapshot.m_dataContainer.push_back(dataInfo); - } -} - -void Base::saveLinksIn(Snapshot::SnapshotObject& snapshot) const -{ - for (const auto& links = this->getLinks(); const auto& link : links) - { - Snapshot::LinkInfo linkInfo; - linkInfo.name = link->getName(); - linkInfo.type = link->getValueTypeString(); - linkInfo.value = link->getValueString(); - - std::string search = "//"; - sofa::helper::replaceAll(linkInfo.value, search,""); - snapshot.m_linkContainer.push_back(linkInfo); - } -} - void Base::saveInternalStateIn(Snapshot::SnapshotObject& snapshot) const { SOFA_UNUSED(snapshot); @@ -735,8 +707,29 @@ std::shared_ptr Base::saveSnapshot(std::vectorm_name = this->getName(); - saveDataIn(*snapshotObject); - saveLinksIn(*snapshotObject); + + for (const auto& dataFields = this->getDataFields(); const auto& data : dataFields) + { + Snapshot::DataInfo dataInfo; + dataInfo.name = data->getName(); + dataInfo.type = data->getValueTypeString(); + dataInfo.value = data->getValueString(); + + snapshotObject->m_dataContainer.push_back(dataInfo); + } + + for (const auto& links = this->getLinks(); const auto& link : links) + { + Snapshot::LinkInfo linkInfo; + linkInfo.name = link->getName(); + linkInfo.type = link->getValueTypeString(); + linkInfo.value = link->getValueString(); + + std::string search = "//"; + sofa::helper::replaceAll(linkInfo.value, search,""); + snapshotObject->m_linkContainer.push_back(linkInfo); + } + saveInternalStateIn(*snapshotObject); return snapshotObject; } @@ -766,7 +759,30 @@ void Base::loadInternalStateFrom(const Snapshot::SnapshotObject& snapshot) } -void Base::loadDataSnapshot(const std::shared_ptr& snapshotObject) const +// void Base::loadDataSnapshot(const std::shared_ptr& snapshotObject) const +// { +// for (const auto& dataInfo : snapshotObject->m_dataContainer) +// { +// if (const auto data = this->findData(dataInfo.name)) +// { +// if(data->read(dataInfo.value) == 0 ) +// msg_error() << "Failed to read " << dataInfo.name << " in " << this->getName() << " from the snapshot " << dataInfo.value; +// } +// } +// } +// +// void Base::loadLinkSnapshot(const std::shared_ptr& snapshotObject) const +// { +// for (const auto& linkInfo : snapshotObject->m_linkContainer) { +// if (const auto link = this->findLink(linkInfo.name)) { +// +// if (link->readFromSnapshot(linkInfo.value) == 0 ) +// msg_error() << "Failed to read " << linkInfo.name << " in " << this->getName() << " from the snapshot " << linkInfo.value; +// } +// } +// } + +void Base::loadSnapshot(const std::shared_ptr& snapshotObject) const { for (const auto& dataInfo : snapshotObject->m_dataContainer) { @@ -776,10 +792,7 @@ void Base::loadDataSnapshot(const std::shared_ptr& sna msg_error() << "Failed to read " << dataInfo.name << " in " << this->getName() << " from the snapshot " << dataInfo.value; } } -} -void Base::loadLinkSnapshot(const std::shared_ptr& snapshotObject) const -{ for (const auto& linkInfo : snapshotObject->m_linkContainer) { if (const auto link = this->findLink(linkInfo.name)) { @@ -789,7 +802,6 @@ void Base::loadLinkSnapshot(const std::shared_ptr& sna } } - }// namespace sofa::core::objectmodel diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h index aa3a1d52a1a..09cc719d536 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/Base.h @@ -365,32 +365,25 @@ class SOFA_CORE_API Base : public IntrusiveObject /// Save a SnapshotObject full of data and link into the snapshot std::shared_ptr saveSnapshot(std::vector>& parents) const; - /// Load data from the snapshot to the scene - void loadDataSnapshot(const std::shared_ptr& snapshotObject) const; + /// Load data and links from the snapshot to the scene + void loadSnapshot(const std::shared_ptr& snapshotObject) const; + + /// Save Internal State to the SnapshotObject + virtual void saveInternalStateIn(Snapshot::SnapshotObject& snapshot) const; - /// Load link from the snapshot to the scene - void loadLinkSnapshot(const std::shared_ptr& snapshotObject) const; + ///Load Internal State from a snapshot to the scene + virtual void loadInternalStateFrom(const Snapshot::SnapshotObject& snapshot); protected: - /// Save data from an object to the SnapshotObject - void saveDataIn(Snapshot::SnapshotObject& snapshot) const; - - /// Save link from an object to the SnapshotObject - void saveLinksIn(Snapshot::SnapshotObject& snapshot) const; - /// Create a SnapshotObject that will contain data and link virtual std::shared_ptr createSnapshotObject(std::vector>& parents) const; + public : /// Find a SnapshotObject corresponding to the object from the scene virtual std::shared_ptr findSnapshotObject(const std::shared_ptr& parents, const std::string& objectname); - /// Save Internal State to the SnapshotObject - virtual void saveInternalStateIn(Snapshot::SnapshotObject& snapshot) const; - - ///Load Internal State from a snapshot to the scene - virtual void loadInternalStateFrom(const Snapshot::SnapshotObject& snapshot) ; protected: /// List of fields (Data instances) VecData m_vecData; diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp index 57c6c7e98e7..37116ab879b 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/LoadSnapshotVisitor.cpp @@ -35,8 +35,9 @@ void LoadSnapshotVisitor::processObject( auto snapshotObject = obj->findSnapshotObject(parent, obj->getName()); if (snapshotObject) { - obj->loadDataSnapshot(snapshotObject); - obj->loadLinkSnapshot(snapshotObject); + // obj->loadDataSnapshot(snapshotObject); + // obj->loadLinkSnapshot(snapshotObject); + obj->loadSnapshot(snapshotObject); obj->loadInternalStateFrom(*snapshotObject); } } @@ -47,8 +48,9 @@ Visitor::Result LoadSnapshotVisitor::processNodeTopDown(simulation::Node* node) if (snapshotObject) { const auto SnapshotNode = std::dynamic_pointer_cast(snapshotObject); - node->loadDataSnapshot(SnapshotNode); - node->loadLinkSnapshot(SnapshotNode); + // node->loadDataSnapshot(SnapshotNode); + // node->loadLinkSnapshot(SnapshotNode); + node->loadSnapshot(SnapshotNode); for (simulation::Node::ObjectIterator it = node->object.begin(); it != node->object.end(); ++it) { this->processObject(it->get(), SnapshotNode); From d731b1f026de9d4d14cfd969990bb8517f53f736 Mon Sep 17 00:00:00 2001 From: Lucas-TJ Date: Wed, 8 Jul 2026 11:16:56 +0200 Subject: [PATCH 56/57] cleaning --- .../simutest/objectmodel/Snapshot_test.cpp | 1 - .../core/objectmodel/SnapshotJSONExporter.h | 12 +++++----- .../src/sofa/simulation/SnapshotManager.cpp | 24 +++++++++---------- .../src/sofa/simulation/SnapshotManager.h | 8 +++---- 4 files changed, 22 insertions(+), 23 deletions(-) diff --git a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp index d770723feab..dd0abee4773 100644 --- a/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp +++ b/Sofa/framework/Core/simutest/objectmodel/Snapshot_test.cpp @@ -407,4 +407,3 @@ TEST_F(Snapshot_test, SnapshotJSONExporter) std::filesystem::remove(path); } - diff --git a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h index 679375ba4b9..31c1ed444ff 100644 --- a/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h +++ b/Sofa/framework/Core/src/sofa/core/objectmodel/SnapshotJSONExporter.h @@ -27,21 +27,21 @@ namespace sofa::core::objectmodel { /// Export a single Snapshot to a JSON file - void exportToJSON(Snapshot& snapshot, const std::string& filename); + SOFA_CORE_API void exportToJSON(Snapshot& snapshot, const std::string& filename); /// Import a single Snapshot from a JSON file - void importFrom(Snapshot& snapshot, const std::string& filename); + SOFA_CORE_API void importFrom(Snapshot& snapshot, const std::string& filename); /// Read a JSON file and returns its content as a string - std::string fileToString(const std::string& filename); + SOFA_CORE_API std::string fileToString(const std::string& filename); /// Serialize a Snapshot to a JSON string - std::string snapshotToString(const Snapshot& snapshot); + SOFA_CORE_API std::string snapshotToString(const Snapshot& snapshot); /// Export a collection of Snapshots to a single JSON file - void exportToJSON(std::map>& snapshots, const std::string& filename); + SOFA_CORE_API void exportToJSON(std::map>& snapshots, const std::string& filename); /// Import a collection of Snapshots from a single JSON file - void importFrom(std::map>& snapshots, const std::string& filename); + SOFA_CORE_API void importFrom(std::map>& snapshots, const std::string& filename); } // namespace sofa::core::objectmodel diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotManager.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotManager.cpp index 5e525c84217..bbb467ee964 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotManager.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotManager.cpp @@ -40,17 +40,17 @@ SnapshotManager::SnapshotManager() = default; SnapshotManager::~SnapshotManager() = default; -void SnapshotManager::addRecentFile(const std::string& path) +void SnapshotManager::addSnapshotFromFile(const std::string& path) { - m_recentSnapshotsFromFiles.erase(std::remove(m_recentSnapshotsFromFiles.begin(), m_recentSnapshotsFromFiles.end(), path), m_recentSnapshotsFromFiles.end()); - m_recentSnapshotsFromFiles.push_back(path); + m_snapshotsFromFiles.erase(std::remove(m_snapshotsFromFiles.begin(), m_snapshotsFromFiles.end(), path), m_snapshotsFromFiles.end()); + m_snapshotsFromFiles.push_back(path); } -void SnapshotManager::addRecentSnapshot(std::shared_ptr snapshot, +void SnapshotManager::addSnapshotFromMemory(std::shared_ptr snapshot, double snapshotTime) { static int index = 0; - m_recentSnapshotsFromMemory["Memory_Snapshot " + std::to_string(index++) + " at " + std::to_string(snapshotTime)] = std::move(snapshot); + m_snapshotsFromMemory["Memory_Snapshot " + std::to_string(index++) + " at " + std::to_string(snapshotTime)] = std::move(snapshot); } void SnapshotManager::doMemorySave(sofa::core::sptr& groot) @@ -58,18 +58,18 @@ void SnapshotManager::doMemorySave(sofa::core::sptr& groot) auto snapshot = std::make_shared(); auto visitor = SaveSnapshotVisitor(nullptr, *snapshot); groot->execute(visitor); - addRecentSnapshot(snapshot, groot->getTime()); + addSnapshotFromMemory(snapshot, groot->getTime()); } void SnapshotManager::doMemoryLoad(sofa::core::sptr& groot) { - if (m_recentSnapshotsFromMemory.empty()) + if (m_snapshotsFromMemory.empty()) { msg_warning("MemoryLoad") << "No Snapshot in memory"; return; } - const auto& snapshot = m_recentSnapshotsFromMemory.rbegin()->second; + const auto& snapshot = m_snapshotsFromMemory.rbegin()->second; auto visitor = LoadSnapshotVisitor(nullptr, *snapshot); groot->execute(visitor); } @@ -85,11 +85,11 @@ void SnapshotManager::doSaveTo(sofa::core::sptr& groot,s if (FileExtension == "json" && !isGroup) exportToJSON(*m_snapshot,savePath); else if (FileExtension == "json" && isGroup) - exportToJSON(m_recentSnapshotsFromMemory,savePath); + exportToJSON(m_snapshotsFromMemory,savePath); else msg_error("SaveSnapshot") << "Snapshot " << savePath << " not supported"; - addRecentFile(savePath); + addSnapshotFromFile(savePath); msg_info("SaveSnapshot") << "Snapshot " << savePath << " saved"; } @@ -102,7 +102,7 @@ void SnapshotManager::doLoadTo(sofa::core::sptr& groot, auto visitor = LoadSnapshotVisitor(nullptr,*m_snapshot); groot->execute(visitor); } - addRecentFile(outPath); + addSnapshotFromFile(outPath); msg_info("LoadSnapshot") << "Snapshot " << outPath << " loaded"; } @@ -136,7 +136,7 @@ void SnapshotManager::doLoadToGroup(const std::string& filename) snapshotTime = data.value; } - addRecentSnapshot(snapshot, std::stod(snapshotTime)); + addSnapshotFromMemory(snapshot, std::stod(snapshotTime)); } msg_info("LoadSnapshot") << "Snapshot " << filename << " loaded"; diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotManager.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotManager.h index 64077d63e66..efbd32f07fd 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotManager.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotManager.h @@ -51,16 +51,16 @@ class SOFA_SIMULATION_CORE_API SnapshotManager ~SnapshotManager(); /// Container of snapshot from Files - std::vector m_recentSnapshotsFromFiles; + std::vector m_snapshotsFromFiles; /// Container of snapshot from Memory - std::map> m_recentSnapshotsFromMemory; + std::map> m_snapshotsFromMemory; /// Store every snapshot from files in m_recentSnapshotsFromFiles and sort them by filename - void addRecentFile(const std::string& path); + void addSnapshotFromFile(const std::string& path); /// Store every snapshot in memory in m_recentSnapshotsFromMemory and sort them by simulation time - void addRecentSnapshot(std::shared_ptr snapshot, + void addSnapshotFromMemory(std::shared_ptr snapshot, double snapshotTime); /// Save and store a Snapshot in memory From 7b6dd9fe82d163a4f19d53c6e0af09707c9e6287 Mon Sep 17 00:00:00 2001 From: Lucas-TJ Date: Wed, 8 Jul 2026 15:00:21 +0200 Subject: [PATCH 57/57] add documentation SnapshotManager.h --- .../src/sofa/simulation/SnapshotManager.h | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotManager.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotManager.h index efbd32f07fd..c58a277b2b7 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotManager.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/SnapshotManager.h @@ -36,12 +36,23 @@ namespace sofa::simulation { /** - * \brief Snapshot container and memory save/load helper. + * \brief SnapshotManager is responsible for storing and managing snapshots, whether they are kept in memory or stored on disk. * - * Actually, this class: - * - Store snapshots (from files or memory) - * - Do save/load in memory - * - Do save/load in a file + * Snapshots are stored in two separate containers: + * - m_snapshotsFromMemory for in-memory snapshots. + * - m_snapshotsFromFiles for snapshots stored on disk. + * + * New snapshots can be added using addSnapshotFromMemory() and + * addSnapshotFromFile(). + * + * Although in-memory and on-disk snapshots are handled separately, + * both follow the same overall design: + * + * - doMemorySave() and doMemoryLoad() save and restore snapshots in memory. + * - doSaveTo() and doLoadTo() save and load snapshots from disk. The output file format can be specified when calling doSaveTo(). + * + * The doSaveTo() function also provides an isGroup parameter, while doLoadToGroup() is used to load a collection of snapshots. + * These functions allow groups of snapshots to be saved to and restored from a single file. * */ class SOFA_SIMULATION_CORE_API SnapshotManager