From 7f8102c36933647ceb675ed39c11601f8fcfe0bd Mon Sep 17 00:00:00 2001
From: Mathias Paulin <mathias.paulin@irit.fr>
Date: Fri, 11 Feb 2022 16:51:11 +0100
Subject: [PATCH] [nodeeditor] fix loading/updating nodeGraph when the renderer
 has already one

---
 src/Mara/RadiumPlayer.cpp                     | 21 +++---
 .../include/nodes/internal/FlowScene.hpp      | 10 +++
 .../RadiumNBR/Gui/NodeGraphControllerGui.cpp  | 34 ++++++++-
 .../RenderGraphEditor/EnvMapSourceModel.cpp   |  3 +
 .../RenderGraphEditor/EnvMapSourceModel.hpp   |  2 +
 .../RenderGraphEditor/NodeAdapterModel.hpp    |  4 +
 .../RenderGraphEditor/NodeAdapterModel.inl    | 73 +++++++++++++++++++
 .../RenderGraphEditorView.cpp                 |  4 +-
 .../RadiumNBR/NodeGraph/NodeFactory.cpp       |  1 +
 .../RadiumNBR/NodeGraph/RenderGraph.cpp       |  4 +-
 10 files changed, 141 insertions(+), 15 deletions(-)

diff --git a/src/Mara/RadiumPlayer.cpp b/src/Mara/RadiumPlayer.cpp
index e49edd4..0525110 100644
--- a/src/Mara/RadiumPlayer.cpp
+++ b/src/Mara/RadiumPlayer.cpp
@@ -218,7 +218,17 @@ void RadiumPlayer::addRenderers() {
         // 2 - Initialize the renderer using default or customized NodeGraphController
         auto renderControl       = new RadiumNBR::NodeGraphController;
         auto myRenderer          = std::make_shared<RadiumNBR::NodeBasedRenderer>( *renderControl );
-// TODO find why this is problematic as the graph is not displayed in the editor
+
+        std::string rendererName = myRenderer->getRendererName();
+        // The panel returned by buildNodeGraphControllerGui will manage the Qt NodeEditor window
+        // This function must initialize the default nodeEditor functionality for the edited renderGraph
+        // (i.e. DataModelRegistry)
+        auto controlPanel        = RadiumNBR::buildNodeGraphControllerGui(
+            myRenderer.get(), [this]() { this->askForUpdate(); } );
+
+
+        mainWindow->addRenderer( rendererName, myRenderer, controlPanel );
+
 #if 1
         // 3 - load default graph or user provided graph
         auto resourcesCheck =
@@ -238,15 +248,6 @@ void RadiumPlayer::addRenderers() {
         myRenderer->signalReloadJson();
 #endif
 
-        std::string rendererName = myRenderer->getRendererName();
-        // The panel returned by buildNodeGraphControllerGui will manage the Qt NodeEditor window
-        // This function must initialize the default nodeEditor functionality for the edited renderGraph
-        // (i.e. DataModelRegistry)
-        auto controlPanel        = RadiumNBR::buildNodeGraphControllerGui(
-            myRenderer.get(), [this]() { this->askForUpdate(); } );
-
-
-        mainWindow->addRenderer( rendererName, myRenderer, controlPanel );
     }
 
     // add the default forward renderer
diff --git a/src/libRender/RadiumNBR/Gui/NodeEditor/include/nodes/internal/FlowScene.hpp b/src/libRender/RadiumNBR/Gui/NodeEditor/include/nodes/internal/FlowScene.hpp
index 6d59725..184f727 100644
--- a/src/libRender/RadiumNBR/Gui/NodeEditor/include/nodes/internal/FlowScene.hpp
+++ b/src/libRender/RadiumNBR/Gui/NodeEditor/include/nodes/internal/FlowScene.hpp
@@ -100,6 +100,14 @@ public:
 
   void loadFromMemory(const QByteArray& data);
 
+  void setSceneName(const QString& newname) {
+      _scenename = newname;
+  }
+
+  QString getSceneName() const {
+      return _scenename;
+  }
+
 Q_SIGNALS:
 
   /**
@@ -148,6 +156,8 @@ private:
   std::unordered_map<QUuid, SharedConnection> _connections;
   std::unordered_map<QUuid, UniqueNode>       _nodes;
 
+  // name of the scene
+  QString _scenename {""};
 private Q_SLOTS:
 
   void setupConnectionSignals(Connection const& c);
diff --git a/src/libRender/RadiumNBR/Gui/NodeGraphControllerGui.cpp b/src/libRender/RadiumNBR/Gui/NodeGraphControllerGui.cpp
index bfe42ae..7d1248e 100644
--- a/src/libRender/RadiumNBR/Gui/NodeGraphControllerGui.cpp
+++ b/src/libRender/RadiumNBR/Gui/NodeGraphControllerGui.cpp
@@ -37,6 +37,7 @@ RadiumNBR::Gui::RendererPanel* buildNodeGraphControllerGui( NodeBasedRenderer* r
             QFile file( fileName );
             if ( file.open( QIODevice::ReadOnly ) ) {
                 nodeEditor->scene->clearScene();
+                renderer->getRenderGraph()->clearNodes();
                 QByteArray wholeFile = file.readAll();
                 nodeEditor->scene->loadFromMemory( wholeFile );
                 nodeEditor->setWindowTitle( std::string( "RenderGraph Node Editor - " +
@@ -44,6 +45,7 @@ RadiumNBR::Gui::RendererPanel* buildNodeGraphControllerGui( NodeBasedRenderer* r
                                                          " - " + fileName.toStdString() )
                                                 .c_str() );
                 renderer->setJsonFilePath( fileName.toStdString() );
+                nodeEditor->scene->setSceneName( fileName );
                 appUpdateCallback();
             }
         }
@@ -109,15 +111,43 @@ RadiumNBR::Gui::RendererPanel* buildNodeGraphControllerGui( NodeBasedRenderer* r
     nodeEditor->connections.push_back(
         QObject::connect( nodeEditor->newAction, &QAction::triggered, newGraph) );
 
-    controlPanel->addButton( "Node Editor", [nodeEditor]()  {
+
+    auto show_hideNodeEditor = [renderer, nodeEditor]()  {
         if ( !nodeEditor->isVisible() )
         {
+            // Fill the flowscene in the editor with the current graph if any
+            if ( renderer->getJsonFilePath() != "" ) {
+                // Fill the editor with the current graph ...
+                // TODO modify the editor to reflect exactly the same graph than in the renderer (e.g. if adding a node programatically, update the flowscene
+                if ( nodeEditor->scene->getSceneName().compare( renderer->getJsonFilePath().c_str() ) != 0) {
+                    if ( QFileInfo::exists( renderer->getJsonFilePath().c_str() ) )
+                    {
+                        QFile file( renderer->getJsonFilePath().c_str() );
+                        if ( file.open( QIODevice::ReadOnly ) )
+                        {
+                            std::cerr << "Loading nodegraph " << renderer->getJsonFilePath() << " in the editor." << std::endl;
+                            nodeEditor->scene->clearScene();
+                            renderer->getRenderGraph()->clearNodes();
+                            QByteArray wholeFile = file.readAll();
+                            nodeEditor->scene->loadFromMemory( wholeFile );
+                            nodeEditor->scene->setSceneName( renderer->getJsonFilePath().c_str() );
+                            nodeEditor->setWindowTitle( std::string( "RenderGraph Node Editor - " +
+                                                                     renderer->getRendererName() + " - " +
+                                                                     renderer->getJsonFilePath() )
+                                                            .c_str() );
+                        }
+                    }
+                }
+            }
+
             nodeEditor->resize(800, 600);
             nodeEditor->show();
         } else {
             nodeEditor->hide();
         }
-    } );
+    };
+
+    controlPanel->addButton( "Node Editor", show_hideNodeEditor );
 
     controlPanel->beginLayout( QBoxLayout::LeftToRight );
     controlPanel->addButton( "Open graph", loadGraph );
diff --git a/src/libRender/RadiumNBR/Gui/RenderGraphEditor/EnvMapSourceModel.cpp b/src/libRender/RadiumNBR/Gui/RenderGraphEditor/EnvMapSourceModel.cpp
index c7e8430..a8371fd 100644
--- a/src/libRender/RadiumNBR/Gui/RenderGraphEditor/EnvMapSourceModel.cpp
+++ b/src/libRender/RadiumNBR/Gui/RenderGraphEditor/EnvMapSourceModel.cpp
@@ -1,3 +1,4 @@
+#if 0
 #include <RadiumNBR/Gui/PowerSlider.hpp>
 #include <RadiumNBR/Gui/RenderGraphEditor/EnvMapSourceModel.hpp>
 #include <RadiumNBR/Gui/RendererPanel.hpp>
@@ -105,3 +106,5 @@ NodeBasedRenderer_LIBRARY_API void EnvMapSourceModel::restore( QJsonObject const
         slider->setValue( s );
     }
 }
+
+#endif
diff --git a/src/libRender/RadiumNBR/Gui/RenderGraphEditor/EnvMapSourceModel.hpp b/src/libRender/RadiumNBR/Gui/RenderGraphEditor/EnvMapSourceModel.hpp
index aa626bd..d48afe2 100644
--- a/src/libRender/RadiumNBR/Gui/RenderGraphEditor/EnvMapSourceModel.hpp
+++ b/src/libRender/RadiumNBR/Gui/RenderGraphEditor/EnvMapSourceModel.hpp
@@ -1,6 +1,8 @@
+#if 0
 #pragma once
 #include <RadiumNBR/Gui/RenderGraphEditor/SourceNodeModel.hpp>
 #include <RadiumNBR/EnvMap.hpp>
 
 using EnvMapData = std::shared_ptr<RadiumNBR::EnvMap>;
 using EnvMapSourceModel = SourceNodeModel<EnvMapData>;
+#endif
diff --git a/src/libRender/RadiumNBR/Gui/RenderGraphEditor/NodeAdapterModel.hpp b/src/libRender/RadiumNBR/Gui/RenderGraphEditor/NodeAdapterModel.hpp
index bf59f68..1c5ca10 100644
--- a/src/libRender/RadiumNBR/Gui/RenderGraphEditor/NodeAdapterModel.hpp
+++ b/src/libRender/RadiumNBR/Gui/RenderGraphEditor/NodeAdapterModel.hpp
@@ -200,6 +200,10 @@ class NodeAdapterModel : public QtNodes::NodeDataModel
     std::vector<bool> m_inputsConnected;
     mutable QtNodes::NodeValidationState m_validationState = QtNodes::NodeValidationState::Valid;
     mutable QString m_validationError                      = QString( "" );
+
+  public:
+    QJsonObject save() const override;
+    void restore(QJsonObject const & p) override;
 };
 
 #include <RadiumNBR/Gui/RenderGraphEditor/NodeAdapterModel.inl>
diff --git a/src/libRender/RadiumNBR/Gui/RenderGraphEditor/NodeAdapterModel.inl b/src/libRender/RadiumNBR/Gui/RenderGraphEditor/NodeAdapterModel.inl
index c6734ca..a13f4f4 100644
--- a/src/libRender/RadiumNBR/Gui/RenderGraphEditor/NodeAdapterModel.inl
+++ b/src/libRender/RadiumNBR/Gui/RenderGraphEditor/NodeAdapterModel.inl
@@ -1,3 +1,14 @@
+
+template <typename T>
+QJsonObject NodeAdapterModel<T>::save() const {
+    return QtNodes::NodeDataModel::save();
+}
+
+template <typename T>
+void NodeAdapterModel<T>::restore( const QJsonObject& p ) {
+    QtNodes::NodeDataModel::restore(p);
+}
+
 template <>
 void NodeAdapterModel<DataNode<NodeTypeRenderObject>>::init() {
     m_node = m_renderGraph->getDataNode<NodeTypeRenderObject>();
@@ -45,3 +56,65 @@ template <>
 void NodeAdapterModel<DisplaySinkNode>::destroy() {
 
 }
+
+// ---------
+// method specialization for models with internal parameters
+#include <RadiumNBR/NodeGraph/PremadeNodes/Sources/SourceNode.hpp>
+#include <RadiumNBR/Gui/PowerSlider.hpp>
+#include <filesystem>
+template <>
+QJsonObject NodeAdapterModel<SourceNode<std::shared_ptr<RadiumNBR::EnvMap>>>::save() const {
+    QJsonObject modelJson = NodeDataModel::save();
+    modelJson["files"]    = m_node->getData()->getImageName().c_str();
+    modelJson["type"]     = QString::number( int( m_node->getData()->getImageType() ) );
+    modelJson["strength"] = QString::number( float( m_node->getData()->getEnvStrength() ) * 100. );
+    return modelJson;
+}
+
+template <>
+void NodeAdapterModel<SourceNode<std::shared_ptr<RadiumNBR::EnvMap>>>::restore( QJsonObject const& p ) {
+    auto controlPanel = dynamic_cast<RadiumNBR::Gui::RendererPanel*>( m_widget );
+
+    QJsonValue n      = p["files"];
+    std::string files = n.toString().toStdString();
+    if ( files.empty() ) { m_node->setData( nullptr ); }
+    else
+    {
+        std::string type = p["type"].toString().toStdString();
+        int t            = std::stoi( type );
+        RadiumNBR::EnvMap::EnvMapType envType;
+        switch ( t )
+        {
+        case 0:
+            envType = RadiumNBR::EnvMap::EnvMapType::ENVMAP_PFM;
+            break;
+        case 1:
+            envType = RadiumNBR::EnvMap::EnvMapType::ENVMAP_CUBE;
+            break;
+        case 2:
+            envType = RadiumNBR::EnvMap::EnvMapType::ENVMAP_LATLON;
+            break;
+        }
+        // check if the file exists
+        bool envmap_exist;
+        float s = 100.;
+        if ( envType == RadiumNBR::EnvMap::EnvMapType::ENVMAP_CUBE )
+        {
+            std::string f1 = files.substr( 0, files.find( ';' ) - 1 );
+            envmap_exist   = std::filesystem::exists( f1 );
+        }
+        else
+        { envmap_exist = std::filesystem::exists( files ); }
+        if ( !envmap_exist ) { m_node->setData( nullptr ); }
+        else
+        {
+            // for now, only skyboxes are managed
+            m_node->setData( std::make_shared<RadiumNBR::EnvMap>( files, envType, true ) );
+            s = std::atof( p["strength"].toString().toStdString().c_str() );
+            m_node->getData()->setEnvStrength( s / 100. );
+        }
+        // This assume thereis only one powerslider in the control panel
+        auto slider = controlPanel->findChild<PowerSlider*>( "Strength" );
+        slider->setValue( s );
+    }
+}
diff --git a/src/libRender/RadiumNBR/Gui/RenderGraphEditor/RenderGraphEditorView.cpp b/src/libRender/RadiumNBR/Gui/RenderGraphEditor/RenderGraphEditorView.cpp
index c8fe4aa..415c253 100644
--- a/src/libRender/RadiumNBR/Gui/RenderGraphEditor/RenderGraphEditorView.cpp
+++ b/src/libRender/RadiumNBR/Gui/RenderGraphEditor/RenderGraphEditorView.cpp
@@ -223,10 +223,10 @@ RenderGraphEditorView::RenderGraphEditorView( QWidget* parent ) : QWidget( paren
 #include <RadiumNBR/Gui/RenderGraphEditor/NodeAdapterModel.hpp>
 #include <RadiumNBR/Gui/RenderGraphEditor/FilterRenderObjectNameModel.hpp>
 #include <RadiumNBR/Gui/RenderGraphEditor/FilterRenderObjectTypeModel.hpp>
-#include <RadiumNBR/Gui/RenderGraphEditor/EnvMapSourceModel.hpp>
 #include <RadiumNBR/Gui/RenderGraphEditor/SourceColorTextureModel.hpp>
 #include <RadiumNBR/Gui/RenderGraphEditor/SourceDepthTextureModel.hpp>
-#include <RadiumNBR/Gui/RenderGraphEditor/SourceNodeModel.hpp>
+
+using EnvMapData = std::shared_ptr<RadiumNBR::EnvMap>;
 
 #include <RadiumNBR/NodeGraph/PremadeNodes/PremadeNodesIncludes.hpp>
 
diff --git a/src/libRender/RadiumNBR/NodeGraph/NodeFactory.cpp b/src/libRender/RadiumNBR/NodeGraph/NodeFactory.cpp
index 4949c9c..a8aabc7 100644
--- a/src/libRender/RadiumNBR/NodeGraph/NodeFactory.cpp
+++ b/src/libRender/RadiumNBR/NodeGraph/NodeFactory.cpp
@@ -69,6 +69,7 @@ void initializeNodeFactory() {
             float red              = std::stof( valueRed ) / 255.0f;
             float green            = std::stof( valueGreen ) / 255.0f;
             float blue             = std::stof( valueBlue ) / 255.0f;
+
             auto sourceColor       = new SourceNode<NodeTypeColor>(
                 "color" + std::to_string( NodeFactory::newNodeId() ) );
 
diff --git a/src/libRender/RadiumNBR/NodeGraph/RenderGraph.cpp b/src/libRender/RadiumNBR/NodeGraph/RenderGraph.cpp
index 26bc5ae..0b44a8a 100644
--- a/src/libRender/RadiumNBR/NodeGraph/RenderGraph.cpp
+++ b/src/libRender/RadiumNBR/NodeGraph/RenderGraph.cpp
@@ -124,7 +124,9 @@ void RenderGraph::loadFromJson( const std::string& jsonFilePath ) {
         { nodeById.emplace( id, getDisplayNode() ); }
         else
         { 
-            Node* newNode = NodeFactory::createNode( name, n );
+            auto newNode = NodeFactory::createNode( name, n );
+
+            std::cerr << "TYPE = " << typeid(*newNode).name() << " --- " << std::endl;
             nodeById.emplace( id, newNode );
             addNode( newNode );
         }
-- 
GitLab