Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
4879dbc
SaveSnapshotv1
Lucas-TJ Dec 22, 2025
724af0f
Save Snapshot - choose filename
Lucas-TJ Dec 23, 2025
06f2410
new feature : select type of snapshot (only JSON)
Lucas-TJ Jan 6, 2026
03b1950
fix tree structure SaveSnapshot
Lucas-TJ Jan 13, 2026
82f7b8a
update Snapshot
Lucas-TJ Jan 26, 2026
cfbc57f
[Snapshot] ADD codes for load a snapshot
Lucas-TJ Jan 27, 2026
eac5dfd
clean some comments
Lucas-TJ Jan 28, 2026
f6d1d0e
[SNAPSHOT] FIX save and load snapshotAPI
Lucas-TJ Feb 3, 2026
53dfb58
Update laodSnapshot
Lucas-TJ Feb 9, 2026
0a97a35
[Snapshot] Fix LoadSnapshot for JSON
Lucas-TJ Feb 25, 2026
c59fd04
modify API for save/load snapshot
Lucas-TJ Feb 26, 2026
f93eb39
clean 27/02
Lucas-TJ Feb 27, 2026
2ffba4c
Renaming SnapshotVisitor to SaveSnapshotVisitor
Lucas-TJ Mar 3, 2026
3201b1b
(draft) split data and link visitor for loading
Lucas-TJ Mar 11, 2026
f3de55f
update 19/03
Lucas-TJ Mar 19, 2026
e93a9c0
rename BaseSnapshot to Snapshot
Lucas-TJ Mar 19, 2026
6f9a080
Refactoring the API of snapshot (Snapshot, SnapshotJSONExporter and S…
Lucas-TJ Mar 20, 2026
1079e40
Fix loadDataSnapshot and update SnapshotManager
Lucas-TJ Mar 23, 2026
158d1c4
update snapshot API
Lucas-TJ May 5, 2026
f1a48a3
update GUI with snapshot
Lucas-TJ May 11, 2026
72d1739
SaveSnapshotv1
Lucas-TJ Dec 22, 2025
4355f6f
[Snapshot] ADD codes for load a snapshot
Lucas-TJ Jan 27, 2026
25a67bb
(draft) split data and link visitor for loading
Lucas-TJ Mar 11, 2026
651fea5
update 19/03
Lucas-TJ Mar 19, 2026
b9192a8
rename BaseSnapshot to Snapshot
Lucas-TJ Mar 19, 2026
fdea447
Refactoring the API of snapshot (Snapshot, SnapshotJSONExporter and S…
Lucas-TJ Mar 20, 2026
b61f319
Fix loadDataSnapshot and update SnapshotManager
Lucas-TJ Mar 23, 2026
88253ff
update snapshot API
Lucas-TJ May 5, 2026
1be3685
update GUI with snapshot
Lucas-TJ May 11, 2026
8309993
Merge branch 'master' into saveSnapshotAPI2
Lucas-TJ May 11, 2026
163e903
fix snapshot menu
Lucas-TJ May 11, 2026
b0f7701
SaveSnapshotv1
Lucas-TJ Dec 22, 2025
2e70e9a
Save Snapshot - choose filename
Lucas-TJ Dec 23, 2025
978ec7f
new feature : select type of snapshot (only JSON)
Lucas-TJ Jan 6, 2026
7abea11
fix tree structure SaveSnapshot
Lucas-TJ Jan 13, 2026
f10335e
update Snapshot
Lucas-TJ Jan 26, 2026
f145ee5
[Snapshot] ADD codes for load a snapshot
Lucas-TJ Jan 27, 2026
5c909cd
clean some comments
Lucas-TJ Jan 28, 2026
e35af87
[SNAPSHOT] FIX save and load snapshotAPI
Lucas-TJ Feb 3, 2026
0a09581
Update laodSnapshot
Lucas-TJ Feb 9, 2026
fc58501
[Snapshot] Fix LoadSnapshot for JSON
Lucas-TJ Feb 25, 2026
56480f6
modify API for save/load snapshot
Lucas-TJ Feb 26, 2026
b57bc89
clean 27/02
Lucas-TJ Feb 27, 2026
9f477c6
Renaming SnapshotVisitor to SaveSnapshotVisitor
Lucas-TJ Mar 3, 2026
22ba5a9
(draft) split data and link visitor for loading
Lucas-TJ Mar 11, 2026
28b7c7b
update 19/03
Lucas-TJ Mar 19, 2026
290881f
rename BaseSnapshot to Snapshot
Lucas-TJ Mar 19, 2026
f3929df
Refactoring the API of snapshot (Snapshot, SnapshotJSONExporter and S…
Lucas-TJ Mar 20, 2026
a9e97f3
Fix loadDataSnapshot and update SnapshotManager
Lucas-TJ Mar 23, 2026
6b5e623
bindings snapshot + python scripts
Lucas-TJ May 5, 2026
7313b4a
bindings snapshot + python scripts
Lucas-TJ Mar 20, 2026
543ec1e
clean
Lucas-TJ May 12, 2026
bedf539
clean
Lucas-TJ May 12, 2026
e6c66cc
Merge branch 'sofa-framework:master' into saveSnapshotAPI2
Lucas-TJ Jun 12, 2026
eea7035
update 15/06
Lucas-TJ Jun 15, 2026
76909c4
clean Snapshot API
Lucas-TJ Jun 15, 2026
2777140
remove LoadDataSnapshotVisitor and LoadLinkSnapshotVisitor
Lucas-TJ Jul 2, 2026
2a9eb0a
fix & clean
Lucas-TJ Jul 3, 2026
0c7e9c5
Modifications to SnapshotManager class
Lucas-TJ Jul 7, 2026
308330f
cleaning
Lucas-TJ Jul 8, 2026
e6cd61d
Merge branch 'sofa-framework:master' into saveSnapshotAPI2
Lucas-TJ Jul 9, 2026
f9590eb
cleaning
Lucas-TJ Jul 10, 2026
d1c94c7
cleaning
Lucas-TJ Jul 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions SofaImGui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ set(HEADER_FILES
${SOFAIMGUI_SOURCE_DIR}/windows/DisplayFlags.h
${SOFAIMGUI_SOURCE_DIR}/windows/Plugins.h
${SOFAIMGUI_SOURCE_DIR}/windows/Components.h
${SOFAIMGUI_SOURCE_DIR}/windows/Snapshot.h
${SOFAIMGUI_SOURCE_DIR}/AppIniFile.h
${SOFAIMGUI_SOURCE_DIR}/windows/WindowState.h
${SOFAIMGUI_SOURCE_DIR}/guis/BaseAdditionalGUI.h
Expand All @@ -146,6 +147,7 @@ set(SOURCE_FILES
${SOFAIMGUI_SOURCE_DIR}/windows/DisplayFlags.cpp
${SOFAIMGUI_SOURCE_DIR}/windows/Plugins.cpp
${SOFAIMGUI_SOURCE_DIR}/windows/Components.cpp
${SOFAIMGUI_SOURCE_DIR}/windows/Snapshot.cpp
${SOFAIMGUI_SOURCE_DIR}/windows/Settings.cpp
${SOFAIMGUI_SOURCE_DIR}/windows/ViewPort.cpp
${SOFAIMGUI_SOURCE_DIR}/AppIniFile.cpp
Expand Down
16 changes: 14 additions & 2 deletions SofaImGui/src/SofaImGui/ImGuiGUIEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include "windows/DisplayFlags.h"
#include "windows/Log.h"
#include "windows/MouseManager.h"
#include "windows/Snapshot.h"
#include "windows/Performances.h"
#include "windows/Plugins.h"
#include "windows/Profiler.h"
Expand All @@ -68,6 +69,7 @@
#include <imgui.h>
#include <imgui_internal.h> //imgui_internal.h is included in order to use the DockspaceBuilder API (which is still in development)
#include <implot.h>
#include <iostream>
#include <nfd.h>
#include <SimpleIni.h>
#include <sofa/component/visual/VisualStyle.h>
Expand All @@ -83,7 +85,6 @@

#include <clocale>


using namespace sofa;

namespace sofaimgui
Expand All @@ -104,6 +105,7 @@ ImGuiGUIEngine::ImGuiGUIEngine()
, winManagerComponents(helper::system::FileSystem::append(sofaimgui::getConfigurationFolderPath(), std::string("components.txt")))
, winManagerLog(helper::system::FileSystem::append(sofaimgui::getConfigurationFolderPath(), std::string("log.txt")))
, winManagerMouse(helper::system::FileSystem::append(sofaimgui::getConfigurationFolderPath(), std::string("mouse.txt")))
, winManagerSnapshot(helper::system::FileSystem::append(sofaimgui::getConfigurationFolderPath(), std::string("snapshot.txt")))
, winManagerSettings(helper::system::FileSystem::append(sofaimgui::getConfigurationFolderPath(), std::string("settings.txt")))
, winManagerViewPort(helper::system::FileSystem::append(sofaimgui::getConfigurationFolderPath(), std::string("viewport.txt")))
, firstRunState(helper::system::FileSystem::append(sofaimgui::getConfigurationFolderPath(), std::string("firstrun.txt")))
Expand Down Expand Up @@ -215,7 +217,7 @@ void ImGuiGUIEngine::loadFile(sofaglfw::SofaGLFWBaseGUI* baseGUI, sofa::core::sp
sofa::simulation::node::unload(groot);

groot = sofa::simulation::node::load(filePathName.c_str());

if( !groot )
groot = sofa::simulation::getSimulation()->createNewGraph("");

Expand Down Expand Up @@ -406,6 +408,7 @@ void ImGuiGUIEngine::startFrame(sofaglfw::SofaGLFWBaseGUI* baseGUI)
static constexpr auto windowNameComponents = ICON_FA_LIST " Components";
static constexpr auto windowNameLog = ICON_FA_TERMINAL " Log";
static constexpr auto windowNameMouse = ICON_FA_COMPUTER_MOUSE " Mouse Manager";
static constexpr auto windowNameSnapshot = ICON_FA_FLOPPY_DISK " Snapshot";
static constexpr auto windowNameSettings = ICON_FA_SLIDERS " Settings";

if (!*firstRunState.getStatePtr())
Expand Down Expand Up @@ -550,6 +553,8 @@ void ImGuiGUIEngine::startFrame(sofaglfw::SofaGLFWBaseGUI* baseGUI)

ImGui::Checkbox(windowNameMouse, winManagerMouse.getStatePtr());

ImGui::Checkbox(windowNameSnapshot, winManagerSnapshot.getStatePtr());

if (guis::MainAdditionGUIRegistry::getAllGUIs().empty() == false)
{
ImGui::Separator();
Expand Down Expand Up @@ -742,6 +747,11 @@ void ImGuiGUIEngine::startFrame(sofaglfw::SofaGLFWBaseGUI* baseGUI)
**************************************/
windows::showManagerMouseWindow(windowNameMouse, winManagerMouse, baseGUI);

/***************************************
* Snapshot window
**************************************/
windows::showSnapshot(windowNameSnapshot, winManagerSnapshot, groot);

/***************************************
* Additional GUIs
**************************************/
Expand Down Expand Up @@ -1036,4 +1046,6 @@ type::Vec2i ImGuiGUIEngine::getFrameBufferPixels(std::vector<uint8_t>& pixels)
return {viewport[2], viewport[3]};
}



} //namespace sofaimgui
1 change: 1 addition & 0 deletions SofaImGui/src/SofaImGui/ImGuiGUIEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ class ImGuiGUIEngine : public sofaglfw::BaseGUIEngine
windows::WindowState winManagerComponents;
windows::WindowState winManagerLog;
windows::WindowState winManagerMouse;
windows::WindowState winManagerSnapshot;
windows::WindowState winManagerSettings;
windows::WindowState winManagerViewPort;
std::map<std::string, windows::WindowState> winManagerAdditionalGUIs;
Expand Down
193 changes: 193 additions & 0 deletions SofaImGui/src/SofaImGui/windows/Snapshot.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
/******************************************************************************
* 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 General Public License as published by the Free *
* Software Foundation; either version 2 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 General Public License for *
* more details. *
* *
* You should have received a copy of the GNU General Public License along *
* with this program. If not, see <http://www.gnu.org/licenses/>. *
*******************************************************************************
* Authors: The SOFA Team and external contributors (see Authors.txt) *
* *
* Contact information: contact@sofa-framework.org *
******************************************************************************/
#include <SofaImGui/ImGuiGUIEngine.h>
#include <SofaGLFW/SofaGLFWBaseGUI.h>
#include <sofa/core/CategoryLibrary.h>
#include <sofa/core/loader/SceneLoader.h>
#include <sofa/simulation/SceneLoaderFactory.h>
#include <sofa/simulation/Simulation.h>
#include <imgui.h>
#include <nfd.h>
#include <IconsFontAwesome6.h>
#include <SofaImGui/ImGuiDataWidget.h>
#include <sofa/type/vector.h>
#include <sofa/core/ObjectFactory.h>
#include <sofa/core/visual/VisualParams.h>
#include <sofa/component/visual/LineAxis.h>
#include <sofa/gui/common/BaseGUI.h>
#include <sofa/simulation/Node.h>
#include <fstream>
#include <iostream>
#include <memory>

#include "Snapshot.h"

namespace windows
{
SnapshotManager snapshot_manager;

void showSnapshot(const char* const& windowNameSnapshot,
WindowState& winManagerSnapshot, sofa::core::sptr<sofa::simulation::Node>& groot)
{

if (*winManagerSnapshot.getStatePtr())
{
if (ImGui::Begin(windowNameSnapshot, winManagerSnapshot.getStatePtr()))
{
static ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_Borders| ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg;
if(ImGui::BeginTable("MainTable", 2, flags, ImVec2(0.f, 400.f))) {
ImGui::TableSetupColumn("Save/Load");
ImGui::TableSetupColumn("Snapshot in memory");
ImGui::TableHeadersRow();
ImGui::TableNextRow();

ImGui::TableSetColumnIndex(0);
float totalHeight = ImGui::GetContentRegionAvail().y;
float halfHeight = totalHeight * 0.5f - 4.0f;

ImGui::BeginChild("Save Snapshot", ImVec2(0, halfHeight), ImGuiChildFlags_Borders);
ImGui::Text("Save Snapshot");
ImGui::Separator();
if (ImGui::Button("Memory"))
{
snapshot_manager.doMemorySave(groot);
}
if (ImGui::Button("File"))
{
doFileSave(groot, false);
}
if (ImGui::Button("Set of Snapshots"))
{
if (!snapshot_manager.m_snapshotsFromMemory.empty())
{
doFileSave(groot, true);
}
else
std::cout << "No snapshot" << std::endl;

}
ImGui::EndChild();

ImGui::BeginChild("Load Snapshot", ImVec2(0, halfHeight), ImGuiChildFlags_Borders);
ImGui::Text("Load Snapshot");
ImGui::Separator();
if (ImGui::Button("Memory (recent)"))
{
snapshot_manager.doMemoryLoad(groot);
}
if (ImGui::Button("File"))
{
doFileLoad(groot, false);
}

if (ImGui::Button("Set of Snapshots"))
{
doFileLoad(groot, true);
}
ImGui::EndChild();

ImGui::TableSetColumnIndex(1);

float listHeight = ImGui::GetContentRegionAvail().y - 8.0f;

ImGui::BeginChild("Recents", ImVec2(0, listHeight), true);

if (snapshot_manager.m_snapshotsFromFiles.empty() && snapshot_manager.m_snapshotsFromMemory.empty())
{
ImGui::TextDisabled("(No recent files)");
}
else
{
for (auto file : snapshot_manager.m_snapshotsFromFiles)
{
if (ImGui::Selectable(file.c_str()))
{
if(file.ends_with(".json"))
{
auto m_snapshot = std::make_shared<sofa::core::objectmodel::Snapshot>();
importFrom(*m_snapshot,file);
auto visitor = LoadSnapshotVisitor(nullptr,*m_snapshot);
groot->execute(visitor);
}
}
}
for (auto [name, file] : snapshot_manager.m_snapshotsFromMemory)
{
if(ImGui::Selectable(name.c_str()))
{
auto m_snapshot = std::make_shared<sofa::core::objectmodel::Snapshot>();
m_snapshot = file;
auto visitor = LoadSnapshotVisitor(nullptr,*m_snapshot);
groot->execute(visitor);
}
}
}
ImGui::EndChild();
ImGui::EndTable();
}
}
ImGui::End();
}
}

void doFileSave(sofa::core::sptr<sofa::simulation::Node>& groot, bool isSet)
{
NFD_Init();
nfdchar_t* savePath;
nfdfilteritem_t filterItem[1] = {{"Snapshot code", "json,txt"}};
std::string filepath = "null";
nfdresult_t result = NFD_SaveDialog(&savePath, filterItem, 1, NULL, "Untitled.json");
if (result == NFD_OKAY)
{
std::string path(savePath);
snapshot_manager.doSaveTo(groot,path,isSet);
}
else
{
msg_error("SaveSnapshot") << "Error of saving snapshot" ;
}
NFD_Quit();
}

void doFileLoad(sofa::core::sptr<sofa::simulation::Node>& groot, bool isSet)
{
nfdchar_t *outPath = NULL;
nfdfilteritem_t filterItem[1] = {{"Snapshot code", "json"}};
nfdresult_t result = NFD_OpenDialog(&outPath, filterItem, 1, NULL);
std::string filepath = "null";
if ( result == NFD_OKAY && !isSet)
{
std::string path(outPath);
snapshot_manager.doLoadTo(groot,path);
}
else if (result == NFD_OKAY && isSet)
{
std::string path(outPath);
snapshot_manager.doLoadToSet(path);
}
else
{
msg_error("LoadSnapshot") << "Error of loading snapshot" ;
}
NFD_Quit();
}
}
50 changes: 50 additions & 0 deletions SofaImGui/src/SofaImGui/windows/Snapshot.h
Original file line number Diff line number Diff line change
@@ -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 General Public License as published by the Free *
* Software Foundation; either version 2 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 General Public License for *
* more details. *
* *
* You should have received a copy of the GNU General Public License along *
* with this program. If not, see <http://www.gnu.org/licenses/>. *
*******************************************************************************
* Authors: The SOFA Team and external contributors (see Authors.txt) *
* *
* Contact information: contact@sofa-framework.org *
******************************************************************************/
#pragma once

#include <sofa/simulation/Node.h>
#include "WindowState.h"

#include <sofa/helper/system/FileSystem.h>
using sofa::helper::system::FileSystem;
#include <sofa/core/objectmodel/SnapshotJSONExporter.h>
#include <sofa/simulation/SnapshotManager.h>
using sofa::simulation::SnapshotManager;
#include <sofa/simulation/LoadSnapshotVisitor.h>
using sofa::simulation::LoadSnapshotVisitor;


namespace windows
{
/**
* @brief Shows the Snapshot window.
*
* This function displays a window which user can use Snapshot's features.
*
*/
void showSnapshot(const char* const& windowNameSnapshot,
WindowState& winManagerSnapshot,sofa::core::sptr<sofa::simulation::Node>& groot);

void doFileSave(sofa::core::sptr<sofa::simulation::Node>& groot, bool isSet);
void doFileLoad(sofa::core::sptr<sofa::simulation::Node>& groot, bool isSet);

} // namespace sofaimgui