diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4fdcefb7fb..aeba7b2c45 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -25,19 +25,19 @@ jobs: python: 3.7 cmake_config: -DMATERIALX_BUILD_SHARED_LIBS=ON - - name: Linux_GCC_11_Python39 - os: ubuntu-20.04 - compiler: gcc - compiler_version: "11" - python: 3.9 - build_javascript: ON - - name: Linux_GCC_12_Python311 os: ubuntu-22.04 compiler: gcc compiler_version: "12" python: 3.11 - upload_shaders: ON + build_javascript: ON + + - name: Linux_GCC_13_Python312 + os: ubuntu-22.04 + compiler: gcc + compiler_version: "13" + python: 3.12 + static_analysis: ON - name: Linux_GCC_CoverageAnalysis os: ubuntu-22.04 @@ -53,20 +53,19 @@ jobs: compiler_version: "10" python: 3.7 cmake_config: -DMATERIALX_BUILD_SHARED_LIBS=ON - static_analysis: ON - - name: Linux_Clang_14_Python311 + - name: Linux_Clang_15_Python312 os: ubuntu-22.04 compiler: clang - compiler_version: "14" - python: 3.11 + compiler_version: "15" + python: 3.12 test_render: ON clang_format: ON - - name: Linux_Clang_14_DynamicAnalysis + - name: Linux_Clang_DynamicAnalysis os: ubuntu-22.04 compiler: clang - compiler_version: "14" + compiler_version: "15" python: None cmake_config: -DMATERIALX_DYNAMIC_ANALYSIS=ON dynamic_analysis: ON @@ -104,18 +103,19 @@ jobs: python: 3.7 cmake_config: -G "Visual Studio 16 2019" -A "Win32" -DMATERIALX_BUILD_SHARED_LIBS=ON - - name: Windows_VS2022_x64_Python39 + - name: Windows_VS2022_x64_Python311 os: windows-2022 architecture: x64 - python: 3.9 + python: 3.11 cmake_config: -G "Visual Studio 17 2022" -A "x64" + test_shaders: ON - - name: Windows_VS2022_x64_Python311 + - name: Windows_VS2022_x64_Python312 os: windows-2022 architecture: x64 - python: 3.11 + python: 3.12 cmake_config: -G "Visual Studio 17 2022" -A "x64" - test_shaders: ON + upload_shaders: ON steps: - name: Sync Repository @@ -172,6 +172,10 @@ jobs: python-version: ${{ matrix.python }} architecture: ${{ matrix.architecture }} + - name: Install Python Dependencies + if: matrix.python != 'None' + run: pip install setuptools + - name: Install Emscripten if: matrix.build_javascript == 'ON' run: | diff --git a/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx b/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx index 0081dec924..022f0896f1 100644 --- a/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx +++ b/libraries/stdlib/genmdl/stdlib_genmdl_impl.mtlx @@ -22,22 +22,22 @@ - + - + - + - + - + - + diff --git a/python/Scripts/baketextures.py b/python/Scripts/baketextures.py index caf2aaed3e..ce132036a6 100644 --- a/python/Scripts/baketextures.py +++ b/python/Scripts/baketextures.py @@ -5,9 +5,8 @@ import sys, os, argparse from sys import platform + import MaterialX as mx -from MaterialX import PyMaterialXGenShader -from MaterialX import PyMaterialXGenGlsl from MaterialX import PyMaterialXRender as mx_render from MaterialX import PyMaterialXRenderGlsl as mx_render_glsl if platform == "darwin": diff --git a/python/Scripts/generateshader.py b/python/Scripts/generateshader.py index 8329f7231e..038625eacf 100644 --- a/python/Scripts/generateshader.py +++ b/python/Scripts/generateshader.py @@ -5,12 +5,13 @@ ''' import sys, os, argparse, subprocess + import MaterialX as mx -import MaterialX.PyMaterialXGenShader as mx_gen_shader import MaterialX.PyMaterialXGenGlsl as mx_gen_glsl -import MaterialX.PyMaterialXGenOsl as mx_gen_osl import MaterialX.PyMaterialXGenMdl as mx_gen_mdl import MaterialX.PyMaterialXGenMsl as mx_gen_msl +import MaterialX.PyMaterialXGenOsl as mx_gen_osl +import MaterialX.PyMaterialXGenShader as mx_gen_shader def validateCode(sourceCodeFile, codevalidator, codevalidatorArgs): if codevalidator: diff --git a/python/Scripts/translateshader.py b/python/Scripts/translateshader.py index 71d7a480b5..f7c5686211 100644 --- a/python/Scripts/translateshader.py +++ b/python/Scripts/translateshader.py @@ -5,15 +5,13 @@ ''' import sys, os, argparse -import MaterialX as mx - from sys import platform + +import MaterialX as mx from MaterialX import PyMaterialXGenShader as mx_gen_shader -from MaterialX import PyMaterialXGenGlsl as ms_gen_glsl from MaterialX import PyMaterialXRender as mx_render from MaterialX import PyMaterialXRenderGlsl as mx_render_glsl if platform == "darwin": - from MaterialX import PyMaterialXGenMsl as ms_gen_msl from MaterialX import PyMaterialXRenderMsl as mx_render_msl def main(): diff --git a/source/MaterialXGenMdl/MdlShaderGenerator.cpp b/source/MaterialXGenMdl/MdlShaderGenerator.cpp index f64b555c20..e10d586d69 100644 --- a/source/MaterialXGenMdl/MdlShaderGenerator.cpp +++ b/source/MaterialXGenMdl/MdlShaderGenerator.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -187,6 +188,14 @@ MdlShaderGenerator::MdlShaderGenerator() : // registerImplementation("IM_sheen_bsdf_" + MdlShaderGenerator::TARGET, LayerableNodeMdl::create); + + // + registerImplementation("IM_image_float_" + MdlShaderGenerator::TARGET, ImageNodeMdl::create); + registerImplementation("IM_image_color3_" + MdlShaderGenerator::TARGET, ImageNodeMdl::create); + registerImplementation("IM_image_color4_" + MdlShaderGenerator::TARGET, ImageNodeMdl::create); + registerImplementation("IM_image_vector2_" + MdlShaderGenerator::TARGET, ImageNodeMdl::create); + registerImplementation("IM_image_vector3_" + MdlShaderGenerator::TARGET, ImageNodeMdl::create); + registerImplementation("IM_image_vector4_" + MdlShaderGenerator::TARGET, ImageNodeMdl::create); } ShaderPtr MdlShaderGenerator::generate(const string& name, ElementPtr element, GenContext& context) const diff --git a/source/MaterialXGenMdl/Nodes/ImageNodeMdl.cpp b/source/MaterialXGenMdl/Nodes/ImageNodeMdl.cpp new file mode 100644 index 0000000000..502711fe01 --- /dev/null +++ b/source/MaterialXGenMdl/Nodes/ImageNodeMdl.cpp @@ -0,0 +1,50 @@ +// +// Copyright Contributors to the MaterialX Project +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include +#include + +MATERIALX_NAMESPACE_BEGIN + +const string ImageNodeMdl::FLIP_V = "flip_v"; + +ShaderNodeImplPtr ImageNodeMdl::create() +{ + return std::make_shared(); +} + +void ImageNodeMdl::addInputs(ShaderNode& node, GenContext& context) const +{ + BASE::addInputs(node, context); + node.addInput(ImageNodeMdl::FLIP_V, Type::BOOLEAN)->setUniform(); +} + +bool ImageNodeMdl::isEditable(const ShaderInput& input) const +{ + if (input.getName() == ImageNodeMdl::FLIP_V) + { + return false; + } + return BASE::isEditable(input); +} + +void ImageNodeMdl::emitFunctionCall(const ShaderNode& _node, GenContext& context, ShaderStage& stage) const +{ + DEFINE_SHADER_STAGE(stage, Stage::PIXEL) + { + ShaderNode& node = const_cast(_node); + ShaderInput* flipUInput = node.getInput(ImageNodeMdl::FLIP_V); + ValuePtr value = TypedValue::createValue(context.getOptions().fileTextureVerticalFlip); + if (flipUInput) + { + flipUInput->setValue(value); + } + BASE::emitFunctionCall(_node, context, stage); + } +} + +MATERIALX_NAMESPACE_END diff --git a/source/MaterialXGenMdl/Nodes/ImageNodeMdl.h b/source/MaterialXGenMdl/Nodes/ImageNodeMdl.h new file mode 100644 index 0000000000..fe88b2ce09 --- /dev/null +++ b/source/MaterialXGenMdl/Nodes/ImageNodeMdl.h @@ -0,0 +1,34 @@ +// +// Copyright Contributors to the MaterialX Project +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef MATERIALX_IMAGENODEMDL_H +#define MATERIALX_IMAGENODEMDL_H + +#include + +#include "SourceCodeNodeMdl.h" + +MATERIALX_NAMESPACE_BEGIN + +/// Image node implementation for MDL +class MX_GENMDL_API ImageNodeMdl : public SourceCodeNodeMdl +{ + using BASE = SourceCodeNodeMdl; + + public: + static const string FLIP_V; ///< the empty string "" + + static ShaderNodeImplPtr create(); + + void addInputs(ShaderNode& node, GenContext& context) const override; + + bool isEditable(const ShaderInput& input) const override; + + void emitFunctionCall(const ShaderNode& node, GenContext& context, ShaderStage& stage) const override; +}; + +MATERIALX_NAMESPACE_END + +#endif diff --git a/source/MaterialXGenMdl/mdl/materialx/hsv.mdl b/source/MaterialXGenMdl/mdl/materialx/hsv.mdl index 888d4ada86..9adb1505cb 100644 --- a/source/MaterialXGenMdl/mdl/materialx/hsv.mdl +++ b/source/MaterialXGenMdl/mdl/materialx/hsv.mdl @@ -25,16 +25,16 @@ import ::limits::*; export float3 mx_hsvtorgb(float3 hsv) { // from "Color Imaging, Fundamentals and Applications", Reinhard et al., p. 442 - // A hue of 1.0 is questionably valid, and needs to be interpreted as 0.0f - float h_prime = (hsv.x < 1.0f) ? hsv.x * 6.0f : 0.0f; // H * 360.0/60.0 - float h_floor = math::floor(h_prime); - float f = h_prime - h_floor; + float h = 6.0 * (hsv.x - math::floor(hsv.x)); + int hi = int(h); // truncate + float f = h - float(hi); + float zy = hsv.z*hsv.y; float a = hsv.z - zy; float b = hsv.z - zy*f; float c = a + zy*f; - switch(int(h_floor)) { + switch(hi) { default: // hue out of [0,1] range... // fall through... diff --git a/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl b/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl index 8089feb7f0..4ba4f0875a 100644 --- a/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl +++ b/source/MaterialXGenMdl/mdl/materialx/stdlib.mdl @@ -139,6 +139,11 @@ export float mx_image_float( anno::description("Enumeration {constant,clamp,periodic,mirror}."), anno::display_name("Frame End Action"), anno::unused() + ]], + uniform bool mxp_flip_v = false + [[ + anno::usage("for applying the 'fileTextureVerticalFlip' shader generator option."), + anno::hidden() ]] ) [[ @@ -153,7 +158,9 @@ export float mx_image_float( return mxp_default; float returnValue = ::tex::lookup_float(tex: mxp_file, - coord: mxp_texcoord, + coord: mxp_flip_v + ? float2(mxp_texcoord.x, 1.0f - mxp_texcoord.y) + : mxp_texcoord, wrap_u: map_addressmode(mxp_uaddressmode), wrap_v: map_addressmode(mxp_vaddressmode)); return returnValue; @@ -207,6 +214,11 @@ export color mx_image_color3( anno::description("Enumeration {constant,clamp,periodic,mirror}."), anno::display_name("Frame End Action"), anno::unused() + ]], + uniform bool mxp_flip_v = false + [[ + anno::usage("for applying the 'fileTextureVerticalFlip' shader generator option."), + anno::hidden() ]] ) [[ @@ -221,7 +233,9 @@ export color mx_image_color3( return mxp_default; color returnValue = ::tex::lookup_color(tex: mxp_file, - coord: mxp_texcoord, + coord: mxp_flip_v + ? float2(mxp_texcoord.x, 1.0f - mxp_texcoord.y) + : mxp_texcoord, wrap_u: map_addressmode(mxp_uaddressmode), wrap_v: map_addressmode(mxp_vaddressmode)); return returnValue; @@ -275,6 +289,11 @@ export color4 mx_image_color4( anno::description("Enumeration {constant,clamp,periodic,mirror}."), anno::display_name("Frame End Action"), anno::unused() + ]], + uniform bool mxp_flip_v = false + [[ + anno::usage("for applying the 'fileTextureVerticalFlip' shader generator option."), + anno::hidden() ]] ) [[ @@ -289,7 +308,9 @@ export color4 mx_image_color4( return mxp_default; color4 returnValue = mk_color4( ::tex::lookup_float4(tex: mxp_file, - coord: mxp_texcoord, + coord: mxp_flip_v + ? float2(mxp_texcoord.x, 1.0f - mxp_texcoord.y) + : mxp_texcoord, wrap_u: map_addressmode(mxp_uaddressmode), wrap_v: map_addressmode(mxp_vaddressmode))); return returnValue; @@ -343,6 +364,11 @@ export float2 mx_image_vector2( anno::description("Enumeration {constant,clamp,periodic,mirror}."), anno::display_name("Frame End Action"), anno::unused() + ]], + uniform bool mxp_flip_v = false + [[ + anno::usage("for applying the 'fileTextureVerticalFlip' shader generator option."), + anno::hidden() ]] ) [[ @@ -357,7 +383,9 @@ export float2 mx_image_vector2( return mxp_default; float2 returnValue = ::tex::lookup_float2(tex: mxp_file, - coord: mxp_texcoord, + coord: mxp_flip_v + ? float2(mxp_texcoord.x, 1.0f - mxp_texcoord.y) + : mxp_texcoord, wrap_u: map_addressmode(mxp_uaddressmode), wrap_v: map_addressmode(mxp_vaddressmode)); return returnValue; @@ -411,6 +439,11 @@ export float3 mx_image_vector3( anno::description("Enumeration {constant,clamp,periodic,mirror}."), anno::display_name("Frame End Action"), anno::unused() + ]], + uniform bool mxp_flip_v = false + [[ + anno::usage("for applying the 'fileTextureVerticalFlip' shader generator option."), + anno::hidden() ]] ) [[ @@ -425,7 +458,9 @@ export float3 mx_image_vector3( return mxp_default; float3 returnValue = ::tex::lookup_float3(tex: mxp_file, - coord: mxp_texcoord, + coord: mxp_flip_v + ? float2(mxp_texcoord.x, 1.0f - mxp_texcoord.y) + : mxp_texcoord, wrap_u: map_addressmode(mxp_uaddressmode), wrap_v: map_addressmode(mxp_vaddressmode)); return returnValue; @@ -479,6 +514,11 @@ export float4 mx_image_vector4( anno::description("Enumeration {constant,clamp,periodic,mirror}."), anno::display_name("Frame End Action"), anno::unused() + ]], + uniform bool mxp_flip_v = false + [[ + anno::usage("for applying the 'fileTextureVerticalFlip' shader generator option."), + anno::hidden() ]] ) [[ @@ -493,7 +533,9 @@ export float4 mx_image_vector4( return mxp_default; float4 returnValue = ::tex::lookup_float4(tex: mxp_file, - coord: mxp_texcoord, + coord: mxp_flip_v + ? float2(mxp_texcoord.x, 1.0f - mxp_texcoord.y) + : mxp_texcoord, wrap_u: map_addressmode(mxp_uaddressmode), wrap_v: map_addressmode(mxp_vaddressmode)); return returnValue; diff --git a/source/MaterialXGraphEditor/Graph.cpp b/source/MaterialXGraphEditor/Graph.cpp index 889789706b..88ee10a4c1 100644 --- a/source/MaterialXGraphEditor/Graph.cpp +++ b/source/MaterialXGraphEditor/Graph.cpp @@ -3241,13 +3241,27 @@ void Graph::graphButtons() // Create two windows using splitter float paneWidth = (leftPaneWidth - 2.0f); - ImGui::BeginChild("Selection", ImVec2(paneWidth, 0)); + + float aspectRatio = _renderer->getPixelRatio(); + ImVec2 screenSize = ImVec2(paneWidth, paneWidth / aspectRatio); + + ImVec2 mousePos = ImGui::GetMousePos(); + ImVec2 tempWindowPos = ImGui::GetCursorPos(); + bool cursorInRenderView = mousePos.x > tempWindowPos.x && mousePos.x < (tempWindowPos.x + screenSize.x) && + mousePos.y > tempWindowPos.y && mousePos.y < (tempWindowPos.y + screenSize.y); + + ImGuiWindowFlags windowFlags = 0; + + if (cursorInRenderView) + { + windowFlags |= ImGuiWindowFlags_NoScrollWithMouse; + } + + ImGui::BeginChild("Selection", ImVec2(paneWidth, 0), false, windowFlags); ImVec2 windowPos = ImGui::GetWindowPos(); // RenderView window ImVec2 wsize = ImVec2((float) _renderer->getViewWidth(), (float) _renderer->getViewHeight()); - float aspectRatio = _renderer->getPixelRatio(); - ImVec2 screenSize = ImVec2(paneWidth, paneWidth / aspectRatio); _renderer->setViewWidth((int) screenSize[0]); _renderer->setViewHeight((int) screenSize[1]); @@ -3267,7 +3281,10 @@ void Graph::graphButtons() ImGui::EndChild(); ImGui::SameLine(0.0f, 12.0f); - handleRenderViewInputs(windowPos, screenSize[0], screenSize[1]); + if (cursorInRenderView) + { + handleRenderViewInputs(); + } } void Graph::propertyEditor() @@ -3830,56 +3847,54 @@ void Graph::shaderPopup() } } -void Graph::handleRenderViewInputs(ImVec2 minValue, float width, float height) +void Graph::handleRenderViewInputs() { ImVec2 mousePos = ImGui::GetMousePos(); - if (mousePos.x > minValue.x && mousePos.x < (minValue.x + width) && mousePos.y > minValue.y && mousePos.y < (minValue.y + height)) + mx::Vector2 mxMousePos = mx::Vector2(mousePos.x, mousePos.y); + float scrollAmt = ImGui::GetIO().MouseWheel; + int button = -1; + bool down = false; + if (ImGui::IsMouseDragging(0) || ImGui::IsMouseDragging(1)) { - mx::Vector2 mxMousePos = mx::Vector2(mousePos.x, mousePos.y); - float scrollAmt = ImGui::GetIO().MouseWheel; - int button = -1; - bool down = false; - if (ImGui::IsMouseDragging(0) || ImGui::IsMouseDragging(1)) - { - _renderer->setMouseMotionEvent(mxMousePos); - } - if (ImGui::IsMouseClicked(0)) - { - button = 0; - down = true; - _renderer->setMouseButtonEvent(button, down, mxMousePos); - } - else if (ImGui::IsMouseClicked(1)) - { - button = 1; - down = true; - _renderer->setMouseButtonEvent(button, down, mxMousePos); - } - else if (ImGui::IsMouseReleased(0)) - { - button = 0; - _renderer->setMouseButtonEvent(button, down, mxMousePos); - } - else if (ImGui::IsMouseReleased(1)) - { - button = 1; - _renderer->setMouseButtonEvent(button, down, mxMousePos); - } - else if (ImGui::IsKeyPressed(ImGuiKey_KeypadAdd)) - { - _renderer->setKeyEvent(ImGuiKey_KeypadAdd); - } - else if (ImGui::IsKeyPressed(ImGuiKey_KeypadSubtract)) - { - _renderer->setKeyEvent(ImGuiKey_KeypadSubtract); - } + _renderer->setMouseMotionEvent(mxMousePos); + } + if (ImGui::IsMouseClicked(0)) + { + button = 0; + down = true; + _renderer->setMouseButtonEvent(button, down, mxMousePos); + } + else if (ImGui::IsMouseClicked(1)) + { + button = 1; + down = true; + _renderer->setMouseButtonEvent(button, down, mxMousePos); + } + else if (ImGui::IsMouseReleased(0)) + { + button = 0; + _renderer->setMouseButtonEvent(button, down, mxMousePos); + } + else if (ImGui::IsMouseReleased(1)) + { + button = 1; + _renderer->setMouseButtonEvent(button, down, mxMousePos); + } + else if (ImGui::IsKeyPressed(ImGuiKey_KeypadAdd)) + { + _renderer->setKeyEvent(ImGuiKey_KeypadAdd); + } + else if (ImGui::IsKeyPressed(ImGuiKey_KeypadSubtract)) + { + _renderer->setKeyEvent(ImGuiKey_KeypadSubtract); + } - // Scrolling not possible if open or save file dialog is open - if (scrollAmt != 0 && !_fileDialogSave.isOpened() && !_fileDialog.isOpened() && !_fileDialogGeom.isOpened()) - { - _renderer->setScrollEvent(scrollAmt); - } + // Scrolling not possible if open or save file dialog is open + if (scrollAmt != 0 && !_fileDialogSave.isOpened() && !_fileDialog.isOpened() && !_fileDialogGeom.isOpened()) + { + _renderer->setScrollEvent(scrollAmt); } + } void Graph::drawGraph(ImVec2 mousePos) diff --git a/source/MaterialXGraphEditor/Graph.h b/source/MaterialXGraphEditor/Graph.h index fcdf93723e..821ecf71fd 100644 --- a/source/MaterialXGraphEditor/Graph.h +++ b/source/MaterialXGraphEditor/Graph.h @@ -225,7 +225,7 @@ class Graph void selectMaterial(UiNodePtr node); // Allow for camera manipulation of render view window - void handleRenderViewInputs(ImVec2 minValue, float width, float height); + void handleRenderViewInputs(); // Set the node to display in render view based on selected node or nodegraph void setRenderMaterial(UiNodePtr node); diff --git a/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp b/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp index 1a3e127cde..22ad0d456e 100644 --- a/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp +++ b/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp @@ -288,7 +288,10 @@ void MdlShaderGeneratorTester::compileSource(const std::vector& so std::string iblFile = (rootPath / "resources/lights/san_giuseppe_bridge.hdr").asString(); renderCommand += " --hdr \"" + iblFile + "\" --hdr_rotate 90"; // set scene - renderCommand += " --uv_scale 0.5 1.0 --uv_offset 0.0 0.0 --uv_repeat --uv_flip"; + renderCommand += " --uv_scale 0.5 1.0 --uv_offset 0.0 0.0 --uv_repeat"; + renderCommand += " --uv_flip"; // this will flip the v coordinate of the vertices, which flips all the + // UV operations. In contrast, the fileTextureVerticalFlip option will + // only flip the image access nodes. renderCommand += " --camera 0 0 3 0 0 0 --fov 45"; // set the material @@ -365,6 +368,19 @@ TEST_CASE("GenShader: MDL Shader Generation", "[genmdl]") mx::GenOptions genOptions; genOptions.targetColorSpaceOverride = "lin_rec709"; + + // Flipping the texture lookups for the test renderer only. + // This is because OSL testrender does not allow to change the UV layout of their sphere (yet) and the MaterialX test suite + // adopts the OSL behavior in order to produce comparable results. This means that raw texture coordinates, or procedurals + // that use the texture coordinates, do not match what might be expected when reading the MaterialX spec: + // "[...] the image is mapped onto the geometry based on geometry UV coordinates, with the lower-left corner of an image + // mapping to the (0,0) UV coordinate [...]" + // This means for MDL: here, and only here in the test suite, we flip the UV coordinates of mesh using the `--uv_flip` option + // of the renderer, and to correct the image orientation, we apply `fileTextureVerticalFlip`. + // In regular MDL integrations this is not needed because MDL and MaterialX define the texture space equally with the origin + // at the bottom left. + genOptions.fileTextureVerticalFlip = true; + mx::FilePath optionsFilePath = searchPath.find("resources/Materials/TestSuite/_options.mtlx"); tester.validate(genOptions, optionsFilePath); } diff --git a/source/PyMaterialX/PyMaterialX.h b/source/PyMaterialX/PyMaterialX.h index 7af67ac4bd..1e7bc7ff87 100644 --- a/source/PyMaterialX/PyMaterialX.h +++ b/source/PyMaterialX/PyMaterialX.h @@ -16,4 +16,16 @@ #include #include +// Define a macro to import a PyMaterialX module, e.g. `PyMaterialXCore`, +// either within the `MaterialX` Python package, e.g. in `installed/python/`, +// or as a standalone module, e.g. in `lib/` +#define PYMATERIALX_IMPORT_MODULE(MODULE_NAME) \ + try \ + { \ + pybind11::module::import("MaterialX." #MODULE_NAME); \ + } \ + catch (const py::error_already_set&) \ + { \ + pybind11::module::import(#MODULE_NAME); \ + } #endif diff --git a/source/PyMaterialX/PyMaterialXFormat/PyModule.cpp b/source/PyMaterialX/PyMaterialXFormat/PyModule.cpp index 842087d24f..3965f48753 100644 --- a/source/PyMaterialX/PyMaterialXFormat/PyModule.cpp +++ b/source/PyMaterialX/PyMaterialXFormat/PyModule.cpp @@ -15,6 +15,9 @@ PYBIND11_MODULE(PyMaterialXFormat, mod) { mod.doc() = "Module containing Python bindings for the MaterialXFormat library"; + // PyMaterialXFormat depends on types defined in PyMaterialXCore + PYMATERIALX_IMPORT_MODULE(PyMaterialXCore); + bindPyFile(mod); bindPyXmlIo(mod); bindPyUtil(mod); diff --git a/source/PyMaterialX/PyMaterialXGenGlsl/PyModule.cpp b/source/PyMaterialX/PyMaterialXGenGlsl/PyModule.cpp index a36b815d32..9ab46e514d 100644 --- a/source/PyMaterialX/PyMaterialXGenGlsl/PyModule.cpp +++ b/source/PyMaterialX/PyMaterialXGenGlsl/PyModule.cpp @@ -16,6 +16,9 @@ PYBIND11_MODULE(PyMaterialXGenGlsl, mod) { mod.doc() = "Module containing Python bindings for the MaterialXGenGlsl library"; + // PyMaterialXGenGlsl depends on types defined in PyMaterialXGenShader + PYMATERIALX_IMPORT_MODULE(PyMaterialXGenShader); + bindPyGlslShaderGenerator(mod); bindPyGlslResourceBindingContext(mod); diff --git a/source/PyMaterialX/PyMaterialXGenMdl/PyModule.cpp b/source/PyMaterialX/PyMaterialXGenMdl/PyModule.cpp index 020c944e63..a34b28a729 100644 --- a/source/PyMaterialX/PyMaterialXGenMdl/PyModule.cpp +++ b/source/PyMaterialX/PyMaterialXGenMdl/PyModule.cpp @@ -13,5 +13,8 @@ PYBIND11_MODULE(PyMaterialXGenMdl, mod) { mod.doc() = "Module containing Python bindings for the MaterialXGenMdl library"; + // PyMaterialXGenMdl depends on types defined in PyMaterialXGenShader + PYMATERIALX_IMPORT_MODULE(PyMaterialXGenShader); + bindPyMdlShaderGenerator(mod); }; diff --git a/source/PyMaterialX/PyMaterialXGenMsl/PyModule.cpp b/source/PyMaterialX/PyMaterialXGenMsl/PyModule.cpp index 6eda44871b..b3dcdb10a8 100644 --- a/source/PyMaterialX/PyMaterialXGenMsl/PyModule.cpp +++ b/source/PyMaterialX/PyMaterialXGenMsl/PyModule.cpp @@ -14,6 +14,9 @@ PYBIND11_MODULE(PyMaterialXGenMsl, mod) { mod.doc() = "Module containing Python bindings for the MaterialXGenMsl library"; + // PyMaterialXGenMsl depends on types defined in PyMaterialXGenShader + PYMATERIALX_IMPORT_MODULE(PyMaterialXGenShader); + bindPyMslShaderGenerator(mod); bindPyMslResourceBindingContext(mod); } diff --git a/source/PyMaterialX/PyMaterialXGenOsl/PyModule.cpp b/source/PyMaterialX/PyMaterialXGenOsl/PyModule.cpp index d772d18b6a..54d7d2439a 100644 --- a/source/PyMaterialX/PyMaterialXGenOsl/PyModule.cpp +++ b/source/PyMaterialX/PyMaterialXGenOsl/PyModule.cpp @@ -13,5 +13,8 @@ PYBIND11_MODULE(PyMaterialXGenOsl, mod) { mod.doc() = "Module containing Python bindings for the MaterialXGenOsl library"; + // PyMaterialXGenOsl depends on types defined in PyMaterialXGenShader + PYMATERIALX_IMPORT_MODULE(PyMaterialXGenShader); + bindPyOslShaderGenerator(mod); } diff --git a/source/PyMaterialX/PyMaterialXRender/PyModule.cpp b/source/PyMaterialX/PyMaterialXRender/PyModule.cpp index 1c60142346..bbf9688403 100644 --- a/source/PyMaterialX/PyMaterialXRender/PyModule.cpp +++ b/source/PyMaterialX/PyMaterialXRender/PyModule.cpp @@ -25,6 +25,9 @@ PYBIND11_MODULE(PyMaterialXRender, mod) { mod.doc() = "Module containing Python bindings for the MaterialXRender library"; + // PyMaterialXRender depends on types defined in PyMaterialXCore + PYMATERIALX_IMPORT_MODULE(PyMaterialXCore); + bindPyMesh(mod); bindPyGeometryHandler(mod); bindPyLightHandler(mod); diff --git a/source/PyMaterialX/PyMaterialXRenderGlsl/PyModule.cpp b/source/PyMaterialX/PyMaterialXRenderGlsl/PyModule.cpp index 32fb79239d..d0ef04158d 100644 --- a/source/PyMaterialX/PyMaterialXRenderGlsl/PyModule.cpp +++ b/source/PyMaterialX/PyMaterialXRenderGlsl/PyModule.cpp @@ -16,6 +16,9 @@ PYBIND11_MODULE(PyMaterialXRenderGlsl, mod) { mod.doc() = "Module containing Python bindings for the MaterialXRenderGlsl library"; + // PyMaterialXRenderGlsl depends on types defined in PyMaterialXRender + PYMATERIALX_IMPORT_MODULE(PyMaterialXRender); + bindPyGlslProgram(mod); bindPyGlslRenderer(mod); bindPyGLTextureHandler(mod); diff --git a/source/PyMaterialX/PyMaterialXRenderMsl/PyModule.mm b/source/PyMaterialX/PyMaterialXRenderMsl/PyModule.mm index 10b440d21c..f4d0dbeaeb 100644 --- a/source/PyMaterialX/PyMaterialXRenderMsl/PyModule.mm +++ b/source/PyMaterialX/PyMaterialXRenderMsl/PyModule.mm @@ -16,6 +16,9 @@ { mod.doc() = "Module containing Python bindings for the MaterialXRenderMsl library"; + // PyMaterialXRenderMsl depends on types defined in PyMaterialXRender + PYMATERIALX_IMPORT_MODULE(PyMaterialXRender); + bindPyMslProgram(mod); bindPyMslRenderer(mod); bindPyMetalTextureHandler(mod); diff --git a/source/PyMaterialX/PyMaterialXRenderOsl/PyModule.cpp b/source/PyMaterialX/PyMaterialXRenderOsl/PyModule.cpp index 15610066f3..4019d364ab 100644 --- a/source/PyMaterialX/PyMaterialXRenderOsl/PyModule.cpp +++ b/source/PyMaterialX/PyMaterialXRenderOsl/PyModule.cpp @@ -13,5 +13,8 @@ PYBIND11_MODULE(PyMaterialXRenderOsl, mod) { mod.doc() = "Module containing Python bindings for the MaterialXRenderOsl library"; + // PyMaterialXRenderOsl depends on types defined in PyMaterialXRender + PYMATERIALX_IMPORT_MODULE(PyMaterialXRender); + bindPyOslRenderer(mod); }