From ac843fe5b8cf59639d8eef38124610db9bb97cbf Mon Sep 17 00:00:00 2001 From: "georgiy.m.markelov@gmail.com" Date: Thu, 5 Oct 2023 21:13:28 +0300 Subject: [PATCH 1/5] MaterialX: added support for script node --- .../nodes/shader/materialx/material.cc | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/source/blender/nodes/shader/materialx/material.cc b/source/blender/nodes/shader/materialx/material.cc index 12fe16ad009..b3afbecbdd0 100644 --- a/source/blender/nodes/shader/materialx/material.cc +++ b/source/blender/nodes/shader/materialx/material.cc @@ -7,7 +7,11 @@ #include "material.h" #include "node_parser.h" +#include "BKE_main.h" +#include "BLI_path_util.h" +#include "BLI_string.h" #include "DEG_depsgraph.hh" +#include "DEG_depsgraph_query.hh" #include "DNA_material_types.h" @@ -63,6 +67,23 @@ MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, MaterialX::DocumentPtr doc = MaterialX::createDocument(); if (material->use_nodes) { material->nodetree->ensure_topology_cache(); + Main *bmain = DEG_get_bmain(depsgraph); + /* Look for first script node with assigned file. + * If it's found, we load content and ignore everything other. */ + LISTBASE_FOREACH (bNode *, node, &material->nodetree->nodes) { + if (node->typeinfo->type == SH_NODE_SCRIPT) + { + NodeShaderScript *script = static_cast(node->storage); + if (script && script->filepath[0] != '\0' && script->mode & NODE_SCRIPT_EXTERNAL) { + char filepath[FILE_MAX]; + STRNCPY(filepath, script->filepath); + BLI_path_abs(filepath, BKE_main_blendfile_path(bmain)); + MaterialX::readFromXmlFile(doc, filepath); + return doc; + } + } + } + bNode *output_node = ntreeShaderOutputNode(material->nodetree, SHD_OUTPUT_ALL); if (output_node) { NodeParserData data = {doc.get(), @@ -100,7 +121,7 @@ MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, CLOG_INFO(LOG_MATERIALX_SHADER, 1, - "Material: %s\n%s", + "Material: %s//n%s", material->id.name, MaterialX::writeToXmlString(doc).c_str()); return doc; -- 2.30.2 From 6c15b9811794f052e458f11cd61cdada9fdcad43 Mon Sep 17 00:00:00 2001 From: "georgiy.m.markelov@gmail.com" Date: Thu, 5 Oct 2023 22:18:05 +0300 Subject: [PATCH 2/5] MaterialX: added support for script node internal mode --- .../nodes/shader/materialx/material.cc | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/source/blender/nodes/shader/materialx/material.cc b/source/blender/nodes/shader/materialx/material.cc index b3afbecbdd0..456bbccdeba 100644 --- a/source/blender/nodes/shader/materialx/material.cc +++ b/source/blender/nodes/shader/materialx/material.cc @@ -10,10 +10,12 @@ #include "BKE_main.h" #include "BLI_path_util.h" #include "BLI_string.h" + #include "DEG_depsgraph.hh" #include "DEG_depsgraph_query.hh" #include "DNA_material_types.h" +#include "DNA_text_types.h" #include "NOD_shader.h" @@ -71,19 +73,34 @@ MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, /* Look for first script node with assigned file. * If it's found, we load content and ignore everything other. */ LISTBASE_FOREACH (bNode *, node, &material->nodetree->nodes) { - if (node->typeinfo->type == SH_NODE_SCRIPT) - { + if (node->typeinfo->type == SH_NODE_SCRIPT) { NodeShaderScript *script = static_cast(node->storage); - if (script && script->filepath[0] != '\0' && script->mode & NODE_SCRIPT_EXTERNAL) { - char filepath[FILE_MAX]; - STRNCPY(filepath, script->filepath); - BLI_path_abs(filepath, BKE_main_blendfile_path(bmain)); - MaterialX::readFromXmlFile(doc, filepath); - return doc; + if (script->mode == NODE_SCRIPT_EXTERNAL) { + if (script && script->filepath[0] != '\0') { + char filepath[FILE_MAX]; + STRNCPY(filepath, script->filepath); + BLI_path_abs(filepath, BKE_main_blendfile_path(bmain)); + MaterialX::readFromXmlFile(doc, filepath); + return doc; + } + } + else if (script->mode == NODE_SCRIPT_INTERNAL) { + Text *text = reinterpret_cast(node->id); + if (text) { + std::string text_content; + LISTBASE_FOREACH (TextLine *, line, &text->lines) { + text_content.append(line->line); + } + MaterialX::readFromXmlString(doc, text_content); + return doc; + } + } + else { + BLI_assert_unreachable(); } } } - + bNode *output_node = ntreeShaderOutputNode(material->nodetree, SHD_OUTPUT_ALL); if (output_node) { NodeParserData data = {doc.get(), -- 2.30.2 From 0246757e3db70dd16f426d17d9a58cb97432696d Mon Sep 17 00:00:00 2001 From: "georgiy.m.markelov@gmail.com" Date: Fri, 6 Oct 2023 13:53:24 +0300 Subject: [PATCH 3/5] MaterialX: added logs, code improvements --- .../nodes/shader/materialx/material.cc | 43 ++++++++++++++----- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/source/blender/nodes/shader/materialx/material.cc b/source/blender/nodes/shader/materialx/material.cc index 456bbccdeba..0fd023bbb29 100644 --- a/source/blender/nodes/shader/materialx/material.cc +++ b/source/blender/nodes/shader/materialx/material.cc @@ -67,6 +67,7 @@ MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, CLOG_INFO(LOG_MATERIALX_SHADER, 0, "Material: %s", material->id.name); MaterialX::DocumentPtr doc = MaterialX::createDocument(); + bool script_found = false; if (material->use_nodes) { material->nodetree->ensure_topology_cache(); Main *bmain = DEG_get_bmain(depsgraph); @@ -75,24 +76,46 @@ MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, LISTBASE_FOREACH (bNode *, node, &material->nodetree->nodes) { if (node->typeinfo->type == SH_NODE_SCRIPT) { NodeShaderScript *script = static_cast(node->storage); - if (script->mode == NODE_SCRIPT_EXTERNAL) { - if (script && script->filepath[0] != '\0') { - char filepath[FILE_MAX]; - STRNCPY(filepath, script->filepath); - BLI_path_abs(filepath, BKE_main_blendfile_path(bmain)); + if (script->mode == NODE_SCRIPT_EXTERNAL && script->filepath[0] != '\0') { + script_found = true; + char filepath[FILE_MAX]; + STRNCPY(filepath, script->filepath); + BLI_path_abs(filepath, BKE_main_blendfile_path(bmain)); + try { MaterialX::readFromXmlFile(doc, filepath); - return doc; } + catch (MaterialX::ExceptionParseError) { + CLOG_WARN(LOG_MATERIALX_SHADER, + "Material: %s, Node: %s: parsing error", + material->id.name, + node->name); + } + catch (MaterialX::ExceptionFileMissing) { + CLOG_WARN(LOG_MATERIALX_SHADER, + "Material: %s, Node: %s: file not found", + material->id.name, + node->name); + } + break; } else if (script->mode == NODE_SCRIPT_INTERNAL) { Text *text = reinterpret_cast(node->id); if (text) { + script_found = true; std::string text_content; LISTBASE_FOREACH (TextLine *, line, &text->lines) { text_content.append(line->line); } - MaterialX::readFromXmlString(doc, text_content); - return doc; + try { + MaterialX::readFromXmlString(doc, text_content); + } + catch (MaterialX::ExceptionParseError) { + CLOG_WARN(LOG_MATERIALX_SHADER, + "Material: %s, Node: %s: parsing error", + material->id.name, + node->name); + } + break; } } else { @@ -102,7 +125,7 @@ MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, } bNode *output_node = ntreeShaderOutputNode(material->nodetree, SHD_OUTPUT_ALL); - if (output_node) { + if (output_node && !script_found) { NodeParserData data = {doc.get(), depsgraph, material, @@ -138,7 +161,7 @@ MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, CLOG_INFO(LOG_MATERIALX_SHADER, 1, - "Material: %s//n%s", + "Material: %s\n%s", material->id.name, MaterialX::writeToXmlString(doc).c_str()); return doc; -- 2.30.2 From 34c3bd420f3786db3413a440ab0f58956994c442 Mon Sep 17 00:00:00 2001 From: "georgiy.m.markelov@gmail.com" Date: Fri, 6 Oct 2023 18:08:31 +0300 Subject: [PATCH 4/5] MaterialX: moved code to separate function --- .../nodes/shader/materialx/material.cc | 130 ++++++++++-------- 1 file changed, 73 insertions(+), 57 deletions(-) diff --git a/source/blender/nodes/shader/materialx/material.cc b/source/blender/nodes/shader/materialx/material.cc index 0fd023bbb29..7cedbf68c9c 100644 --- a/source/blender/nodes/shader/materialx/material.cc +++ b/source/blender/nodes/shader/materialx/material.cc @@ -2,6 +2,8 @@ * * SPDX-License-Identifier: GPL-2.0-or-later */ +#include + #include #include "material.h" @@ -60,23 +62,17 @@ class DefaultMaterialNodeParser : public NodeParser { } }; -MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, - Material *material, - ExportImageFunction export_image_fn) +static bool export_script_node(MaterialX::DocumentPtr doc, + Depsgraph *depsgraph, + Material *material) { - CLOG_INFO(LOG_MATERIALX_SHADER, 0, "Material: %s", material->id.name); - - MaterialX::DocumentPtr doc = MaterialX::createDocument(); bool script_found = false; - if (material->use_nodes) { - material->nodetree->ensure_topology_cache(); - Main *bmain = DEG_get_bmain(depsgraph); - /* Look for first script node with assigned file. - * If it's found, we load content and ignore everything other. */ - LISTBASE_FOREACH (bNode *, node, &material->nodetree->nodes) { - if (node->typeinfo->type == SH_NODE_SCRIPT) { - NodeShaderScript *script = static_cast(node->storage); - if (script->mode == NODE_SCRIPT_EXTERNAL && script->filepath[0] != '\0') { + Main *bmain = DEG_get_bmain(depsgraph); + LISTBASE_FOREACH (bNode *, node, &material->nodetree->nodes) { + if (node->typeinfo->type == SH_NODE_SCRIPT) { + NodeShaderScript *script = static_cast(node->storage); + if (script->mode == NODE_SCRIPT_EXTERNAL) { + if (script->filepath[0] != '\0') { script_found = true; char filepath[FILE_MAX]; STRNCPY(filepath, script->filepath); @@ -98,53 +94,73 @@ MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, } break; } - else if (script->mode == NODE_SCRIPT_INTERNAL) { - Text *text = reinterpret_cast(node->id); - if (text) { - script_found = true; - std::string text_content; - LISTBASE_FOREACH (TextLine *, line, &text->lines) { - text_content.append(line->line); - } - try { - MaterialX::readFromXmlString(doc, text_content); - } - catch (MaterialX::ExceptionParseError) { - CLOG_WARN(LOG_MATERIALX_SHADER, - "Material: %s, Node: %s: parsing error", - material->id.name, - node->name); - } - break; + } + else if (script->mode == NODE_SCRIPT_INTERNAL) { + Text *text = reinterpret_cast(node->id); + if (text) { + script_found = true; + std::stringstream text_content; + LISTBASE_FOREACH (TextLine *, line, &text->lines) { + text_content << line->line; } - } - else { - BLI_assert_unreachable(); + try { + MaterialX::readFromXmlStream(doc, text_content); + } + catch (MaterialX::ExceptionParseError) { + CLOG_WARN(LOG_MATERIALX_SHADER, + "Material: %s, Node: %s: parsing error", + material->id.name, + node->name); + } + break; } } + else { + BLI_assert_unreachable(); + } } + } + return script_found; +} - bNode *output_node = ntreeShaderOutputNode(material->nodetree, SHD_OUTPUT_ALL); - if (output_node && !script_found) { - NodeParserData data = {doc.get(), - depsgraph, - material, - NodeItem::Type::Material, - nullptr, - NodeItem(doc.get()), - export_image_fn}; - output_node->typeinfo->materialx_fn(&data, output_node, nullptr); - } - else { - DefaultMaterialNodeParser(doc.get(), - depsgraph, - material, - nullptr, - nullptr, - NodeItem::Type::Material, - nullptr, - export_image_fn) - .compute_error(); +MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, + Material *material, + ExportImageFunction export_image_fn) +{ + CLOG_INFO(LOG_MATERIALX_SHADER, 0, "Material: %s", material->id.name); + + MaterialX::DocumentPtr doc = MaterialX::createDocument(); + bool script_found = false; + if (material->use_nodes) { + material->nodetree->ensure_topology_cache(); + + /* Look for first script node with assigned file. + * If it's found, we load content and ignore everything other. */ + script_found = export_script_node(doc, depsgraph, material); + + if (!script_found) { + bNode *output_node = ntreeShaderOutputNode(material->nodetree, SHD_OUTPUT_ALL); + if (output_node) { + NodeParserData data = {doc.get(), + depsgraph, + material, + NodeItem::Type::Material, + nullptr, + NodeItem(doc.get()), + export_image_fn}; + output_node->typeinfo->materialx_fn(&data, output_node, nullptr); + } + else { + DefaultMaterialNodeParser(doc.get(), + depsgraph, + material, + nullptr, + nullptr, + NodeItem::Type::Material, + nullptr, + export_image_fn) + .compute_error(); + } } } else { -- 2.30.2 From 8e2b9acaa8178c4af9e14e90339fe90cc93c4c5c Mon Sep 17 00:00:00 2001 From: "georgiy.m.markelov@gmail.com" Date: Mon, 9 Oct 2023 12:12:06 +0300 Subject: [PATCH 5/5] MaterialX: code improvements --- .../blender/nodes/shader/materialx/material.cc | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/source/blender/nodes/shader/materialx/material.cc b/source/blender/nodes/shader/materialx/material.cc index 7cedbf68c9c..11f8814f72c 100644 --- a/source/blender/nodes/shader/materialx/material.cc +++ b/source/blender/nodes/shader/materialx/material.cc @@ -66,14 +66,12 @@ static bool export_script_node(MaterialX::DocumentPtr doc, Depsgraph *depsgraph, Material *material) { - bool script_found = false; Main *bmain = DEG_get_bmain(depsgraph); LISTBASE_FOREACH (bNode *, node, &material->nodetree->nodes) { if (node->typeinfo->type == SH_NODE_SCRIPT) { NodeShaderScript *script = static_cast(node->storage); if (script->mode == NODE_SCRIPT_EXTERNAL) { - if (script->filepath[0] != '\0') { - script_found = true; + if (!STREQ(script->filepath, "")) { char filepath[FILE_MAX]; STRNCPY(filepath, script->filepath); BLI_path_abs(filepath, BKE_main_blendfile_path(bmain)); @@ -92,13 +90,12 @@ static bool export_script_node(MaterialX::DocumentPtr doc, material->id.name, node->name); } - break; + return true; } } else if (script->mode == NODE_SCRIPT_INTERNAL) { Text *text = reinterpret_cast(node->id); if (text) { - script_found = true; std::stringstream text_content; LISTBASE_FOREACH (TextLine *, line, &text->lines) { text_content << line->line; @@ -112,7 +109,7 @@ static bool export_script_node(MaterialX::DocumentPtr doc, material->id.name, node->name); } - break; + return true; } } else { @@ -120,7 +117,7 @@ static bool export_script_node(MaterialX::DocumentPtr doc, } } } - return script_found; + return false; } MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, @@ -130,15 +127,12 @@ MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, CLOG_INFO(LOG_MATERIALX_SHADER, 0, "Material: %s", material->id.name); MaterialX::DocumentPtr doc = MaterialX::createDocument(); - bool script_found = false; if (material->use_nodes) { material->nodetree->ensure_topology_cache(); /* Look for first script node with assigned file. * If it's found, we load content and ignore everything other. */ - script_found = export_script_node(doc, depsgraph, material); - - if (!script_found) { + if (!export_script_node(doc, depsgraph, material)) { bNode *output_node = ntreeShaderOutputNode(material->nodetree, SHD_OUTPUT_ALL); if (output_node) { NodeParserData data = {doc.get(), -- 2.30.2