Program Listing for File SceneLoaderJson.cpp
Program Listing for File SceneLoaderJson.cpp#
↰ Return to documentation for file (src/JsonReader/SceneLoaderJson.cpp
)
#include <JsonReader/SceneLoaderJson.h>
#include <sofa/simulation/SceneLoaderFactory.h>
#include <sofa/simulation/Node.h>
#include <algorithm>
#include <fstream>
#include <JsonReader/json.hpp>
#include <sofa/core/ObjectFactory.h>
#include <sofa/simulation/graph/DAGNode.h>
namespace sofa::simulation
{
// register the loader in the factory
const SceneLoader* loaderJson = SceneLoaderFactory::getInstance()->addEntry(new SceneLoaderJson());
bool SceneLoaderJson::loadSucceed = true;
bool SceneLoaderJson::canLoadFileExtension(const char* extension)
{
std::string ext = extension;
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
return ext == "json" || ext == "jscn";
}
bool SceneLoaderJson::canWriteFileExtension(const char* extension)
{
return canLoadFileExtension(extension);
}
void createObject(const std::string& objectType, nlohmann::basic_json<nlohmann::ordered_map>::reference json, Node::SPtr parent, const std::string& filename)
{
std::string objectName = parent->getNameHelper().resolveName(objectType, sofa::core::ComponentNameHelper::Convention::xml);
if (!json.is_string())
{
try
{
objectName = json.value("name", objectName);
}
catch (nlohmann::json::exception& e)
{
msg_error("SceneLoaderJson") << e.what() ;
}
}
core::objectmodel::BaseObjectDescription desc {objectName.c_str(), objectType.c_str()};
if (json.is_object())
{
for (const auto& [key, value] : json.items())
{
if (value.is_string())
{
desc.setAttribute(key, value);
}
}
}
auto object = core::ObjectFactory::CreateObject(parent.get(), &desc);
object->setInstanciationSourceFileName(filename);
}
void readNodeData(core::BaseData* data, const std::string& key, nlohmann::basic_json<nlohmann::ordered_map>::const_reference val)
{
if (data)
{
if (val.is_string())
{
data->read(val);
}
else
{
msg_error("SceneLoaderJson") << "Cannot parse " << val << " for node data " << key;
}
}
}
Node::SPtr createNode(nlohmann::basic_json<nlohmann::ordered_map>::reference json, Node::SPtr parent, const std::string& filename)
{
std::string nodeName;
if (json.is_array())
{
Node::SPtr probablyRoot;
for (auto& el : json)
{
Node::SPtr node = createNode(el, parent, filename);
if (parent == nullptr)
{
probablyRoot = node;
}
}
return probablyRoot;
}
else
{
try
{
nodeName=json.value("name", "Node");
}
catch(nlohmann::json::exception& e)
{
msg_error("SceneLoaderJson") << e.what();
}
Node::SPtr node=core::objectmodel::New<sofa::simulation::graph::DAGNode>(nodeName,
dynamic_cast<sofa::simulation::graph::DAGNode*>(parent.get()));
node->setInstanciationSourceFileName(filename);
for(auto& [key, val] : json.items())
{
const bool isInObjectFactory = core::ObjectFactory::getInstance()->hasCreator(key);
if(isInObjectFactory)
{
if (val.is_array())
{
for (auto& el : val)
{
createObject(key, el, node, filename);
}
}
else
{
createObject(key, val, node, filename);
}
}
else
{
if(auto* data=node->findData(key))
{
readNodeData(data, key, val);
}
else
{
if (key != "Node")
{
msg_warning("SceneLoaderJson") << "Json node not found in the object factory, and not a Node Data: " << key << ": " << val;
}
createNode(val, node, filename);
}
}
}
return node;
}
}
Node::SPtr processJson(nlohmann::ordered_json json, const std::string& filename)
{
sofa::simulation::NodeSPtr root;
for (auto& [key, val] : json.items())
{
if (root)
{
msg_error("SceneLoaderJson") << "Root node has already been created. Abort";
break;
}
const bool isInObjectFactory = core::ObjectFactory::getInstance()->hasCreator(key);
if (isInObjectFactory)
{
msg_error("SceneLoaderJson") << key << " found in object factory: it should be a child of a Node";
}
else
{
root = createNode(val, nullptr, filename);
}
}
return root;
}
sofa::simulation::NodeSPtr SceneLoaderJson::doLoad(const std::string& filename,
const std::vector<std::string>& sceneArgs)
{
if (!canLoadFileName(filename.c_str()))
return nullptr;
std::ifstream f(filename);
nlohmann::ordered_json data = nlohmann::ordered_json::parse(f);
sofa::simulation::Node::SPtr root = processJson(data, filename);
return root;
}
std::string SceneLoaderJson::getFileTypeDesc()
{
return "JSON Scenes";
}
void SceneLoaderJson::getExtensionList(ExtensionList* list)
{
list->clear();
list->push_back("json");
list->push_back("jscn");
}
NodeSPtr SceneLoaderJson::loadFromMemory(const char* filename, const char* data)
{
sofa::simulation::Node::SPtr root;
try
{
nlohmann::ordered_json parsedData = nlohmann::ordered_json::parse(data);
root = processJson(parsedData, filename);
}
catch(nlohmann::json::exception& e)
{
msg_error("SceneLoaderJson") << "Error reading json string from memory: " << e.what();
}
return root;
}
} // namespace sofa::simulation