diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index fecdbf7a52..d5ac9d3f79 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -47,18 +47,12 @@ jobs:
cmake_config: -DMATERIALX_BUILD_SHARED_LIBS=ON
static_analysis: ON
- - name: Linux_Clang_13_Python39
- os: ubuntu-22.04
- compiler: clang
- compiler_version: "13"
- python: 3.9
- test_render: ON
-
- name: Linux_Clang_14_Python311
os: ubuntu-22.04
compiler: clang
compiler_version: "14"
python: 3.11
+ test_render: ON
clang_format: ON
- name: Linux_Clang_14_DynamicAnalysis
@@ -89,6 +83,13 @@ jobs:
python: 3.11
test_shaders: ON
+ - name: iOS_Xcode_15
+ os: macos-13
+ compiler: xcode
+ compiler_version: "15.0"
+ python: None
+ cmake_config: -DMATERIALX_BUILD_IOS=ON -DCMAKE_OSX_SYSROOT=`xcrun --sdk iphoneos --show-sdk-path` -DCMAKE_OSX_ARCHITECTURES=arm64
+
- name: Windows_VS2019_Win32_Python37
os: windows-2019
architecture: x86
@@ -159,11 +160,6 @@ jobs:
python-version: ${{ matrix.python }}
architecture: ${{ matrix.architecture }}
- - name: Install OpenImageIO
- if: matrix.install_oiio == 'ON' && runner.os == 'Windows'
- run: |
- vcpkg/vcpkg install openimageio --triplet=x64-windows
-
- name: Install Emscripten
if: matrix.build_javascript == 'ON'
run: |
@@ -325,3 +321,91 @@ jobs:
name: MaterialX_JavaScript
path: javascript/build/installed/JavaScript/MaterialX
if-no-files-found: ignore
+
+ sdist:
+ name: Python SDist
+ runs-on: ubuntu-latest
+ if: github.repository == 'AcademySoftwareFoundation/MaterialX'
+ outputs:
+ sdist_filename: ${{ steps.generate.outputs.filename }}
+
+ steps:
+ - name: Sync Repository
+ uses: actions/checkout@v3
+
+ - name: Install Python
+ uses: actions/setup-python@v4
+ with:
+ python-version: 3.11
+
+ - name: Build SDist
+ id: generate
+ run: |
+ python -m pip install build
+ python -m build -s . --outdir dist
+ echo "filename=$(ls dist)" >> "$GITHUB_OUTPUT"
+
+ - name: Upload SDist
+ uses: actions/upload-artifact@v3
+ with:
+ name: MaterialX_Python_SDist
+ path: dist/*.tar.gz
+
+ wheels:
+ name: Python Wheels
+ runs-on: ${{ matrix.os }}
+ needs: ['sdist']
+ if: github.repository == 'AcademySoftwareFoundation/MaterialX'
+ strategy:
+ fail-fast: false
+ matrix:
+ python-minor: ['7', '8', '9', '10', '11']
+ os: ['ubuntu-latest', 'macos-latest', 'windows-latest']
+
+ steps:
+ - name: Sync Repository
+ uses: actions/checkout@v3
+
+ - name: Install Python 3.${{ matrix.python-minor }}
+ uses: actions/setup-python@v4
+ with:
+ python-version: 3.${{ matrix.python-minor }}
+
+ - name: Download Sdist
+ uses: actions/download-artifact@v3
+ with:
+ name: MaterialX_Python_SDist
+ path: sdist
+
+ - name: Build Wheel
+ uses: pypa/cibuildwheel@v2.13.1
+ with:
+ package-dir: ${{ github.workspace }}/sdist/${{ needs.sdist.outputs.sdist_filename }}
+ env:
+ CIBW_BUILD: 'cp3${{ matrix.python-minor }}-*'
+ CIBW_SKIP: '*musllinux*'
+ CIBW_ARCHS: 'auto64'
+ # https://github.com/pypa/manylinux
+ # manylinux2014 is CentOS 7 based. Which means GCC 10 and glibc 2.17.
+ CIBW_MANYLINUX_X86_64_IMAGE: manylinux2014
+ CIBW_BEFORE_ALL_LINUX: yum install -y libXt-devel
+ CIBW_BEFORE_ALL_MACOS: sudo xcode-select -switch /Applications/Xcode_13.4.app
+ CIBW_BUILD_VERBOSITY: 1
+ CIBW_ENVIRONMENT: CMAKE_BUILD_PARALLEL_LEVEL=2
+ # CIBW_BUILD_FRONTEND: build # https://github.com/pypa/build
+ MACOSX_DEPLOYMENT_TARGET: '10.15'
+
+ - name: Install Wheel
+ run: python -m pip install MaterialX --find-links wheelhouse --no-index
+
+ - name: Python Tests
+ run: |
+ python MaterialXTest/main.py
+ python MaterialXTest/genshader.py
+ working-directory: python
+
+ - name: Upload Wheel
+ uses: actions/upload-artifact@v3
+ with:
+ name: MaterialX_Python_Wheels
+ path: wheelhouse/*.whl
diff --git a/.gitignore b/.gitignore
index 378eac25d3..9d0b71a3c7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
build
+dist
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a27b8d124c..5704c54b84 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,40 @@
# Change Log
-## [1.38.8] - Development
+## [1.38.8] - 2023-09-08
+
+### Added
+- Added a broad set of new pattern nodes to MaterialX, including [Circle, Hexagon, Cloverleaf, Line, Grid, Crosshatch](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1411), [Checkerboard](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1328), [Random Color, Random Float](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1330), [Triangle Wave](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1334), [Integer Floor, Integer Ceiling](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1362), and [Distance](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1333).
+- Added support for [MaterialX builds on iOS](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1435).
+- Added support for [drag-and-drop import](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1482) of MaterialX files in the [Web Viewer](https://academysoftwarefoundation.github.io/MaterialX/).
+- Added generation of [MaterialX Python wheels](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1317) in GitHub Actions, enabling the distribution of MaterialX Python packages through PyPI.
+- Added support for the [lin_displayp3 and srgb_displayp3](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1368) colorspaces in shader generation.
+- Added support for the [blackbody PBR node](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1367) in shader generation.
+- Added support for [displacement](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1396) in MDL generation.
+- Added [blend](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1350) and [up-axis](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1489) controls to the triplanar projection node.
+- Added version details to [shared libraries](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1447) on Windows.
+- Added a [MacOS 13](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1375) build to GitHub Actions.
+
+### Changed
+- Raised the minimum C++ version for MaterialX builds to [C++14](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1340).
+- Upgraded the [PyBind11 library](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1343) to version 2.10.4, raising the minimum Python version to 3.6, and enabling support for Python versions 3.11 and beyond.
+- Improved the performance and convergence of [GGX importance sampling](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1390) in GLSL generation, leveraging insights from the HPG 2023 paper by Jonathan Dupuy and Anis Benyoub.
+- Improved [property panel display](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1346) in the MaterialX Graph Editor.
+- Improved [node spacing](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1476) in the MaterialX Graph Editor.
+- Improved the robustness of [MaterialX unit tests](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1370) with respect to the current working directory.
+- Simplified the handling of [default colors](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1452) in GLSL generation, removing dynamic branches on texture size.
+- Simplified the definitions of the [default color transforms](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1352), implementing them as language-independent MaterialX graphs.
+- Simplified the interface of [ShaderGenerator::emitFunctionCall](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1344), marking its original interface as deprecated.
+- Marked legacy interfaces for [findRenderableElements and findRenderableMaterialNodes](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1340) as deprecated, making their usage visible to clients as compiler warnings.
+- Moved the MaterialX specification to [public Markdown files in GitHub](https://github.com/AcademySoftwareFoundation/MaterialX/tree/main/documents/Specification), enabling direct contributions from the community.
+
+### Fixed
+- Fixed brightness artifacts in the [triplanar projection node](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1350).
+- Aligned default values for [conductor_bsdf](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1379) with the MaterialX specification.
+- Fixed [volume mixing](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1395) in MDL generation.
+- Fixed a bug to improve [shader generation determinism](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1376).
+- Fixed a bug to improve the [consistency of auto layout](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1389) in the MaterialX Graph Editor.
+- Fixed a bug to enable [multi-output connection edits](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1506) in the MaterialX Graph Editor.
+- Fixed a bug in [dot node optimizations](https://github.com/AcademySoftwareFoundation/MaterialX/pull/1522) for shader generation.
## [1.38.7] - 2023-04-21
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a1731b0df0..504563d28b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,7 +5,7 @@ set(MATERIALX_BUILD_VERSION 0)
set(MATERIALX_LIBRARY_VERSION ${MATERIALX_MAJOR_VERSION}.${MATERIALX_MINOR_VERSION}.${MATERIALX_BUILD_VERSION})
# Cmake setup
-cmake_minimum_required(VERSION 3.1)
+cmake_minimum_required(VERSION 3.5)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
set(CMAKE_MACOSX_RPATH ON)
@@ -31,7 +31,7 @@ if (MATERIALX_BUILD_JS)
endif()
endif()
-project(MaterialX)
+project(MaterialX VERSION ${MATERIALX_LIBRARY_VERSION})
option(MATERIALX_BUILD_PYTHON "Build the MaterialX Python package from C++ bindings. Requires Python 3.6 or greater." OFF)
option(MATERIALX_BUILD_VIEWER "Build the MaterialX Viewer." OFF)
@@ -49,11 +49,25 @@ option(MATERIALX_BUILD_TESTS "Build unit tests." ON)
option(MATERIALX_BUILD_SHARED_LIBS "Build MaterialX libraries as shared rather than static." OFF)
option(MATERIALX_PYTHON_LTO "Enable link-time optimizations for MaterialX Python." ON)
option(MATERIALX_INSTALL_PYTHON "Install the MaterialX Python package as a third-party library when the install target is built." ON)
+option(MATERIALX_INSTALL_RESOURCES "Install the resources folder when building render modules." ON)
option(MATERIALX_TEST_RENDER "Run rendering tests for MaterialX Render module. GPU required for graphics validation." ON)
option(MATERIALX_WARNINGS_AS_ERRORS "Interpret all compiler warnings as errors." OFF)
option(MATERIALX_DYNAMIC_ANALYSIS "Build MaterialX libraries with dynamic analysis on supporting platforms." OFF)
option(MATERIALX_OSL_LEGACY_CLOSURES "Build OSL shader generation supporting the legacy OSL closures." ON)
+option(MATERIALX_BUILD_IOS "Build MaterialX for iOS." OFF)
+if (MATERIALX_BUILD_IOS)
+ set(CMAKE_SYSTEM_NAME iOS)
+ add_definitions(-DTARGET_OS_IOS=1)
+ set(MATERIALX_BUILD_PYTHON OFF)
+ set(MATERIALX_BUILD_VIEWER OFF)
+ set(MATERIALX_BUILD_GRAPH_EDITOR OFF)
+ set(MATERIALX_BUILD_GEN_GLSL OFF)
+ set(MATERIALX_BUILD_GEN_OSL OFF)
+ set(MATERIALX_BUILD_GEN_MDL OFF)
+ set(MATERIALX_BUILD_TESTS OFF)
+endif()
+
set(MATERIALX_PYTHON_VERSION "" CACHE STRING
"Python version to be used in building the MaterialX Python package (e.g. '3.9').")
set(MATERIALX_PYTHON_EXECUTABLE "" CACHE FILEPATH
@@ -79,6 +93,12 @@ set(MATERIALX_OSL_BINARY_OSLC "" CACHE FILEPATH "Full path to the OSL compiler b
set(MATERIALX_OSL_BINARY_TESTRENDER "" CACHE FILEPATH "Full path to the OSL test render binary.")
set(MATERIALX_OSL_INCLUDE_PATH "" CACHE PATH "Full path to OSL shader includes (e.g. 'stdosl.h').")
+set(MATERIALX_PYTHON_FOLDER_NAME "python/MaterialX" CACHE INTERNAL "Folder name to user for installing the Python library.")
+
+if(SKBUILD)
+ set(MATERIALX_PYTHON_FOLDER_NAME "MaterialX")
+endif()
+
# Helpers for MDL validation
if (MATERIALX_BUILD_GEN_MDL)
set(MATERIALX_MDLC_EXECUTABLE "" CACHE FILEPATH "Full path to the mdlc binary.")
@@ -115,6 +135,7 @@ mark_as_advanced(MATERIALX_NAMESPACE_SUFFIX)
mark_as_advanced(MATERIALX_LIBNAME_SUFFIX)
mark_as_advanced(MATERIALX_PYTHON_LTO)
mark_as_advanced(MATERIALX_INSTALL_PYTHON)
+mark_as_advanced(MATERIALX_INSTALL_RESOURCES)
mark_as_advanced(MATERIALX_TEST_RENDER)
mark_as_advanced(MATERIALX_WARNINGS_AS_ERRORS)
mark_as_advanced(MATERIALX_DYNAMIC_ANALYSIS)
@@ -132,6 +153,7 @@ mark_as_advanced(MATERIALX_INSTALL_LIB_PATH)
mark_as_advanced(MATERIALX_INSTALL_STDLIB_PATH)
mark_as_advanced(MATERIALX_BUILD_JS)
mark_as_advanced(MATERIALX_EMSDK_PATH)
+mark_as_advanced(MATERIALX_BUILD_IOS)
if (MATERIALX_BUILD_GEN_MDL)
mark_as_advanced(MATERIALX_MDLC_EXECUTABLE)
mark_as_advanced(MATERIALX_MDL_RENDER_EXECUTABLE)
@@ -183,6 +205,12 @@ set(MATERIALX_SAME_DIR_RPATH "${RPATH_RELATIVE_SYMBOL};${CMAKE_INSTALL_PREFIX}/$
set(MATERIALX_UP_ONE_RPATH "${RPATH_RELATIVE_SYMBOL}/../${MATERIALX_INSTALL_LIB_PATH};${MATERIALX_SAME_DIR_RPATH}")
# For linking to libraries where source is two directories deep, ie: "MATX/python/MaterialX/../../lib"
set(MATERIALX_UP_TWO_RPATH "${RPATH_RELATIVE_SYMBOL}/../../${MATERIALX_INSTALL_LIB_PATH};${MATERIALX_SAME_DIR_RPATH}")
+if(SKBUILD)
+ # When building the Python wheels, we don't want to set any RPATH because
+ # we want to wheel to be self-contained. We don't want any interference from
+ # external paths.
+ set(MATERIALX_UP_TWO_RPATH "${RPATH_RELATIVE_SYMBOL}")
+endif()
# Adjust compiler settings
if(MSVC)
@@ -276,7 +304,9 @@ if(MATERIALX_BUILD_RENDER)
if(MATERIALX_BUILD_GRAPH_EDITOR)
add_subdirectory(source/MaterialXGraphEditor)
endif()
- add_subdirectory(resources)
+ if(MATERIALX_INSTALL_RESOURCES AND NOT SKBUILD)
+ add_subdirectory(resources)
+ endif()
endif()
# Add test subdirectory
@@ -309,26 +339,28 @@ if(${CMAKE_VERSION} VERSION_GREATER "3.6.2")
endif()
# Install root-level documents
-install(FILES LICENSE CHANGELOG.md README.md THIRD-PARTY.md
- DESTINATION .)
-
-set(MATERIALX_GEN_CONFIG_PATH "${MATERIALX_INSTALL_LIB_PATH}/cmake/${CMAKE_PROJECT_NAME}")
-
-include(CMakePackageConfigHelpers)
-configure_package_config_file(cmake/modules/MaterialXConfig.cmake.in
- ${CMAKE_BINARY_DIR}/cmake/${CMAKE_PROJECT_NAME}Config.cmake
- INSTALL_DESTINATION "${MATERIALX_GEN_CONFIG_PATH}"
- PATH_VARS CMAKE_INSTALL_PREFIX CMAKE_PROJECT_NAME)
-write_basic_package_version_file(${CMAKE_BINARY_DIR}/cmake/${CMAKE_PROJECT_NAME}ConfigVersion.cmake
- VERSION ${MATERIALX_LIBRARY_VERSION}
- COMPATIBILITY AnyNewerVersion)
-
-# Install the auto-generated CMake configuration files:
-
-install(EXPORT MaterialX
- DESTINATION "${MATERIALX_GEN_CONFIG_PATH}"
- FILE ${CMAKE_PROJECT_NAME}Targets.cmake)
-
-install(FILES "${CMAKE_BINARY_DIR}/cmake/${CMAKE_PROJECT_NAME}ConfigVersion.cmake"
- "${CMAKE_BINARY_DIR}/cmake/${CMAKE_PROJECT_NAME}Config.cmake"
- DESTINATION "${MATERIALX_GEN_CONFIG_PATH}")
+if(NOT SKBUILD)
+ install(FILES LICENSE CHANGELOG.md README.md THIRD-PARTY.md
+ DESTINATION .)
+
+ set(MATERIALX_GEN_CONFIG_PATH "${MATERIALX_INSTALL_LIB_PATH}/cmake/${CMAKE_PROJECT_NAME}")
+
+ include(CMakePackageConfigHelpers)
+ configure_package_config_file(cmake/modules/MaterialXConfig.cmake.in
+ ${CMAKE_BINARY_DIR}/cmake/${CMAKE_PROJECT_NAME}Config.cmake
+ INSTALL_DESTINATION "${MATERIALX_GEN_CONFIG_PATH}"
+ PATH_VARS CMAKE_INSTALL_PREFIX CMAKE_PROJECT_NAME)
+ write_basic_package_version_file(${CMAKE_BINARY_DIR}/cmake/${CMAKE_PROJECT_NAME}ConfigVersion.cmake
+ VERSION ${MATERIALX_LIBRARY_VERSION}
+ COMPATIBILITY AnyNewerVersion)
+
+ # Install the auto-generated CMake configuration files:
+
+ install(EXPORT MaterialX
+ DESTINATION "${MATERIALX_GEN_CONFIG_PATH}"
+ FILE ${CMAKE_PROJECT_NAME}Targets.cmake)
+
+ install(FILES "${CMAKE_BINARY_DIR}/cmake/${CMAKE_PROJECT_NAME}ConfigVersion.cmake"
+ "${CMAKE_BINARY_DIR}/cmake/${CMAKE_PROJECT_NAME}Config.cmake"
+ DESTINATION "${MATERIALX_GEN_CONFIG_PATH}")
+endif()
diff --git a/cmake/modules/MaterialXConfig.cmake.in b/cmake/modules/MaterialXConfig.cmake.in
index b4c8b7fad6..e1598087bf 100644
--- a/cmake/modules/MaterialXConfig.cmake.in
+++ b/cmake/modules/MaterialXConfig.cmake.in
@@ -22,6 +22,8 @@ set_and_check(MATERIALX_STDLIB_DIR "@PACKAGE_CMAKE_INSTALL_PREFIX@/libraries")
if(@MATERIALX_BUILD_PYTHON@ AND @MATERIALX_INSTALL_PYTHON@)
set_and_check(MATERIALX_PYTHON_DIR "@PACKAGE_CMAKE_INSTALL_PREFIX@/python")
endif()
-set_and_check(MATERIALX_RESOURCES_DIR "@PACKAGE_CMAKE_INSTALL_PREFIX@/resources")
+if(@MATERIALX_BUILD_RENDER@ AND @MATERIALX_INSTALL_RESOURCES@)
+ set_and_check(MATERIALX_RESOURCES_DIR "@PACKAGE_CMAKE_INSTALL_PREFIX@/resources")
+endif()
check_required_components(@CMAKE_PROJECT_NAME@)
diff --git a/cmake/modules/MaterialXVersion.rc.in b/cmake/modules/MaterialXVersion.rc.in
new file mode 100644
index 0000000000..989fbb8e55
--- /dev/null
+++ b/cmake/modules/MaterialXVersion.rc.in
@@ -0,0 +1,34 @@
+
+#define MATERIALX_FILEVERSION @MATERIALX_MAJOR_VERSION@,@MATERIALX_MINOR_VERSION@,@MATERIALX_BUILD_VERSION@,0
+#define MATERIALX_FILEVERSION_STR "@MATERIALX_MAJOR_VERSION@.@MATERIALX_MINOR_VERSION@.@MATERIALX_BUILD_VERSION@.0\0"
+#define MATERIALX_FILENAME_STR "@MATERIALX_MODULE_NAME@.dll\0"
+
+1 VERSIONINFO
+ FILEVERSION MATERIALX_FILEVERSION
+ PRODUCTVERSION MATERIALX_FILEVERSION
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904E4"
+ BEGIN
+ VALUE "FileVersion", MATERIALX_FILEVERSION_STR
+ VALUE "LegalCopyright", "Apache License 2.0\0"
+ VALUE "OriginalFilename", MATERIALX_FILENAME_STR
+ VALUE "ProductName", "MaterialX\0"
+ VALUE "ProductVersion", MATERIALX_FILEVERSION_STR
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1252
+ END
+END
diff --git a/documents/Specification/MaterialX.Specification.md b/documents/Specification/MaterialX.Specification.md
index 3a90a269fb..7e876bdb57 100644
--- a/documents/Specification/MaterialX.Specification.md
+++ b/documents/Specification/MaterialX.Specification.md
@@ -656,6 +656,7 @@ Standard Texture nodes:
* **`image`**: samples data from a single image, or from a layer within a multi-layer image. When used in the context of rendering a geometry, 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 (or to the fractional (0,0) UV coordinate for tiled images).
+The type of the <image> node determines the number of channels output, which may be less than the number of channels in the image file, outputting the first N channels from the image file. So a `float` <image> would return the Red channel of an RGB image, and a `color3` <image> would return the RGB channels of an RGBA image.
* `file` (uniform filename): the URI of an image file. The filename can include one or more substitutions to change the file name (including frame number) that is accessed, as described in the [Filename Substitutions](#filename-substitutions) section above.
* `layer` (uniform string): the name of the layer to extract from a multi-layer input file. If no value for `layer` is provided and the input file has multiple layers, then the "default" layer will be used, or "rgba" if there is no "default" layer. Note: the number of channels defined by the `type` of the `` must match the number of channels in the named layer.
* `default` (float or colorN or vectorN): a default value to use if the `file` reference can not be resolved (e.g. if a <_geometry token_>, [_interface token_] or {_hostattr_} is included in the filename but no substitution value or default is defined, or if the resolved `file` URI cannot be read), or if the specified `layer` does not exist in the file. The `default` value must be the same type as the `` element itself. If `default` is not defined, the default color value will be 0.0 in all channels.
@@ -786,8 +787,8 @@ Standard Procedural nodes:
* **`checkerboard`**: a 2D checkerboard pattern.
* `color1` (color3): The first color used in the checkerboard pattern.
* `color2` (color3): The second color used in the checkerboard pattern.
- * `freq` (vector2): The frequency of checkers, with higher values producing smaller squares. Default is (8, 8).
- * `offset` (vector2): Shift the pattern in 2d space. Default is (0, 0).
+ * `uvtiling` (vector2): The tiling of the checkerboard pattern along each axis, with higher values producing smaller squares. Default is (8, 8).
+ * `uvoffset` (vector2): The offset of the checkerboard pattern along each axis. Default is (0, 0).
* `texcoord` (vector2): The input 2d space. Default is the first texture coordinates.
@@ -2369,7 +2370,7 @@ An input with a shader-semantic type may be given a value of "" to indicate no s
The Standard MaterialX Library defines the following nodes and node variants operating on "shader"-semantic types. Standard library shaders do not respond to external illumination; please refer to the [**MaterialX Physically Based Shading Nodes**](./MaterialX.PBRSpec.md#materialx-pbs-library) document for definitions of additional nodes and shader constructors which do respond to illumination.
-
+
* **`surface_unlit`**: an unlit surface shader node, representing a surface that can emit and transmit light, but does not receive illumination from light sources or other surfaces. Output type surfaceshader.
* `emission` (float): the surface emission amount; default is 1.0
diff --git a/javascript/MaterialXView/package-lock.json b/javascript/MaterialXView/package-lock.json
index 84d65f8589..7bdf38ceba 100644
--- a/javascript/MaterialXView/package-lock.json
+++ b/javascript/MaterialXView/package-lock.json
@@ -10,8 +10,8 @@
"license": "ISC",
"dependencies": {
"dat.gui": "^0.7.9",
- "three": "^0.135.0",
- "webpack": "^5.88.1"
+ "three": "^0.136.0",
+ "webpack": "^5.88.2"
},
"devDependencies": {
"copy-webpack-plugin": "^8.1.1",
@@ -166,9 +166,9 @@
}
},
"node_modules/@types/eslint": {
- "version": "8.40.2",
- "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.40.2.tgz",
- "integrity": "sha512-PRVjQ4Eh9z9pmmtaq8nTjZjQwKFk7YIHIud3lRoKRBgUQjgjRmoGxxGEPXQkF+lH7QkHJRNr5F4aBgYCW0lqpQ==",
+ "version": "8.44.1",
+ "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.1.tgz",
+ "integrity": "sha512-XpNDc4Z5Tb4x+SW1MriMVeIsMoONHCkWFMkR/aPJbzEsxqHy+4Glu/BqTdPrApfDeMaXbtNh6bseNgl5KaWrSg==",
"dependencies": {
"@types/estree": "*",
"@types/json-schema": "*"
@@ -245,9 +245,9 @@
"dev": true
},
"node_modules/@types/node": {
- "version": "20.3.3",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.3.tgz",
- "integrity": "sha512-wheIYdr4NYML61AjC8MKj/2jrR/kDQri/CIpVoZwldwhnIrD/j9jIU5bJ8yBKuB2VhpFV7Ab6G2XkBjv9r9Zzw=="
+ "version": "20.4.5",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.5.tgz",
+ "integrity": "sha512-rt40Nk13II9JwQBdeYqmbn2Q6IVTA5uPhvSO+JVqdXw/6/4glI6oR9ezty/A9Hg5u7JH4OmYmuQ+XvjKm0Datg=="
},
"node_modules/@types/qs": {
"version": "6.9.7",
@@ -506,9 +506,9 @@
}
},
"node_modules/acorn": {
- "version": "8.9.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz",
- "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==",
+ "version": "8.10.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
+ "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
"bin": {
"acorn": "bin/acorn"
},
@@ -798,9 +798,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001512",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001512.tgz",
- "integrity": "sha512-2S9nK0G/mE+jasCUsMPlARhRCts1ebcp2Ji8Y8PWi4NDE1iRdLCnEPHkEfeBrGC45L4isBx5ur3IQ6yTE2mRZw==",
+ "version": "1.0.30001517",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001517.tgz",
+ "integrity": "sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA==",
"funding": [
{
"type": "opencollective",
@@ -1223,9 +1223,9 @@
"dev": true
},
"node_modules/electron-to-chromium": {
- "version": "1.4.449",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.449.tgz",
- "integrity": "sha512-TxLRpRUj/107ATefeP8VIUWNOv90xJxZZbCW/eIbSZQiuiFANCx2b7u+GbVc9X4gU+xnbvypNMYVM/WArE1DNQ=="
+ "version": "1.4.470",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.470.tgz",
+ "integrity": "sha512-zZM48Lmy2FKWgqyvsX9XK+J6FfP7aCDUFLmgooLJzA7v1agCs/sxSoBpTIwDLhmbhpx9yJIxj2INig/ncjJRqg=="
},
"node_modules/encodeurl": {
"version": "1.0.2",
@@ -1427,9 +1427,9 @@
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"node_modules/fast-glob": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz",
- "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==",
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
+ "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
"dev": true,
"dependencies": {
"@nodelib/fs.stat": "^2.0.2",
@@ -2397,9 +2397,9 @@
}
},
"node_modules/node-releases": {
- "version": "2.0.12",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz",
- "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ=="
+ "version": "2.0.13",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
+ "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ=="
},
"node_modules/normalize-path": {
"version": "3.0.0",
@@ -3405,9 +3405,9 @@
}
},
"node_modules/terser": {
- "version": "5.18.2",
- "resolved": "https://registry.npmjs.org/terser/-/terser-5.18.2.tgz",
- "integrity": "sha512-Ah19JS86ypbJzTzvUCX7KOsEIhDaRONungA4aYBjEP3JZRf4ocuDzTg4QWZnPn9DEMiMYGJPiSOy7aykoCc70w==",
+ "version": "5.19.2",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.19.2.tgz",
+ "integrity": "sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==",
"dependencies": {
"@jridgewell/source-map": "^0.3.3",
"acorn": "^8.8.2",
@@ -3468,9 +3468,9 @@
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
},
"node_modules/three": {
- "version": "0.135.0",
- "resolved": "https://registry.npmjs.org/three/-/three-0.135.0.tgz",
- "integrity": "sha512-kuEpuuxRzLv0MDsXai9huCxOSQPZ4vje6y0gn80SRmQvgz6/+rI0NAvCRAw56zYaWKMGMfqKWsxF9Qa2Z9xymQ=="
+ "version": "0.136.0",
+ "resolved": "https://registry.npmjs.org/three/-/three-0.136.0.tgz",
+ "integrity": "sha512-+fEMX7nYLz2ZesVP/dyifli5Jf8gR3XPAnFJveQ80aMhibFduzrADnjMbARXh8+W9qLK7rshJCjAIL/6cDxC+A=="
},
"node_modules/thunky": {
"version": "1.1.0",
@@ -3500,9 +3500,9 @@
}
},
"node_modules/tslib": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz",
- "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==",
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz",
+ "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==",
"dev": true
},
"node_modules/type-is": {
@@ -3625,9 +3625,9 @@
}
},
"node_modules/webpack": {
- "version": "5.88.1",
- "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.1.tgz",
- "integrity": "sha512-FROX3TxQnC/ox4N+3xQoWZzvGXSuscxR32rbzjpXgEzWudJFEJBpdlkkob2ylrv5yzzufD1zph1OoFsLtm6stQ==",
+ "version": "5.88.2",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz",
+ "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==",
"dependencies": {
"@types/eslint-scope": "^3.7.3",
"@types/estree": "^1.0.0",
diff --git a/javascript/MaterialXView/package.json b/javascript/MaterialXView/package.json
index 2113d145cf..adce3d2e82 100644
--- a/javascript/MaterialXView/package.json
+++ b/javascript/MaterialXView/package.json
@@ -11,8 +11,8 @@
"license": "ISC",
"dependencies": {
"dat.gui": "^0.7.9",
- "three": "^0.135.0",
- "webpack": "^5.88.1"
+ "three": "^0.136.0",
+ "webpack": "^5.88.2"
},
"devDependencies": {
"copy-webpack-plugin": "^8.1.1",
diff --git a/javascript/MaterialXView/source/dropHandling.js b/javascript/MaterialXView/source/dropHandling.js
new file mode 100644
index 0000000000..adcbef2ca1
--- /dev/null
+++ b/javascript/MaterialXView/source/dropHandling.js
@@ -0,0 +1,281 @@
+import * as THREE from 'three';
+import * as fflate from 'three/examples/jsm/libs/fflate.module.js';
+
+const debugFileHandling = false;
+let loadingCallback;
+
+export function setLoadingCallback(cb) {
+ loadingCallback = cb;
+}
+
+export function dropHandler(ev) {
+ if (debugFileHandling) console.log('File(s) dropped', ev.dataTransfer.items, ev.dataTransfer.files);
+
+ // Prevent default behavior (Prevent file from being opened)
+ ev.preventDefault();
+
+ if (ev.dataTransfer.items)
+ {
+ const allEntries = [];
+
+ let haveGetAsEntry = false;
+ if (ev.dataTransfer.items.length > 0)
+ haveGetAsEntry =
+ ("getAsEntry" in ev.dataTransfer.items[0]) ||
+ ("webkitGetAsEntry" in ev.dataTransfer.items[0]);
+
+ // Useful for debugging file handling on platforms that don't support newer file system APIs
+ // haveGetAsEntry = false;
+
+ if (haveGetAsEntry) {
+ for (var i = 0; i < ev.dataTransfer.items.length; i++)
+ {
+ let item = ev.dataTransfer.items[i];
+ let entry = ("getAsEntry" in item) ? item.getAsEntry() : item.webkitGetAsEntry();
+ allEntries.push(entry);
+ }
+ handleFilesystemEntries(allEntries);
+ return;
+ }
+
+ for (var i = 0; i < ev.dataTransfer.items.length; i++)
+ {
+ let item = ev.dataTransfer.items[i];
+
+ // API when there's no "getAsEntry" support
+ console.log(item.kind, item);
+ if (item.kind === 'file')
+ {
+ var file = item.getAsFile();
+ testAndLoadFile(file);
+ }
+ // could also be a directory
+ else if (item.kind === 'directory')
+ {
+ var dirReader = item.createReader();
+ dirReader.readEntries(function(entries) {
+ for (var i = 0; i < entries.length; i++) {
+ console.log(entries[i].name);
+ var entry = entries[i];
+ if (entry.isFile) {
+ entry.file(function(file) {
+ testAndLoadFile(file);
+ });
+ }
+ }
+ });
+ }
+ }
+ } else {
+ for (var i = 0; i < ev.dataTransfer.files.length; i++) {
+ let file = ev.dataTransfer.files[i];
+ testAndLoadFile(file);
+ }
+ }
+}
+
+export function dragOverHandler(ev) {
+ ev.preventDefault();
+}
+
+async function getBufferFromFile(fileEntry) {
+
+ if (fileEntry instanceof ArrayBuffer) return fileEntry;
+ if (fileEntry instanceof String) return fileEntry;
+
+ const name = fileEntry.fullPath || fileEntry.name;
+ const ext = name.split('.').pop();
+ const readAsText = ext === 'mtlx';
+
+ if (debugFileHandling) console.log("reading ", fileEntry, "as text?", readAsText);
+
+ if (debugFileHandling) console.log("getBufferFromFile", fileEntry);
+ const buffer = await new Promise((resolve, reject) => {
+ function readFile(file) {
+ var reader = new FileReader();
+ reader.onloadend = function(e) {
+ if (debugFileHandling) console.log("loaded", "should be text?", readAsText, this.result);
+ resolve(this.result);
+ };
+
+ if (readAsText)
+ reader.readAsText(file);
+ else
+ reader.readAsArrayBuffer(file);
+ }
+
+ if ("file" in fileEntry) {
+ fileEntry.file(function(file) {
+ readFile(file);
+ }, (e) => {
+ console.error("Error reading file ", e);
+ });
+ }
+ else {
+ readFile(fileEntry);
+ }
+ });
+ return buffer;
+}
+
+async function handleFilesystemEntries(entries) {
+ const allFiles = [];
+ const fileIgnoreList = [
+ '.gitignore',
+ 'README.md',
+ '.DS_Store',
+ ]
+ const dirIgnoreList = [
+ '.git',
+ 'node_modules',
+ ]
+
+ for (let entry of entries) {
+ if (debugFileHandling) console.log("file entry", entry)
+ if (entry.isFile) {
+ if (debugFileHandling) console.log("single file", entry);
+ if (fileIgnoreList.includes(entry.name)) {
+ continue;
+ }
+ allFiles.push(entry);
+ }
+ else if (entry.isDirectory) {
+ if (dirIgnoreList.includes(entry.name)) {
+ continue;
+ }
+ const files = await readDirectory(entry);
+ if (debugFileHandling) console.log("all files", files);
+ for (const file of files) {
+ if (fileIgnoreList.includes(file.name)) {
+ continue;
+ }
+ allFiles.push(file);
+ }
+ }
+ }
+
+ const imageLoader = new THREE.ImageLoader();
+
+ // unpack zip files first
+ for (const fileEntry of allFiles) {
+ // special case: zip archives
+ if (fileEntry.fullPath.toLowerCase().endsWith('.zip')) {
+ await new Promise(async (resolve, reject) => {
+ const arrayBuffer = await getBufferFromFile(fileEntry);
+
+ // use fflate to unpack them and add the files to the cache
+ fflate.unzip(new Uint8Array(arrayBuffer), (error, unzipped) => {
+ // push these files into allFiles
+ for (const [filePath, buffer] of Object.entries(unzipped)) {
+
+ // mock FileEntry for easier usage downstream
+ const blob = new Blob([buffer]);
+ const newFileEntry = {
+ fullPath: "/" + filePath,
+ name: filePath.split('/').pop(),
+ file: (callback) => {
+ callback(blob);
+ },
+ isFile: true,
+ };
+ allFiles.push(newFileEntry);
+ }
+
+ resolve();
+ });
+ });
+ }
+ }
+
+ // sort so mtlx files come first
+ allFiles.sort((a, b) => {
+ if (a.name.endsWith('.mtlx') && !b.name.endsWith('.mtlx')) {
+ return -1;
+ }
+ if (!a.name.endsWith('.mtlx') && b.name.endsWith('.mtlx')) {
+ return 1;
+ }
+ return 0;
+ });
+
+ if (debugFileHandling) console.log("all files", allFiles);
+
+ // put all files in three' Cache
+ for (const fileEntry of allFiles) {
+
+ const allowedFileTypes = [
+ 'png', 'jpg', 'jpeg'
+ ];
+
+ const ext = fileEntry.fullPath.split('.').pop();
+ if (!allowedFileTypes.includes(ext)) {
+ // console.log("skipping file", fileEntry.fullPath);
+ continue;
+ }
+
+ const buffer = await getBufferFromFile(fileEntry);
+ const img = await imageLoader.loadAsync(URL.createObjectURL(new Blob([buffer])));
+ if (debugFileHandling) console.log("caching file", fileEntry.fullPath, img);
+ THREE.Cache.add(fileEntry.fullPath, img);
+ }
+
+ // TODO we could also allow dropping of multiple MaterialX files (or folders with them inside)
+ // and seed the dropdown from that.
+ // At that point, actually reading files and textures into memory should be deferred until they are actually used.
+ const rootFile = allFiles[0];
+ THREE.Cache.add(rootFile.fullPath, await getBufferFromFile(rootFile));
+
+ if (debugFileHandling) console.log("CACHE", THREE.Cache.files);
+
+ loadingCallback(rootFile);
+}
+
+async function readDirectory(directory) {
+ let entries = [];
+ let getEntries = async (directory) => {
+ let dirReader = directory.createReader();
+ await new Promise((resolve, reject) => {
+ dirReader.readEntries(
+ async (results) => {
+ if (results.length) {
+ // entries = entries.concat(results);
+ for (let entry of results) {
+ if (entry.isDirectory) {
+ await getEntries(entry);
+ }
+ else {
+ entries.push(entry);
+ }
+ }
+ }
+ resolve();
+ },
+ (error) => {
+ /* handle error — error is a FileError object */
+ },
+ )}
+ )};
+
+ await getEntries(directory);
+ return entries;
+}
+
+async function testAndLoadFile(file) {
+ let ext = file.name.split('.').pop();
+ if (debugFileHandling) console.log(file.name + ", " + file.size + ", " + ext);
+
+ const arrayBuffer = await getBufferFromFile(file);
+ console.log(arrayBuffer)
+
+ // mock a fileEntry and pass through the same loading logic
+ const newFileEntry = {
+ fullPath: "/" + file.name,
+ name: file.name.split('/').pop(),
+ isFile: true,
+ file: (callback) => {
+ callback(file);
+ }
+ };
+
+ handleFilesystemEntries([newFileEntry]);
+}
\ No newline at end of file
diff --git a/javascript/MaterialXView/source/helper.js b/javascript/MaterialXView/source/helper.js
index e8ffb9dcae..111dfd9b5d 100644
--- a/javascript/MaterialXView/source/helper.js
+++ b/javascript/MaterialXView/source/helper.js
@@ -20,8 +20,6 @@ const IMAGE_PATH_SEPARATOR = "/";
export function prepareEnvTexture(texture, capabilities)
{
const rgbaTexture = RGBToRGBA_Float(texture);
- // RGBELoader sets flipY to true by default
- rgbaTexture.flipY = false;
rgbaTexture.wrapS = THREE.RepeatWrapping;
rgbaTexture.anisotropy = capabilities.getMaxAnisotropy();
rgbaTexture.minFilter = THREE.LinearMipmapLinearFilter;
diff --git a/javascript/MaterialXView/source/index.js b/javascript/MaterialXView/source/index.js
index 424f63ec43..56e2e1f5a2 100644
--- a/javascript/MaterialXView/source/index.js
+++ b/javascript/MaterialXView/source/index.js
@@ -12,6 +12,7 @@ import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js';
import { GammaCorrectionShader } from 'three/examples/jsm/shaders/GammaCorrectionShader.js';
import { Viewer } from './viewer.js'
+import { dropHandler, dragOverHandler, setLoadingCallback } from './dropHandling.js';
let renderer, composer, orbitControls;
@@ -115,6 +116,20 @@ function init()
console.error(Number.isInteger(err) ? this.getMx().getExceptionMessage(err) : err);
})
+ // allow dropping files and directories
+ document.addEventListener('drop', dropHandler, false);
+ document.addEventListener('dragover', dragOverHandler, false);
+
+ setLoadingCallback(file => {
+ materialFilename = file.fullPath || file.name;
+ viewer.getEditor().clearFolders();
+ viewer.getMaterial().loadMaterials(viewer, materialFilename);
+ viewer.getEditor().updateProperties(0.9);
+ viewer.getScene().setUpdateTransforms();
+ });
+
+ // enable three.js Cache so that dropped files can reference each other
+ THREE.Cache.enabled = true;
}
function onWindowResize()
diff --git a/javascript/MaterialXView/source/viewer.js b/javascript/MaterialXView/source/viewer.js
index 0bc537faf0..d1adfd9ef4 100644
--- a/javascript/MaterialXView/source/viewer.js
+++ b/javascript/MaterialXView/source/viewer.js
@@ -589,6 +589,7 @@ export class Material
// Set search path. Assumes images are relative to current file
// location.
+ if (!materialFilename) materialFilename = "/";
const paths = materialFilename.split('/');
paths.pop();
const searchPath = paths.join('/');
diff --git a/libraries/CMakeLists.txt b/libraries/CMakeLists.txt
index 0d47cad5ed..d60a54cf3b 100644
--- a/libraries/CMakeLists.txt
+++ b/libraries/CMakeLists.txt
@@ -1,20 +1,28 @@
-install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
- DESTINATION "${MATERIALX_INSTALL_STDLIB_PATH}" MESSAGE_NEVER
- PATTERN "CMakeLists.txt" EXCLUDE
- PATTERN "pbrlib_genosl_impl.*" EXCLUDE)
-
if (MATERIALX_OSL_LEGACY_CLOSURES)
set(PBRLIB_SUFFIX "legacy")
else()
set(PBRLIB_SUFFIX "mtlx")
endif()
-install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/pbrlib/genosl/pbrlib_genosl_impl.${PBRLIB_SUFFIX}"
- DESTINATION "${MATERIALX_INSTALL_STDLIB_PATH}/pbrlib/genosl/" RENAME pbrlib_genosl_impl.mtlx)
+if(NOT SKBUILD)
+ install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
+ DESTINATION "${MATERIALX_INSTALL_STDLIB_PATH}"
+ PATTERN "CMakeLists.txt" EXCLUDE
+ PATTERN "pbrlib_genosl_impl.*" EXCLUDE)
+ install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/pbrlib/genosl/pbrlib_genosl_impl.${PBRLIB_SUFFIX}"
+ DESTINATION "${MATERIALX_INSTALL_STDLIB_PATH}/pbrlib/genosl/" RENAME pbrlib_genosl_impl.mtlx)
+endif()
-install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
- DESTINATION "python/MaterialX/${MATERIALX_INSTALL_STDLIB_PATH}"
- PATTERN "CMakeLists.txt" EXCLUDE
- PATTERN "pbrlib_genosl_impl.*" EXCLUDE)
-install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/pbrlib/genosl/pbrlib_genosl_impl.${PBRLIB_SUFFIX}"
- DESTINATION "python/MaterialX/${MATERIALX_INSTALL_STDLIB_PATH}/pbrlib/genosl/" RENAME pbrlib_genosl_impl.mtlx)
+set(MATERIALX_PYTHON_LIBRARIES_PATH "${MATERIALX_PYTHON_FOLDER_NAME}/${MATERIALX_INSTALL_STDLIB_PATH}")
+if(SKBUILD)
+ set(MATERIALX_PYTHON_LIBRARIES_PATH "${SKBUILD_PLATLIB_DIR}/MaterialX/libraries")
+endif()
+
+if(MATERIALX_BUILD_PYTHON)
+ install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
+ DESTINATION "${MATERIALX_PYTHON_LIBRARIES_PATH}"
+ PATTERN "CMakeLists.txt" EXCLUDE
+ PATTERN "pbrlib_genosl_impl.*" EXCLUDE)
+ install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/pbrlib/genosl/pbrlib_genosl_impl.${PBRLIB_SUFFIX}"
+ DESTINATION "${MATERIALX_PYTHON_LIBRARIES_PATH}/pbrlib/genosl/" RENAME pbrlib_genosl_impl.mtlx)
+endif()
diff --git a/libraries/bxdf/gltf_pbr.mtlx b/libraries/bxdf/gltf_pbr.mtlx
index cb393fb82a..6654e63454 100644
--- a/libraries/bxdf/gltf_pbr.mtlx
+++ b/libraries/bxdf/gltf_pbr.mtlx
@@ -359,7 +359,7 @@
-
+
@@ -375,13 +375,10 @@
-
-
-
-
+
@@ -422,7 +419,7 @@
-
+
@@ -434,9 +431,6 @@
-
-
-
@@ -458,7 +452,7 @@
-
+
@@ -480,7 +474,7 @@
-
+
@@ -492,9 +486,6 @@
-
-
-
@@ -516,7 +507,7 @@
-
+
@@ -538,7 +529,7 @@
-
+
@@ -550,9 +541,6 @@
-
-
-
@@ -574,7 +562,7 @@
-
+
@@ -595,7 +583,7 @@
-
+
@@ -607,9 +595,6 @@
-
-
-
@@ -631,7 +616,7 @@
-
+
@@ -648,7 +633,7 @@
-
+
@@ -660,9 +645,6 @@
-
-
-
@@ -687,7 +669,7 @@
-
+
@@ -704,7 +686,7 @@
-
+
@@ -725,7 +707,7 @@
-
+
diff --git a/libraries/pbrlib/genosl/mx_blackbody.osl b/libraries/pbrlib/genosl/mx_blackbody.osl
index 8b4de5ba9f..95951330f2 100644
--- a/libraries/pbrlib/genosl/mx_blackbody.osl
+++ b/libraries/pbrlib/genosl/mx_blackbody.osl
@@ -1,10 +1,10 @@
-void mx_blackbody(float temperature, output color color_value)
+void mx_blackbody(float temp, output color color_value)
{
float xc, yc;
float t, t2, t3, xc2, xc3;
// if value outside valid range of approximation clamp to accepted temperature range
- temperature = clamp(temperature, 1667.0, 25000.0);
+ float temperature = clamp(temp, 1667.0, 25000.0);
t = 1000.0 / temperature;
t2 = t * t;
@@ -39,9 +39,10 @@ void mx_blackbody(float temperature, output color color_value)
vector XYZ = vector(xc / yc, 1.0, (1 - xc - yc) / yc);
/// XYZ to Rec.709 RGB colorspace conversion
- matrix XYZ_to_RGB = matrix( 3.2406, -0.9689, 0.0557,
- -1.5372, 1.8758, -0.2040,
- -0.4986, 0.0415, 1.0570);
+ matrix XYZ_to_RGB = matrix( 3.2406, -0.9689, 0.0557, 0.0,
+ -1.5372, 1.8758, -0.2040, 0.0,
+ -0.4986, 0.0415, 1.0570, 0.0,
+ 0.0, 0.0, 0.0, 1.0);
color_value = transform(XYZ_to_RGB, XYZ);
color_value = max(color_value, vector(0.0));
diff --git a/libraries/stdlib/genglsl/mx_image_color3.glsl b/libraries/stdlib/genglsl/mx_image_color3.glsl
index 802318f475..8c4c039554 100644
--- a/libraries/stdlib/genglsl/mx_image_color3.glsl
+++ b/libraries/stdlib/genglsl/mx_image_color3.glsl
@@ -2,13 +2,6 @@
void mx_image_color3(sampler2D tex_sampler, int layer, vec3 defaultval, vec2 texcoord, int uaddressmode, int vaddressmode, int filtertype, int framerange, int frameoffset, int frameendaction, vec2 uv_scale, vec2 uv_offset, out vec3 result)
{
- if (textureSize(tex_sampler, 0).x > 1)
- {
- vec2 uv = mx_transform_uv(texcoord, uv_scale, uv_offset);
- result = texture(tex_sampler, uv).rgb;
- }
- else
- {
- result = defaultval;
- }
+ vec2 uv = mx_transform_uv(texcoord, uv_scale, uv_offset);
+ result = texture(tex_sampler, uv).rgb;
}
diff --git a/libraries/stdlib/genglsl/mx_image_color4.glsl b/libraries/stdlib/genglsl/mx_image_color4.glsl
index e74ad9445f..7541b9da04 100644
--- a/libraries/stdlib/genglsl/mx_image_color4.glsl
+++ b/libraries/stdlib/genglsl/mx_image_color4.glsl
@@ -2,13 +2,6 @@
void mx_image_color4(sampler2D tex_sampler, int layer, vec4 defaultval, vec2 texcoord, int uaddressmode, int vaddressmode, int filtertype, int framerange, int frameoffset, int frameendaction, vec2 uv_scale, vec2 uv_offset, out vec4 result)
{
- if (textureSize(tex_sampler, 0).x > 1)
- {
- vec2 uv = mx_transform_uv(texcoord, uv_scale, uv_offset);
- result = texture(tex_sampler, uv);
- }
- else
- {
- result = defaultval;
- }
+ vec2 uv = mx_transform_uv(texcoord, uv_scale, uv_offset);
+ result = texture(tex_sampler, uv);
}
diff --git a/libraries/stdlib/genglsl/mx_image_float.glsl b/libraries/stdlib/genglsl/mx_image_float.glsl
index 9b831035d2..0a402a101c 100644
--- a/libraries/stdlib/genglsl/mx_image_float.glsl
+++ b/libraries/stdlib/genglsl/mx_image_float.glsl
@@ -2,13 +2,6 @@
void mx_image_float(sampler2D tex_sampler, int layer, float defaultval, vec2 texcoord, int uaddressmode, int vaddressmode, int filtertype, int framerange, int frameoffset, int frameendaction, vec2 uv_scale, vec2 uv_offset, out float result)
{
- if (textureSize(tex_sampler, 0).x > 1)
- {
- vec2 uv = mx_transform_uv(texcoord, uv_scale, uv_offset);
- result = texture(tex_sampler, uv).r;
- }
- else
- {
- result = defaultval;
- }
+ vec2 uv = mx_transform_uv(texcoord, uv_scale, uv_offset);
+ result = texture(tex_sampler, uv).r;
}
diff --git a/libraries/stdlib/genglsl/mx_image_vector2.glsl b/libraries/stdlib/genglsl/mx_image_vector2.glsl
index 124cb09287..42a7235297 100644
--- a/libraries/stdlib/genglsl/mx_image_vector2.glsl
+++ b/libraries/stdlib/genglsl/mx_image_vector2.glsl
@@ -2,13 +2,6 @@
void mx_image_vector2(sampler2D tex_sampler, int layer, vec2 defaultval, vec2 texcoord, int uaddressmode, int vaddressmode, int filtertype, int framerange, int frameoffset, int frameendaction, vec2 uv_scale, vec2 uv_offset, out vec2 result)
{
- if (textureSize(tex_sampler, 0).x > 1)
- {
- vec2 uv = mx_transform_uv(texcoord, uv_scale, uv_offset);
- result = texture(tex_sampler, uv).rg;
- }
- else
- {
- result = defaultval;
- }
+ vec2 uv = mx_transform_uv(texcoord, uv_scale, uv_offset);
+ result = texture(tex_sampler, uv).rg;
}
diff --git a/libraries/stdlib/genglsl/mx_image_vector3.glsl b/libraries/stdlib/genglsl/mx_image_vector3.glsl
index 840e60fe6f..d49eab735e 100644
--- a/libraries/stdlib/genglsl/mx_image_vector3.glsl
+++ b/libraries/stdlib/genglsl/mx_image_vector3.glsl
@@ -2,13 +2,6 @@
void mx_image_vector3(sampler2D tex_sampler, int layer, vec3 defaultval, vec2 texcoord, int uaddressmode, int vaddressmode, int filtertype, int framerange, int frameoffset, int frameendaction, vec2 uv_scale, vec2 uv_offset, out vec3 result)
{
- if (textureSize(tex_sampler, 0).x > 1)
- {
- vec2 uv = mx_transform_uv(texcoord, uv_scale, uv_offset);
- result = texture(tex_sampler, uv).rgb;
- }
- else
- {
- result = defaultval;
- }
+ vec2 uv = mx_transform_uv(texcoord, uv_scale, uv_offset);
+ result = texture(tex_sampler, uv).rgb;
}
diff --git a/libraries/stdlib/genglsl/mx_image_vector4.glsl b/libraries/stdlib/genglsl/mx_image_vector4.glsl
index f4b61d83f0..c8bdc66fc4 100644
--- a/libraries/stdlib/genglsl/mx_image_vector4.glsl
+++ b/libraries/stdlib/genglsl/mx_image_vector4.glsl
@@ -2,13 +2,6 @@
void mx_image_vector4(sampler2D tex_sampler, int layer, vec4 defaultval, vec2 texcoord, int uaddressmode, int vaddressmode, int filtertype, int framerange, int frameoffset, int frameendaction, vec2 uv_scale, vec2 uv_offset, out vec4 result)
{
- if (textureSize(tex_sampler, 0).x > 1)
- {
- vec2 uv = mx_transform_uv(texcoord, uv_scale, uv_offset);
- result = texture(tex_sampler, uv);
- }
- else
- {
- result = defaultval;
- }
+ vec2 uv = mx_transform_uv(texcoord, uv_scale, uv_offset);
+ result = texture(tex_sampler, uv);
}
diff --git a/libraries/stdlib/stdlib_defs.mtlx b/libraries/stdlib/stdlib_defs.mtlx
index bc1240e574..bb5e8edd1f 100644
--- a/libraries/stdlib/stdlib_defs.mtlx
+++ b/libraries/stdlib/stdlib_defs.mtlx
@@ -307,6 +307,7 @@
+
@@ -324,6 +325,7 @@
+
@@ -341,6 +343,7 @@
+
@@ -358,6 +361,7 @@
+
@@ -375,6 +379,7 @@
+
@@ -392,6 +397,7 @@
+
@@ -1083,12 +1089,131 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libraries/stdlib/stdlib_ng.mtlx b/libraries/stdlib/stdlib_ng.mtlx
index f40001e14d..e031e72412 100644
--- a/libraries/stdlib/stdlib_ng.mtlx
+++ b/libraries/stdlib/stdlib_ng.mtlx
@@ -226,11 +226,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -242,7 +276,7 @@
-
+
@@ -254,7 +288,7 @@
-
+
@@ -346,11 +380,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -362,7 +430,7 @@
-
+
@@ -374,7 +442,7 @@
-
+
@@ -466,11 +534,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -482,7 +584,7 @@
-
+
@@ -494,7 +596,7 @@
-
+
@@ -586,11 +688,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -602,7 +738,7 @@
-
+
@@ -614,7 +750,7 @@
-
+
@@ -706,11 +842,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -722,7 +892,7 @@
-
+
@@ -734,7 +904,7 @@
-
+
@@ -826,11 +996,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -842,7 +1046,7 @@
-
+
@@ -854,7 +1058,7 @@
-
+
@@ -1246,13 +1450,9 @@
-
-
-
-
-
-
+
+
@@ -1380,49 +1580,788 @@
A 2D checkerboard pattern.
-->
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000000..e674339900
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,78 @@
+[build-system]
+# Use a fixed version because we use an experimental feature
+# (a custom plugin) and for now that functionality has
+# no compatibility promises.
+requires = ["scikit-build-core==0.4.4"]
+build-backend = "scikit_build_core.build"
+
+[project]
+name = "MaterialX"
+dynamic = ["version"]
+
+authors = [
+ { name="Contributors to the MaterialX project", email="materialx-discussion@lists.aswf.io" },
+]
+readme = "README.md"
+requires-python = ">=3.6"
+
+classifiers = [
+ "Programming Language :: Python :: 3",
+ "License :: OSI Approved :: Apache Software License",
+ "Operating System :: OS Independent",
+]
+
+[project.urls]
+"Homepage" = "https://materialx.org"
+"Source" = "https://github.com/AcademySoftwareFoundation/MaterialX"
+"Bug Tracker" = "https://github.com/AcademySoftwareFoundation/MaterialX/issues"
+
+[project.scripts]
+baketextures = "MaterialX._scripts.baketextures:main"
+generateshader = "MaterialX._scripts.generateshader:main"
+genmdl = "MaterialX._scripts.genmdl:main"
+mxdoc = "MaterialX._scripts.mxdoc:main"
+mxupdate = "MaterialX._scripts.mxupdate:main"
+mxvalidate = "MaterialX._scripts.mxvalidate:main"
+translateshader = "MaterialX._scripts.translateshader:main"
+writenodegraphs = "MaterialX._scripts.writenodegraphs:main"
+
+[tool.scikit-build]
+cmake.minimum-version = "3.18"
+cmake.verbose = false
+cmake.build-type = "Release"
+
+# Enable experimental features if any are available
+# In this case we need custom local plugin to get
+# the project version from cmake.
+experimental = true
+metadata.version.provider = "mtx_skbuild_plugin"
+metadata.version.provider-path = "./python"
+
+# Uncoment when developing locally to enable inplace builds.
+# build-dir = "build/"
+
+logging.level = "DEBUG"
+
+# Since the python package doesn't live in a standard directory
+# in the source (i.e ./src or ./), we need to manually specify
+# where the package is.
+wheel.packages = ["python/MaterialX"]
+
+sdist.exclude = [
+ "/build",
+ "/dist",
+ "/resources",
+ "/javascript",
+ "/documents",
+ "/.github",
+ "MANIFEST.in"
+]
+
+[tool.scikit-build.cmake.define]
+MATERIALX_BUILD_SHARED_LIBS = 'OFF' # Be explicit
+MATERIALX_BUILD_PYTHON = 'ON'
+MATERIALX_TEST_RENDER = 'OFF'
+MATERIALX_WARNINGS_AS_ERRORS = 'ON'
+MATERIALX_BUILD_TESTS = 'OFF'
+# TODO: How could we harmonize this variable with SKBUILD?
+MATERIALX_INSTALL_PYTHON = 'OFF'
diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index e036c5abd5..da35a38b72 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -1,18 +1,25 @@
-set(SETUP_PY_IN "${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in")
-set(SETUP_PY "${CMAKE_INSTALL_PREFIX}/python/setup.py")
-
-configure_file(${SETUP_PY_IN} ${SETUP_PY})
+if(NOT SKBUILD)
+ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/MaterialX" DESTINATION "python" MESSAGE_NEVER)
+ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/Scripts" DESTINATION "python" MESSAGE_NEVER)
+endif()
-install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/MaterialX" DESTINATION "python" MESSAGE_NEVER)
-install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/Scripts" DESTINATION "python" MESSAGE_NEVER)
+if(SKBUILD)
+ install(
+ DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/Scripts/"
+ DESTINATION "${MATERIALX_PYTHON_FOLDER_NAME}/_scripts"
+ PATTERN "README.md" EXCLUDE
+ )
+endif()
if(MATERIALX_PYTHON_OCIO_DIR)
if(NOT EXISTS "${MATERIALX_PYTHON_OCIO_DIR}/config.ocio")
message(WARNING "No file named config.ocio was found in the given OCIO directory.")
endif()
- install(DIRECTORY "${MATERIALX_PYTHON_OCIO_DIR}/" DESTINATION "python/MaterialX/config/" MESSAGE_NEVER)
+ install(DIRECTORY "${MATERIALX_PYTHON_OCIO_DIR}/" DESTINATION "${MATERIALX_PYTHON_FOLDER_NAME}/config/" MESSAGE_NEVER)
endif()
-if(MATERIALX_INSTALL_PYTHON AND PYTHON_EXECUTABLE)
- install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} ${SETUP_PY} install clean --all)" MESSAGE_NEVER)
+if(MATERIALX_INSTALL_PYTHON AND PYTHON_EXECUTABLE AND NOT SKBUILD)
+ set(SETUP_PY "${CMAKE_INSTALL_PREFIX}/python/setup.py")
+ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in" "${SETUP_PY}")
+ install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} ${SETUP_PY} install clean --all)")
endif()
diff --git a/python/MaterialX/_scripts/README.md b/python/MaterialX/_scripts/README.md
new file mode 100644
index 0000000000..f3586c5133
--- /dev/null
+++ b/python/MaterialX/_scripts/README.md
@@ -0,0 +1,2 @@
+This directory is empty buit it's used when packaging the Python library.
+the files in ../../Scripts will be copied inside.
diff --git a/python/MaterialX/_scripts/__init__.py b/python/MaterialX/_scripts/__init__.py
new file mode 100644
index 0000000000..1217aefc79
--- /dev/null
+++ b/python/MaterialX/_scripts/__init__.py
@@ -0,0 +1 @@
+# Only required for entry-points.
diff --git a/python/mtx_skbuild_plugin.py b/python/mtx_skbuild_plugin.py
new file mode 100644
index 0000000000..56de6a9f53
--- /dev/null
+++ b/python/mtx_skbuild_plugin.py
@@ -0,0 +1,90 @@
+"""
+This is a custom scikit-build-core plugin that will
+fetch the MaterialX version from the CMake project.
+"""
+import os
+import tempfile
+import subprocess
+from pathlib import Path
+from typing import FrozenSet, Dict, Optional, Union, List
+
+from scikit_build_core.file_api.query import stateless_query
+from scikit_build_core.file_api.reply import load_reply_dir
+
+
+def dynamic_metadata(
+ fields: FrozenSet[str],
+ settings: Optional[Dict[str, object]] = None,
+) -> Dict[str, Union[str, Dict[str, Optional[str]]]]:
+ print("mtx_skbuild_plugin: Computing MaterialX version from CMake...")
+
+ if fields != {"version"}:
+ msg = "Only the 'version' field is supported"
+ raise ValueError(msg)
+
+ if settings:
+ msg = "No inline configuration is supported"
+ raise ValueError(msg)
+
+ current_dir = os.path.dirname(__file__)
+
+ with tempfile.TemporaryDirectory() as tmpdir:
+ # We will use CMake's file API to get the version
+ # instead of parsing the CMakeLists files.
+
+ # First generate the query folder so that CMake can generate replies.
+ reply_dir = stateless_query(Path(tmpdir))
+
+ # Run cmake (configure). CMake will generate a reply automatically.
+ try:
+ subprocess.run(
+ [
+ "cmake",
+ "-S",
+ os.path.dirname(current_dir),
+ "-B",
+ tmpdir,
+ "-DMATERIALX_BUILD_SHARED_LIBS=OFF",
+ "-DMATERIALX_BUILD_PYTHON=OFF",
+ "-DMATERIALX_TEST_RENDER=OFF",
+ "-DMATERIALX_BUILD_TESTS=OFF",
+ "-DMATERIALX_INSTALL_PYTHON=OFF",
+ "-DMATERIALX_BUILD_RENDER=OFF",
+ ],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ check=True,
+ text=True,
+ )
+ except subprocess.CalledProcessError as exc:
+ print(exc.stdout)
+ raise RuntimeError(
+ "Failed to configure project to get the version"
+ ) from exc
+
+ # Get the generated replies.
+ index = load_reply_dir(reply_dir)
+
+ # Get the version from the CMAKE_PROJECT_VERSION variable.
+ entries = [
+ entry
+ for entry in index.reply.cache_v2.entries
+ if entry.name == "CMAKE_PROJECT_VERSION"
+ ]
+
+ if not entries:
+ raise ValueError("Could not find MaterialX version from CMake project")
+
+ if len(entries) > 1:
+ raise ValueError("More than one entry for CMAKE_PROJECT_VERSION found...")
+
+ version = entries[0].value
+ print("mtx_skbuild_plugin: Computed version: {0}".format(version))
+
+ return {"version": version}
+
+
+def get_requires_for_dynamic_metadata(
+ _settings: Optional[Dict[str, object]] = None,
+) -> List[str]:
+ return ["cmake"]
diff --git a/python/setup.py.in b/python/setup.py.in
index dfe67330c2..072bafa968 100644
--- a/python/setup.py.in
+++ b/python/setup.py.in
@@ -14,4 +14,5 @@ setup(name='MaterialX',
url='www.materialx.org',
version='${MATERIALX_MAJOR_VERSION}.${MATERIALX_MINOR_VERSION}.${MATERIALX_BUILD_VERSION}',
packages=['MaterialX'],
- package_data={'MaterialX' : getRecursivePackageData('MaterialX')})
+ package_data={'MaterialX' : getRecursivePackageData('MaterialX')},
+ zip_safe = False)
diff --git a/resources/CMakeLists.txt b/resources/CMakeLists.txt
index 5c1a433cf9..10212c95c2 100644
--- a/resources/CMakeLists.txt
+++ b/resources/CMakeLists.txt
@@ -1,2 +1,4 @@
-install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
- DESTINATION "resources" MESSAGE_NEVER)
+if(NOT SKBUILD)
+ install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
+ DESTINATION "resources" MESSAGE_NEVER)
+endif()
diff --git a/resources/Materials/TestSuite/stdlib/nodegraph_inputs/top_level_input.mtlx b/resources/Materials/TestSuite/stdlib/nodegraph_inputs/top_level_input.mtlx
new file mode 100644
index 0000000000..d92eae7f19
--- /dev/null
+++ b/resources/Materials/TestSuite/stdlib/nodegraph_inputs/top_level_input.mtlx
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/Materials/TestSuite/stdlib/organization/organization.mtlx b/resources/Materials/TestSuite/stdlib/organization/organization.mtlx
index 21154aecdd..0f4c024848 100644
--- a/resources/Materials/TestSuite/stdlib/organization/organization.mtlx
+++ b/resources/Materials/TestSuite/stdlib/organization/organization.mtlx
@@ -90,4 +90,14 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/Materials/TestSuite/stdlib/procedural/linepattern.mtlx b/resources/Materials/TestSuite/stdlib/procedural/linepattern.mtlx
new file mode 100644
index 0000000000..032abf129d
--- /dev/null
+++ b/resources/Materials/TestSuite/stdlib/procedural/linepattern.mtlx
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/Materials/TestSuite/stdlib/procedural/tiledshape.mtlx b/resources/Materials/TestSuite/stdlib/procedural/tiledshape.mtlx
new file mode 100644
index 0000000000..69fd225f2c
--- /dev/null
+++ b/resources/Materials/TestSuite/stdlib/procedural/tiledshape.mtlx
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/Materials/TestSuite/stdlib/texture/image_default.mtlx b/resources/Materials/TestSuite/stdlib/texture/image_default.mtlx
new file mode 100644
index 0000000000..89b99c3c39
--- /dev/null
+++ b/resources/Materials/TestSuite/stdlib/texture/image_default.mtlx
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/MaterialXCore/CMakeLists.txt b/source/MaterialXCore/CMakeLists.txt
index 37edf7929a..33e4fafdf4 100644
--- a/source/MaterialXCore/CMakeLists.txt
+++ b/source/MaterialXCore/CMakeLists.txt
@@ -1,25 +1,33 @@
+set(MATERIALX_MODULE_NAME MaterialXCore)
+
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Generated.h.in ${CMAKE_CURRENT_BINARY_DIR}/Generated.h)
file(GLOB materialx_source "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
file(GLOB materialx_headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h" "${CMAKE_CURRENT_BINARY_DIR}/*.h")
-add_library(MaterialXCore ${materialx_source} ${materialx_headers})
+add_library(${MATERIALX_MODULE_NAME} ${materialx_source} ${materialx_headers})
add_definitions(-DMATERIALX_CORE_EXPORTS)
+# Create version resource
+if(MATERIALX_BUILD_SHARED_LIBS AND MSVC)
+ configure_file(${CMAKE_SOURCE_DIR}/cmake/modules/MaterialXVersion.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
+ target_sources(${MATERIALX_MODULE_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
+endif()
+
set_target_properties(
- MaterialXCore PROPERTIES
- OUTPUT_NAME MaterialXCore${MATERIALX_LIBNAME_SUFFIX}
+ ${MATERIALX_MODULE_NAME} PROPERTIES
+ OUTPUT_NAME ${MATERIALX_MODULE_NAME}${MATERIALX_LIBNAME_SUFFIX}
COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS}"
LINK_FLAGS "${EXTERNAL_LINK_FLAGS}"
VERSION "${MATERIALX_LIBRARY_VERSION}"
SOVERSION "${MATERIALX_MAJOR_VERSION}")
target_link_libraries(
- MaterialXCore
+ ${MATERIALX_MODULE_NAME}
${CMAKE_DL_LIBS})
-target_include_directories(MaterialXCore
+target_include_directories(${MATERIALX_MODULE_NAME}
PUBLIC
$
$
@@ -27,14 +35,16 @@ target_include_directories(MaterialXCore
PRIVATE
${EXTERNAL_INCLUDE_DIRS})
-install(TARGETS MaterialXCore
- EXPORT MaterialX
- ARCHIVE DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
- LIBRARY DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
- RUNTIME DESTINATION bin)
+if(NOT SKBUILD)
+ install(TARGETS ${MATERIALX_MODULE_NAME}
+ EXPORT MaterialX
+ ARCHIVE DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
+ LIBRARY DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
+ RUNTIME DESTINATION bin)
-install(FILES ${materialx_headers}
- DESTINATION ${MATERIALX_INSTALL_INCLUDE_PATH}/MaterialXCore/)
+ install(FILES ${materialx_headers}
+ DESTINATION ${MATERIALX_INSTALL_INCLUDE_PATH}/${MATERIALX_MODULE_NAME}/)
-install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/MaterialXCore.pdb"
- DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${MATERIALX_MODULE_NAME}.pdb"
+ DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
+endif()
diff --git a/source/MaterialXCore/Definition.cpp b/source/MaterialXCore/Definition.cpp
index 5ec7044325..cf9587ecda 100644
--- a/source/MaterialXCore/Definition.cpp
+++ b/source/MaterialXCore/Definition.cpp
@@ -72,17 +72,29 @@ InterfaceElementPtr NodeDef::getImplementation(const string& target) const
const TargetDefPtr targetDef = getDocument()->getTargetDef(target);
const StringVec candidateTargets = targetDef ? targetDef->getMatchingTargets() : StringVec();
- // Search the candidate targets in order
+ // First, search for a target-specific match.
for (const string& candidateTarget : candidateTargets)
{
for (InterfaceElementPtr interface : interfaces)
{
- if (targetStringsMatch(interface->getTarget(), candidateTarget))
+ const std::string& interfaceTarget = interface->getTarget();
+ if (!interfaceTarget.empty() && targetStringsMatch(interfaceTarget, candidateTarget))
{
return interface;
}
}
}
+
+ // Then search for a generic match.
+ for (InterfaceElementPtr interface : interfaces)
+ {
+ // Look for interfaces without targets
+ const std::string& interfaceTarget = interface->getTarget();
+ if (interfaceTarget.empty())
+ {
+ return interface;
+ }
+ }
return InterfaceElementPtr();
}
diff --git a/source/MaterialXCore/Document.cpp b/source/MaterialXCore/Document.cpp
index 46d0552250..79297fa5a9 100644
--- a/source/MaterialXCore/Document.cpp
+++ b/source/MaterialXCore/Document.cpp
@@ -124,6 +124,7 @@ class Document::Cache
for (ElementPtr elem : doc.lock()->traverseTree())
{
const string& nodeName = elem->getAttribute(PortElement::NODE_NAME_ATTRIBUTE);
+ const string& nodeGraphName = elem->getAttribute(PortElement::NODE_GRAPH_ATTRIBUTE);
const string& nodeString = elem->getAttribute(NodeDef::NODE_ATTRIBUTE);
const string& nodeDefString = elem->getAttribute(InterfaceElement::NODE_DEF_ATTRIBUTE);
@@ -135,6 +136,17 @@ class Document::Cache
portElementMap.emplace(portElem->getQualifiedName(nodeName), portElem);
}
}
+ else
+ {
+ if (!nodeGraphName.empty())
+ {
+ PortElementPtr portElem = elem->asA();
+ if (portElem)
+ {
+ portElementMap.emplace(portElem->getQualifiedName(nodeGraphName), portElem);
+ }
+ }
+ }
if (!nodeString.empty())
{
NodeDefPtr nodeDef = elem->asA();
diff --git a/source/MaterialXCore/Element.h b/source/MaterialXCore/Element.h
index 8e43d9aa33..0e00bf596a 100644
--- a/source/MaterialXCore/Element.h
+++ b/source/MaterialXCore/Element.h
@@ -300,7 +300,7 @@ class MX_CORE_API Element : public std::enable_shared_from_this
/// Return the element, if any, that this one directly inherits from.
ElementPtr getInheritsFrom() const
{
- return resolveNameReference(getInheritString());
+ return hasInheritString() ? resolveNameReference(getInheritString()) : nullptr;
}
/// Return true if this element has the given element as an inherited base,
@@ -739,13 +739,13 @@ class MX_CORE_API Element : public std::enable_shared_from_this
void copyContentFrom(const ConstElementPtr& source);
/// Clear all attributes and descendants from this element.
- void clearContent();
+ virtual void clearContent();
/// Using the input name as a starting point, modify it to create a valid,
/// unique name for a child element.
string createValidChildName(string name) const
{
- name = createValidName(name);
+ name = name.empty() ? "_" : createValidName(name);
while (_childMap.count(name))
{
name = incrementName(name);
diff --git a/source/MaterialXCore/Interface.cpp b/source/MaterialXCore/Interface.cpp
index 3a93a384c2..65570ab6b6 100644
--- a/source/MaterialXCore/Interface.cpp
+++ b/source/MaterialXCore/Interface.cpp
@@ -305,7 +305,7 @@ InputPtr Input::getInterfaceInput() const
{
if (hasInterfaceName())
{
- ConstNodeGraphPtr graph = getAncestorOfType();
+ ConstGraphElementPtr graph = getAncestorOfType();
if (graph)
{
return graph->getInput(getInterfaceName());
@@ -611,6 +611,13 @@ ConstInterfaceElementPtr InterfaceElement::getDeclaration(const string&) const
return InterfaceElementPtr();
}
+void InterfaceElement::clearContent()
+{
+ _inputCount = 0;
+ _outputCount = 0;
+ TypedElement::clearContent();
+}
+
bool InterfaceElement::hasExactInputMatch(ConstInterfaceElementPtr declaration, string* message) const
{
for (InputPtr input : getActiveInputs())
diff --git a/source/MaterialXCore/Interface.h b/source/MaterialXCore/Interface.h
index 94f6eddbaa..0773d5f836 100644
--- a/source/MaterialXCore/Interface.h
+++ b/source/MaterialXCore/Interface.h
@@ -639,6 +639,9 @@ class MX_CORE_API InterfaceElement : public TypedElement
/// no declaration was found.
virtual ConstInterfaceElementPtr getDeclaration(const string& target = EMPTY_STRING) const;
+ /// Clear all attributes and descendants from this element.
+ void clearContent() override;
+
/// Return true if this instance has an exact input match with the given
/// declaration, where each input of this the instance corresponds to a
/// declaration input of the same name and type.
diff --git a/source/MaterialXCore/Node.cpp b/source/MaterialXCore/Node.cpp
index 45524b116d..9596d905bc 100644
--- a/source/MaterialXCore/Node.cpp
+++ b/source/MaterialXCore/Node.cpp
@@ -439,9 +439,7 @@ vector GraphElement::topologicalSort() const
}
}
- size_t visitCount = 0;
vector result;
-
while (!childQueue.empty())
{
// Pop the queue and add to topological order.
@@ -467,14 +465,6 @@ vector GraphElement::topologicalSort() const
}
}
}
-
- visitCount++;
- }
-
- // Check if there was a cycle.
- if (visitCount != children.size())
- {
- throw ExceptionFoundCycle("Encountered a cycle in graph: " + getName());
}
return result;
@@ -738,6 +728,25 @@ InterfaceElementPtr NodeGraph::getImplementation() const
return nodedef ? nodedef->getImplementation() : InterfaceElementPtr();
}
+vector NodeGraph::getDownstreamPorts() const
+{
+ vector downstreamPorts;
+ for (PortElementPtr port : getDocument()->getMatchingPorts(getQualifiedName(getName())))
+ {
+ ElementPtr node = port->getParent();
+ ElementPtr graph = node ? node->getParent() : nullptr;
+ if (graph && graph->isA() && graph == getParent())
+ {
+ downstreamPorts.push_back(port);
+ }
+ }
+ std::sort(downstreamPorts.begin(), downstreamPorts.end(), [](const ConstElementPtr& a, const ConstElementPtr& b)
+ {
+ return a->getName() > b->getName();
+ });
+ return downstreamPorts;
+}
+
bool NodeGraph::validate(string* message) const
{
bool res = true;
diff --git a/source/MaterialXCore/Node.h b/source/MaterialXCore/Node.h
index a316b0eb6c..55846cf2e3 100644
--- a/source/MaterialXCore/Node.h
+++ b/source/MaterialXCore/Node.h
@@ -308,7 +308,6 @@ class MX_CORE_API GraphElement : public InterfaceElement
/// Return a vector of all children (nodes and outputs) sorted in
/// topological order.
- /// @throws ExceptionFoundCycle if a cycle is encountered.
vector topologicalSort() const;
/// If not yet present, add a geometry node to this graph matching the given property
@@ -358,6 +357,14 @@ class MX_CORE_API NodeGraph : public GraphElement
/// none was found.
InterfaceElementPtr getImplementation() const;
+ /// @}
+ /// @name Traversal
+ /// @{
+
+ /// Return a vector of all downstream ports that connect to this graph, ordered by
+ /// the names of the port elements.
+ vector getDownstreamPorts() const;
+
/// @}
/// @name Utility
/// @{
diff --git a/source/MaterialXCore/Types.h b/source/MaterialXCore/Types.h
index 68f477ee04..5c64d0950a 100644
--- a/source/MaterialXCore/Types.h
+++ b/source/MaterialXCore/Types.h
@@ -592,9 +592,9 @@ class MX_CORE_API Matrix33 : public MatrixN
float m20, float m21, float m22) :
MatrixN(Uninit{})
{
- _arr = { m00, m01, m02,
- m10, m11, m12,
- m20, m21, m22 };
+ _arr = { RowArray{ m00, m01, m02 },
+ RowArray{ m10, m11, m12 },
+ RowArray{ m20, m21, m22 } };
}
/// @name Matrix Operations
@@ -663,10 +663,10 @@ class MX_CORE_API Matrix44 : public MatrixN
float m30, float m31, float m32, float m33) :
MatrixN(Uninit{})
{
- _arr = { m00, m01, m02, m03,
- m10, m11, m12, m13,
- m20, m21, m22, m23,
- m30, m31, m32, m33 };
+ _arr = { RowArray{ m00, m01, m02, m03 },
+ RowArray{ m10, m11, m12, m13 },
+ RowArray{ m20, m21, m22, m23 },
+ RowArray{ m30, m31, m32, m33 } };
}
/// @name Matrix Operations
diff --git a/source/MaterialXFormat/CMakeLists.txt b/source/MaterialXFormat/CMakeLists.txt
index 940ef9662c..420149bae4 100644
--- a/source/MaterialXFormat/CMakeLists.txt
+++ b/source/MaterialXFormat/CMakeLists.txt
@@ -1,16 +1,24 @@
+set(MATERIALX_MODULE_NAME MaterialXFormat)
+
file(GLOB_RECURSE materialx_source "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
file(GLOB_RECURSE materialx_headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h*")
assign_source_group("Source Files" ${materialx_source})
assign_source_group("Header Files" ${materialx_headers})
-add_library(MaterialXFormat ${materialx_source} ${materialx_headers})
+add_library(${MATERIALX_MODULE_NAME} ${materialx_source} ${materialx_headers})
add_definitions(-DMATERIALX_FORMAT_EXPORTS)
+# Create version resource
+if(MATERIALX_BUILD_SHARED_LIBS AND MSVC)
+ configure_file(${CMAKE_SOURCE_DIR}/cmake/modules/MaterialXVersion.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
+ target_sources(${MATERIALX_MODULE_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
+endif()
+
set_target_properties(
- MaterialXFormat PROPERTIES
- OUTPUT_NAME MaterialXFormat${MATERIALX_LIBNAME_SUFFIX}
+ ${MATERIALX_MODULE_NAME} PROPERTIES
+ OUTPUT_NAME ${MATERIALX_MODULE_NAME}${MATERIALX_LIBNAME_SUFFIX}
COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS}"
LINK_FLAGS "${EXTERNAL_LINK_FLAGS}"
INSTALL_RPATH "${MATERIALX_SAME_DIR_RPATH}"
@@ -18,26 +26,28 @@ set_target_properties(
SOVERSION "${MATERIALX_MAJOR_VERSION}")
target_link_libraries(
- MaterialXFormat
+ ${MATERIALX_MODULE_NAME}
MaterialXCore
${CMAKE_DL_LIBS})
-target_include_directories(MaterialXFormat
+target_include_directories(${MATERIALX_MODULE_NAME}
PUBLIC
$
$
PRIVATE
${EXTERNAL_INCLUDE_DIRS})
-install(TARGETS MaterialXFormat
- EXPORT MaterialX
- ARCHIVE DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
- LIBRARY DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
- RUNTIME DESTINATION bin)
+if(NOT SKBUILD)
+ install(TARGETS ${MATERIALX_MODULE_NAME}
+ EXPORT MaterialX
+ ARCHIVE DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
+ LIBRARY DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
+ RUNTIME DESTINATION bin)
-install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/"
- DESTINATION ${MATERIALX_INSTALL_INCLUDE_PATH}/MaterialXFormat/ MESSAGE_NEVER
- FILES_MATCHING PATTERN "*.h*")
+ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/"
+ DESTINATION ${MATERIALX_INSTALL_INCLUDE_PATH}/${MATERIALX_MODULE_NAME}/ MESSAGE_NEVER
+ FILES_MATCHING PATTERN "*.h*")
-install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/MaterialXFormat.pdb"
- DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${MATERIALX_MODULE_NAME}.pdb"
+ DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
+endif()
diff --git a/source/MaterialXGenGlsl/CMakeLists.txt b/source/MaterialXGenGlsl/CMakeLists.txt
index 2ddcb5475c..da497f9f88 100644
--- a/source/MaterialXGenGlsl/CMakeLists.txt
+++ b/source/MaterialXGenGlsl/CMakeLists.txt
@@ -1,16 +1,24 @@
+set(MATERIALX_MODULE_NAME MaterialXGenGlsl)
+
file(GLOB_RECURSE materialx_source "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
file(GLOB_RECURSE materialx_headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h*")
assign_source_group("Source Files" ${materialx_source})
assign_source_group("Header Files" ${materialx_headers})
-add_library(MaterialXGenGlsl ${materialx_source} ${materialx_headers})
+add_library(${MATERIALX_MODULE_NAME} ${materialx_source} ${materialx_headers})
add_definitions(-DMATERIALX_GENGLSL_EXPORTS)
+# Create version resource
+if(MATERIALX_BUILD_SHARED_LIBS AND MSVC)
+ configure_file(${CMAKE_SOURCE_DIR}/cmake/modules/MaterialXVersion.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
+ target_sources(${MATERIALX_MODULE_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
+endif()
+
set_target_properties(
- MaterialXGenGlsl PROPERTIES
- OUTPUT_NAME MaterialXGenGlsl${MATERIALX_LIBNAME_SUFFIX}
+ ${MATERIALX_MODULE_NAME} PROPERTIES
+ OUTPUT_NAME ${MATERIALX_MODULE_NAME}${MATERIALX_LIBNAME_SUFFIX}
COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS}"
LINK_FLAGS "${EXTERNAL_LINK_FLAGS}"
INSTALL_RPATH "${MATERIALX_SAME_DIR_RPATH}"
@@ -18,27 +26,29 @@ set_target_properties(
SOVERSION "${MATERIALX_MAJOR_VERSION}")
target_link_libraries(
- MaterialXGenGlsl
+ ${MATERIALX_MODULE_NAME}
MaterialXGenShader
MaterialXCore
${CMAKE_DL_LIBS})
-target_include_directories(MaterialXGenGlsl
+target_include_directories(${MATERIALX_MODULE_NAME}
PUBLIC
$
$
PRIVATE
${EXTERNAL_INCLUDE_DIRS})
-install(TARGETS MaterialXGenGlsl
- EXPORT MaterialX
- ARCHIVE DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
- LIBRARY DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
- RUNTIME DESTINATION bin)
+if(NOT SKBUILD)
+ install(TARGETS ${MATERIALX_MODULE_NAME}
+ EXPORT MaterialX
+ ARCHIVE DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
+ LIBRARY DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
+ RUNTIME DESTINATION bin)
-install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/"
- DESTINATION ${MATERIALX_INSTALL_INCLUDE_PATH}/MaterialXGenGlsl/ MESSAGE_NEVER
- FILES_MATCHING PATTERN "*.h*")
+ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/"
+ DESTINATION ${MATERIALX_INSTALL_INCLUDE_PATH}/${MATERIALX_MODULE_NAME}/ MESSAGE_NEVER
+ FILES_MATCHING PATTERN "*.h*")
-install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/MaterialXGenGlsl.pdb"
- DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${MATERIALX_MODULE_NAME}.pdb"
+ DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
+endif()
diff --git a/source/MaterialXGenMdl/CMakeLists.txt b/source/MaterialXGenMdl/CMakeLists.txt
index b73e674b7f..d9991843ce 100644
--- a/source/MaterialXGenMdl/CMakeLists.txt
+++ b/source/MaterialXGenMdl/CMakeLists.txt
@@ -1,16 +1,24 @@
+set(MATERIALX_MODULE_NAME MaterialXGenMdl)
+
file(GLOB_RECURSE materialx_source "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
file(GLOB_RECURSE materialx_headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h*")
assign_source_group("Source Files" ${materialx_source})
assign_source_group("Header Files" ${materialx_headers})
-add_library(MaterialXGenMdl ${materialx_source} ${materialx_headers})
+add_library(${MATERIALX_MODULE_NAME} ${materialx_source} ${materialx_headers})
add_definitions(-DMATERIALX_GENMDL_EXPORTS)
+# Create version resource
+if(MATERIALX_BUILD_SHARED_LIBS AND MSVC)
+ configure_file(${CMAKE_SOURCE_DIR}/cmake/modules/MaterialXVersion.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
+ target_sources(${MATERIALX_MODULE_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
+endif()
+
set_target_properties(
- MaterialXGenMdl PROPERTIES
- OUTPUT_NAME MaterialXGenMdl${MATERIALX_LIBNAME_SUFFIX}
+ ${MATERIALX_MODULE_NAME} PROPERTIES
+ OUTPUT_NAME ${MATERIALX_MODULE_NAME}${MATERIALX_LIBNAME_SUFFIX}
COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS}"
LINK_FLAGS "${EXTERNAL_LINK_FLAGS}"
INSTALL_RPATH "${MATERIALX_SAME_DIR_RPATH}"
@@ -18,30 +26,32 @@ set_target_properties(
SOVERSION "${MATERIALX_MAJOR_VERSION}")
target_link_libraries(
- MaterialXGenMdl
+ ${MATERIALX_MODULE_NAME}
MaterialXGenShader
MaterialXCore
${CMAKE_DL_LIBS})
-target_include_directories(MaterialXGenMdl
+target_include_directories(${MATERIALX_MODULE_NAME}
PUBLIC
$
$
PRIVATE
${EXTERNAL_INCLUDE_DIRS})
-install(TARGETS MaterialXGenMdl
- EXPORT MaterialX
- ARCHIVE DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
- LIBRARY DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
- RUNTIME DESTINATION bin)
+if(NOT SKBUILD)
+ install(TARGETS ${MATERIALX_MODULE_NAME}
+ EXPORT MaterialX
+ ARCHIVE DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
+ LIBRARY DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
+ RUNTIME DESTINATION bin)
-install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/"
- DESTINATION ${MATERIALX_INSTALL_INCLUDE_PATH}/MaterialXGenMdl/ MESSAGE_NEVER
- FILES_MATCHING PATTERN "*.h*")
+ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/"
+ DESTINATION ${MATERIALX_INSTALL_INCLUDE_PATH}/${MATERIALX_MODULE_NAME}/ MESSAGE_NEVER
+ FILES_MATCHING PATTERN "*.h*")
-install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/mdl
- DESTINATION "${MATERIALX_INSTALL_MDL_MODULE_PATH}")
+ install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/mdl
+ DESTINATION "${MATERIALX_INSTALL_MDL_MODULE_PATH}")
-install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/MaterialXGenMdl.pdb"
- DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${MATERIALX_MODULE_NAME}.pdb"
+ DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
+endif()
diff --git a/source/MaterialXGenMsl/CMakeLists.txt b/source/MaterialXGenMsl/CMakeLists.txt
index 31d2599531..8d6d009f50 100644
--- a/source/MaterialXGenMsl/CMakeLists.txt
+++ b/source/MaterialXGenMsl/CMakeLists.txt
@@ -1,16 +1,24 @@
+set(MATERIALX_MODULE_NAME MaterialXGenMsl)
+
file(GLOB_RECURSE materialx_source "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
file(GLOB_RECURSE materialx_headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h*")
assign_source_group("Source Files" ${materialx_source})
assign_source_group("Header Files" ${materialx_headers})
-add_library(MaterialXGenMsl ${materialx_source} ${materialx_headers})
+add_library(${MATERIALX_MODULE_NAME} ${materialx_source} ${materialx_headers})
add_definitions(-DMATERIALX_GENMSL_EXPORTS)
+# Create version resource
+if(MATERIALX_BUILD_SHARED_LIBS AND MSVC)
+ configure_file(${CMAKE_SOURCE_DIR}/cmake/modules/MaterialXVersion.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
+ target_sources(${MATERIALX_MODULE_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
+endif()
+
set_target_properties(
- MaterialXGenMsl PROPERTIES
- OUTPUT_NAME MaterialXGenMsl${MATERIALX_LIBNAME_SUFFIX}
+ ${MATERIALX_MODULE_NAME} PROPERTIES
+ OUTPUT_NAME ${MATERIALX_MODULE_NAME}${MATERIALX_LIBNAME_SUFFIX}
COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS}"
LINK_FLAGS "${EXTERNAL_LINK_FLAGS}"
INSTALL_RPATH "${MATERIALX_SAME_DIR_RPATH}"
@@ -18,27 +26,29 @@ set_target_properties(
SOVERSION "${MATERIALX_MAJOR_VERSION}")
target_link_libraries(
- MaterialXGenMsl
+ ${MATERIALX_MODULE_NAME}
MaterialXGenShader
MaterialXCore
${CMAKE_DL_LIBS})
-target_include_directories(MaterialXGenMsl
+target_include_directories(${MATERIALX_MODULE_NAME}
PUBLIC
$
$
PRIVATE
${EXTERNAL_INCLUDE_DIRS})
-install(TARGETS MaterialXGenMsl
- EXPORT MaterialX
- ARCHIVE DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
- LIBRARY DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
- RUNTIME DESTINATION bin)
+if(NOT SKBUILD)
+ install(TARGETS ${MATERIALX_MODULE_NAME}
+ EXPORT MaterialX
+ ARCHIVE DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
+ LIBRARY DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
+ RUNTIME DESTINATION bin)
-install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/"
- DESTINATION ${MATERIALX_INSTALL_INCLUDE_PATH}/MaterialXGenMsl/ MESSAGE_NEVER
- FILES_MATCHING PATTERN "*.h*")
+ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/"
+ DESTINATION ${MATERIALX_INSTALL_INCLUDE_PATH}/${MATERIALX_MODULE_NAME}/ MESSAGE_NEVER
+ FILES_MATCHING PATTERN "*.h*")
-install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/MaterialXGenMsl.pdb"
- DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${MATERIALX_MODULE_NAME}.pdb"
+ DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
+endif()
diff --git a/source/MaterialXGenMsl/MslShaderGenerator.cpp b/source/MaterialXGenMsl/MslShaderGenerator.cpp
index 61a1c8f572..dcb0a3ed69 100644
--- a/source/MaterialXGenMsl/MslShaderGenerator.cpp
+++ b/source/MaterialXGenMsl/MslShaderGenerator.cpp
@@ -43,6 +43,8 @@
#include "MslResourceBindingContext.h"
+#include
+
MATERIALX_NAMESPACE_BEGIN
const string MslShaderGenerator::TARGET = "genmsl";
diff --git a/source/MaterialXGenOsl/CMakeLists.txt b/source/MaterialXGenOsl/CMakeLists.txt
index 03e30de0c1..3cf7b93438 100644
--- a/source/MaterialXGenOsl/CMakeLists.txt
+++ b/source/MaterialXGenOsl/CMakeLists.txt
@@ -1,16 +1,24 @@
+set(MATERIALX_MODULE_NAME MaterialXGenOsl)
+
file(GLOB_RECURSE materialx_source "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
file(GLOB_RECURSE materialx_headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h*")
assign_source_group("Source Files" ${materialx_source})
assign_source_group("Header Files" ${materialx_headers})
-add_library(MaterialXGenOsl ${materialx_source} ${materialx_headers})
+add_library(${MATERIALX_MODULE_NAME} ${materialx_source} ${materialx_headers})
add_definitions(-DMATERIALX_GENOSL_EXPORTS)
+# Create version resource
+if(MATERIALX_BUILD_SHARED_LIBS AND MSVC)
+ configure_file(${CMAKE_SOURCE_DIR}/cmake/modules/MaterialXVersion.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
+ target_sources(${MATERIALX_MODULE_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
+endif()
+
set_target_properties(
- MaterialXGenOsl PROPERTIES
- OUTPUT_NAME MaterialXGenOsl${MATERIALX_LIBNAME_SUFFIX}
+ ${MATERIALX_MODULE_NAME} PROPERTIES
+ OUTPUT_NAME ${MATERIALX_MODULE_NAME}${MATERIALX_LIBNAME_SUFFIX}
COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS}"
LINK_FLAGS "${EXTERNAL_LINK_FLAGS}"
INSTALL_RPATH "${MATERIALX_SAME_DIR_RPATH}"
@@ -18,28 +26,29 @@ set_target_properties(
SOVERSION "${MATERIALX_MAJOR_VERSION}")
target_link_libraries(
- MaterialXGenOsl
+ ${MATERIALX_MODULE_NAME}
MaterialXGenShader
MaterialXCore
${CMAKE_DL_LIBS})
-target_include_directories(MaterialXGenOsl
+target_include_directories(${MATERIALX_MODULE_NAME}
PUBLIC
$
$
PRIVATE
${EXTERNAL_INCLUDE_DIRS})
-install(TARGETS MaterialXGenOsl
- EXPORT MaterialX
- ARCHIVE DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
- LIBRARY DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
- RUNTIME DESTINATION bin)
-
-install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/"
- DESTINATION ${MATERIALX_INSTALL_INCLUDE_PATH}/MaterialXGenOsl/ MESSAGE_NEVER
- FILES_MATCHING PATTERN "*.h*")
+if(NOT SKBUILD)
+ install(TARGETS ${MATERIALX_MODULE_NAME}
+ EXPORT MaterialX
+ ARCHIVE DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
+ LIBRARY DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
+ RUNTIME DESTINATION bin)
-install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/MaterialXGenOsl.pdb"
- DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
+ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/"
+ DESTINATION ${MATERIALX_INSTALL_INCLUDE_PATH}/${MATERIALX_MODULE_NAME}/ MESSAGE_NEVER
+ FILES_MATCHING PATTERN "*.h*")
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${MATERIALX_MODULE_NAME}.pdb"
+ DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
+endif()
diff --git a/source/MaterialXGenShader/CMakeLists.txt b/source/MaterialXGenShader/CMakeLists.txt
index 231dda6e5c..1b9533e0a5 100644
--- a/source/MaterialXGenShader/CMakeLists.txt
+++ b/source/MaterialXGenShader/CMakeLists.txt
@@ -1,16 +1,24 @@
+set(MATERIALX_MODULE_NAME MaterialXGenShader)
+
file(GLOB_RECURSE materialx_source "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
file(GLOB_RECURSE materialx_headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h*")
assign_source_group("Source Files" ${materialx_source})
assign_source_group("Header Files" ${materialx_headers})
-add_library(MaterialXGenShader ${materialx_source} ${materialx_headers})
+add_library(${MATERIALX_MODULE_NAME} ${materialx_source} ${materialx_headers})
add_definitions(-DMATERIALX_GENSHADER_EXPORTS)
+# Create version resource
+if(MATERIALX_BUILD_SHARED_LIBS AND MSVC)
+ configure_file(${CMAKE_SOURCE_DIR}/cmake/modules/MaterialXVersion.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
+ target_sources(${MATERIALX_MODULE_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
+endif()
+
set_target_properties(
- MaterialXGenShader PROPERTIES
- OUTPUT_NAME MaterialXGenShader${MATERIALX_LIBNAME_SUFFIX}
+ ${MATERIALX_MODULE_NAME} PROPERTIES
+ OUTPUT_NAME ${MATERIALX_MODULE_NAME}${MATERIALX_LIBNAME_SUFFIX}
COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS}"
LINK_FLAGS "${EXTERNAL_LINK_FLAGS}"
INSTALL_RPATH "${MATERIALX_SAME_DIR_RPATH}"
@@ -18,30 +26,32 @@ set_target_properties(
SOVERSION "${MATERIALX_MAJOR_VERSION}")
target_link_libraries(
- MaterialXGenShader
+ ${MATERIALX_MODULE_NAME}
MaterialXCore
MaterialXFormat
${CMAKE_DL_LIBS})
-target_include_directories(MaterialXGenShader
+target_include_directories(${MATERIALX_MODULE_NAME}
PUBLIC
$
$
PRIVATE
${EXTERNAL_INCLUDE_DIRS})
-install(TARGETS MaterialXGenShader
- EXPORT MaterialX
- ARCHIVE DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
- LIBRARY DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
- RUNTIME DESTINATION bin)
+if(NOT SKBUILD)
+ install(TARGETS ${MATERIALX_MODULE_NAME}
+ EXPORT MaterialX
+ ARCHIVE DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
+ LIBRARY DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
+ RUNTIME DESTINATION bin)
-install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/"
- DESTINATION ${MATERIALX_INSTALL_INCLUDE_PATH}/MaterialXGenShader/ MESSAGE_NEVER
- FILES_MATCHING PATTERN "*.h*")
+ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/"
+ DESTINATION ${MATERIALX_INSTALL_INCLUDE_PATH}/${MATERIALX_MODULE_NAME}/ MESSAGE_NEVER
+ FILES_MATCHING PATTERN "*.h*")
-install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/MaterialXGenShader.pdb"
- DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${MATERIALX_MODULE_NAME}.pdb"
+ DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
-install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../../resources"
- DESTINATION . MESSAGE_NEVER)
+ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../../resources"
+ DESTINATION . MESSAGE_NEVER)
+endif()
diff --git a/source/MaterialXGenShader/ShaderGraph.cpp b/source/MaterialXGenShader/ShaderGraph.cpp
index e6ad6eca29..8482659b34 100644
--- a/source/MaterialXGenShader/ShaderGraph.cpp
+++ b/source/MaterialXGenShader/ShaderGraph.cpp
@@ -1027,48 +1027,16 @@ void ShaderGraph::optimize(GenContext& context)
}
else if (node->hasClassification(ShaderNode::Classification::DOT))
{
- // Dot nodes without modifiers can be elided by moving their connection downstream.
+ // Filename dot nodes must be elided so they do not create extra samplers.
ShaderInput* in = node->getInput("in");
- if (in->getChannels().empty())
+ if (in->getChannels().empty() && in->getType() == Type::FILENAME)
{
bypass(context, node, 0);
++numEdits;
}
}
- else if (node->hasClassification(ShaderNode::Classification::IFELSE))
- {
- // Check if we have a constant conditional expression
- ShaderInput* intest = node->getInput("intest");
- if (!intest->getConnection())
- {
- // Find which branch should be taken
- ShaderInput* cutoff = node->getInput("cutoff");
- ValuePtr value = intest->getValue();
- const float intestValue = value ? value->asA() : 0.0f;
- const int branch = (intestValue <= cutoff->getValue()->asA() ? 2 : 3);
-
- // Bypass the conditional using the taken branch
- bypass(context, node, branch);
-
- ++numEdits;
- }
- }
- else if (node->hasClassification(ShaderNode::Classification::SWITCH))
- {
- // Check if we have a constant conditional expression
- const ShaderInput* which = node->getInput("which");
- if (!which->getConnection())
- {
- // Find which branch should be taken
- ValuePtr value = which->getValue();
- const int branch = int(value == nullptr ? 0 : (which->getType() == Type::FLOAT ? value->asA() : value->asA()));
-
- // Bypass the conditional using the taken branch
- bypass(context, node, branch);
-
- ++numEdits;
- }
- }
+ // Adding more nodes here requires them to have an input that is tagged
+ // "uniform" in the NodeDef or to handle very specific cases, like FILENAME.
}
if (numEdits > 0)
@@ -1225,12 +1193,6 @@ void ShaderGraph::topologicalSort()
}
}
}
-
- // Check if there was a cycle.
- if (count != _nodeMap.size())
- {
- throw ExceptionFoundCycle("Encountered a cycle in graph: " + getName());
- }
}
void ShaderGraph::setVariableNames(GenContext& context)
diff --git a/source/MaterialXGenShader/ShaderGraph.h b/source/MaterialXGenShader/ShaderGraph.h
index 4e30c4ae66..4117599c27 100644
--- a/source/MaterialXGenShader/ShaderGraph.h
+++ b/source/MaterialXGenShader/ShaderGraph.h
@@ -103,7 +103,6 @@ class MX_GENSHADER_API ShaderGraph : public ShaderNode
void addDefaultGeomNode(ShaderInput* input, const GeomPropDef& geomprop, GenContext& context);
/// Sort the nodes in topological order.
- /// @throws ExceptionFoundCycle if a cycle is encountered.
void topologicalSort();
/// Return an iterator for traversal upstream from the given output
diff --git a/source/MaterialXGenShader/ShaderNode.cpp b/source/MaterialXGenShader/ShaderNode.cpp
index c923e4be57..04551cb6d2 100644
--- a/source/MaterialXGenShader/ShaderNode.cpp
+++ b/source/MaterialXGenShader/ShaderNode.cpp
@@ -135,8 +135,6 @@ const ShaderNodePtr ShaderNode::NONE = createEmptyNode();
const string ShaderNode::CONSTANT = "constant";
const string ShaderNode::DOT = "dot";
const string ShaderNode::IMAGE = "image";
-const string ShaderNode::COMPARE = "compare";
-const string ShaderNode::SWITCH = "switch";
const string ShaderNode::SURFACESHADER = "surfaceshader";
const string ShaderNode::SCATTER_MODE = "scatter_mode";
const string ShaderNode::BSDF_R = "R";
@@ -292,14 +290,6 @@ ShaderNodePtr ShaderNode::create(const ShaderGraph* parent, const string& name,
{
newNode->_classification = Classification::TEXTURE | Classification::DOT;
}
- else if (nodeDef.getNodeString() == COMPARE)
- {
- newNode->_classification = Classification::TEXTURE | Classification::CONDITIONAL | Classification::IFELSE;
- }
- else if (nodeDef.getNodeString() == SWITCH)
- {
- newNode->_classification = Classification::TEXTURE | Classification::CONDITIONAL | Classification::SWITCH;
- }
// Third, check for file texture classification by group name
else if (groupName == TEXTURE2D_GROUPNAME || groupName == TEXTURE3D_GROUPNAME)
{
@@ -381,7 +371,17 @@ void ShaderNode::initialize(const Node& node, const NodeDef& nodeDef, GenContext
ShaderInput* input = getInput(nodeValue->getName());
if (input)
{
- input->setPath(nodeValue->getNamePath());
+ string path = nodeValue->getNamePath();
+ InputPtr nodeInput = nodeValue->asA();
+ if (nodeInput)
+ {
+ InputPtr interfaceInput = nodeInput->getInterfaceInput();
+ if (interfaceInput)
+ {
+ path = interfaceInput->getNamePath();
+ }
+ }
+ input->setPath(path);
}
}
diff --git a/source/MaterialXGenShader/ShaderNode.h b/source/MaterialXGenShader/ShaderNode.h
index 30e3ab6d59..536e0adc1e 100644
--- a/source/MaterialXGenShader/ShaderNode.h
+++ b/source/MaterialXGenShader/ShaderNode.h
@@ -350,14 +350,11 @@ class MX_GENSHADER_API ShaderNode
static const uint32_t VOLUME = 1 << 15; /// A volume shader node
static const uint32_t LIGHT = 1 << 16; /// A light shader node
static const uint32_t UNLIT = 1 << 17; /// An unlit surface shader node
- // Specific conditional types
- static const uint32_t IFELSE = 1 << 18; /// An if-else statement
- static const uint32_t SWITCH = 1 << 19; /// A switch statement
// Types based on nodegroup
- static const uint32_t SAMPLE2D = 1 << 20; /// Can be sampled in 2D (uv space)
- static const uint32_t SAMPLE3D = 1 << 21; /// Can be sampled in 3D (position)
- static const uint32_t GEOMETRIC = 1 << 22; /// Geometric input
- static const uint32_t DOT = 1 << 23; /// A dot node
+ static const uint32_t SAMPLE2D = 1 << 18; /// Can be sampled in 2D (uv space)
+ static const uint32_t SAMPLE3D = 1 << 19; /// Can be sampled in 3D (position)
+ static const uint32_t GEOMETRIC = 1 << 20; /// Geometric input
+ static const uint32_t DOT = 1 << 21; /// A dot node
};
static const ShaderNodePtr NONE;
@@ -365,8 +362,6 @@ class MX_GENSHADER_API ShaderNode
static const string CONSTANT;
static const string DOT;
static const string IMAGE;
- static const string COMPARE;
- static const string SWITCH;
static const string SURFACESHADER;
static const string SCATTER_MODE;
static const string BSDF_R;
diff --git a/source/MaterialXGraphEditor/Graph.cpp b/source/MaterialXGraphEditor/Graph.cpp
index 9e3fbccc40..2b28317ee2 100644
--- a/source/MaterialXGraphEditor/Graph.cpp
+++ b/source/MaterialXGraphEditor/Graph.cpp
@@ -17,13 +17,13 @@
namespace
{
-// the default node size is based off the of the size of the dot_color3 node using ed::getNodeSize() on that node
+// Based on the dimensions of the dot_color3 node, computed by calling ed::getNodeSize
const ImVec2 DEFAULT_NODE_SIZE = ImVec2(138, 116);
const int DEFAULT_ALPHA = 255;
const int FILTER_ALPHA = 50;
-// Function based off ImRect_Expanded function from ImGui Node Editor blueprints-example.cpp
+// Based on ImRect_Expanded function in ImGui Node Editor blueprints-example.cpp
ImRect expandImRect(const ImRect& rect, float x, float y)
{
ImRect result = rect;
@@ -34,10 +34,40 @@ ImRect expandImRect(const ImRect& rect, float x, float y)
return result;
}
-// Get more user friendly node definition identifier.
-// Will try and remove "ND_" prefix if it exists. Otherwise just returns
-// the nodedef identifier.
-std::string getNodeDefId(const std::string& val)
+// Based on the splitter function in the ImGui Node Editor blueprints-example.cpp
+static bool splitter(bool split_vertically, float thickness, float* size1, float* size2, float min_size1, float min_size2, float splitter_long_axis_size = -1.0f)
+{
+ using namespace ImGui;
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ ImGuiID id = window->GetID("##Splitter");
+ ImRect bb;
+ bb.Min = window->DC.CursorPos + (split_vertically ? ImVec2(*size1, 0.0f) : ImVec2(0.0f, *size1));
+ bb.Max = bb.Min + CalcItemSize(split_vertically ? ImVec2(thickness, splitter_long_axis_size) : ImVec2(splitter_long_axis_size, thickness), 0.0f, 0.0f);
+ return SplitterBehavior(bb, id, split_vertically ? ImGuiAxis_X : ImGuiAxis_Y, size1, size2, min_size1, min_size2, 0.0f);
+}
+
+// Based on showLabel from ImGui Node Editor blueprints-example.cpp
+auto showLabel = [](const char* label, ImColor color)
+{
+ ImGui::SetCursorPosY(ImGui::GetCursorPosY() - ImGui::GetTextLineHeight());
+ auto size = ImGui::CalcTextSize(label);
+
+ auto padding = ImGui::GetStyle().FramePadding;
+ auto spacing = ImGui::GetStyle().ItemSpacing;
+
+ ImGui::SetCursorPos(ImGui::GetCursorPos() + ImVec2(spacing.x, -spacing.y));
+
+ auto rectMin = ImGui::GetCursorScreenPos() - padding;
+ auto rectMax = ImGui::GetCursorScreenPos() + size + padding;
+
+ auto drawList = ImGui::GetWindowDrawList();
+ drawList->AddRectFilled(rectMin, rectMax, color, size.y * 0.15f);
+ ImGui::TextUnformatted(label);
+};
+
+// Create a more user-friendly node definition name
+std::string getUserNodeDefName(const std::string& val)
{
const std::string ND_PREFIX = "ND_";
std::string result = val;
@@ -72,7 +102,8 @@ Graph::Graph(const std::string& materialFilename,
_isCut(false),
_autoLayout(false),
_frameCount(INT_MIN),
- _pinFilterType(mx::EMPTY_STRING)
+ _fontScale(1.0f),
+ _saveNodePositions(true)
{
loadStandardLibraries();
setPinColor();
@@ -84,7 +115,6 @@ Graph::Graph(const std::string& materialFilename,
_geomFilter.push_back(".gltf");
_graphDoc = loadDocument(materialFilename);
- _graphDoc->importLibrary(_stdLib);
_initial = true;
createNodeUIList(_stdLib);
@@ -177,12 +207,16 @@ mx::DocumentPtr Graph::loadDocument(mx::FilePath filename)
if (!filename.isEmpty())
{
mx::readFromXmlFile(doc, filename, _searchPath, &readOptions);
+ doc->importLibrary(_stdLib);
std::string message;
if (!doc->validate(&message))
{
std::cerr << "*** Validation warnings for " << filename.asString() << " ***" << std::endl;
std::cerr << message << std::endl;
}
+
+ // Cache the currently loaded file
+ _materialFilename = filename;
}
}
catch (mx::Exception& e)
@@ -195,7 +229,6 @@ mx::DocumentPtr Graph::loadDocument(mx::FilePath filename)
return doc;
}
-// populate nodes to add with input output group and nodegraph nodes which are not found in the stdlib
void Graph::addExtraNodes()
{
if (!_graphDoc)
@@ -203,10 +236,10 @@ void Graph::addExtraNodes()
return;
}
- // clear any old nodes, if we previously used tab with another graph doc
+ // Clear any old nodes, if we previously used tab with another graph doc
_extraNodes.clear();
- // get all types from the doc
+ // Get all types from the doc
std::vector types;
std::vector typeDefs = _graphDoc->getTypeDefs();
types.reserve(typeDefs.size());
@@ -215,7 +248,7 @@ void Graph::addExtraNodes()
types.push_back(typeDef->getName());
}
- // add input and output nodes for all types
+ // Add input and output nodes for all types
for (const std::string& type : types)
{
std::string nodeName = "ND_input_" + type;
@@ -224,16 +257,15 @@ void Graph::addExtraNodes()
_extraNodes["Output Nodes"].push_back({ nodeName, type, "output" });
}
- // add group node
+ // Add group node
std::vector groupNode{ "ND_group", "", "group" };
_extraNodes["Group Nodes"].push_back(groupNode);
- // add nodegraph node
+ // Add nodegraph node
std::vector nodeGraph{ "ND_nodegraph", "", "nodegraph" };
_extraNodes["Node Graph"].push_back(nodeGraph);
}
-// return output pin needed to link the inputs and outputs
ed::PinId Graph::getOutputPin(UiNodePtr node, UiNodePtr upNode, UiPinPtr input)
{
if (upNode->getNodeGraph() != nullptr)
@@ -286,11 +318,11 @@ ed::PinId Graph::getOutputPin(UiNodePtr node, UiNodePtr upNode, UiPinPtr input)
}
}
-// connect links via connected nodes in UiNodePtr
void Graph::linkGraph()
{
_currLinks.clear();
- // start with bottom of graph
+
+ // Start with bottom of graph
for (UiNodePtr node : _graphNodes)
{
std::vector inputs = node->inputPins;
@@ -298,20 +330,21 @@ void Graph::linkGraph()
{
for (size_t i = 0; i < inputs.size(); i++)
{
- // get upstream node for all inputs
+ // Get upstream node for all inputs
std::string inputName = inputs[i]->_name;
UiNodePtr inputNode = node->getConnectedNode(inputName);
if (inputNode != nullptr)
{
Link link;
- // getting the input connections for the current uiNode
+
+ // Get the input connections for the current UiNode
ax::NodeEditor::PinId id = inputs[i]->_pinId;
inputs[i]->setConnected(true);
int end = int(id.Get());
link._endAttr = end;
- // get id number of output of node
+ // Get id number of output of node
ed::PinId outputId = getOutputPin(node, inputNode, inputs[i]);
int start = int(outputId.Get());
@@ -352,21 +385,16 @@ void Graph::linkGraph()
}
}
-// connect all the links via the graph editor library
void Graph::connectLinks()
{
-
for (Link const& link : _currLinks)
{
-
ed::Link(link.id, link._startAttr, link._endAttr);
}
}
-// find link position in currLinks vector from link id
int Graph::findLinkPosition(int id)
{
-
int count = 0;
for (size_t i = 0; i < _currLinks.size(); i++)
{
@@ -378,7 +406,7 @@ int Graph::findLinkPosition(int id)
}
return -1;
}
-// check if a node has already been assigned a position
+
bool Graph::checkPosition(UiNodePtr node)
{
if (node->getMxElement() != nullptr)
@@ -390,7 +418,8 @@ bool Graph::checkPosition(UiNodePtr node)
}
return false;
}
-// calculate the total vertical space the node level takes up
+
+// Calculate the total vertical space the node level takes up
float Graph::totalHeight(int level)
{
float total = 0.f;
@@ -400,7 +429,8 @@ float Graph::totalHeight(int level)
}
return total;
}
-// set the y position of node based of the starting position and the nodes above it
+
+// Set the y-position of node based on the starting position and the nodes above it
void Graph::setYSpacing(int level, float startingPos)
{
// set the y spacing for each node
@@ -413,7 +443,7 @@ void Graph::setYSpacing(int level, float startingPos)
}
}
-// calculate the average y position for a specific node level
+// Calculate the average y-position for a specific node level
float Graph::findAvgY(const std::vector& nodes)
{
// find the mid point of node level grou[
@@ -432,8 +462,8 @@ float Graph::findAvgY(const std::vector& nodes)
void Graph::findYSpacing(float startY)
{
- // assume level 0 is set
- // for each level find the average y position of the previous level to use as a spacing guide
+ // Assume level 0 is set
+ // For each level find the average y position of the previous level to use as a spacing guide
int i = 0;
for (std::pair> levelChunk : _levelMap)
{
@@ -441,7 +471,6 @@ void Graph::findYSpacing(float startY)
{
if (_levelMap[i][0]->_level > 0)
{
-
int prevLevel = _levelMap[i].front()->_level - 1;
float avgY = findAvgY(_levelMap[prevLevel]);
float height = totalHeight(_levelMap[i].front()->_level);
@@ -458,14 +487,13 @@ void Graph::findYSpacing(float startY)
}
}
-// layout the x position by assigning the node levels based off its distance from the first node
ImVec2 Graph::layoutPosition(UiNodePtr layoutNode, ImVec2 startingPos, bool initialLayout, int level)
{
if (checkPosition(layoutNode) && !_autoLayout)
{
for (UiNodePtr node : _graphNodes)
{
- // since nodegrpah nodes do not have any materialX info they are placed based off their conneced node
+ // Since nodegraph nodes do not have MaterialX info they are placed based on their connected node
if (node->getNodeGraph() != nullptr)
{
std::vector outputCon = node->getOutputConnections();
@@ -478,7 +506,7 @@ ImVec2 Graph::layoutPosition(UiNodePtr layoutNode, ImVec2 startingPos, bool init
}
else
{
- // don't set position of group nodes
+ // Don't set position of group nodes
if (node->getMessage().empty())
{
if (node->getMxElement()->hasAttribute("xpos"))
@@ -506,7 +534,7 @@ ImVec2 Graph::layoutPosition(UiNodePtr layoutNode, ImVec2 startingPos, bool init
{
if (layoutNode->_level < level)
{
- // remove the old instance of the node from the map
+ // Remove the old instance of the node from the map
int levelNum = 0;
int removeNum = -1;
for (UiNodePtr levelNode : _levelMap[layoutNode->_level])
@@ -533,7 +561,7 @@ ImVec2 Graph::layoutPosition(UiNodePtr layoutNode, ImVec2 startingPos, bool init
auto it = _levelMap.find(layoutNode->_level);
if (it != _levelMap.end())
{
- // key already exists add to it
+ // Key already exists so add to it
bool nodeFound = false;
for (UiNodePtr node : it->second)
{
@@ -550,30 +578,31 @@ ImVec2 Graph::layoutPosition(UiNodePtr layoutNode, ImVec2 startingPos, bool init
}
else
{
- // insert new vector into key
+ // Insert new vector into key
std::vector newValue = { layoutNode };
_levelMap.insert({ layoutNode->_level, newValue });
}
std::vector pins = layoutNode->inputPins;
if (initialLayout)
{
- // check number of inputs that are connected to node
+ // Check number of inputs that are connected to node
if (layoutNode->getInputConnect() > 0)
{
- // not top of node graph stop recursion
+ // Not top of node graph so stop recursion
if (pins.size() != 0 && layoutNode->getInput() == nullptr)
{
for (size_t i = 0; i < pins.size(); i++)
{
- // get upstream node for all inputs
+ // Get upstream node for all inputs
newPos = startingPos;
UiNodePtr nextNode = layoutNode->getConnectedNode(pins[i]->_name);
if (nextNode)
{
- startingPos.x = (1200.f - ((layoutNode->_level) * 350)) * _fontScale;
+ startingPos.x = (1200.f - ((layoutNode->_level) * 250)) * _fontScale;
ed::SetNodePosition(layoutNode->getId(), startingPos);
layoutNode->setPos(ImVec2(startingPos));
- // call layout position on upstream node with newPos as -140 to the left of current node
+
+ // Call layout position on upstream node with newPos to the left of current node
layoutPosition(nextNode, ImVec2(newPos.x, startingPos.y), initialLayout, layoutNode->_level + 1);
}
}
@@ -581,9 +610,10 @@ ImVec2 Graph::layoutPosition(UiNodePtr layoutNode, ImVec2 startingPos, bool init
}
else
{
- startingPos.x = (1200.f - ((layoutNode->_level) * 350)) * _fontScale;
+ startingPos.x = (1200.f - ((layoutNode->_level) * 250)) * _fontScale;
layoutNode->setPos(ImVec2(startingPos));
- // set current node position
+
+ // Set current node position
ed::SetNodePosition(layoutNode->getId(), ImVec2(startingPos));
}
}
@@ -591,10 +621,9 @@ ImVec2 Graph::layoutPosition(UiNodePtr layoutNode, ImVec2 startingPos, bool init
}
}
-// extra layout pass for inputs and nodes that do not attach to an output node
void Graph::layoutInputs()
{
- // layout inputs after other nodes so that they can be all in a line on far left side of node graph
+ // Layout inputs after other nodes so that they can be all in a line on far left side of node graph
if (_levelMap.begin() != _levelMap.end())
{
int levelCount = -1;
@@ -613,7 +642,6 @@ void Graph::layoutInputs()
startingPos.y += ed::GetNodeSize(uiNode->getId()).y;
startingPos.y += 23;
}
- // accoutning for extra nodes like in gltf
else if (uiNode->getOutputConnections().size() == 0 && (uiNode->getNode() != nullptr))
{
if (uiNode->getNode()->getCategory() != mx::SURFACE_MATERIAL_NODE_STRING)
@@ -625,7 +653,6 @@ void Graph::layoutInputs()
}
}
-// reutrn pin color based on the type of the value of that pin
void Graph::setPinColor()
{
_pinColor.insert(std::make_pair("integer", ImColor(255, 255, 28, 255)));
@@ -644,8 +671,8 @@ void Graph::setPinColor()
_pinColor.insert(std::make_pair("BSDF", ImColor(10, 181, 150, 255)));
_pinColor.insert(std::make_pair("EDF", ImColor(255, 50, 100, 255)));
_pinColor.insert(std::make_pair("VDF", ImColor(0, 100, 151, 255)));
- _pinColor.insert(std::make_pair("surfaceshader", ImColor(150, 255, 255, 255)));
- _pinColor.insert(std::make_pair("material", ImColor(255, 255, 255, 255)));
+ _pinColor.insert(std::make_pair(mx::SURFACE_SHADER_TYPE_STRING, ImColor(150, 255, 255, 255)));
+ _pinColor.insert(std::make_pair(mx::MATERIAL_TYPE_STRING, ImColor(255, 255, 255, 255)));
_pinColor.insert(std::make_pair(mx::DISPLACEMENT_SHADER_TYPE_STRING, ImColor(155, 50, 100, 255)));
_pinColor.insert(std::make_pair(mx::VOLUME_SHADER_TYPE_STRING, ImColor(155, 250, 100, 255)));
_pinColor.insert(std::make_pair(mx::LIGHT_SHADER_TYPE_STRING, ImColor(100, 150, 100, 255)));
@@ -662,28 +689,9 @@ void Graph::setPinColor()
_pinColor.insert(std::make_pair("stringarray", ImColor(120, 180, 100)));
}
-// based off of showLabel from ImGui Node Editor blueprints-example.cpp
-auto showLabel = [](const char* label, ImColor color)
-{
- ImGui::SetCursorPosY(ImGui::GetCursorPosY() - ImGui::GetTextLineHeight());
- auto size = ImGui::CalcTextSize(label);
-
- auto padding = ImGui::GetStyle().FramePadding;
- auto spacing = ImGui::GetStyle().ItemSpacing;
-
- ImGui::SetCursorPos(ImGui::GetCursorPos() + ImVec2(spacing.x, -spacing.y));
-
- auto rectMin = ImGui::GetCursorScreenPos() - padding;
- auto rectMax = ImGui::GetCursorScreenPos() + size + padding;
-
- auto drawList = ImGui::GetWindowDrawList();
- drawList->AddRectFilled(rectMin, rectMax, color, size.y * 0.15f);
- ImGui::TextUnformatted(label);
-};
-
void Graph::selectMaterial(UiNodePtr uiNode)
{
- // find renderable element that correspond with material uiNode
+ // Find renderable element that corresponds with material UiNode
std::vector elems = mx::findRenderableElements(_graphDoc);
mx::TypedElementPtr typedElem = nullptr;
for (mx::TypedElementPtr elem : elems)
@@ -698,13 +706,17 @@ void Graph::selectMaterial(UiNodePtr uiNode)
_renderer->setMaterial(typedElem);
}
-// set the node to display in render veiw based off the selected node or nodegraph
void Graph::setRenderMaterial(UiNodePtr node)
{
- // set render node right away is node is a material
- if (node->getNode() && node->getNode()->getType() == "material")
+ // For now only surface shaders and materials are considered renderable.
+ // This can be adjusted as desired to include being able to use outputs,
+ // and / a sub-graph in the nodegraph.
+ const mx::StringSet RENDERABLE_TYPES = { mx::MATERIAL_TYPE_STRING, mx::SURFACE_SHADER_TYPE_STRING };
+
+ // Set render node right away is node is renderable
+ if (node->getNode() && RENDERABLE_TYPES.count(node->getNode()->getType()))
{
- // only set new render node if different material has been selected
+ // Only set new render node if different material has been selected
if (_currRenderNode != node)
{
_currRenderNode = node;
@@ -712,55 +724,124 @@ void Graph::setRenderMaterial(UiNodePtr node)
_renderer->setMaterialCompilation(true);
}
}
+
+ // Traverse downstream looking for the first renderable element.
else
{
- // continue downstream using output connections until a material node is found
- std::vector outNodes = node->getOutputConnections();
- if (outNodes.size() > 0)
+ mx::NodePtr mtlxNode = node->getNode();
+ mx::NodeGraphPtr mtlxNodeGraph = node->getNodeGraph();
+ mx::OutputPtr mtlxOutput = node->getOutput();
+ if (mtlxOutput)
{
- if (outNodes[0]->getNode())
+ mx::ElementPtr parent = mtlxOutput->getParent();
+ if (parent->isA())
+ mtlxNodeGraph = parent->asA();
+ else if (parent->isA())
+ mtlxNode = parent->asA();
+ }
+ mx::StringSet testPaths;
+ if (mtlxNode)
+ {
+ mx::ElementPtr parent = mtlxNode->getParent();
+ if (parent->isA())
{
- if (outNodes[0]->getNode()->getType() == mx::SURFACE_SHADER_TYPE_STRING)
+ // There is no logic to support traversing from inside a functional graph
+ // to it's instance and hence downstream so skip this from consideration.
+ // The closest approach would be to "flatten" all definitions to compound graphs.
+ mx::NodeGraphPtr parentGraph = parent->asA();
+ if (parentGraph->getNodeDef())
{
- std::vector shaderOut = outNodes[0]->getOutputConnections();
- if (shaderOut.size() > 0)
+ return;
+ }
+ }
+ testPaths.insert(mtlxNode->getNamePath());
+ }
+ else if (mtlxNodeGraph)
+ {
+ testPaths.insert(mtlxNodeGraph->getNamePath());
+ }
+
+ mx::NodePtr foundNode = nullptr;
+ while (!testPaths.empty() && !foundNode)
+ {
+ mx::StringSet nextPaths;
+ for (const std::string& testPath : testPaths)
+ {
+ mx::ElementPtr testElem = _graphDoc->getDescendant(testPath);
+ mx::NodePtr testNode = testElem->asA();
+ std::vector downstreamPorts;
+ if (testNode)
+ {
+ downstreamPorts = testNode->getDownstreamPorts();
+ }
+ else
+ {
+ mx::NodeGraphPtr testGraph = testElem->asA();
+ if (testGraph)
{
- if (shaderOut[0])
+ downstreamPorts = testGraph->getDownstreamPorts();
+ }
+ }
+
+ // Test all downstream ports. If the port's node is renderable
+ // then stop searching.
+ for (mx::PortElementPtr downstreamPort : downstreamPorts)
+ {
+ mx::ElementPtr parent = downstreamPort->getParent();
+ if (parent)
+ {
+ mx::NodePtr downstreamNode = parent->asA();
+ if (downstreamNode)
{
- if (shaderOut[0]->getNode()->getType() == "material")
+ mx::NodeDefPtr nodeDef = downstreamNode->getNodeDef();
+ if (nodeDef)
{
- if (_currRenderNode != shaderOut[0])
+ if (RENDERABLE_TYPES.count(nodeDef->getType()))
{
- _currRenderNode = shaderOut[0];
- _frameCount = ImGui::GetFrameCount();
- _renderer->setMaterialCompilation(true);
+ foundNode = downstreamNode;
+ break;
}
}
}
+ if (!foundNode)
+ {
+ nextPaths.insert(parent->getNamePath());
+ }
}
- else
- {
- _currRenderNode = nullptr;
- }
}
- else if (outNodes[0]->getNode()->getType() == mx::MATERIAL_TYPE_STRING)
+ if (foundNode)
+ {
+ break;
+ }
+ }
+
+ // Set up next set of nodes to search downstream
+ testPaths = nextPaths;
+ }
+
+ // Update rendering. If found use that node, otherwise
+ // use the current fallback of using the first renderable node.
+ if (foundNode)
+ {
+ for (auto uiNode : _graphNodes)
+ {
+ if (uiNode->getNode() == foundNode)
{
- if (_currRenderNode != outNodes[0])
+ if (_currRenderNode != uiNode)
{
- _currRenderNode = outNodes[0];
+ _currRenderNode = uiNode;
_frameCount = ImGui::GetFrameCount();
_renderer->setMaterialCompilation(true);
}
+ break;
}
}
- else
- {
- _currRenderNode = nullptr;
- }
}
else
{
_currRenderNode = nullptr;
+ _frameCount = ImGui::GetFrameCount();
+ _renderer->setMaterialCompilation(true);
}
}
}
@@ -768,38 +849,15 @@ void Graph::setRenderMaterial(UiNodePtr node)
void Graph::updateMaterials(mx::InputPtr input, mx::ValuePtr value)
{
std::string renderablePath;
- mx::TypedElementPtr renderableElem;
- std::vector elems = mx::findRenderableElements(_graphDoc);
-
- size_t num = 0;
- int num2 = 0;
- for (mx::TypedElementPtr elem : elems)
+ if (_currRenderNode)
{
- renderableElem = elem;
- mx::NodePtr node = elem->asA();
- if (node)
+ if (_currRenderNode->getNode())
{
- if (_currRenderNode)
- {
- if (node->getName() == _currRenderNode->getName())
- {
- renderablePath = renderableElem->getNamePath();
- break;
- }
- }
- else
- {
- renderablePath = renderableElem->getNamePath();
- }
+ renderablePath = _currRenderNode->getNode()->getNamePath();
}
- else
+ else if (_currRenderNode->getOutput())
{
- renderablePath = renderableElem->getNamePath();
- if (num2 == 2)
- {
- break;
- }
- num2++;
+ renderablePath = _currRenderNode->getOutput()->getNamePath();
}
}
@@ -821,42 +879,37 @@ void Graph::updateMaterials(mx::InputPtr input, mx::ValuePtr value)
else
{
std::string name = input->getNamePath();
- // need to use exact interface name in order for input
- mx::InputPtr interfaceInput = findInput(input, input->getName());
- if (interfaceInput)
- {
- name = interfaceInput->getNamePath();
- }
+
// Note that if there is a topogical change due to
// this value change or a transparency change, then
// this is not currently caught here.
- _renderer->getMaterials()[num]->modifyUniform(name, value);
+ _renderer->getMaterials()[0]->modifyUniform(name, value);
}
}
}
-// set the value of the selected node constants in the node property editor
+
void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIProperties& uiProperties)
{
- std::string inName = !uiProperties.uiName.empty() ? uiProperties.uiName : input->getName();
ImGui::PushItemWidth(-1);
mx::ValuePtr minVal = uiProperties.uiMin;
mx::ValuePtr maxVal = uiProperties.uiMax;
- // if input is a float set the float slider Ui to the value
+ // If input is a float set the float slider UI to the value
if (input->getType() == "float")
{
mx::ValuePtr val = input->getValue();
if (val && val->isA())
{
- // updates the value to the default for new nodes
+ // Update the value to the default for new nodes
float prev = val->asA(), temp = val->asA();
float min = minVal ? minVal->asA() : 0.f;
float max = maxVal ? maxVal->asA() : 100.f;
float speed = (max - min) / 1000.0f;
ImGui::DragFloat("##hidelabel", &temp, speed, min, max);
- // set input value and update materials if different from previous value
+
+ // Set input value and update materials if different from previous value
if (prev != temp)
{
addNodeInput(_currUiNode, input);
@@ -875,7 +928,8 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIPropert
int max = maxVal ? maxVal->asA() : 100;
float speed = (max - min) / 100.0f;
ImGui::DragInt("##hidelabel", &temp, speed, min, max);
- // set input value and update materials if different from previous value
+
+ // Set input value and update materials if different from previous value
if (prev != temp)
{
addNodeInput(_currUiNode, input);
@@ -899,7 +953,7 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIPropert
ImGui::SameLine();
ImGui::ColorEdit3("##color", &temp[0], ImGuiColorEditFlags_NoInputs);
- // set input value and update materials if different from previous value
+ // Set input value and update materials if different from previous value
if (prev != temp)
{
addNodeInput(_currUiNode, input);
@@ -921,9 +975,11 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIPropert
ImGui::DragFloat4("##hidelabel", &temp[0], speed, min, max);
ImGui::PopItemWidth();
ImGui::SameLine();
- // color edit for the color picker to the right of the color floats
+
+ // Color edit for the color picker to the right of the color floats
ImGui::ColorEdit4("##color", &temp[0], ImGuiColorEditFlags_NoInputs);
- // set input value and update materials if different from previous value
+
+ // Set input value and update materials if different from previous value
if (temp != prev)
{
addNodeInput(_currUiNode, input);
@@ -942,7 +998,8 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIPropert
float max = maxVal ? maxVal->asA()[0] : 100.f;
float speed = (max - min) / 1000.0f;
ImGui::DragFloat2("##hidelabel", &temp[0], speed, min, max);
- // set input value and update materials if different from previous value
+
+ // Set input value and update materials if different from previous value
if (prev != temp)
{
addNodeInput(_currUiNode, input);
@@ -961,7 +1018,8 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIPropert
float max = maxVal ? maxVal->asA()[0] : 100.f;
float speed = (max - min) / 1000.0f;
ImGui::DragFloat3("##hidelabel", &temp[0], speed, min, max);
- // set input value and update materials if different from previous value
+
+ // Set input value and update materials if different from previous value
if (prev != temp)
{
addNodeInput(_currUiNode, input);
@@ -980,7 +1038,8 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIPropert
float max = maxVal ? maxVal->asA()[0] : 100.f;
float speed = (max - min) / 1000.0f;
ImGui::DragFloat4("##hidelabel", &temp[0], speed, min, max);
- // set input value and update materials if different from previous value
+
+ // Set input value and update materials if different from previous value
if (prev != temp)
{
addNodeInput(_currUiNode, input);
@@ -996,7 +1055,8 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIPropert
{
std::string prev = val->asA(), temp = val->asA();
ImGui::InputText("##constant", &temp);
- // set input value and update materials if different from previous value
+
+ // Set input value and update materials if different from previous value
if (prev != temp)
{
addNodeInput(_currUiNode, input);
@@ -1014,10 +1074,12 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIPropert
std::string temp = val->asA(), prev = val->asA();
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.15f, .15f, .15f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.2f, .4f, .6f, 1.0f));
- // browser button to select new file
+
+ // Browser button to select new file
ImGui::PushItemWidth(-100);
if (ImGui::Button("Browse"))
{
+ _fileDialogImageInputName = input->getName();
_fileDialogImage.setTitle("Node Input Dialog");
_fileDialogImage.open();
_fileDialogImage.setTypeFilters(_imageFilter);
@@ -1028,19 +1090,21 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIPropert
ImGui::PopStyleColor();
ImGui::PopStyleColor();
- // create and load document from selected file
- if (_fileDialogImage.hasSelected())
+ // Create and load document from selected file
+ if (_fileDialogImage.hasSelected() && _fileDialogImageInputName == input->getName())
{
- // set the new filename to the complete file path
+ // Set the new filename to the complete file path
mx::FilePath fileName = _fileDialogImage.getSelected();
temp = fileName;
- // need to set the file prefix for the input to "" so that it can find the new file
+
+ // Need to clear the file prefix so that it can find the new file
input->setAttribute(input->FILE_PREFIX_ATTRIBUTE, "");
_fileDialogImage.clearSelected();
_fileDialogImage.setTypeFilters(std::vector());
+ _fileDialogImageInputName = "";
}
- // set input value and update materials if different from previous value
+ // Set input value and update materials if different from previous value
if (prev != temp)
{
addNodeInput(_currUiNode, input);
@@ -1057,7 +1121,8 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIPropert
{
bool prev = val->asA(), temp = val->asA();
ImGui::Checkbox("", &temp);
- // set input value and update materials if different from previous value
+
+ // Set input value and update materials if different from previous value
if (prev != temp)
{
addNodeInput(_currUiNode, input);
@@ -1069,13 +1134,14 @@ void Graph::setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIPropert
ImGui::PopItemWidth();
}
-// build the initial graph of a loaded mtlx document including shader, material and nodegraph node
+
void Graph::setUiNodeInfo(UiNodePtr node, const std::string& type, const std::string& category)
{
node->setType(type);
node->setCategory(category);
++_graphTotalSize;
- // create pins
+
+ // Create pins
if (node->getNodeGraph())
{
std::vector outputs = node->getNodeGraph()->getOutputs();
@@ -1155,14 +1221,13 @@ void Graph::setUiNodeInfo(UiNodePtr node, const std::string& type, const std::st
_graphNodes.push_back(std::move(node));
}
-// Generate node UI from nodedefs.
void Graph::createNodeUIList(mx::DocumentPtr doc)
{
_nodesToAdd.clear();
const std::string EXTRA_GROUP_NAME = "extra";
for (mx::NodeDefPtr nodeDef : doc->getNodeDefs())
{
- // nodeDef is the key for the map
+ // NodeDef is the key for the map
std::string group = nodeDef->getNodeGroup();
if (group.empty())
{
@@ -1178,7 +1243,6 @@ void Graph::createNodeUIList(mx::DocumentPtr doc)
addExtraNodes();
}
-// build the UiNode node graph based off of loading a document
void Graph::buildUiBaseGraph(mx::DocumentPtr doc)
{
std::vector nodeGraphs = doc->getNodeGraphs();
@@ -1194,7 +1258,8 @@ void Graph::buildUiBaseGraph(mx::DocumentPtr doc)
_newLinks.clear();
_currPins.clear();
_graphTotalSize = 1;
- // creating uiNodes for nodes that belong to the document so they are not in a nodegraph
+
+ // Create UiNodes for nodes that belong to the document so they are not in a nodegraph
for (mx::NodePtr node : docNodes)
{
if (!includeElement(node))
@@ -1204,7 +1269,8 @@ void Graph::buildUiBaseGraph(mx::DocumentPtr doc)
currNode->setNode(node);
setUiNodeInfo(currNode, node->getType(), node->getCategory());
}
- // creating uiNodes for the nodegraph
+
+ // Create UiNodes for the nodegraph
for (mx::NodeGraphPtr nodeGraph : nodeGraphs)
{
if (!includeElement(nodeGraph))
@@ -1230,7 +1296,8 @@ void Graph::buildUiBaseGraph(mx::DocumentPtr doc)
currNode->setOutput(output);
setUiNodeInfo(currNode, output->getType(), output->getCategory());
}
- // creating edges for nodegraphs
+
+ // Create edges for nodegraphs
for (mx::NodeGraphPtr graph : nodeGraphs)
{
for (mx::InputPtr input : graph->getActiveInputs())
@@ -1256,7 +1323,8 @@ void Graph::buildUiBaseGraph(mx::DocumentPtr doc)
}
}
}
- // creating edges for surface and material nodes
+
+ // Create edges for surface and material nodes
for (mx::NodePtr node : docNodes)
{
mx::NodeDefPtr nD = node->getNodeDef(node->getName());
@@ -1291,7 +1359,6 @@ void Graph::buildUiBaseGraph(mx::DocumentPtr doc)
}
if (upNum != -1)
{
-
UiEdge newEdge = UiEdge(_graphNodes[upNum], _graphNodes[downNum], input);
if (!edgeExists(newEdge))
{
@@ -1304,11 +1371,10 @@ void Graph::buildUiBaseGraph(mx::DocumentPtr doc)
}
}
}
-// build the UiNode node graph based off of diving into a node graph node
+
void Graph::buildUiNodeGraph(const mx::NodeGraphPtr& nodeGraphs)
{
-
- // clear all values so that ids can start with 0 or 1
+ // Clear all values so that ids can start with 0 or 1
_graphNodes.clear();
_currLinks.clear();
_currEdge.clear();
@@ -1319,12 +1385,10 @@ void Graph::buildUiNodeGraph(const mx::NodeGraphPtr& nodeGraphs)
{
mx::NodeGraphPtr nodeGraph = nodeGraphs;
std::vector children = nodeGraph->topologicalSort();
- // Write out all nodes.
-
mx::NodeDefPtr nodeDef = nodeGraph->getNodeDef();
mx::NodeDefPtr currNodeDef;
- // create input nodes
+ // Create input nodes
if (nodeDef)
{
std::vector inputs = nodeDef->getActiveInputs();
@@ -1337,7 +1401,7 @@ void Graph::buildUiNodeGraph(const mx::NodeGraphPtr& nodeGraphs)
}
}
- // search node graph children to create uiNodes
+ // Search node graph children to create uiNodes
for (mx::ElementPtr elem : children)
{
mx::NodePtr node = elem->asA();
@@ -1410,10 +1474,9 @@ void Graph::buildUiNodeGraph(const mx::NodeGraphPtr& nodeGraphs)
}
int upNode = findNode(upName, upstreamType);
int downNode = findNode(downName, downstreamType);
- if (downNode > 0 && upNode > 0 &&
- _graphNodes[downNode]->getOutput() != nullptr)
+ if (downNode > 0 && upNode > 0 && _graphNodes[downNode]->getOutput())
{
- // creating edges for the output nodes
+ // Create edges for the output nodes
UiEdge newEdge = UiEdge(_graphNodes[upNode], _graphNodes[downNode], nullptr);
if (!edgeExists(newEdge))
{
@@ -1448,7 +1511,7 @@ void Graph::buildUiNodeGraph(const mx::NodeGraphPtr& nodeGraphs)
std::vector ins = upstreamNode->getActiveInputs();
for (mx::InputPtr input : ins)
{
- // connecting input nodes
+ // Connect input nodes
if (input->hasInterfaceName())
{
std::string interfaceName = input->getInterfaceName();
@@ -1474,7 +1537,7 @@ void Graph::buildUiNodeGraph(const mx::NodeGraphPtr& nodeGraphs)
}
}
- // second pass to catch all of the connections that arent part of an output
+ // Second pass to catch all of the connections that arent part of an output
for (mx::ElementPtr elem : children)
{
mx::NodePtr node = elem->asA();
@@ -1543,7 +1606,6 @@ void Graph::buildUiNodeGraph(const mx::NodeGraphPtr& nodeGraphs)
}
}
-// return node position in _graphNodes based off node name and type to account for input/output UiNodes with same names as mx Nodes
int Graph::findNode(const std::string& name, const std::string& type)
{
int count = 0;
@@ -1573,13 +1635,12 @@ int Graph::findNode(const std::string& name, const std::string& type)
return -1;
}
-// set position of pasted nodes based off of original node position
void Graph::positionPasteBin(ImVec2 pos)
{
ImVec2 totalPos = ImVec2(0, 0);
ImVec2 avgPos = ImVec2(0, 0);
- // get average position of original nodes
+ // Get average position of original nodes
for (auto pasteNode : _copiedNodes)
{
ImVec2 origPos = ed::GetNodePosition(pasteNode.first->getId());
@@ -1589,7 +1650,7 @@ void Graph::positionPasteBin(ImVec2 pos)
avgPos.x = totalPos.x / (int) _copiedNodes.size();
avgPos.y = totalPos.y / (int) _copiedNodes.size();
- // get offset from clciked position
+ // Get offset from clicked position
ImVec2 offset = ImVec2(0, 0);
offset.x = pos.x - avgPos.x;
offset.y = pos.y - avgPos.y;
@@ -1605,11 +1666,12 @@ void Graph::positionPasteBin(ImVec2 pos)
ed::SetNodePosition(pasteNode.second->getId(), newPos);
}
}
+
void Graph::createEdge(UiNodePtr upNode, UiNodePtr downNode, mx::InputPtr connectingInput)
{
if (downNode->getOutput())
{
- // creating edges for the output nodes
+ // Create edges for the output nodes
UiEdge newEdge = UiEdge(upNode, downNode, nullptr);
if (!edgeExists(newEdge))
{
@@ -1674,6 +1736,7 @@ void Graph::copyUiNode(UiNodePtr node)
_copiedNodes[node] = copyNode;
_graphNodes.push_back(copyNode);
}
+
void Graph::copyNodeGraph(UiNodePtr origGraph, UiNodePtr copyGraph)
{
copyGraph->getNodeGraph()->copyContentFrom(origGraph->getNodeGraph());
@@ -1684,6 +1747,7 @@ void Graph::copyNodeGraph(UiNodePtr origGraph, UiNodePtr copyGraph)
input->setName(newName);
}
}
+
void Graph::copyInputs()
{
for (std::map::iterator iter = _copiedNodes.begin(); iter != _copiedNodes.end(); ++iter)
@@ -1695,19 +1759,18 @@ void Graph::copyInputs()
{
if (origNode->getConnectedNode(pin->_name) && !_ctrlClick)
{
- // if original node is connected check if connect node is in copied nodes
+ // If original node is connected check if connect node is in copied nodes
if (_copiedNodes.find(origNode->getConnectedNode(pin->_name)) != _copiedNodes.end())
{
- // set copy node connected to the value at this key
- // create an edge
+ // Set copy node connected to the value at this key
createEdge(_copiedNodes[origNode->getConnectedNode(pin->_name)], copyNode, copyNode->inputPins[count]->_input);
UiNodePtr upNode = _copiedNodes[origNode->getConnectedNode(pin->_name)];
if (copyNode->getNode() || copyNode->getNodeGraph())
{
-
mx::InputPtr connectingInput = nullptr;
copyNode->inputPins[count]->_input->copyContentFrom(pin->_input);
- // update value to be empty
+
+ // Update value to be empty
if (copyNode->getNode() && copyNode->getNode()->getType() == mx::SURFACE_SHADER_TYPE_STRING)
{
if (upNode->getOutput())
@@ -1721,7 +1784,6 @@ void Graph::copyInputs()
}
else
{
- // node graph
if (upNode->getNodeGraph())
{
ed::PinId outputId = getOutputPin(copyNode, upNode, copyNode->inputPins[count]);
@@ -1761,7 +1823,7 @@ void Graph::copyInputs()
copyNode->getOutput()->setConnectedNode(upNode->getNode());
}
- // update input node num and output connections
+ // Update input node num and output connections
copyNode->setInputNodeNum(1);
upNode->setOutputConnection(copyNode);
}
@@ -1781,12 +1843,13 @@ void Graph::copyInputs()
}
}
}
-// add node to graphNodes based off of node def information
+
void Graph::addNode(const std::string& category, const std::string& name, const std::string& type)
{
mx::NodePtr node = nullptr;
std::vector matchingNodeDefs;
- // create document or node graph is there is not already one
+
+ // Create document or node graph is there is not already one
if (category == "output")
{
std::string outName = "";
@@ -1803,7 +1866,8 @@ void Graph::addNode(const std::string& category, const std::string& name, const
{
std::string inName = "";
mx::InputPtr newIn = nullptr;
- // add input as child of correct parent and create valid name
+
+ // Add input as child of correct parent and create valid name
inName = _currGraphElem->createValidChildName(name);
newIn = _currGraphElem->addInput(inName, type);
auto inputNode = std::make_shared(inName, int(++_graphTotalSize));
@@ -1815,20 +1879,23 @@ void Graph::addNode(const std::string& category, const std::string& name, const
else if (category == "group")
{
auto groupNode = std::make_shared(name, int(++_graphTotalSize));
- // set message of group uinode in order to identify it as such
+
+ // Set message of group UiNode in order to identify it as such
groupNode->setMessage("Comment");
setUiNodeInfo(groupNode, type, "group");
- // create ui portions of group node
+
+ // Create ui portions of group node
buildGroupNode(_graphNodes.back());
return;
}
else if (category == "nodegraph")
{
- // create new mx::NodeGraph and set as current node graph
+ // Create new mx::NodeGraph and set as current node graph
_graphDoc->addNodeGraph();
std::string nodeGraphName = _graphDoc->getNodeGraphs().back()->getName();
auto nodeGraphNode = std::make_shared(nodeGraphName, int(++_graphTotalSize));
- // set mx::Nodegraph as node graph for uiNode
+
+ // Set mx::Nodegraph as node graph for uiNode
nodeGraphNode->setNodeGraph(_graphDoc->getNodeGraphs().back());
setUiNodeInfo(nodeGraphNode, type, "nodegraph");
@@ -1839,9 +1906,8 @@ void Graph::addNode(const std::string& category, const std::string& name, const
matchingNodeDefs = _graphDoc->getMatchingNodeDefs(category);
for (mx::NodeDefPtr nodedef : matchingNodeDefs)
{
- std::string nodedefName = nodedef->getName();
- std::string sub = getNodeDefId(nodedefName);
- if (sub == name)
+ std::string userNodeDefName = getUserNodeDefName(nodedef->getName());
+ if (userNodeDefName == name)
{
node = _currGraphElem->addNodeInstance(nodedef, _currGraphElem->createValidChildName(name));
}
@@ -1854,17 +1920,16 @@ void Graph::addNode(const std::string& category, const std::string& name, const
int countDef = 0;
for (size_t i = 0; i < matchingNodeDefs.size(); i++)
{
- // use substring of name in order to remove ND_
- std::string nodedefName = matchingNodeDefs[i]->getName();
- std::string sub = getNodeDefId(nodedefName);
- if (sub == name)
+ std::string userNodeDefName = getUserNodeDefName(matchingNodeDefs[i]->getName());
+ if (userNodeDefName == name)
{
num = countDef;
}
countDef++;
}
std::vector defInputs = matchingNodeDefs[num]->getActiveInputs();
- // adding inputs to ui node as pins so that we can later add them to the node if necessary
+
+ // Add inputs to UiNode as pins so that we can later add them to the node if necessary
auto newNode = std::make_shared(node->getName(), int(++_graphTotalSize));
newNode->setCategory(category);
newNode->setType(type);
@@ -1892,7 +1957,7 @@ void Graph::addNode(const std::string& category, const std::string& name, const
updateMaterials();
}
}
-// return node pos
+
int Graph::getNodeId(ed::PinId pinId)
{
for (UiPinPtr pin : _currPins)
@@ -1905,7 +1970,6 @@ int Graph::getNodeId(ed::PinId pinId)
return -1;
}
-// return pin based off of UiPin id
UiPinPtr Graph::getPin(ed::PinId pinId)
{
for (UiPinPtr pin : _currPins)
@@ -1919,8 +1983,7 @@ UiPinPtr Graph::getPin(ed::PinId pinId)
return nullPin;
}
-// This function is based off of the pin icon function in the ImGui Node Editor blueprints-example.cpp
-void Graph::DrawPinIcon(std::string type, bool connected, int alpha)
+void Graph::drawPinIcon(std::string type, bool connected, int alpha)
{
ax::Drawing::IconType iconType = ax::Drawing::IconType::Flow;
ImColor color = ImColor(0, 0, 0, 255);
@@ -1934,7 +1997,6 @@ void Graph::DrawPinIcon(std::string type, bool connected, int alpha)
ax::Widgets::Icon(ImVec2(24, 24), iconType, connected, color, ImColor(32, 32, 32, alpha));
}
-// This function is based off of the comment node in the ImGui Node Editor blueprints-example.cpp
void Graph::buildGroupNode(UiNodePtr node)
{
const float commentAlpha = 0.75f;
@@ -1991,12 +2053,14 @@ void Graph::buildGroupNode(UiNodePtr node)
}
ed::EndGroupHint();
}
+
bool Graph::readOnly()
{
- // if the sources are not the same then the current graph cannot be modified
+ // If the sources are not the same then the current graph cannot be modified
return _currGraphElem->getActiveSourceUri() != _graphDoc->getActiveSourceUri();
}
-mx::InputPtr Graph::findInput(mx::InputPtr nodeInput, std::string name)
+
+mx::InputPtr Graph::findInput(mx::InputPtr nodeInput, const std::string& name)
{
if (_isNodeGraph)
{
@@ -2008,7 +2072,6 @@ mx::InputPtr Graph::findInput(mx::InputPtr nodeInput, std::string name)
{
if (input->getInterfaceInput())
{
-
if (input->getInterfaceInput() == nodeInput)
{
return input;
@@ -2040,18 +2103,6 @@ mx::InputPtr Graph::findInput(mx::InputPtr nodeInput, std::string name)
}
return nullptr;
}
-// This function is based off the splitter function in the ImGui Node Editor blueprints-example.cpp
-static bool Splitter(bool split_vertically, float thickness, float* size1, float* size2, float min_size1, float min_size2, float splitter_long_axis_size = -1.0f)
-{
- using namespace ImGui;
- ImGuiContext& g = *GImGui;
- ImGuiWindow* window = g.CurrentWindow;
- ImGuiID id = window->GetID("##Splitter");
- ImRect bb;
- bb.Min = window->DC.CursorPos + (split_vertically ? ImVec2(*size1, 0.0f) : ImVec2(0.0f, *size1));
- bb.Max = bb.Min + CalcItemSize(split_vertically ? ImVec2(thickness, splitter_long_axis_size) : ImVec2(splitter_long_axis_size, thickness), 0.0f, 0.0f);
- return SplitterBehavior(bb, id, split_vertically ? ImGuiAxis_X : ImGuiAxis_Y, size1, size2, min_size1, min_size2, 0.0f);
-}
void Graph::drawOutputPins(UiNodePtr node, const std::string& longestInputLabel)
{
@@ -2075,11 +2126,11 @@ void Graph::drawOutputPins(UiNodePtr node, const std::string& longestInputLabel)
bool connected = pin->getConnected();
if (!_pinFilterType.empty())
{
- DrawPinIcon(pin->_type, connected, _pinFilterType == pin->_type ? DEFAULT_ALPHA : FILTER_ALPHA);
+ drawPinIcon(pin->_type, connected, _pinFilterType == pin->_type ? DEFAULT_ALPHA : FILTER_ALPHA);
}
else
{
- DrawPinIcon(pin->_type, connected, DEFAULT_ALPHA);
+ drawPinIcon(pin->_type, connected, DEFAULT_ALPHA);
}
ed::EndPin();
@@ -2096,16 +2147,16 @@ void Graph::drawInputPin(UiPinPtr pin)
{
if (_pinFilterType == pin->_type)
{
- DrawPinIcon(pin->_type, connected, DEFAULT_ALPHA);
+ drawPinIcon(pin->_type, connected, DEFAULT_ALPHA);
}
else
{
- DrawPinIcon(pin->_type, connected, FILTER_ALPHA);
+ drawPinIcon(pin->_type, connected, FILTER_ALPHA);
}
}
else
{
- DrawPinIcon(pin->_type, connected, DEFAULT_ALPHA);
+ drawPinIcon(pin->_type, connected, DEFAULT_ALPHA);
}
ImGui::PopID();
ed::EndPin();
@@ -2126,7 +2177,7 @@ std::vector Graph::createNodes(bool nodegraph)
}
else
{
- // color for output pin
+ // Color for output pin
std::string outputType;
if (node->getNode() != nullptr)
{
@@ -2180,8 +2231,8 @@ std::vector Graph::createNodes(bool nodegraph)
}
}
drawOutputPins(node, longestInputLabel);
- // set color of output pin
+ // Set color of output pin
if (node->getNode()->getType() == mx::SURFACE_SHADER_TYPE_STRING)
{
if (node->getOutputConnections().size() > 0)
@@ -2241,16 +2292,16 @@ std::vector Graph::createNodes(bool nodegraph)
{
if (_pinFilterType == pin->_type)
{
- DrawPinIcon(pin->_type, true, DEFAULT_ALPHA);
+ drawPinIcon(pin->_type, true, DEFAULT_ALPHA);
}
else
{
- DrawPinIcon(pin->_type, true, FILTER_ALPHA);
+ drawPinIcon(pin->_type, true, FILTER_ALPHA);
}
}
else
{
- DrawPinIcon(pin->_type, true, DEFAULT_ALPHA);
+ drawPinIcon(pin->_type, true, DEFAULT_ALPHA);
}
ImGui::SameLine();
@@ -2311,16 +2362,16 @@ std::vector Graph::createNodes(bool nodegraph)
{
if (_pinFilterType == pin->_type)
{
- DrawPinIcon(pin->_type, true, DEFAULT_ALPHA);
+ drawPinIcon(pin->_type, true, DEFAULT_ALPHA);
}
else
{
- DrawPinIcon(pin->_type, true, FILTER_ALPHA);
+ drawPinIcon(pin->_type, true, FILTER_ALPHA);
}
}
else
{
- DrawPinIcon(pin->_type, true, DEFAULT_ALPHA);
+ drawPinIcon(pin->_type, true, DEFAULT_ALPHA);
}
ImGui::SameLine();
ImGui::TextUnformatted("input");
@@ -2377,7 +2428,6 @@ std::vector Graph::createNodes(bool nodegraph)
return outputNum;
}
-// add mx::InputPtr to node based off of input pin
void Graph::addNodeInput(UiNodePtr node, mx::InputPtr& input)
{
if (node->getNode())
@@ -2433,165 +2483,211 @@ void Graph::setDefaults(mx::InputPtr input)
}
}
-// add link to nodegraph and set up connections between UiNodes and MaterialX Nodes to update shader
-void Graph::AddLink(ed::PinId inputPinId, ed::PinId outputPinId)
+void Graph::addLink(ed::PinId inputPinId, ed::PinId outputPinId)
{
int end_attr = int(outputPinId.Get());
int start_attr = int(inputPinId.Get());
UiPinPtr inputPin = getPin(outputPinId);
UiPinPtr outputPin = getPin(inputPinId);
- if (inputPinId && outputPinId && (outputPin->_type == inputPin->_type))
+
+ if (!inputPin || !outputPin)
{
- if (inputPin->_connected == false)
+ ed::RejectNewItem();
+ return;
+ }
+
+ // Perform type check
+ bool typesMatch = (outputPin->_type == inputPin->_type);
+ if (!typesMatch)
+ {
+ ed::RejectNewItem();
+ showLabel("Invalid connection due to mismatched types", ImColor(50, 50, 50, 255));
+ return;
+ }
+
+ if (inputPin->_connected == false)
+ {
+ int upNode = getNodeId(inputPinId);
+ int downNode = getNodeId(outputPinId);
+ UiNodePtr uiDownNode = _graphNodes[downNode];
+ UiNodePtr uiUpNode = _graphNodes[upNode];
+ if (!uiDownNode || !uiUpNode)
{
- int upNode = getNodeId(inputPinId);
- int downNode = getNodeId(outputPinId);
+ ed::RejectNewItem();
+ return;
+ }
- // make sure there is an implementation for node
- const mx::ShaderGenerator& shadergen = _renderer->getGenContext().getShaderGenerator();
+ // make sure there is an implementation for node
+ const mx::ShaderGenerator& shadergen = _renderer->getGenContext().getShaderGenerator();
+
+ // Prevent direct connecting from input to output
+ if (uiDownNode->getInput() && uiUpNode->getOutput())
+ {
+ ed::RejectNewItem();
+ showLabel("Direct connections between inputs and outputs is invalid", ImColor(50, 50, 50, 255));
+ return;
+ }
- // Find the implementation for this nodedef if not an input or output uinode
- if (_graphNodes[downNode]->getInput() && _isNodeGraph)
+ // Find the implementation for this nodedef if not an input or output uinode
+ if (uiDownNode->getInput() && _isNodeGraph)
+ {
+ ed::RejectNewItem();
+ showLabel("Cannot connect to inputs inside of graph", ImColor(50, 50, 50, 255));
+ return;
+ }
+ else if (uiUpNode->getNode())
+ {
+ mx::ShaderNodeImplPtr impl = shadergen.getImplementation(*_graphNodes[upNode]->getNode()->getNodeDef(), _renderer->getGenContext());
+ if (!impl)
{
ed::RejectNewItem();
- showLabel("Cannot connect to inputs inside of graph", ImColor(50, 50, 50, 255));
+ showLabel("Invalid Connection: Node does not have an implementation", ImColor(50, 50, 50, 255));
return;
}
- else if (_graphNodes[upNode]->getNode())
- {
- mx::ShaderNodeImplPtr impl = shadergen.getImplementation(*_graphNodes[upNode]->getNode()->getNodeDef(), _renderer->getGenContext());
- if (!impl)
- {
- ed::RejectNewItem();
- showLabel("Invalid Connection: Node does not have an implementation", ImColor(50, 50, 50, 255));
- return;
- }
- }
+ }
- if (ed::AcceptNewItem())
- {
- // Since we accepted new link, lets add one to our list of links.
- Link link;
- link._startAttr = start_attr;
- link._endAttr = end_attr;
- _currLinks.push_back(link);
- _frameCount = ImGui::GetFrameCount();
- _renderer->setMaterialCompilation(true);
+ if (ed::AcceptNewItem())
+ {
+ // Since we accepted new link, lets add one to our list of links.
+ Link link;
+ link._startAttr = start_attr;
+ link._endAttr = end_attr;
+ _currLinks.push_back(link);
+ _frameCount = ImGui::GetFrameCount();
+ _renderer->setMaterialCompilation(true);
- if (_graphNodes[downNode]->getNode() || _graphNodes[downNode]->getNodeGraph())
+ if (uiDownNode->getNode() || uiDownNode->getNodeGraph())
+ {
+ mx::InputPtr connectingInput = nullptr;
+ for (UiPinPtr pin : uiDownNode->inputPins)
{
- mx::InputPtr connectingInput = nullptr;
- for (UiPinPtr pin : _graphNodes[downNode]->inputPins)
+ if (pin->_pinId == outputPinId)
{
- if (pin->_pinId == outputPinId)
+ addNodeInput(uiDownNode, pin->_input);
+ // update value to be empty
+ if (uiDownNode->getNode() && uiDownNode->getNode()->getType() == mx::SURFACE_SHADER_TYPE_STRING)
{
- addNodeInput(_graphNodes[downNode], pin->_input);
- // update value to be empty
- if (_graphNodes[downNode]->getNode() && _graphNodes[downNode]->getNode()->getType() == mx::SURFACE_SHADER_TYPE_STRING)
+ if (uiUpNode->getOutput() != nullptr)
{
- if (_graphNodes[upNode]->getOutput() != nullptr)
- {
- pin->_input->setConnectedOutput(_graphNodes[upNode]->getOutput());
- }
- else if (_graphNodes[upNode]->getInput() != nullptr)
- {
- pin->_input->setInterfaceName(_graphNodes[upNode]->getName());
- }
- else
+ pin->_input->setConnectedOutput(uiUpNode->getOutput());
+ }
+ else if (uiUpNode->getInput() != nullptr)
+ {
+ pin->_input->setInterfaceName(uiUpNode->getName());
+ }
+ else
+ {
+ // node graph
+ if (uiUpNode->getNodeGraph() != nullptr)
{
- // node graph
- if (_graphNodes[upNode]->getNodeGraph() != nullptr)
+ for (UiPinPtr outPin : uiUpNode->outputPins)
{
- for (UiPinPtr outPin : _graphNodes[upNode]->outputPins)
+ // set pin connection to correct output
+ if (outPin->_pinId == inputPinId)
{
- // set pin connection to correct output
- if (outPin->_pinId == inputPinId)
- {
- mx::OutputPtr outputs = _graphNodes[upNode]->getNodeGraph()->getOutput(outPin->_name);
- pin->_input->setConnectedOutput(outputs);
- }
+ mx::OutputPtr outputs = uiUpNode->getNodeGraph()->getOutput(outPin->_name);
+ pin->_input->setConnectedOutput(outputs);
}
}
- else
- {
- pin->_input->setConnectedNode(_graphNodes[upNode]->getNode());
- }
}
+ else
+ {
+ pin->_input->setConnectedNode(uiUpNode->getNode());
+ }
+ }
+ }
+ else
+ {
+ if (uiUpNode->getInput())
+ {
+ pin->_input->setInterfaceName(uiUpNode->getName());
}
else
{
- if (_graphNodes[upNode]->getInput())
+ if (uiUpNode->getNode())
{
-
- pin->_input->setInterfaceName(_graphNodes[upNode]->getName());
- }
- else
- {
- if (_graphNodes[upNode]->getNode())
+ mx::NodePtr upstreamNode = _graphNodes[upNode]->getNode();
+ mx::NodeDefPtr upstreamNodeDef = upstreamNode->getNodeDef();
+ bool isMultiOutput = upstreamNodeDef ? upstreamNodeDef->getOutputs().size() > 1 : false;
+
+ // This is purely to avoid adding a reference to an update node only 1 output,
+ // as currently validation consides adding this an error. Otherwise
+ // it will add an "output" attribute all the time.
+ if (!isMultiOutput)
{
- pin->_input->setConnectedNode(_graphNodes[upNode]->getNode());
+ pin->_input->setConnectedNode(uiUpNode->getNode());
}
- else if (_graphNodes[upNode]->getNodeGraph())
+ else
{
for (UiPinPtr outPin : _graphNodes[upNode]->outputPins)
{
// set pin connection to correct output
if (outPin->_pinId == inputPinId)
{
- mx::OutputPtr outputs = _graphNodes[upNode]->getNodeGraph()->getOutput(outPin->_name);
+ mx::OutputPtr outputs = uiUpNode->getNode()->getOutput(outPin->_name);
+ if (!outputs)
+ {
+ outputs = uiUpNode->getNode()->addOutput(outPin->_name, pin->_input->getType());
+ }
pin->_input->setConnectedOutput(outputs);
}
}
}
}
+ else if (uiUpNode->getNodeGraph())
+ {
+ for (UiPinPtr outPin : uiUpNode->outputPins)
+ {
+ // set pin connection to correct output
+ if (outPin->_pinId == inputPinId)
+ {
+ mx::OutputPtr outputs = uiUpNode->getNodeGraph()->getOutput(outPin->_name);
+ pin->_input->setConnectedOutput(outputs);
+ }
+ }
+ }
}
-
- pin->setConnected(true);
- pin->_input->removeAttribute(mx::ValueElement::VALUE_ATTRIBUTE);
- connectingInput = pin->_input;
- break;
}
+
+ pin->setConnected(true);
+ pin->_input->removeAttribute(mx::ValueElement::VALUE_ATTRIBUTE);
+ connectingInput = pin->_input;
+ break;
}
- // create new edge and set edge information
- createEdge(_graphNodes[upNode], _graphNodes[downNode], connectingInput);
}
- else if (_graphNodes[downNode]->getOutput() != nullptr)
- {
- mx::InputPtr connectingInput = nullptr;
- _graphNodes[downNode]->getOutput()->setConnectedNode(_graphNodes[upNode]->getNode());
+ // create new edge and set edge information
+ createEdge(_graphNodes[upNode], _graphNodes[downNode], connectingInput);
+ }
+ else if (_graphNodes[downNode]->getOutput() != nullptr)
+ {
+ mx::InputPtr connectingInput = nullptr;
+ _graphNodes[downNode]->getOutput()->setConnectedNode(_graphNodes[upNode]->getNode());
- // create new edge and set edge information
- createEdge(_graphNodes[upNode], _graphNodes[downNode], connectingInput);
- }
- else
+ // create new edge and set edge information
+ createEdge(_graphNodes[upNode], _graphNodes[downNode], connectingInput);
+ }
+ else
+ {
+ // create new edge and set edge info
+ UiEdge newEdge = UiEdge(_graphNodes[upNode], _graphNodes[downNode], nullptr);
+ if (!edgeExists(newEdge))
{
- // create new edge and set edge info
- UiEdge newEdge = UiEdge(_graphNodes[upNode], _graphNodes[downNode], nullptr);
- if (!edgeExists(newEdge))
- {
- _graphNodes[downNode]->edges.push_back(newEdge);
- _currEdge.push_back(newEdge);
+ _graphNodes[downNode]->edges.push_back(newEdge);
+ _currEdge.push_back(newEdge);
- // update input node num and output connections
- _graphNodes[downNode]->setInputNodeNum(1);
- _graphNodes[upNode]->setOutputConnection(_graphNodes[downNode]);
- }
+ // update input node num and output connections
+ _graphNodes[downNode]->setInputNodeNum(1);
+ _graphNodes[upNode]->setOutputConnection(_graphNodes[downNode]);
}
}
}
- else
- {
- ed::RejectNewItem();
- }
}
else
{
ed::RejectNewItem();
- showLabel("Invalid Connection due to Mismatch Types", ImColor(50, 50, 50, 255));
}
}
-// remove node edge based of off connecting input
void Graph::removeEdge(int downNode, int upNode, UiPinPtr pin)
{
int num = _graphNodes[downNode]->getEdgeIndex(_graphNodes[upNode]->getId(), pin);
@@ -2607,9 +2703,7 @@ void Graph::removeEdge(int downNode, int upNode, UiPinPtr pin)
}
}
- // downNode set node num -1
_graphNodes[downNode]->setInputNodeNum(-1);
- // upNode remove outputconnection
_graphNodes[upNode]->removeOutputConnection(_graphNodes[downNode]->getName());
}
@@ -2617,8 +2711,8 @@ void Graph::deleteLinkInfo(int startAttr, int endAttr)
{
int upNode = getNodeId(startAttr);
int downNode = getNodeId(endAttr);
- // change input so that is default val
- // change informtion of actual mx::Node
+
+ // Change input to default value
if (_graphNodes[downNode]->getNode())
{
mx::NodeDefPtr nodeDef = _graphNodes[downNode]->getNode()->getNodeDef(_graphNodes[downNode]->getNode()->getName());
@@ -2639,14 +2733,18 @@ void Graph::deleteLinkInfo(int startAttr, int endAttr)
}
if (_graphNodes[upNode]->getInput())
{
- // remove interface value in order to set the default of the input
+ // Remove interface value in order to set the default of the input
pin->_input->removeAttribute(mx::ValueElement::INTERFACE_NAME_ATTRIBUTE);
setDefaults(pin->_input);
setDefaults(_graphNodes[upNode]->getInput());
}
+ // Remove any output reference
+ pin->_input->removeAttribute(mx::PortElement::OUTPUT_ATTRIBUTE);
+
pin->setConnected(false);
- // if a value exists update the input with it
+
+ // If a value exists update the input with it
if (val)
{
pin->_input->setValueString(val->getValueString());
@@ -2656,7 +2754,7 @@ void Graph::deleteLinkInfo(int startAttr, int endAttr)
}
else if (_graphNodes[downNode]->getNodeGraph())
{
- // set default values for nodegraph node pins ie nodegraph inputs
+ // Set default values for nodegraph node pins ie nodegraph inputs
mx::NodeDefPtr nodeDef = _graphNodes[downNode]->getNodeGraph()->getNodeDef();
for (UiPinPtr pin : _graphNodes[downNode]->inputPins)
{
@@ -2687,7 +2785,7 @@ void Graph::deleteLinkInfo(int startAttr, int endAttr)
}
}
}
-// delete link from currLink vector and remove any connections in UiNode or MaterialX Nodes to update shader
+
void Graph::deleteLink(ed::LinkId deletedLinkId)
{
// If you agree that link can be deleted, accept deletion.
@@ -2696,10 +2794,11 @@ void Graph::deleteLink(ed::LinkId deletedLinkId)
_renderer->setMaterialCompilation(true);
_frameCount = ImGui::GetFrameCount();
int link_id = int(deletedLinkId.Get());
+
// Then remove link from your data.
int pos = findLinkPosition(link_id);
- // link start -1 equals node num
+ // Link start -1 equals node num
Link currLink = _currLinks[pos];
deleteLinkInfo(currLink._startAttr, currLink._endAttr);
_currLinks.erase(_currLinks.begin() + pos);
@@ -2708,7 +2807,7 @@ void Graph::deleteLink(ed::LinkId deletedLinkId)
void Graph::deleteNode(UiNodePtr node)
{
- // delete link
+ // Delete link
for (UiPinPtr inputPin : node->inputPins)
{
UiNodePtr upNode = node->getConnectedNode(inputPin->_name);
@@ -2716,7 +2815,8 @@ void Graph::deleteNode(UiNodePtr node)
{
upNode->removeOutputConnection(node->getName());
int num = node->getEdgeIndex(upNode->getId(), inputPin);
- // erase edge between node and up node
+
+ // Erase edge between node and up node
if (num != -1)
{
if (node->edges.size() == 1)
@@ -2733,7 +2833,7 @@ void Graph::deleteNode(UiNodePtr node)
if (node->outputPins.size() > 0)
{
- // update downNode info
+ // Update downNode info
for (UiPinPtr pin : node->outputPins.front()->getConnections())
{
mx::ValuePtr val;
@@ -2741,7 +2841,7 @@ void Graph::deleteNode(UiNodePtr node)
{
mx::NodeDefPtr nodeDef = pin->_pinNode->getNode()->getNodeDef(pin->_pinNode->getNode()->getName());
val = nodeDef->getActiveInput(pin->_input->getName())->getValue();
- if (pin->_pinNode->getNode()->getType() == "surfaceshader")
+ if (pin->_pinNode->getNode()->getType() == mx::SURFACE_SHADER_TYPE_STRING)
{
pin->_input->setConnectedOutput(nullptr);
}
@@ -2782,19 +2882,19 @@ void Graph::deleteNode(UiNodePtr node)
}
pin->_pinNode->setInputNodeNum(-1);
- // not really necessary since it will be deleted
+
+ // Not really necessary since it will be deleted
node->removeOutputConnection(pin->_pinNode->getName());
}
}
- // remove from NodeGraph
- // all link information is handled in delete link which is called before this
+ // Remove from NodeGraph
+ // All link information is handled in delete link which is called before this
int nodeNum = findNode(node->getId());
_currGraphElem->removeChild(node->getName());
_graphNodes.erase(_graphNodes.begin() + nodeNum);
}
-// create pins for outputs/inputs added while inside the node graph
void Graph::addNodeGraphPins()
{
for (UiNodePtr node : _graphNodes)
@@ -2893,18 +2993,34 @@ void Graph::clearGraph()
_renderer->updateMaterials(nullptr);
}
-void Graph::loadGraphFromFile()
+void Graph::loadGraphFromFile(bool prompt)
{
- // deselect node before loading new file
- if (_currUiNode != nullptr)
+ // Deselect node before loading new file
+ if (_currUiNode)
{
ed::DeselectNode(_currUiNode->getId());
_currUiNode = nullptr;
}
- _fileDialog.setTitle("Open File");
- _fileDialog.setTypeFilters(_mtlxFilter);
- _fileDialog.open();
+ if (prompt || _materialFilename.isEmpty())
+ {
+ _fileDialog.setTitle("Open File");
+ _fileDialog.setTypeFilters(_mtlxFilter);
+ _fileDialog.open();
+ }
+ else
+ {
+ _graphDoc = loadDocument(_materialFilename);
+
+ // Rebuild the UI
+ _initial = true;
+ buildUiBaseGraph(_graphDoc);
+ _currGraphElem = _graphDoc;
+ _prevUiNode = nullptr;
+
+ _renderer->setDocument(_graphDoc);
+ _renderer->updateMaterials(nullptr);
+ }
}
void Graph::saveGraphToFile()
@@ -2930,15 +3046,18 @@ void Graph::graphButtons()
{
if (ImGui::BeginMenu("File"))
{
- // buttons for loading and saving a .mtlx
- // new Material button
+ // Buttons for loading and saving a .mtlx
if (ImGui::MenuItem("New", "Ctrl-N"))
{
clearGraph();
}
else if (ImGui::MenuItem("Open", "Ctrl-O"))
{
- loadGraphFromFile();
+ loadGraphFromFile(true);
+ }
+ else if (ImGui::MenuItem("Reload", "Ctrl-R"))
+ {
+ loadGraphFromFile(false);
}
else if (ImGui::MenuItem("Save", "Ctrl-S"))
{
@@ -2965,6 +3084,12 @@ void Graph::graphButtons()
ImGui::EndMenu();
}
+ if (ImGui::BeginMenu("Options"))
+ {
+ ImGui::Checkbox("Save Node Positions", &_saveNodePositions);
+ ImGui::EndMenu();
+ }
+
if (ImGui::Button("Help"))
{
ImGui::OpenPopup("Help");
@@ -2984,23 +3109,28 @@ void Graph::graphButtons()
{
if (ImGui::IsKeyReleased(ImGuiKey_O))
{
- loadGraphFromFile();
+ loadGraphFromFile(true);
}
else if (ImGui::IsKeyReleased(ImGuiKey_N))
{
clearGraph();
}
+ else if (ImGui::IsKeyReleased(ImGuiKey_R))
+ {
+ loadGraphFromFile(false);
+ }
else if (ImGui::IsKeyReleased(ImGuiKey_S))
{
saveGraphToFile();
}
}
- // split window into panes for NodeEditor
+ // Split window into panes for NodeEditor
static float leftPaneWidth = 375.0f;
static float rightPaneWidth = 750.0f;
- Splitter(true, 4.0f, &leftPaneWidth, &rightPaneWidth, 20.0f, 20.0f);
- // create back button and graph hiearchy name display
+ splitter(true, 4.0f, &leftPaneWidth, &rightPaneWidth, 20.0f, 20.0f);
+
+ // Create back button and graph hierarchy name display
ImGui::Indent(leftPaneWidth + 15.f);
if (ImGui::Button("<"))
{
@@ -3024,20 +3154,21 @@ void Graph::graphButtons()
ImGui::Unindent(leftPaneWidth + 15.f);
ImGui::PopStyleColor();
ImGui::NewLine();
- // creating two windows using splitter
+
+ // Create two windows using splitter
float paneWidth = (leftPaneWidth - 2.0f);
ImGui::BeginChild("Selection", ImVec2(paneWidth, 0));
ImVec2 windowPos = ImGui::GetWindowPos();
- // renderView window
+
+ // 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]);
- if (_renderer != nullptr)
+ if (_renderer)
{
-
glEnable(GL_FRAMEBUFFER_SRGB);
_renderer->getViewCamera()->setViewportSize(mx::Vector2(screenSize[0], screenSize[1]));
GLuint64 my_image_texture = _renderer->_textureID;
@@ -3047,19 +3178,20 @@ void Graph::graphButtons()
}
ImGui::Separator();
- // property editor for current nodes
+ // Property editor for current nodes
propertyEditor();
ImGui::EndChild();
ImGui::SameLine(0.0f, 12.0f);
handleRenderViewInputs(windowPos, screenSize[0], screenSize[1]);
}
+
void Graph::propertyEditor()
{
ImGui::Text("Node Property Editor");
if (_currUiNode)
{
- // set and edit name
+ // Set and edit name
ImGui::Text("Name: ");
ImGui::SameLine();
std::string original = _currUiNode->getName();
@@ -3095,9 +3227,7 @@ void Graph::propertyEditor()
{
if (temp != original)
{
-
std::string name = _currUiNode->getInput()->getParent()->createValidChildName(temp);
-
std::vector downstreamNodes = _currUiNode->getOutputConnections();
for (UiNodePtr nodes : downstreamNodes)
{
@@ -3157,7 +3287,8 @@ void Graph::propertyEditor()
ImGui::Text("Category:");
ImGui::SameLine();
- // change button color to match background
+
+ // Change button color to match background
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.096f, .096f, .096f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.1f, .1f, .1f, 1.0f));
if (_currUiNode->getNode())
@@ -3202,7 +3333,8 @@ void Graph::propertyEditor()
mx::getUIProperties(input->_input, mx::EMPTY_STRING, uiProperties);
std::string inputLabel = !uiProperties.uiName.empty() ? uiProperties.uiName : input->_input->getName();
mx::OutputPtr out = input->_input->getConnectedOutput();
- // setting comment help box
+
+ // Set comment help box
ImGui::PushID(int(input->_pinId.Get()));
ImGui::Text("%s", inputLabel.c_str());
mx::InputPtr tempInt = _currUiNode->getNode()->getNodeDef()->getActiveInput(input->_input->getName());
@@ -3218,7 +3350,7 @@ void Graph::propertyEditor()
}
docString += "\t \n";
- // setting constant sliders for input values
+ // Set constant sliders for input values
ImGui::TableNextColumn();
if (!input->getConnected())
{
@@ -3265,13 +3397,13 @@ void Graph::propertyEditor()
mx::getUIProperties(mxinput, mx::EMPTY_STRING, uiProperties);
std::string inputLabel = !uiProperties.uiName.empty() ? uiProperties.uiName : mxinput->getName();
- // setting comment help box
+ // Set comment help box
ImGui::PushID(int(inputs[i]->_pinId.Get()));
ImGui::Text("%s", inputLabel.c_str());
ImGui::TableNextColumn();
- // setting constant sliders for input values
+ // Set constant sliders for input values
if (!inputs[i]->getConnected())
{
setConstant(_currUiNode, inputs[i]->_input, uiProperties);
@@ -3324,7 +3456,7 @@ void Graph::propertyEditor()
mx::getUIProperties(mxinput, mx::EMPTY_STRING, uiProperties);
std::string inputLabel = !uiProperties.uiName.empty() ? uiProperties.uiName : mxinput->getName();
- // setting comment help box
+ // Set comment help box
ImGui::PushID(int(input->_pinId.Get()));
ImGui::Text("%s", inputLabel.c_str());
@@ -3368,7 +3500,6 @@ void Graph::propertyEditor()
}
}
-// Helper to display basic user controls.
void Graph::showHelp() const
{
ImGui::Text("MATERIALX GRAPH EDITOR HELP");
@@ -3431,11 +3562,13 @@ void Graph::addNodePopup(bool cursor)
}
ImGui::InputText("##input", input, sizeof(input));
std::string subs(input);
- // input string length
- // filter extra nodes - includes inputs, outputs, groups, and node graphs
+
+ // Input string length
+ // Filter extra nodes - includes inputs, outputs, groups, and node graphs
+ const std::string NODEGRAPH_ENTRY = "Node Graph";
for (std::unordered_map>>::iterator it = _extraNodes.begin(); it != _extraNodes.end(); ++it)
{
- // filter out list of nodes
+ // Filter out list of nodes
if (subs.size() > 0)
{
ImGui::SetNextWindowSizeConstraints(ImVec2(250.0f, 300.0f), ImVec2(-1.0f, 500.0f));
@@ -3443,14 +3576,21 @@ void Graph::addNodePopup(bool cursor)
{
std::string str(it->second[i][0]);
std::string nodeName = it->second[i][0];
- // allow spaces to be used to search for node names
+
+ // Disallow creating nested nodegraphs
+ if (_isNodeGraph && it->first == NODEGRAPH_ENTRY)
+ {
+ continue;
+ }
+
+ // Allow spaces to be used to search for node names
std::replace(subs.begin(), subs.end(), ' ', '_');
if (str.find(subs) != std::string::npos)
{
- if (ImGui::MenuItem(getNodeDefId(nodeName).c_str()) || (ImGui::IsItemFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Enter)))
+ if (ImGui::MenuItem(getUserNodeDefName(nodeName).c_str()) || (ImGui::IsItemFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Enter)))
{
- addNode(it->second[i][2], getNodeDefId(nodeName), it->second[i][1]);
+ addNode(it->second[i][2], getUserNodeDefName(nodeName), it->second[i][1]);
_addNewNode = true;
memset(input, '\0', sizeof(input));
}
@@ -3466,9 +3606,9 @@ void Graph::addNodePopup(bool cursor)
for (size_t j = 0; j < it->second.size(); j++)
{
std::string name = it->second[j][0];
- if (ImGui::MenuItem(getNodeDefId(name).c_str()) || (ImGui::IsItemFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Enter)))
+ if (ImGui::MenuItem(getUserNodeDefName(name).c_str()) || (ImGui::IsItemFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Enter)))
{
- addNode(it->second[j][2], getNodeDefId(name), it->second[j][1]);
+ addNode(it->second[j][2], getUserNodeDefName(name), it->second[j][1]);
_addNewNode = true;
}
}
@@ -3476,10 +3616,11 @@ void Graph::addNodePopup(bool cursor)
}
}
}
- // filter nodedefs and add to menu if matches filter
+
+ // Filter nodedefs and add to menu if matches filter
for (std::unordered_map>::iterator it = _nodesToAdd.begin(); it != _nodesToAdd.end(); ++it)
{
- // filter out list of nodes
+ // Filter out list of nodes
if (subs.size() > 0)
{
ImGui::SetNextWindowSizeConstraints(ImVec2(250.0f, 300.0f), ImVec2(-1.0f, 500.0f));
@@ -3489,7 +3630,7 @@ void Graph::addNodePopup(bool cursor)
std::string nodeName = it->second[i]->getName();
if (str.find(subs) != std::string::npos)
{
- std::string val = getNodeDefId(nodeName);
+ std::string val = getUserNodeDefName(nodeName);
if (ImGui::MenuItem(val.c_str()) || (ImGui::IsItemFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Enter)))
{
addNode(it->second[i]->getNodeString(), val, it->second[i]->getType());
@@ -3508,7 +3649,7 @@ void Graph::addNodePopup(bool cursor)
for (size_t i = 0; i < it->second.size(); i++)
{
std::string name = it->second[i]->getName();
- std::string val = getNodeDefId(name);
+ std::string val = getUserNodeDefName(name);
if (ImGui::MenuItem(val.c_str()) || (ImGui::IsItemFocused() && ImGui::IsKeyPressedMap(ImGuiKey_Enter)))
{
addNode(it->second[i]->getNodeString(), val, it->second[i]->getType());
@@ -3524,6 +3665,7 @@ void Graph::addNodePopup(bool cursor)
open_AddPopup = false;
}
}
+
void Graph::searchNodePopup(bool cursor)
{
const bool open_search = ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows) && ImGui::IsKeyDown(ImGuiKey_F) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl);
@@ -3547,7 +3689,6 @@ void Graph::searchNodePopup(bool cursor)
if (std::string(input).size() > 0)
{
-
for (UiNodePtr node : _graphNodes)
{
if (node->getName().find(std::string(input)) != std::string::npos)
@@ -3581,7 +3722,6 @@ void Graph::readOnlyPopup()
}
}
-// compiling shaders message
void Graph::shaderPopup()
{
if (_renderer->getMaterialCompilation())
@@ -3601,7 +3741,6 @@ void Graph::shaderPopup()
}
}
-// allow for camera manipulation of render view window
void Graph::handleRenderViewInputs(ImVec2 minValue, float width, float height)
{
ImVec2 mousePos = ImGui::GetMousePos();
@@ -3645,14 +3784,15 @@ void Graph::handleRenderViewInputs(ImVec2 minValue, float width, float height)
{
_renderer->setKeyEvent(ImGuiKey_KeypadSubtract);
}
- // scrolling not possible if open or save file dialog is open
+
+ // Scrolling not possible if open or save file dialog is open
if (scrollAmt != 0 && !_fileDialogSave.isOpened() && !_fileDialog.isOpened() && !_fileDialogGeom.isOpened())
{
_renderer->setScrollEvent(scrollAmt);
}
}
}
-// sets up graph editor
+
void Graph::drawGraph(ImVec2 mousePos)
{
if (_searchNodeId > 0)
@@ -3663,7 +3803,8 @@ void Graph::drawGraph(ImVec2 mousePos)
}
bool TextCursor = false;
- // center imgui window and setting size
+
+ // Center imgui window and set size
ImGuiIO& io2 = ImGui::GetIO();
ImGui::SetNextWindowSize(io2.DisplaySize);
ImGui::SetNextWindowPos(ImVec2(io2.DisplaySize.x * 0.5f, io2.DisplaySize.y * 0.5f), ImGuiCond_Always, ImVec2(0.5f, 0.5f));
@@ -3676,7 +3817,8 @@ void Graph::drawGraph(ImVec2 mousePos)
ed::Begin("My Editor");
{
ed::Suspend();
- // set up pop ups for adding a node when tab is pressed
+
+ // Set up popups for adding a node when tab is pressed
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.f, 8.f));
ImGui::SetNextWindowSizeConstraints(ImVec2(250.0f, 300.0f), ImVec2(-1.0f, 500.0f));
addNodePopup(TextCursor);
@@ -3686,7 +3828,7 @@ void Graph::drawGraph(ImVec2 mousePos)
ed::Resume();
- // Gathering selected nodes / links - from ImGui Node Editor blueprints-example.cpp
+ // Gather selected nodes / links - from ImGui Node Editor blueprints-example.cpp
std::vector selectedNodes;
std::vector selectedLinks;
selectedNodes.resize(ed::GetSelectedObjectCount());
@@ -3702,29 +3844,23 @@ void Graph::drawGraph(ImVec2 mousePos)
_ctrlClick = true;
}
- // setting current node based off of selected node
+ // Set current node based off of selected node
if (selectedNodes.size() > 0)
{
int graphPos = findNode(int(selectedNodes[0].Get()));
if (graphPos > -1)
{
- // only selected not if its not the same as previously selected
+ // Only selected if its not the same as previously selected
if (!_prevUiNode || (_prevUiNode->getName() != _graphNodes[graphPos]->getName()))
{
_currUiNode = _graphNodes[graphPos];
- // update render material if needed
+
+ // Update render material if needed
if (_currUiNode->getNode())
- {
- if (_currUiNode->getNode()->getType() == mx::SURFACE_SHADER_TYPE_STRING || _currUiNode->getNode()->getType() == mx::MATERIAL_TYPE_STRING)
- {
- setRenderMaterial(_currUiNode);
- }
- }
- else if (_currUiNode->getNodeGraph())
{
setRenderMaterial(_currUiNode);
}
- else if (_currUiNode->getOutput())
+ else if (_currUiNode->getNodeGraph() || _currUiNode->getOutput())
{
setRenderMaterial(_currUiNode);
}
@@ -3733,7 +3869,7 @@ void Graph::drawGraph(ImVec2 mousePos)
}
}
- // check if keyboard shortcuts for copy/cut/paste have been used
+ // Check if keyboard shortcuts for copy/cut/paste have been used
if (ed::BeginShortcut())
{
if (ed::AcceptCopy())
@@ -3753,7 +3889,8 @@ void Graph::drawGraph(ImVec2 mousePos)
if (!readOnly())
{
_copiedNodes.clear();
- // same as copy but remove from graphNodes
+
+ // Same as copy but remove from graphNodes
for (ed::NodeId selected : selectedNodes)
{
int pos = findNode((int) selected.Get());
@@ -3786,40 +3923,44 @@ void Graph::drawGraph(ImVec2 mousePos)
}
}
- // set y position of first node
+ // Set y-position of first node
std::vector outputNum = createNodes(_isNodeGraph);
- // address copy information if applicable and relink graph if a new node has been added
+ // Address copy information if applicable and relink graph if a new node has been added
if (_addNewNode)
{
copyInputs();
linkGraph();
ImVec2 canvasPos = ed::ScreenToCanvas(mousePos);
- // place the copied nodes or the individual new nodes
- if ((int) _copiedNodes.size() > 0)
+
+ // Place the copied nodes or the individual new nodes
+ if (!_copiedNodes.empty())
{
positionPasteBin(canvasPos);
}
- else
+ else if (!_graphNodes.empty())
{
ed::SetNodePosition(_graphNodes.back()->getId(), canvasPos);
}
_copiedNodes.clear();
_addNewNode = false;
}
- // layout and link graph during the initial call of drawGraph()
+
+ // Layout and link graph during the initial call of drawGraph
if (_initial || _autoLayout)
{
_currLinks.clear();
float y = 0.f;
_levelMap = std::unordered_map>();
- // start layout with output or material nodes since layout algorithm works right to left
+
+ // Start layout with output or material nodes since layout algorithm works right to left
for (int outN : outputNum)
{
layoutPosition(_graphNodes[outN], ImVec2(1200.f, y), true, 0);
y += 350;
}
- // if there are no output or material nodes but the nodes have position layout each individual node
+
+ // If there are no output or material nodes but the nodes have position layout each individual node
if (_graphNodes.size() > 0)
{
@@ -3834,7 +3975,8 @@ void Graph::drawGraph(ImVec2 mousePos)
linkGraph();
findYSpacing(0.f);
layoutInputs();
- // automatically frame node graph upon loading
+
+ // Automatically frame node graph upon loading
ed::NavigateToContent();
}
if (_delete)
@@ -3844,13 +3986,15 @@ void Graph::drawGraph(ImVec2 mousePos)
_delete = false;
}
connectLinks();
- // set to false after intial layout so that nodes can be moved
+
+ // Set to false after intial layout so that nodes can be moved
_initial = false;
_autoLayout = false;
- // delete selected nodes and their links if delete key is pressed or if the shortcut for cut is used
+
+ // Delete selected nodes and their links if delete key is pressed
+ // or if the shortcut for cut is used
if (ImGui::IsKeyReleased(ImGuiKey_Delete) || _isCut)
{
-
if (selectedNodes.size() > 0)
{
_frameCount = ImGui::GetFrameCount();
@@ -3880,24 +4024,25 @@ void Graph::drawGraph(ImVec2 mousePos)
_isCut = false;
}
- // start the session with content centered
+ // Start the session with content centered
if (ImGui::GetFrameCount() == 2)
{
ed::NavigateToContent(0.0f);
}
- // hotkey to frame selected node(s)
+ // Hotkey to frame selected node(s)
if (ImGui::IsKeyReleased(ImGuiKey_F) && !_fileDialogSave.isOpened())
{
ed::NavigateToSelection();
}
- // go back up from inside a subgraph
+ // Go back up from inside a subgraph
if (ImGui::IsKeyReleased(ImGuiKey_U) && (!ImGui::IsPopupOpen("add node")) && (!ImGui::IsPopupOpen("search")) && !_fileDialogSave.isOpened())
{
upNodeGraph();
}
- // adding new link
+
+ // Add new link
if (ed::BeginCreate())
{
ed::PinId inputPinId, outputPinId, filterPinId;
@@ -3905,7 +4050,7 @@ void Graph::drawGraph(ImVec2 mousePos)
{
if (!readOnly())
{
- AddLink(inputPinId, outputPinId);
+ addLink(inputPinId, outputPinId);
}
else
{
@@ -3925,7 +4070,8 @@ void Graph::drawGraph(ImVec2 mousePos)
_pinFilterType = mx::EMPTY_STRING;
}
ed::EndCreate();
- // deleting link
+
+ // Delete link
if (ed::BeginDelete())
{
ed::LinkId deletedLinkId;
@@ -3944,7 +4090,7 @@ void Graph::drawGraph(ImVec2 mousePos)
ed::EndDelete();
}
- // diving into a node that has a subgraph
+ // Dive into a node that has a subgraph
ed::NodeId clickedNode = ed::GetDoubleClickedNode();
if (clickedNode.Get() > 0)
{
@@ -3952,9 +4098,9 @@ void Graph::drawGraph(ImVec2 mousePos)
{
if (_currUiNode->getNode() != nullptr)
{
-
mx::InterfaceElementPtr impl = _currUiNode->getNode()->getImplementation();
- // only dive if current node is a node graph
+
+ // Only dive if current node is a node graph
if (impl && impl->isA())
{
savePosition();
@@ -4022,22 +4168,21 @@ void Graph::drawGraph(ImVec2 mousePos)
ed::Suspend();
_fileDialogSave.display();
- // saving file
+
+ // Save file
if (_fileDialogSave.hasSelected())
{
-
std::string message;
if (!_graphDoc->validate(&message))
{
std::cerr << "*** Validation warnings for " << _materialFilename.getBaseName() << " ***" << std::endl;
std::cerr << message;
}
- std::string fileName = _fileDialogSave.getSelected();
- mx::FilePath name = _fileDialogSave.getSelected();
+ _materialFilename = _fileDialogSave.getSelected();
ed::Resume();
savePosition();
- writeText(fileName, name);
+ saveDocument(_materialFilename);
_fileDialogSave.clearSelected();
}
else
@@ -4049,7 +4194,8 @@ void Graph::drawGraph(ImVec2 mousePos)
ImGui::End();
_fileDialog.display();
- // create and load document from selected file
+
+ // Create and load document from selected file
if (_fileDialog.hasSelected())
{
mx::FilePath fileName = _fileDialog.getSelected();
@@ -4057,7 +4203,6 @@ void Graph::drawGraph(ImVec2 mousePos)
std::string graphName = fileName.getBaseName();
_currGraphName.push_back(graphName.substr(0, graphName.length() - 5));
_graphDoc = loadDocument(fileName);
- _graphDoc->importLibrary(_stdLib);
_initial = true;
buildUiBaseGraph(_graphDoc);
@@ -4081,7 +4226,6 @@ void Graph::drawGraph(ImVec2 mousePos)
_fileDialogImage.display();
}
-// return node location in graphNodes vector based off of node id
int Graph::findNode(int nodeId)
{
int count = 0;
@@ -4096,7 +4240,6 @@ int Graph::findNode(int nodeId)
return -1;
}
-// find a link based on an attribute id
std::vector Graph::findLinkId(int id)
{
std::vector ids;
@@ -4109,7 +4252,7 @@ std::vector Graph::findLinkId(int id)
}
return ids;
}
-// check if current edge is already in edge vector
+
bool Graph::edgeExists(UiEdge newEdge)
{
if (_currEdge.size() > 0)
@@ -4145,7 +4288,6 @@ bool Graph::edgeExists(UiEdge newEdge)
return false;
}
-// check if a link exists in currLink vector
bool Graph::linkExists(Link newLink)
{
for (const auto& link : _currLinks)
@@ -4154,7 +4296,6 @@ bool Graph::linkExists(Link newLink)
{
if (link._endAttr == newLink._endAttr)
{
- // link exists
return true;
}
}
@@ -4162,7 +4303,6 @@ bool Graph::linkExists(Link newLink)
{
if (link._endAttr == newLink._startAttr)
{
- // link exists
return true;
}
}
@@ -4170,12 +4310,11 @@ bool Graph::linkExists(Link newLink)
return false;
}
-// set materialX attribute positions for nodes which changed pos
void Graph::savePosition()
{
for (UiNodePtr node : _graphNodes)
{
- if (node->getMxElement() != nullptr)
+ if (node->getMxElement())
{
ImVec2 pos = ed::GetNodePosition(node->getId());
pos.x /= DEFAULT_NODE_SIZE.x;
@@ -4189,14 +4328,27 @@ void Graph::savePosition()
}
}
}
-void Graph::writeText(std::string fileName, mx::FilePath filePath)
+void Graph::saveDocument(mx::FilePath filePath)
{
if (filePath.getExtension() != mx::MTLX_EXTENSION)
{
filePath.addExtension(mx::MTLX_EXTENSION);
}
+ mx::DocumentPtr writeDoc = _graphDoc;
+
+ // If requested, create a modified version of the document for saving.
+ if (!_saveNodePositions)
+ {
+ writeDoc = _graphDoc->copy();
+ for (mx::ElementPtr elem : writeDoc->traverseTree())
+ {
+ elem->removeAttribute("xpos");
+ elem->removeAttribute("ypos");
+ }
+ }
+
mx::XmlWriteOptions writeOptions;
writeOptions.elementPredicate = getElementPredicate();
- mx::writeToXmlFile(_graphDoc, filePath, &writeOptions);
+ mx::writeToXmlFile(writeDoc, filePath, &writeOptions);
}
diff --git a/source/MaterialXGraphEditor/Graph.h b/source/MaterialXGraphEditor/Graph.h
index 68140cdaae..8c76f0f68d 100644
--- a/source/MaterialXGraphEditor/Graph.h
+++ b/source/MaterialXGraphEditor/Graph.h
@@ -60,105 +60,160 @@ class Graph
private:
mx::ElementPredicate getElementPredicate() const;
void loadStandardLibraries();
+
+ // Generate node UI from nodedefs
void createNodeUIList(mx::DocumentPtr doc);
+
+ // Build UiNode nodegraph upon loading a document
void buildUiBaseGraph(mx::DocumentPtr doc);
+
+ // Build UiNode node graph upon diving into a nodegraph node
void buildUiNodeGraph(const mx::NodeGraphPtr& nodeGraphs);
+
+ // Based on the comment node in the ImGui Node Editor blueprints-example.cpp.
void buildGroupNode(UiNodePtr node);
- // handling link information
+ // Connect links via connected nodes in UiNodePtr
void linkGraph();
+
+ // Connect all links via the graph editor library
void connectLinks();
+
+ // Find link position in current links vector from link id
int findLinkPosition(int id);
+
+ // Find link from attribute id
std::vector findLinkId(int attrId);
+
+ // Check if link exists in the current link vector
bool linkExists(Link newLink);
- void AddLink(ed::PinId inputPinId, ed::PinId outputPinId);
+
+ // Add link to nodegraph and set up connections between UiNodes and
+ // MaterialX Nodes to update shader
+ void addLink(ed::PinId inputPinId, ed::PinId outputPinId);
+
+ // Delete link from current link vector and remove any connections in
+ // UiNode or MaterialX Nodes to update shader
void deleteLink(ed::LinkId deletedLinkId);
+
void deleteLinkInfo(int startAtrr, int endAttr);
- // functions for the layout of the nodes
+ // Layout the x-position by assigning the node levels based on its distance from the first node
ImVec2 layoutPosition(UiNodePtr node, ImVec2 pos, bool initialLayout, int level);
+
+ // Extra layout pass for inputs and nodes that do not attach to an output node
void layoutInputs();
+
void findYSpacing(float startPos);
float totalHeight(int level);
void setYSpacing(int level, float startingPos);
float findAvgY(const std::vector& nodes);
- // pin information
+ // Return pin color based on the type of the value of that pin
void setPinColor();
- void DrawPinIcon(std::string type, bool connected, int alpha);
+
+ // Based on the pin icon function in the ImGui Node Editor blueprints-example.cpp
+ void drawPinIcon(std::string type, bool connected, int alpha);
+
UiPinPtr getPin(ed::PinId id);
void drawInputPin(UiPinPtr pin);
+
+ // Return output pin needed to link the inputs and outputs
ed::PinId getOutputPin(UiNodePtr node, UiNodePtr inputNode, UiPinPtr input);
+
void drawOutputPins(UiNodePtr node, const std::string& longestInputLabel);
+
+ // Create pins for outputs/inputs added while inside the node graph
void addNodeGraphPins();
- // UiNode functions
std::vector createNodes(bool nodegraph);
int getNodeId(ed::PinId pinId);
+
+ // Find node location in graph nodes vector from node id
int findNode(int nodeId);
+
+ // Return node position in _graphNodes from node name and type to account for
+ // input/output UiNodes with same names as MaterialX nodes
int findNode(const std::string& name, const std::string& type);
+
+ // Add node to graphNodes based on nodedef information
void addNode(const std::string& category, const std::string& name, const std::string& type);
+
void deleteNode(UiNodePtr node);
+
+ // Build the initial graph of a loaded document including shader, material and nodegraph node
void setUiNodeInfo(UiNodePtr node, const std::string& type, const std::string& category);
- // UiEdge functions
+ // Check if edge exists in edge vector
bool edgeExists(UiEdge edge);
+
void createEdge(UiNodePtr upNode, UiNodePtr downNode, mx::InputPtr connectingInput);
+
+ // Remove node edge based on connecting input
void removeEdge(int downNode, int upNode, UiPinPtr pin);
- void writeText(std::string filename, mx::FilePath filePath);
+ void saveDocument(mx::FilePath filePath);
+
+ // Set position attributes for nodes which changed position
void savePosition();
+
+ // Check if node has already been assigned a position
bool checkPosition(UiNodePtr node);
+ // Add input pointer to node based on input pin
void addNodeInput(UiNodePtr node, mx::InputPtr& input);
- mx::InputPtr findInput(mx::InputPtr input, std::string name);
- // travel up from inside a node graph
+ mx::InputPtr findInput(mx::InputPtr input, const std::string& name);
void upNodeGraph();
- // property editor information
+ // Set the value of the selected node constants in the node property editor
void setConstant(UiNodePtr node, mx::InputPtr& input, const mx::UIProperties& uiProperties);
+
void propertyEditor();
void setDefaults(mx::InputPtr input);
- // set up Ui information for add node popup
+ // Setup UI information for add node popup
void addExtraNodes();
- // copy and paste functions
void copyInputs();
+
+ // Set position of pasted nodes based on original node position
void positionPasteBin(ImVec2 pos);
+
void copyNodeGraph(UiNodePtr origGraph, UiNodePtr copyGraph);
void copyUiNode(UiNodePtr node);
- // renderview window and buttons
void graphButtons();
- // popup information
void addNodePopup(bool cursor);
void searchNodePopup(bool cursor);
bool readOnly();
void readOnlyPopup();
+
+ // Compiling shaders message
void shaderPopup();
- // modifying materials
void updateMaterials(mx::InputPtr input = nullptr, mx::ValuePtr value = nullptr);
void selectMaterial(UiNodePtr node);
+
+ // Allow for camera manipulation of render view window
void handleRenderViewInputs(ImVec2 minValue, float width, float height);
+
+ // Set the node to display in render view based on selected node or nodegraph
void setRenderMaterial(UiNodePtr node);
- // File I/O
void clearGraph();
- void loadGraphFromFile();
+ void loadGraphFromFile(bool prompt);
void saveGraphToFile();
void loadGeometry();
+ void showHelp() const;
+
+ private:
mx::StringVec _geomFilter;
mx::StringVec _mtlxFilter;
mx::StringVec _imageFilter;
- // Help
- void showHelp() const;
-
RenderViewPtr _renderer;
// document and intializing information
@@ -214,7 +269,7 @@ class Graph
FileDialog _fileDialogSave;
FileDialog _fileDialogImage;
FileDialog _fileDialogGeom;
-
+ std::string _fileDialogImageInputName;
bool _isNodeGraph;
@@ -236,7 +291,10 @@ class Graph
std::string _pinFilterType;
// DPI scaling for fonts
- float _fontScale = 1.0f;
+ float _fontScale;
+
+ // Options
+ bool _saveNodePositions;
};
#endif
diff --git a/source/MaterialXGraphEditor/RenderView.cpp b/source/MaterialXGraphEditor/RenderView.cpp
index faf48f543a..176014ba65 100644
--- a/source/MaterialXGraphEditor/RenderView.cpp
+++ b/source/MaterialXGraphEditor/RenderView.cpp
@@ -159,7 +159,6 @@ RenderView::RenderView(mx::DocumentPtr doc,
_genContext(mx::GlslShaderGenerator::create()),
_unitRegistry(mx::UnitConverterRegistry::create()),
_splitByUdims(true),
- _mergeMaterials(false),
_materialCompilation(false),
_renderTransparency(true),
_renderDoubleSided(true),
@@ -410,18 +409,15 @@ void RenderView::updateMaterials(mx::TypedElementPtr typedElem)
// Clear user data on the generator.
_genContext.clearUserData();
- // Clear materials if merging is not requested.
- if (!_mergeMaterials)
+ // Clear materials.
+ for (mx::MeshPartitionPtr geom : _geometryList)
{
- for (mx::MeshPartitionPtr geom : _geometryList)
+ if (_materialAssignments.count(geom))
{
- if (_materialAssignments.count(geom))
- {
- assignMaterial(geom, nullptr);
- }
+ assignMaterial(geom, nullptr);
}
- _materials.clear();
}
+ _materials.clear();
std::vector newMaterials;
try
@@ -434,10 +430,19 @@ void RenderView::updateMaterials(mx::TypedElementPtr typedElem)
// Apply direct lights.
applyDirectLights(_document);
- //// Check for any udim set.
+ // Check for any udim set.
mx::ValuePtr udimSetValue = _document->getGeomPropValue(mx::UDIM_SET_PROPERTY);
- //// Create new materials.
+ // Skip material nodes without upstream shaders.
+ mx::NodePtr node = typedElem ? typedElem->asA() : nullptr;
+ if (node &&
+ node->getCategory() == mx::SURFACE_MATERIAL_NODE_STRING &&
+ mx::getShaderNodes(node).empty())
+ {
+ typedElem = nullptr;
+ }
+
+ // Create new materials.
if (!typedElem)
{
std::vector elems = mx::findRenderableElements(_document);
@@ -451,8 +456,7 @@ void RenderView::updateMaterials(mx::TypedElementPtr typedElem)
mx::NodePtr materialNode = nullptr;
if (typedElem)
{
- mx::NodePtr node = typedElem->asA();
- materialNode = node && node->getType() == mx::MATERIAL_TYPE_STRING ? node : nullptr;
+ materialNode = node;
if (udimSetValue && udimSetValue->isA())
{
for (const std::string& udim : udimSetValue->asA())
@@ -551,14 +555,11 @@ void RenderView::updateMaterials(mx::TypedElementPtr typedElem)
// Apply fallback assignments.
mx::GlslMaterialPtr fallbackMaterial = newMaterials[0];
- if (!_mergeMaterials || fallbackMaterial->getUdim().empty())
+ for (mx::MeshPartitionPtr geom : _geometryList)
{
- for (mx::MeshPartitionPtr geom : _geometryList)
+ if (!_materialAssignments[geom])
{
- if (!_materialAssignments[geom])
- {
- assignMaterial(geom, fallbackMaterial);
- }
+ assignMaterial(geom, fallbackMaterial);
}
}
@@ -720,7 +721,7 @@ void RenderView::loadEnvironmentLight()
envIrradianceMap = _imageHandler->acquireImage(envIrradiancePath);
// If not found, then generate an irradiance map via spherical harmonics.
- if (envIrradianceMap == _imageHandler->getInvalidImage())
+ if (envIrradianceMap == _imageHandler->getZeroImage())
{
mx::Sh3ColorCoeffs shIrradiance = mx::projectEnvironment(envRadianceMap, true);
envIrradianceMap = mx::renderEnvironment(shIrradiance, IRRADIANCE_MAP_WIDTH, IRRADIANCE_MAP_HEIGHT);
diff --git a/source/MaterialXGraphEditor/RenderView.h b/source/MaterialXGraphEditor/RenderView.h
index e931be9592..354e898ce1 100644
--- a/source/MaterialXGraphEditor/RenderView.h
+++ b/source/MaterialXGraphEditor/RenderView.h
@@ -145,11 +145,6 @@ class RenderView
return _materialAssignments;
}
- bool getMergeMaterials()
- {
- return _mergeMaterials;
- }
-
std::vector getMaterials()
{
return _materials;
@@ -323,7 +318,6 @@ class RenderView
bool _splitByUdims;
// Material options
- bool _mergeMaterials;
bool _materialCompilation;
// Unit options
diff --git a/source/MaterialXRender/CMakeLists.txt b/source/MaterialXRender/CMakeLists.txt
index d0a50232cd..52d07e688e 100644
--- a/source/MaterialXRender/CMakeLists.txt
+++ b/source/MaterialXRender/CMakeLists.txt
@@ -1,3 +1,5 @@
+set(MATERIALX_MODULE_NAME MaterialXRender)
+
include_directories(
${EXTERNAL_INCLUDE_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/../)
@@ -18,12 +20,18 @@ if(UNIX)
add_compile_options(-Wno-unused-function)
endif()
-add_library(MaterialXRender ${materialx_source} ${materialx_headers} ${materialx_inlined})
+add_library(${MATERIALX_MODULE_NAME} ${materialx_source} ${materialx_headers} ${materialx_inlined})
add_definitions(-DMATERIALX_RENDER_EXPORTS)
+# Create version resource
+if(MATERIALX_BUILD_SHARED_LIBS AND MSVC)
+ configure_file(${CMAKE_SOURCE_DIR}/cmake/modules/MaterialXVersion.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
+ target_sources(${MATERIALX_MODULE_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
+endif()
+
target_link_libraries(
- MaterialXRender
+ ${MATERIALX_MODULE_NAME}
MaterialXGenShader
${CMAKE_DL_LIBS})
@@ -33,7 +41,7 @@ if(MATERIALX_BUILD_OIIO)
find_package(OpenImageIO REQUIRED)
if(OPENIMAGEIO_FOUND)
include_directories(${OPENIMAGEIO_INCLUDE_DIR})
- target_link_libraries(MaterialXRender ${OPENIMAGEIO_LIBRARIES})
+ target_link_libraries(${MATERIALX_MODULE_NAME} ${OPENIMAGEIO_LIBRARIES})
# Also needed by MaterialXTest:
set(OPENIMAGEIO_FOUND "${OPENIMAGEIO_FOUND}" PARENT_SCOPE)
set(OPENIMAGEIO_INCLUDE_DIR "${OPENIMAGEIO_INCLUDE_DIR}" PARENT_SCOPE)
@@ -44,25 +52,27 @@ if(MATERIALX_BUILD_OIIO)
endif()
set_target_properties(
- MaterialXRender PROPERTIES
- OUTPUT_NAME MaterialXRender${MATERIALX_LIBNAME_SUFFIX}
+ ${MATERIALX_MODULE_NAME} PROPERTIES
+ OUTPUT_NAME ${MATERIALX_MODULE_NAME}${MATERIALX_LIBNAME_SUFFIX}
COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS}"
LINK_FLAGS "${EXTERNAL_LINK_FLAGS}"
INSTALL_RPATH "${MATERIALX_SAME_DIR_RPATH}"
VERSION "${MATERIALX_LIBRARY_VERSION}"
SOVERSION "${MATERIALX_MAJOR_VERSION}")
-install(TARGETS MaterialXRender
- EXPORT MaterialX
- ARCHIVE DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
- LIBRARY DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
- RUNTIME DESTINATION bin)
+if(NOT SKBUILD)
+ install(TARGETS ${MATERIALX_MODULE_NAME}
+ EXPORT MaterialX
+ ARCHIVE DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
+ LIBRARY DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
+ RUNTIME DESTINATION bin)
-install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/"
- DESTINATION ${MATERIALX_INSTALL_INCLUDE_PATH}/MaterialXRender/ MESSAGE_NEVER
- FILES_MATCHING
- PATTERN "*.h*"
- PATTERN "*.inl")
+ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/"
+ DESTINATION ${MATERIALX_INSTALL_INCLUDE_PATH}/${MATERIALX_MODULE_NAME}/ MESSAGE_NEVER
+ FILES_MATCHING
+ PATTERN "*.h*"
+ PATTERN "*.inl")
-install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/MaterialXRender.pdb"
- DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${MATERIALX_MODULE_NAME}.pdb"
+ DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
+endif()
diff --git a/source/MaterialXRender/External/OpenImageIO/FindOpenImageIO.cmake b/source/MaterialXRender/External/OpenImageIO/FindOpenImageIO.cmake
index 4fab4f9814..6c1b1682d6 100644
--- a/source/MaterialXRender/External/OpenImageIO/FindOpenImageIO.cmake
+++ b/source/MaterialXRender/External/OpenImageIO/FindOpenImageIO.cmake
@@ -45,6 +45,13 @@ find_library ( OPENIMAGEIO_LIBRARY
HINTS ${OPENIMAGEIO_ROOT_DIR}/lib
PATH_SUFFIXES lib64 lib
PATHS "${OPENIMAGEIO_ROOT_DIR}/lib" )
+
+find_library ( OPENIMAGEIO_UTIL_LIBRARY
+ NAMES OpenImageIO_Util${OIIO_LIBNAME_SUFFIX}
+ HINTS ${OPENIMAGEIO_ROOT_DIR}/lib
+ PATH_SUFFIXES lib64 lib
+ PATHS "${OPENIMAGEIO_ROOT_DIR}/lib" )
+
find_path ( OPENIMAGEIO_INCLUDE_DIR
NAMES OpenImageIO/imageio.h
HINTS ${OPENIMAGEIO_ROOT_DIR}/include
@@ -66,7 +73,7 @@ if (EXISTS "${OIIO_VERSION_HEADER}")
set (OPENIMAGEIO_VERSION "${OPENIMAGEIO_VERSION_MAJOR}.${OPENIMAGEIO_VERSION_MINOR}.${OPENIMAGEIO_VERSION_PATCH}")
endif ()
-set ( OPENIMAGEIO_LIBRARIES ${OPENIMAGEIO_LIBRARY})
+set ( OPENIMAGEIO_LIBRARIES ${OPENIMAGEIO_LIBRARY} ${OPENIMAGEIO_UTIL_LIBRARY})
get_filename_component (OPENIMAGEIO_LIBRARY_DIRS "${OPENIMAGEIO_LIBRARY}" DIRECTORY CACHE)
if (NOT OpenImageIO_FIND_QUIETLY)
diff --git a/source/MaterialXRender/ImageHandler.cpp b/source/MaterialXRender/ImageHandler.cpp
index bc43b617ff..d54a18fedd 100644
--- a/source/MaterialXRender/ImageHandler.cpp
+++ b/source/MaterialXRender/ImageHandler.cpp
@@ -56,9 +56,6 @@ ImageHandler::ImageHandler(ImageLoaderPtr imageLoader)
{
addLoader(imageLoader);
_zeroImage = createUniformImage(2, 2, 4, Image::BaseType::UINT8, Color4(0.0f));
-
- // Generated shaders interpret 1x1 textures as invalid images.
- _invalidImage = createUniformImage(1, 1, 4, Image::BaseType::UINT8, Color4(0.0f));
}
void ImageHandler::addLoader(ImageLoaderPtr loader)
@@ -118,7 +115,7 @@ bool ImageHandler::saveImage(const FilePath& filePath,
return false;
}
-ImagePtr ImageHandler::acquireImage(const FilePath& filePath)
+ImagePtr ImageHandler::acquireImage(const FilePath& filePath, const Color4& defaultColor)
{
// Resolve the input filepath.
FilePath resolvedFilePath = filePath;
@@ -142,9 +139,12 @@ ImagePtr ImageHandler::acquireImage(const FilePath& filePath)
return image;
}
- // No valid image was found, so cache the sentinel invalid image.
- cacheImage(resolvedFilePath, _invalidImage);
- return _invalidImage;
+ // No valid image was found, so generate a uniform texture with the given default color.
+ // TODO: This step assumes that the missing image and its default color are in the same
+ // color space, which is not always the case.
+ ImagePtr defaultImage = createUniformImage(1, 1, 4, Image::BaseType::UINT8, defaultColor);
+ cacheImage(resolvedFilePath, defaultImage);
+ return defaultImage;
}
bool ImageHandler::bindImage(ImagePtr, const ImageSamplingProperties&)
@@ -189,7 +189,7 @@ ImageVec ImageHandler::getReferencedImages(ConstDocumentPtr doc)
if (file)
{
ImagePtr image = acquireImage(file->getResolvedValueString());
- if (image && image != _invalidImage)
+ if (image)
{
imageVec.push_back(image);
}
@@ -214,14 +214,6 @@ ImagePtr ImageHandler::loadImage(const FilePath& filePath)
}
if (image)
{
- // Generated shaders interpret 1x1 textures as invalid images, so valid 1x1
- // images must be resized.
- if (image->getWidth() == 1 && image->getHeight() == 1)
- {
- image = createUniformImage(2, 2, image->getChannelCount(),
- image->getBaseType(), image->getTexelColor(0, 0));
- }
-
return image;
}
}
@@ -288,23 +280,23 @@ void ImageSamplingProperties::setProperties(const string& fileNameUniform,
root = root.substr(0, pos);
}
- const string uaddressmodeStr = root + UADDRESS_MODE_SUFFIX;
- const ShaderPort* port = uniformBlock.find(uaddressmodeStr);
+ const ShaderPort* port = uniformBlock.find(root + UADDRESS_MODE_SUFFIX);
ValuePtr intValue = port ? port->getValue() : nullptr;
uaddressMode = ImageSamplingProperties::AddressMode(intValue && intValue->isA() ? intValue->asA() : INVALID_MAPPED_INT_VALUE);
- const string vaddressmodeStr = root + VADDRESS_MODE_SUFFIX;
- port = uniformBlock.find(vaddressmodeStr);
+ port = uniformBlock.find(root + VADDRESS_MODE_SUFFIX);
intValue = port ? port->getValue() : nullptr;
vaddressMode = ImageSamplingProperties::AddressMode(intValue && intValue->isA() ? intValue->asA() : INVALID_MAPPED_INT_VALUE);
- const string filtertypeStr = root + FILTER_TYPE_SUFFIX;
- port = uniformBlock.find(filtertypeStr);
+ port = uniformBlock.find(root + FILTER_TYPE_SUFFIX);
intValue = port ? port->getValue() : nullptr;
filterType = ImageSamplingProperties::FilterType(intValue && intValue->isA() ? intValue->asA() : INVALID_MAPPED_INT_VALUE);
- const string defaultColorStr = root + DEFAULT_COLOR_SUFFIX;
- port = uniformBlock.find(defaultColorStr);
+ port = uniformBlock.find(root + DEFAULT_COLOR_SUFFIX);
+ if (!port)
+ {
+ port = uniformBlock.find(root + DEFAULT_COLOR_SUFFIX + "_cm_in");
+ }
ValuePtr colorValue = port ? port->getValue() : nullptr;
if (colorValue)
{
diff --git a/source/MaterialXRender/ImageHandler.h b/source/MaterialXRender/ImageHandler.h
index ee1fe127c4..c744eb2f6a 100644
--- a/source/MaterialXRender/ImageHandler.h
+++ b/source/MaterialXRender/ImageHandler.h
@@ -188,7 +188,7 @@ class MX_RENDER_API ImageHandler
/// found in the cache, then each image loader will be applied in turn.
/// @param filePath File path of the image.
/// @return On success, a shared pointer to the acquired image.
- ImagePtr acquireImage(const FilePath& filePath);
+ ImagePtr acquireImage(const FilePath& filePath, const Color4& defaultColor = Color4(0.0f));
/// Bind an image for rendering.
/// @param image The image to bind.
@@ -247,13 +247,6 @@ class MX_RENDER_API ImageHandler
return _zeroImage;
}
- /// Return the sentinel invalid image, representing images that cannot be loaded
- /// and should be replaced with their declared default value.
- ImagePtr getInvalidImage() const
- {
- return _invalidImage;
- }
-
/// Acquire all images referenced by the given document, and return the
/// images in a vector.
ImageVec getReferencedImages(ConstDocumentPtr doc);
@@ -278,7 +271,6 @@ class MX_RENDER_API ImageHandler
FileSearchPath _searchPath;
StringResolverPtr _resolver;
ImagePtr _zeroImage;
- ImagePtr _invalidImage;
};
MATERIALX_NAMESPACE_END
diff --git a/source/MaterialXRender/ShaderRenderer.cpp b/source/MaterialXRender/ShaderRenderer.cpp
index a5e81d1f68..3bba62795e 100644
--- a/source/MaterialXRender/ShaderRenderer.cpp
+++ b/source/MaterialXRender/ShaderRenderer.cpp
@@ -25,17 +25,26 @@ const float DEFAULT_FAR_PLANE = 100.0f;
// ShaderRenderer methods
//
-ShaderRenderer::ShaderRenderer(unsigned int width, unsigned int height, Image::BaseType baseType) :
+ShaderRenderer::ShaderRenderer(unsigned int width, unsigned int height, Image::BaseType baseType, MatrixConvention matrixConvention) :
_width(width),
_height(height),
- _baseType(baseType)
+ _baseType(baseType),
+ _matrixConvention(matrixConvention)
{
// Initialize a default camera.
float fH = std::tan(DEFAULT_FIELD_OF_VIEW / 360.0f * PI) * DEFAULT_NEAR_PLANE;
float fW = fH * 1.0f;
_camera = Camera::create();
_camera->setViewMatrix(Camera::createViewMatrix(DEFAULT_EYE_POSITION, DEFAULT_TARGET_POSITION, DEFAULT_UP_VECTOR));
- _camera->setProjectionMatrix(Camera::createPerspectiveMatrix(-fW, fW, -fH, fH, DEFAULT_NEAR_PLANE, DEFAULT_FAR_PLANE));
+
+ if (_matrixConvention == ShaderRenderer::MatrixConvention::Metal)
+ {
+ _camera->setProjectionMatrix(Camera::createPerspectiveMatrixZP(-fW, fW, -fH, fH, DEFAULT_NEAR_PLANE, DEFAULT_FAR_PLANE));
+ }
+ else // MatrixConvention::OpenGL (default)
+ {
+ _camera->setProjectionMatrix(Camera::createPerspectiveMatrix(-fW, fW, -fH, fH, DEFAULT_NEAR_PLANE, DEFAULT_FAR_PLANE));
+ }
}
void ShaderRenderer::createProgram(ShaderPtr)
@@ -50,4 +59,9 @@ void ShaderRenderer::setSize(unsigned int, unsigned int)
{
}
+void ShaderRenderer::updateUniform(const string&, ConstValuePtr)
+{
+ throw ExceptionRenderError("Update uniform is not yet supported");
+}
+
MATERIALX_NAMESPACE_END
diff --git a/source/MaterialXRender/ShaderRenderer.h b/source/MaterialXRender/ShaderRenderer.h
index 2c6f5fbf87..c1cfbecfa0 100644
--- a/source/MaterialXRender/ShaderRenderer.h
+++ b/source/MaterialXRender/ShaderRenderer.h
@@ -30,6 +30,12 @@ using ShaderRendererPtr = std::shared_ptr;
class MX_RENDER_API ShaderRenderer
{
public:
+ /// Viewing API matrix conventions designation (default to OpenGL).
+ enum class MatrixConvention
+ {
+ OpenGL = 0,
+ Metal = 1
+ };
/// A map with name and source code for each shader stage.
using StageMap = StringMap;
@@ -104,6 +110,9 @@ class MX_RENDER_API ShaderRenderer
/// Validate inputs for the program.
virtual void validateInputs() { }
+ /// Update the program with value of the uniform.
+ virtual void updateUniform(const string& name, ConstValuePtr value);
+
/// Set the size of the rendered image.
virtual void setSize(unsigned int width, unsigned int height);
@@ -123,13 +132,16 @@ class MX_RENDER_API ShaderRenderer
/// @}
protected:
- ShaderRenderer(unsigned int width, unsigned int height, Image::BaseType baseType);
+ ShaderRenderer(unsigned int width, unsigned int height, Image::BaseType baseType,
+ MatrixConvention matrixConvention = MatrixConvention::OpenGL);
protected:
unsigned int _width;
unsigned int _height;
Image::BaseType _baseType;
+ MatrixConvention _matrixConvention;
+
CameraPtr _camera;
ImageHandlerPtr _imageHandler;
GeometryHandlerPtr _geometryHandler;
diff --git a/source/MaterialXRenderGlsl/CMakeLists.txt b/source/MaterialXRenderGlsl/CMakeLists.txt
index ddab96c318..cb2f3c27c2 100644
--- a/source/MaterialXRenderGlsl/CMakeLists.txt
+++ b/source/MaterialXRenderGlsl/CMakeLists.txt
@@ -1,3 +1,5 @@
+set(MATERIALX_MODULE_NAME MaterialXRenderGlsl)
+
file(GLOB_RECURSE materialx_source "${CMAKE_CURRENT_SOURCE_DIR}/*.c*")
file(GLOB_RECURSE materialx_headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h*")
@@ -34,12 +36,18 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wno-deprecated-declarations)
endif()
-add_library(MaterialXRenderGlsl ${materialx_source} ${materialx_headers})
+add_library(${MATERIALX_MODULE_NAME} ${materialx_source} ${materialx_headers})
add_definitions(-DMATERIALX_RENDERGLSL_EXPORTS)
+# Create version resource
+if(MATERIALX_BUILD_SHARED_LIBS AND MSVC)
+ configure_file(${CMAKE_SOURCE_DIR}/cmake/modules/MaterialXVersion.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
+ target_sources(${MATERIALX_MODULE_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
+endif()
+
if(MATERIALX_BUILD_SHARED_LIBS)
- target_compile_definitions(MaterialXRenderGlsl PUBLIC GLAD_GLAPI_EXPORT PRIVATE GLAD_GLAPI_EXPORT_BUILD)
+ target_compile_definitions(${MATERIALX_MODULE_NAME} PUBLIC GLAD_GLAPI_EXPORT PRIVATE GLAD_GLAPI_EXPORT_BUILD)
endif()
set(COMMON_LIBRARIES
@@ -50,19 +58,19 @@ set(COMMON_LIBRARIES
if(WIN32)
if(MSVC)
target_link_libraries(
- MaterialXRenderGlsl
+ ${MATERIALX_MODULE_NAME}
${COMMON_LIBRARIES}
Opengl32)
elseif(MINGW)
target_link_libraries(
- MaterialXRenderGlsl
+ ${MATERIALX_MODULE_NAME}
${COMMON_LIBRARIES}
Opengl32
gdi32)
endif()
elseif(APPLE)
target_link_libraries(
- MaterialXRenderGlsl
+ ${MATERIALX_MODULE_NAME}
${COMMON_LIBRARIES}
${OPENGL_LIBRARIES}
"-framework Foundation"
@@ -70,7 +78,7 @@ elseif(APPLE)
"-framework Metal")
elseif(UNIX)
target_link_libraries(
- MaterialXRenderGlsl
+ ${MATERIALX_MODULE_NAME}
${COMMON_LIBRARIES}
${OPENGL_LIBRARIES}
${X11_LIBRARIES}
@@ -78,30 +86,32 @@ elseif(UNIX)
endif()
set_target_properties(
- MaterialXRenderGlsl PROPERTIES
- OUTPUT_NAME MaterialXRenderGlsl${MATERIALX_LIBNAME_SUFFIX}
+ ${MATERIALX_MODULE_NAME} PROPERTIES
+ OUTPUT_NAME ${MATERIALX_MODULE_NAME}${MATERIALX_LIBNAME_SUFFIX}
COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS}"
LINK_FLAGS "${EXTERNAL_LINK_FLAGS}"
INSTALL_RPATH "${MATERIALX_SAME_DIR_RPATH}"
VERSION "${MATERIALX_LIBRARY_VERSION}"
SOVERSION "${MATERIALX_MAJOR_VERSION}")
-target_include_directories(MaterialXRenderGlsl
+target_include_directories(${MATERIALX_MODULE_NAME}
PUBLIC
$
$
PRIVATE
${EXTERNAL_INCLUDE_DIRS})
-install(TARGETS MaterialXRenderGlsl
- EXPORT MaterialX
- ARCHIVE DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
- LIBRARY DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
- RUNTIME DESTINATION bin)
+if(NOT SKBUILD)
+ install(TARGETS ${MATERIALX_MODULE_NAME}
+ EXPORT MaterialX
+ ARCHIVE DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
+ LIBRARY DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
+ RUNTIME DESTINATION bin)
-install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/"
- DESTINATION ${MATERIALX_INSTALL_INCLUDE_PATH}/MaterialXRenderGlsl/ MESSAGE_NEVER
- FILES_MATCHING PATTERN "*.h*")
+ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/"
+ DESTINATION ${MATERIALX_INSTALL_INCLUDE_PATH}/${MATERIALX_MODULE_NAME}/ MESSAGE_NEVER
+ FILES_MATCHING PATTERN "*.h*")
-install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/MaterialXRenderGlsl.pdb"
- DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${MATERIALX_MODULE_NAME}.pdb"
+ DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
+endif()
diff --git a/source/MaterialXRenderGlsl/GlslMaterial.cpp b/source/MaterialXRenderGlsl/GlslMaterial.cpp
index ef7a0ed0c2..ce4582d44f 100644
--- a/source/MaterialXRenderGlsl/GlslMaterial.cpp
+++ b/source/MaterialXRenderGlsl/GlslMaterial.cpp
@@ -209,7 +209,7 @@ ImagePtr GlslMaterial::bindImage(const FilePath& filePath, const std::string& un
imageHandler->setFilenameResolver(resolver);
// Acquire the given image.
- ImagePtr image = imageHandler->acquireImage(filePath);
+ ImagePtr image = imageHandler->acquireImage(filePath, samplingProperties.defaultColor);
if (!image)
{
return nullptr;
diff --git a/source/MaterialXRenderGlsl/GlslProgram.cpp b/source/MaterialXRenderGlsl/GlslProgram.cpp
index a60997716a..900cac0ef1 100644
--- a/source/MaterialXRenderGlsl/GlslProgram.cpp
+++ b/source/MaterialXRenderGlsl/GlslProgram.cpp
@@ -491,7 +491,7 @@ ImagePtr GlslProgram::bindTexture(unsigned int uniformType, int uniformLocation,
uniformType >= GL_SAMPLER_1D && uniformType <= GL_SAMPLER_CUBE)
{
// Acquire the image.
- ImagePtr image = imageHandler->acquireImage(filePath);
+ ImagePtr image = imageHandler->acquireImage(filePath, samplingProperties.defaultColor);
if (imageHandler->bindImage(image, samplingProperties))
{
GLTextureHandlerPtr textureHandler = std::static_pointer_cast(imageHandler);
diff --git a/source/MaterialXRenderGlsl/GlslRenderer.cpp b/source/MaterialXRenderGlsl/GlslRenderer.cpp
index e81ded996e..374305f32f 100644
--- a/source/MaterialXRenderGlsl/GlslRenderer.cpp
+++ b/source/MaterialXRenderGlsl/GlslRenderer.cpp
@@ -25,7 +25,7 @@ GlslRendererPtr GlslRenderer::create(unsigned int width, unsigned int height, Im
}
GlslRenderer::GlslRenderer(unsigned int width, unsigned int height, Image::BaseType baseType) :
- ShaderRenderer(width, height, baseType),
+ ShaderRenderer(width, height, baseType, MatrixConvention::OpenGL),
_initialized(false),
_screenColor(DEFAULT_SCREEN_COLOR_LIN_REC709)
{
@@ -119,6 +119,16 @@ void GlslRenderer::validateInputs()
_program->getAttributesList();
}
+void GlslRenderer::updateUniform(const string& name, ConstValuePtr value)
+{
+ if (!_program->bind())
+ {
+ return;
+ }
+
+ _program->bindUniform(name, value);
+}
+
void GlslRenderer::setSize(unsigned int width, unsigned int height)
{
if (_context->makeCurrent())
diff --git a/source/MaterialXRenderGlsl/GlslRenderer.h b/source/MaterialXRenderGlsl/GlslRenderer.h
index 8538fe2208..9ea121aec9 100644
--- a/source/MaterialXRenderGlsl/GlslRenderer.h
+++ b/source/MaterialXRenderGlsl/GlslRenderer.h
@@ -79,6 +79,9 @@ class MX_RENDERGLSL_API GlslRenderer : public ShaderRenderer
/// Validate inputs for the program
void validateInputs() override;
+ /// Update the program with value of the uniform.
+ void updateUniform(const string& name, ConstValuePtr value) override;
+
/// Set the size of the rendered image
void setSize(unsigned int width, unsigned int height) override;
diff --git a/source/MaterialXRenderHw/CMakeLists.txt b/source/MaterialXRenderHw/CMakeLists.txt
index 85ef13c55c..dfd262a3ae 100644
--- a/source/MaterialXRenderHw/CMakeLists.txt
+++ b/source/MaterialXRenderHw/CMakeLists.txt
@@ -1,8 +1,12 @@
+set(MATERIALX_MODULE_NAME MaterialXRenderHw)
+
file(GLOB materialx_source "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
file(GLOB materialx_headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h*")
if(APPLE)
+if (NOT MATERIALX_BUILD_IOS)
find_library(COCOA_FRAMEWORK Cocoa)
+endif()
file(GLOB materialx_source_oc "${CMAKE_CURRENT_SOURCE_DIR}/*.m")
message("Objective C files: " ${materialx_source_oc})
set_source_files_properties(${materialx_source_oc} PROPERTIES
@@ -20,26 +24,37 @@ endif()
assign_source_group("Source Files" ${materialx_source})
assign_source_group("Header Files" ${materialx_headers})
-add_library(MaterialXRenderHw ${materialx_source} ${materialx_headers})
+add_library(${MATERIALX_MODULE_NAME} ${materialx_source} ${materialx_headers})
add_definitions(-DMATERIALX_RENDERHW_EXPORTS)
+if(APPLE AND NOT MATERIALX_BUILD_IOS)
+set(CMAKE_DL_LIBS
+${CMAKE_DL_LIBS}
+"-framework Cocoa")
+endif()
+
+# Create version resource
+if(MATERIALX_BUILD_SHARED_LIBS AND MSVC)
+ configure_file(${CMAKE_SOURCE_DIR}/cmake/modules/MaterialXVersion.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
+ target_sources(${MATERIALX_MODULE_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
+endif()
+
if(MSVC)
target_link_libraries(
- MaterialXRenderHw
+ ${MATERIALX_MODULE_NAME}
MaterialXRender
${CMAKE_DL_LIBS})
elseif(APPLE)
target_link_libraries(
- MaterialXRenderHw
+ ${MATERIALX_MODULE_NAME}
MaterialXRender
${CMAKE_DL_LIBS}
"-framework Foundation"
- "-framework Cocoa"
"-framework Metal")
elseif(UNIX)
target_link_libraries(
- MaterialXRenderHw
+ ${MATERIALX_MODULE_NAME}
MaterialXRender
${CMAKE_DL_LIBS}
${X11_LIBRARIES}
@@ -47,30 +62,32 @@ elseif(UNIX)
endif()
set_target_properties(
- MaterialXRenderHw PROPERTIES
- OUTPUT_NAME MaterialXRenderHw${MATERIALX_LIBNAME_SUFFIX}
+ ${MATERIALX_MODULE_NAME} PROPERTIES
+ OUTPUT_NAME ${MATERIALX_MODULE_NAME}${MATERIALX_LIBNAME_SUFFIX}
COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS}"
LINK_FLAGS "${EXTERNAL_LINK_FLAGS}"
INSTALL_RPATH "${MATERIALX_SAME_DIR_RPATH}"
VERSION "${MATERIALX_LIBRARY_VERSION}"
SOVERSION "${MATERIALX_MAJOR_VERSION}")
-target_include_directories(MaterialXRenderHw
+target_include_directories(${MATERIALX_MODULE_NAME}
PUBLIC
$
$
PRIVATE
${EXTERNAL_INCLUDE_DIRS})
-install(TARGETS MaterialXRenderHw
- EXPORT MaterialX
- ARCHIVE DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
- LIBRARY DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
- RUNTIME DESTINATION bin)
+if(NOT SKBUILD)
+ install(TARGETS ${MATERIALX_MODULE_NAME}
+ EXPORT MaterialX
+ ARCHIVE DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
+ LIBRARY DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
+ RUNTIME DESTINATION bin)
-install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/"
- DESTINATION ${MATERIALX_INSTALL_INCLUDE_PATH}/MaterialXRenderHw/ MESSAGE_NEVER
- FILES_MATCHING PATTERN "*.h*")
+ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/"
+ DESTINATION ${MATERIALX_INSTALL_INCLUDE_PATH}/${MATERIALX_MODULE_NAME}/ MESSAGE_NEVER
+ FILES_MATCHING PATTERN "*.h*")
-install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/MaterialXRenderHw.pdb"
- DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${MATERIALX_MODULE_NAME}.pdb"
+ DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
+endif()
diff --git a/source/MaterialXRenderHw/SimpleWindowIOS.cpp b/source/MaterialXRenderHw/SimpleWindowIOS.cpp
new file mode 100644
index 0000000000..1d4189b2ab
--- /dev/null
+++ b/source/MaterialXRenderHw/SimpleWindowIOS.cpp
@@ -0,0 +1,40 @@
+//
+// Copyright Contributors to the MaterialX Project
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#if defined(__APPLE__)
+
+#ifdef TARGET_OS_IOS
+
+#include
+
+MATERIALX_NAMESPACE_BEGIN
+
+SimpleWindow::SimpleWindow() :
+ _width(0),
+ _height(0)
+{
+ // Give a unique identifier to this window.
+ static unsigned int windowCount = 1;
+ _id = windowCount;
+ windowCount++;
+}
+
+bool SimpleWindow::initialize(const char* title,
+ unsigned int width, unsigned int height,
+ void* /*applicationShell*/)
+{
+ _windowWrapper = WindowWrapper::create(nullptr);
+ return true;
+}
+
+SimpleWindow::~SimpleWindow()
+{
+}
+
+MATERIALX_NAMESPACE_END
+
+#endif
+
+#endif
diff --git a/source/MaterialXRenderHw/SimpleWindowMac.cpp b/source/MaterialXRenderHw/SimpleWindowMac.cpp
index 1cf070ac74..a04d1f49ae 100644
--- a/source/MaterialXRenderHw/SimpleWindowMac.cpp
+++ b/source/MaterialXRenderHw/SimpleWindowMac.cpp
@@ -5,6 +5,8 @@
#if defined(__APPLE__)
+#ifndef TARGET_OS_IOS
+
#include
#include
@@ -42,3 +44,5 @@ SimpleWindow::~SimpleWindow()
MATERIALX_NAMESPACE_END
#endif
+
+#endif
diff --git a/source/MaterialXRenderHw/WindowCocoaWrappers.m b/source/MaterialXRenderHw/WindowCocoaWrappers.m
index c73de77810..a012966a8f 100644
--- a/source/MaterialXRenderHw/WindowCocoaWrappers.m
+++ b/source/MaterialXRenderHw/WindowCocoaWrappers.m
@@ -5,6 +5,8 @@
#if defined (__APPLE__)
+#ifndef TARGET_OS_IOS
+
#import
#import
#import
@@ -72,3 +74,5 @@ void NSUtilDisposeWindow(void* pWindow)
}
#endif
+
+#endif
diff --git a/source/MaterialXRenderHw/WindowWrapper.cpp b/source/MaterialXRenderHw/WindowWrapper.cpp
index 315960fb2b..654498d5cd 100644
--- a/source/MaterialXRenderHw/WindowWrapper.cpp
+++ b/source/MaterialXRenderHw/WindowWrapper.cpp
@@ -84,8 +84,12 @@ WindowWrapper::WindowWrapper(ExternalWindowHandle externalHandle,
DisplayHandle display)
{
_externalHandle = externalHandle;
+#ifndef TARGET_OS_IOS
// Cache a pointer to the window.
_internalHandle = NSUtilGetView(externalHandle);
+#else
+ _internalHandle = nullptr;
+#endif
}
WindowWrapper::~WindowWrapper()
diff --git a/source/MaterialXRenderMsl/CMakeLists.txt b/source/MaterialXRenderMsl/CMakeLists.txt
index 5ad50ea2cc..4d5e286463 100644
--- a/source/MaterialXRenderMsl/CMakeLists.txt
+++ b/source/MaterialXRenderMsl/CMakeLists.txt
@@ -1,3 +1,5 @@
+set(MATERIALX_MODULE_NAME MaterialXRenderMsl)
+
file(GLOB_RECURSE materialx_source "${CMAKE_CURRENT_SOURCE_DIR}/*.m*")
file(GLOB_RECURSE materialx_headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h*")
@@ -9,8 +11,10 @@ if(POLICY CMP0072)
endif()
if(APPLE)
+if(NOT MATERIALX_BUILD_IOS)
find_library(COCOA_FRAMEWORK Cocoa)
find_package(OpenGL REQUIRED)
+endif()
file(GLOB_RECURSE materialx_source_oc "${CMAKE_CURRENT_SOURCE_DIR}/*.m")
message("Objective C files: " ${materialx_source_oc})
set_source_files_properties(${materialx_source_oc} PROPERTIES
@@ -34,7 +38,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wno-deprecated-declarations)
endif()
-add_library(MaterialXRenderMsl ${materialx_source} ${materialx_headers})
+add_library(${MATERIALX_MODULE_NAME} ${materialx_source} ${materialx_headers})
add_definitions(-DMATERIALX_RENDERMSL_EXPORTS)
@@ -42,23 +46,28 @@ set(COMMON_LIBRARIES
MaterialXRenderHw
MaterialXGenMsl
${CMAKE_DL_LIBS})
+
+if(APPLE AND NOT MATERIALX_BUILD_IOS)
+set(COMMON_LIBRARIES
+ ${COMMON_LIBRARIES}
+ "-framework Cocoa")
+endif()
if(MSVC)
target_link_libraries(
- MaterialXRenderMsl
+ ${MATERIALX_MODULE_NAME}
${COMMON_LIBRARIES}
Opengl32)
elseif(APPLE)
target_link_libraries(
- MaterialXRenderMsl
+ ${MATERIALX_MODULE_NAME}
${COMMON_LIBRARIES}
${OPENGL_LIBRARIES}
"-framework Foundation"
- "-framework Cocoa"
"-framework Metal")
elseif(UNIX)
target_link_libraries(
- MaterialXRenderMsl
+ ${MATERIALX_MODULE_NAME}
${COMMON_LIBRARIES}
${OPENGL_LIBRARIES}
${X11_LIBRARIES}
@@ -66,29 +75,31 @@ elseif(UNIX)
endif()
set_target_properties(
- MaterialXRenderMsl PROPERTIES
- OUTPUT_NAME MaterialXRenderMsl${MATERIALX_LIBNAME_SUFFIX}
+ ${MATERIALX_MODULE_NAME} PROPERTIES
+ OUTPUT_NAME ${MATERIALX_MODULE_NAME}${MATERIALX_LIBNAME_SUFFIX}
COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS}"
LINK_FLAGS "${EXTERNAL_LINK_FLAGS}"
VERSION "${MATERIALX_LIBRARY_VERSION}"
SOVERSION "${MATERIALX_MAJOR_VERSION}")
-target_include_directories(MaterialXRenderMsl
+target_include_directories(${MATERIALX_MODULE_NAME}
PUBLIC
$
$
PRIVATE
${EXTERNAL_INCLUDE_DIRS})
-install(TARGETS MaterialXRenderMsl
- EXPORT MaterialX
- ARCHIVE DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
- LIBRARY DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
- RUNTIME DESTINATION bin)
+if(NOT SKBUILD)
+ install(TARGETS ${MATERIALX_MODULE_NAME}
+ EXPORT MaterialX
+ ARCHIVE DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
+ LIBRARY DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
+ RUNTIME DESTINATION bin)
-install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/"
- DESTINATION ${MATERIALX_INSTALL_INCLUDE_PATH}/MaterialXRenderMsl/ MESSAGE_NEVER
- FILES_MATCHING PATTERN "*.h*")
+ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/"
+ DESTINATION ${MATERIALX_INSTALL_INCLUDE_PATH}/${MATERIALX_MODULE_NAME}/ MESSAGE_NEVER
+ FILES_MATCHING PATTERN "*.h*")
-install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/MaterialXRenderMsl.pdb"
- DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${MATERIALX_MODULE_NAME}.pdb"
+ DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
+endif()
diff --git a/source/MaterialXRenderMsl/MslMaterial.mm b/source/MaterialXRenderMsl/MslMaterial.mm
index 7e9cd38adc..66fc0462f2 100644
--- a/source/MaterialXRenderMsl/MslMaterial.mm
+++ b/source/MaterialXRenderMsl/MslMaterial.mm
@@ -199,7 +199,7 @@
imageHandler->setFilenameResolver(resolver);
// Acquire the given image.
- return imageHandler->acquireImage(filePath);
+ return imageHandler->acquireImage(filePath, samplingProperties.defaultColor);
}
void MslMaterial::bindLighting(LightHandlerPtr lightHandler,
diff --git a/source/MaterialXRenderMsl/MslPipelineStateObject.mm b/source/MaterialXRenderMsl/MslPipelineStateObject.mm
index 84a615fd61..4f8378ae46 100644
--- a/source/MaterialXRenderMsl/MslPipelineStateObject.mm
+++ b/source/MaterialXRenderMsl/MslPipelineStateObject.mm
@@ -542,7 +542,7 @@ int GetStrideOfMetalType(MTLDataType type)
{
// Acquire the image.
string error;
- ImagePtr image = imageHandler->acquireImage(filePath);
+ ImagePtr image = imageHandler->acquireImage(filePath, samplingProperties.defaultColor);
imageHandler->bindImage(image, samplingProperties);
return bindTexture(renderCmdEncoder, uniformLocation, image, imageHandler);
}
diff --git a/source/MaterialXRenderMsl/MslRenderer.h b/source/MaterialXRenderMsl/MslRenderer.h
index bf968078fe..ca87d9dd3e 100644
--- a/source/MaterialXRenderMsl/MslRenderer.h
+++ b/source/MaterialXRenderMsl/MslRenderer.h
@@ -82,6 +82,9 @@ class MX_RENDERMSL_API MslRenderer : public ShaderRenderer
/// Validate inputs for the program
void validateInputs() override;
+ /// Update the program with value of the uniform.
+ void updateUniform(const string& name, ConstValuePtr value) override;
+
/// Set the size of the rendered image
void setSize(unsigned int width, unsigned int height) override;
@@ -126,9 +129,6 @@ class MX_RENDERMSL_API MslRenderer : public ShaderRenderer
protected:
MslRenderer(unsigned int width, unsigned int height, Image::BaseType baseType);
-
- virtual void updateViewInformation();
- virtual void updateWorldInformation();
void triggerProgrammaticCapture();
void stopProgrammaticCapture();
@@ -146,11 +146,6 @@ class MX_RENDERMSL_API MslRenderer : public ShaderRenderer
bool _initialized;
- const Vector3 _eye;
- const Vector3 _center;
- const Vector3 _up;
- float _objectScale;
-
SimpleWindowPtr _window;
Color3 _screenColor;
};
diff --git a/source/MaterialXRenderMsl/MslRenderer.mm b/source/MaterialXRenderMsl/MslRenderer.mm
index f6de188b2f..f5e794c2b3 100644
--- a/source/MaterialXRenderMsl/MslRenderer.mm
+++ b/source/MaterialXRenderMsl/MslRenderer.mm
@@ -14,13 +14,6 @@
MATERIALX_NAMESPACE_BEGIN
-const float PI = std::acos(-1.0f);
-
-// View information
-const float FOV_PERSP = 45.0f; // degrees
-const float NEAR_PLANE_PERSP = 0.05f;
-const float FAR_PLANE_PERSP = 100.0f;
-
//
// MslRenderer methods
//
@@ -36,20 +29,14 @@
}
MslRenderer::MslRenderer(unsigned int width, unsigned int height, Image::BaseType baseType) :
- ShaderRenderer(width, height, baseType),
+ ShaderRenderer(width, height, baseType, MatrixConvention::Metal),
_initialized(false),
- _eye(0.0f, 0.0f, 3.0f),
- _center(0.0f, 0.0f, 0.0f),
- _up(0.0f, 1.0f, 0.0f),
- _objectScale(1.0f),
_screenColor(DEFAULT_SCREEN_COLOR_LIN_REC709)
{
_program = MslProgram::create();
_geometryHandler = GeometryHandler::create();
_geometryHandler->addLoader(TinyObjLoader::create());
-
- _camera = Camera::create();
}
void MslRenderer::initialize(RenderContextHandle)
@@ -137,6 +124,11 @@
_program->getAttributesList();
}
+void MslRenderer::updateUniform(const string& name, ConstValuePtr value)
+{
+ _program->bindUniform(name, value);
+}
+
void MslRenderer::createFrameBuffer(bool encodeSrgb)
{
_framebuffer = MetalFramebuffer::create(_device,
@@ -160,20 +152,6 @@
}
-void MslRenderer::updateViewInformation()
-{
- float fH = std::tan(FOV_PERSP / 360.0f * PI) * NEAR_PLANE_PERSP;
- float fW = fH * 1.0f;
-
- _camera->setViewMatrix(Camera::createViewMatrix(_eye, _center, _up));
- _camera->setProjectionMatrix(Camera::createPerspectiveMatrixZP(-fW, fW, -fH, fH, NEAR_PLANE_PERSP, FAR_PLANE_PERSP));
-}
-
-void MslRenderer::updateWorldInformation()
-{
- _camera->setWorldMatrix(Matrix44::createScale(Vector3(_objectScale)));
-}
-
void MslRenderer::triggerProgrammaticCapture()
{
MTLCaptureManager* captureManager = [MTLCaptureManager sharedCaptureManager];
@@ -217,9 +195,6 @@
[renderCmdEncoder setCullMode:MTLCullModeBack];
-
- updateViewInformation();
- updateWorldInformation();
try
{
diff --git a/source/MaterialXRenderOsl/CMakeLists.txt b/source/MaterialXRenderOsl/CMakeLists.txt
index a4ffa81235..ac1de93d2e 100644
--- a/source/MaterialXRenderOsl/CMakeLists.txt
+++ b/source/MaterialXRenderOsl/CMakeLists.txt
@@ -1,16 +1,24 @@
+set(MATERIALX_MODULE_NAME MaterialXRenderOsl)
+
file(GLOB_RECURSE materialx_source "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
file(GLOB_RECURSE materialx_headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h*")
assign_source_group("Source Files" ${materialx_source})
assign_source_group("Header Files" ${materialx_headers})
-add_library(MaterialXRenderOsl ${materialx_source} ${materialx_headers})
+add_library(${MATERIALX_MODULE_NAME} ${materialx_source} ${materialx_headers})
add_definitions(-DMATERIALX_RENDEROSL_EXPORTS)
+# Create version resource
+if(MATERIALX_BUILD_SHARED_LIBS AND MSVC)
+ configure_file(${CMAKE_SOURCE_DIR}/cmake/modules/MaterialXVersion.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
+ target_sources(${MATERIALX_MODULE_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
+endif()
+
set_target_properties(
- MaterialXRenderOsl PROPERTIES
- OUTPUT_NAME MaterialXRenderOsl${MATERIALX_LIBNAME_SUFFIX}
+ ${MATERIALX_MODULE_NAME} PROPERTIES
+ OUTPUT_NAME ${MATERIALX_MODULE_NAME}${MATERIALX_LIBNAME_SUFFIX}
COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS}"
LINK_FLAGS "${EXTERNAL_LINK_FLAGS}"
INSTALL_RPATH "${MATERIALX_SAME_DIR_RPATH}"
@@ -18,26 +26,28 @@ set_target_properties(
SOVERSION "${MATERIALX_MAJOR_VERSION}")
target_link_libraries(
- MaterialXRenderOsl
+ ${MATERIALX_MODULE_NAME}
MaterialXRender
${CMAKE_DL_LIBS})
-target_include_directories(MaterialXRenderOsl
+target_include_directories(${MATERIALX_MODULE_NAME}
PUBLIC
$
$
PRIVATE
${EXTERNAL_INCLUDE_DIRS})
-install(TARGETS MaterialXRenderOsl
- EXPORT MaterialX
- ARCHIVE DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
- LIBRARY DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
- RUNTIME DESTINATION bin)
+if(NOT SKBUILD)
+ install(TARGETS ${MATERIALX_MODULE_NAME}
+ EXPORT MaterialX
+ ARCHIVE DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
+ LIBRARY DESTINATION ${MATERIALX_INSTALL_LIB_PATH}
+ RUNTIME DESTINATION bin)
-install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/"
- DESTINATION ${MATERIALX_INSTALL_INCLUDE_PATH}/MaterialXRenderOsl/ MESSAGE_NEVER
- FILES_MATCHING PATTERN "*.h*")
+ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/"
+ DESTINATION ${MATERIALX_INSTALL_INCLUDE_PATH}/${MATERIALX_MODULE_NAME}/ MESSAGE_NEVER
+ FILES_MATCHING PATTERN "*.h*")
-install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/MaterialXRenderOsl.pdb"
- DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${MATERIALX_MODULE_NAME}.pdb"
+ DESTINATION "${MATERIALX_INSTALL_LIB_PATH}/" OPTIONAL)
+endif()
diff --git a/source/MaterialXTest/MaterialXCore/Node.cpp b/source/MaterialXTest/MaterialXCore/Node.cpp
index 2477d9f486..655ec5b7fb 100644
--- a/source/MaterialXTest/MaterialXCore/Node.cpp
+++ b/source/MaterialXTest/MaterialXCore/Node.cpp
@@ -136,6 +136,24 @@ TEST_CASE("Node", "[node]")
REQUIRE(doc->getOutputs().empty());
}
+TEST_CASE("Node inputCount repro", "[node]")
+{
+ // Create a document.
+ mx::DocumentPtr doc = mx::createDocument();
+ mx::NodePtr constant = doc->addNode("constant");
+ constant->setInputValue("value", 0.5f);
+
+ // Check that input count is correct after clearContent
+ constant->clearContent();
+ CHECK(constant->getInputCount() == 0);
+
+ // Check that validate succeeds after clear and rebuild
+ constant->setType("float");
+ mx::OutputPtr output = doc->addOutput(mx::EMPTY_STRING, "float");
+ output->setConnectedNode(constant);
+ CHECK(doc->validate());
+}
+
TEST_CASE("Flatten", "[nodegraph]")
{
// Read an example containing graph-based custom nodes.
diff --git a/source/MaterialXTest/MaterialXRenderMsl/RenderMsl.mm b/source/MaterialXTest/MaterialXRenderMsl/RenderMsl.mm
index f33e793690..248d458542 100644
--- a/source/MaterialXTest/MaterialXRenderMsl/RenderMsl.mm
+++ b/source/MaterialXTest/MaterialXRenderMsl/RenderMsl.mm
@@ -78,7 +78,7 @@ void runBake(mx::DocumentPtr doc, const mx::FileSearchPath& imageSearchPath, con
void MslShaderRenderTester::loadAdditionalLibraries(mx::DocumentPtr document,
GenShaderUtil::TestSuiteOptions& options)
{
- mx::FilePath lightDir = mx::FilePath::getCurrentPath() / mx::FilePath("resources/Materials/TestSuite/lights");
+ mx::FilePath lightDir = mx::getDefaultDataSearchPath().find("resources/Materials/TestSuite/lights");
for (const auto& lightFile : options.lightFiles)
{
loadLibrary(lightDir / mx::FilePath(lightFile), document);
@@ -135,6 +135,7 @@ void runBake(mx::DocumentPtr doc, const mx::FileSearchPath& imageSearchPath, con
mx::StbImageLoaderPtr stbLoader = mx::StbImageLoader::create();
mx::ImageHandlerPtr imageHandler =
_renderer->createImageHandler(stbLoader);
+ imageHandler->setSearchPath(mx::getDefaultDataSearchPath());
#if defined(MATERIALX_BUILD_OIIO)
mx::OiioImageLoaderPtr oiioLoader = mx::OiioImageLoader::create();
imageHandler->addLoader(oiioLoader);
@@ -179,6 +180,7 @@ void runBake(mx::DocumentPtr doc, const mx::FileSearchPath& imageSearchPath, con
std::cout << "Validating MSL rendering for: " << doc->getSourceUri() << std::endl;
mx::ScopedTimer totalMSLTime(&profileTimes.languageTimes.totalTime);
+ mx::FileSearchPath searchPath = mx::getDefaultDataSearchPath();
const mx::ShaderGenerator& shadergen = context.getShaderGenerator();
@@ -277,7 +279,7 @@ void runBake(mx::DocumentPtr doc, const mx::FileSearchPath& imageSearchPath, con
{
if (!testOptions.renderGeometry.isAbsolute())
{
- geomPath = mx::FilePath::getCurrentPath() / mx::FilePath("resources/Geometry") / testOptions.renderGeometry;
+ geomPath = searchPath.find("resources/Geometry") / testOptions.renderGeometry;
}
else
{
@@ -286,7 +288,7 @@ void runBake(mx::DocumentPtr doc, const mx::FileSearchPath& imageSearchPath, con
}
else
{
- geomPath = mx::FilePath::getCurrentPath() / mx::FilePath("resources/Geometry/sphere.obj");
+ geomPath = searchPath.find("resources/Geometry/sphere.obj");
}
if (!geomHandler->hasGeometry(geomPath))
@@ -373,7 +375,7 @@ void runBake(mx::DocumentPtr doc, const mx::FileSearchPath& imageSearchPath, con
{
{
mx::ScopedTimer renderTimer(&profileTimes.languageTimes.renderTime);
- _renderer->getImageHandler()->setSearchPath(imageSearchPath);
+ _renderer->getImageHandler()->setSearchPath(mx::getDefaultDataSearchPath());
_renderer->setSize(static_cast(testOptions.renderSize[0]), static_cast(testOptions.renderSize[1]));
_renderer->render();
}
@@ -456,18 +458,10 @@ void runBake(mx::DocumentPtr doc, const mx::FileSearchPath& imageSearchPath, con
TEST_CASE("Render: MSL TestSuite", "[rendermsl]")
{
- MslShaderRenderTester renderTester(mx::MslShaderGenerator::create());
-
- const mx::FilePath testRootPath = mx::FilePath::getCurrentPath() / mx::FilePath("resources/Materials/TestSuite");
- const mx::FilePath testRootPath2 = mx::FilePath::getCurrentPath() / mx::FilePath("resources/Materials/Examples/StandardSurface");
- const mx::FilePath testRootPath3 = mx::FilePath::getCurrentPath() / mx::FilePath("resources/Materials/Examples/UsdPreviewSurface");
- mx::FilePathVec testRootPaths;
- testRootPaths.push_back(testRootPath);
- testRootPaths.push_back(testRootPath2);
- testRootPaths.push_back(testRootPath3);
-
- mx::FilePath optionsFilePath = testRootPath / mx::FilePath("_options.mtlx");
+ mx::FileSearchPath searchPath = mx::getDefaultDataSearchPath();
+ mx::FilePath optionsFilePath = searchPath.find("resources/Materials/TestSuite/_options.mtlx");
+ MslShaderRenderTester renderTester(mx::MslShaderGenerator::create());
renderTester.validate(optionsFilePath);
}
diff --git a/source/MaterialXView/Viewer.cpp b/source/MaterialXView/Viewer.cpp
index ecbb4352fc..6346658d07 100644
--- a/source/MaterialXView/Viewer.cpp
+++ b/source/MaterialXView/Viewer.cpp
@@ -474,7 +474,7 @@ void Viewer::loadEnvironmentLight()
}
// Look for an irradiance map using an expected filename convention.
- mx::ImagePtr envIrradianceMap = _imageHandler->getInvalidImage();
+ mx::ImagePtr envIrradianceMap = _imageHandler->getZeroImage();
if (!_normalizeEnvironment && !_splitDirectLight)
{
mx::FilePath envIrradiancePath = _envRadianceFilename.getParentPath() / IRRADIANCE_MAP_FOLDER / _envRadianceFilename.getBaseName();
@@ -482,7 +482,7 @@ void Viewer::loadEnvironmentLight()
}
// If not found, then generate an irradiance map via spherical harmonics.
- if (envIrradianceMap == _imageHandler->getInvalidImage())
+ if (envIrradianceMap == _imageHandler->getZeroImage())
{
if (_generateReferenceIrradiance)
{
diff --git a/source/PyMaterialX/PyMaterialXCore/CMakeLists.txt b/source/PyMaterialX/PyMaterialXCore/CMakeLists.txt
index dfc2aefac0..9f3d2291c0 100644
--- a/source/PyMaterialX/PyMaterialXCore/CMakeLists.txt
+++ b/source/PyMaterialX/PyMaterialXCore/CMakeLists.txt
@@ -14,8 +14,6 @@ set_target_properties(
COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS}"
LINK_FLAGS "${EXTERNAL_LINK_FLAGS}"
INSTALL_RPATH "${MATERIALX_UP_TWO_RPATH}"
- VERSION "${MATERIALX_LIBRARY_VERSION}"
- SOVERSION "${MATERIALX_MAJOR_VERSION}"
DEBUG_POSTFIX "${MATERIALX_PYTHON_DEBUG_POSTFIX}")
target_link_libraries(
@@ -24,4 +22,4 @@ target_link_libraries(
PRIVATE ${CMAKE_DL_LIBS})
install(TARGETS PyMaterialXCore
- DESTINATION "python/MaterialX")
+ DESTINATION "${MATERIALX_PYTHON_FOLDER_NAME}")
diff --git a/source/PyMaterialX/PyMaterialXCore/PyInterface.cpp b/source/PyMaterialX/PyMaterialXCore/PyInterface.cpp
index 2a4645d3b6..2e9b264381 100644
--- a/source/PyMaterialX/PyMaterialXCore/PyInterface.cpp
+++ b/source/PyMaterialX/PyMaterialXCore/PyInterface.cpp
@@ -93,6 +93,7 @@ void bindPyInterface(py::module& mod)
.def("getDefaultVersion", &mx::InterfaceElement::getDefaultVersion)
.def("getDeclaration", &mx::InterfaceElement::getDeclaration,
py::arg("target") = mx::EMPTY_STRING)
+ .def("clearContent", &mx::InterfaceElement::clearContent)
.def("hasExactInputMatch", &mx::InterfaceElement::hasExactInputMatch,
py::arg("declaration"), py::arg("message") = nullptr)
BIND_INTERFACE_TYPE_INSTANCE(integer, int)
diff --git a/source/PyMaterialX/PyMaterialXCore/PyNode.cpp b/source/PyMaterialX/PyMaterialXCore/PyNode.cpp
index 704cda7589..55448dee80 100644
--- a/source/PyMaterialX/PyMaterialXCore/PyNode.cpp
+++ b/source/PyMaterialX/PyMaterialXCore/PyNode.cpp
@@ -59,6 +59,7 @@ void bindPyNode(py::module& mod)
.def("addInterfaceName", &mx::NodeGraph::addInterfaceName)
.def("removeInterfaceName", &mx::NodeGraph::removeInterfaceName)
.def("modifyInterfaceName", &mx::NodeGraph::modifyInterfaceName)
+ .def("getDownstreamPorts", &mx::NodeGraph::getDownstreamPorts)
.def_readonly_static("CATEGORY", &mx::NodeGraph::CATEGORY);
py::class_(mod, "Backdrop")
diff --git a/source/PyMaterialX/PyMaterialXFormat/CMakeLists.txt b/source/PyMaterialX/PyMaterialXFormat/CMakeLists.txt
index 9566e792fd..095b3eb087 100644
--- a/source/PyMaterialX/PyMaterialXFormat/CMakeLists.txt
+++ b/source/PyMaterialX/PyMaterialXFormat/CMakeLists.txt
@@ -14,8 +14,6 @@ set_target_properties(
COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS}"
LINK_FLAGS "${EXTERNAL_LINK_FLAGS}"
INSTALL_RPATH "${MATERIALX_UP_TWO_RPATH}"
- VERSION "${MATERIALX_LIBRARY_VERSION}"
- SOVERSION "${MATERIALX_MAJOR_VERSION}"
DEBUG_POSTFIX "${MATERIALX_PYTHON_DEBUG_POSTFIX}")
target_link_libraries(
@@ -25,4 +23,4 @@ target_link_libraries(
PRIVATE ${CMAKE_DL_LIBS})
install(TARGETS PyMaterialXFormat
- DESTINATION "python/MaterialX")
+ DESTINATION "${MATERIALX_PYTHON_FOLDER_NAME}")
diff --git a/source/PyMaterialX/PyMaterialXGenGlsl/CMakeLists.txt b/source/PyMaterialX/PyMaterialXGenGlsl/CMakeLists.txt
index b65ef857a4..24266712fd 100644
--- a/source/PyMaterialX/PyMaterialXGenGlsl/CMakeLists.txt
+++ b/source/PyMaterialX/PyMaterialXGenGlsl/CMakeLists.txt
@@ -14,8 +14,6 @@ set_target_properties(
COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS}"
LINK_FLAGS "${EXTERNAL_LINK_FLAGS}"
INSTALL_RPATH "${MATERIALX_UP_TWO_RPATH}"
- VERSION "${MATERIALX_LIBRARY_VERSION}"
- SOVERSION "${MATERIALX_MAJOR_VERSION}"
DEBUG_POSTFIX "${MATERIALX_PYTHON_DEBUG_POSTFIX}")
target_link_libraries(
@@ -25,4 +23,4 @@ target_link_libraries(
PRIVATE ${CMAKE_DL_LIBS})
install(TARGETS PyMaterialXGenGlsl
- DESTINATION "python/MaterialX")
+ DESTINATION "${MATERIALX_PYTHON_FOLDER_NAME}")
diff --git a/source/PyMaterialX/PyMaterialXGenMdl/CMakeLists.txt b/source/PyMaterialX/PyMaterialXGenMdl/CMakeLists.txt
index a1bc225a4f..328a2439ed 100644
--- a/source/PyMaterialX/PyMaterialXGenMdl/CMakeLists.txt
+++ b/source/PyMaterialX/PyMaterialXGenMdl/CMakeLists.txt
@@ -14,8 +14,6 @@ set_target_properties(
COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS}"
LINK_FLAGS "${EXTERNAL_LINK_FLAGS}"
INSTALL_RPATH "${MATERIALX_UP_TWO_RPATH}"
- VERSION "${MATERIALX_LIBRARY_VERSION}"
- SOVERSION "${MATERIALX_MAJOR_VERSION}"
DEBUG_POSTFIX "${MATERIALX_PYTHON_DEBUG_POSTFIX}")
target_link_libraries(
@@ -24,4 +22,4 @@ target_link_libraries(
PRIVATE ${CMAKE_DL_LIBS})
install(TARGETS PyMaterialXGenMdl
- DESTINATION "python/MaterialX")
+ DESTINATION "${MATERIALX_PYTHON_FOLDER_NAME}")
diff --git a/source/PyMaterialX/PyMaterialXGenMsl/CMakeLists.txt b/source/PyMaterialX/PyMaterialXGenMsl/CMakeLists.txt
index 88e21687bc..33dec7319a 100644
--- a/source/PyMaterialX/PyMaterialXGenMsl/CMakeLists.txt
+++ b/source/PyMaterialX/PyMaterialXGenMsl/CMakeLists.txt
@@ -14,8 +14,6 @@ set_target_properties(
COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS}"
LINK_FLAGS "${EXTERNAL_LINK_FLAGS}"
INSTALL_RPATH "${MATERIALX_UP_TWO_RPATH}"
- VERSION "${MATERIALX_LIBRARY_VERSION}"
- SOVERSION "${MATERIALX_MAJOR_VERSION}"
DEBUG_POSTFIX "${MATERIALX_PYTHON_DEBUG_POSTFIX}")
target_link_libraries(
@@ -25,4 +23,4 @@ target_link_libraries(
PRIVATE ${CMAKE_DL_LIBS})
install(TARGETS PyMaterialXGenMsl
- DESTINATION "python/MaterialX")
+ DESTINATION "${MATERIALX_PYTHON_FOLDER_NAME}")
diff --git a/source/PyMaterialX/PyMaterialXGenOsl/CMakeLists.txt b/source/PyMaterialX/PyMaterialXGenOsl/CMakeLists.txt
index 5d30769b4d..65b0dabe67 100644
--- a/source/PyMaterialX/PyMaterialXGenOsl/CMakeLists.txt
+++ b/source/PyMaterialX/PyMaterialXGenOsl/CMakeLists.txt
@@ -14,8 +14,6 @@ set_target_properties(
COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS}"
LINK_FLAGS "${EXTERNAL_LINK_FLAGS}"
INSTALL_RPATH "${MATERIALX_UP_TWO_RPATH}"
- VERSION "${MATERIALX_LIBRARY_VERSION}"
- SOVERSION "${MATERIALX_MAJOR_VERSION}"
DEBUG_POSTFIX "${MATERIALX_PYTHON_DEBUG_POSTFIX}")
target_link_libraries(
@@ -25,4 +23,4 @@ target_link_libraries(
PRIVATE ${CMAKE_DL_LIBS})
install(TARGETS PyMaterialXGenOsl
- DESTINATION "python/MaterialX")
+ DESTINATION "${MATERIALX_PYTHON_FOLDER_NAME}")
diff --git a/source/PyMaterialX/PyMaterialXGenShader/CMakeLists.txt b/source/PyMaterialX/PyMaterialXGenShader/CMakeLists.txt
index 13c01b3351..5bee142c24 100644
--- a/source/PyMaterialX/PyMaterialXGenShader/CMakeLists.txt
+++ b/source/PyMaterialX/PyMaterialXGenShader/CMakeLists.txt
@@ -14,8 +14,6 @@ set_target_properties(
COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS}"
LINK_FLAGS "${EXTERNAL_LINK_FLAGS}"
INSTALL_RPATH "${MATERIALX_UP_TWO_RPATH}"
- VERSION "${MATERIALX_LIBRARY_VERSION}"
- SOVERSION "${MATERIALX_MAJOR_VERSION}"
DEBUG_POSTFIX "${MATERIALX_PYTHON_DEBUG_POSTFIX}")
target_link_libraries(
@@ -26,4 +24,4 @@ target_link_libraries(
PRIVATE ${CMAKE_DL_LIBS})
install(TARGETS PyMaterialXGenShader
- DESTINATION "python/MaterialX")
+ DESTINATION "${MATERIALX_PYTHON_FOLDER_NAME}")
diff --git a/source/PyMaterialX/PyMaterialXRender/CMakeLists.txt b/source/PyMaterialX/PyMaterialXRender/CMakeLists.txt
index a050cb6aa3..2617a0b392 100644
--- a/source/PyMaterialX/PyMaterialXRender/CMakeLists.txt
+++ b/source/PyMaterialX/PyMaterialXRender/CMakeLists.txt
@@ -17,8 +17,6 @@ set_target_properties(
COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS}"
LINK_FLAGS "${EXTERNAL_LINK_FLAGS}"
INSTALL_RPATH "${MATERIALX_UP_TWO_RPATH}"
- VERSION "${MATERIALX_LIBRARY_VERSION}"
- SOVERSION "${MATERIALX_MAJOR_VERSION}"
DEBUG_POSTFIX "${MATERIALX_PYTHON_DEBUG_POSTFIX}")
target_link_libraries(
@@ -28,4 +26,4 @@ target_link_libraries(
PRIVATE ${CMAKE_DL_LIBS})
install(TARGETS PyMaterialXRender
- DESTINATION "python/MaterialX")
+ DESTINATION "${MATERIALX_PYTHON_FOLDER_NAME}")
diff --git a/source/PyMaterialX/PyMaterialXRender/PyImageHandler.cpp b/source/PyMaterialX/PyMaterialXRender/PyImageHandler.cpp
index 7ece49d60b..d261bc7306 100644
--- a/source/PyMaterialX/PyMaterialXRender/PyImageHandler.cpp
+++ b/source/PyMaterialX/PyMaterialXRender/PyImageHandler.cpp
@@ -41,7 +41,8 @@ void bindPyImageHandler(py::module& mod)
.def("addLoader", &mx::ImageHandler::addLoader)
.def("saveImage", &mx::ImageHandler::saveImage,
py::arg("filePath"), py::arg("image"), py::arg("verticalFlip") = false)
- .def("acquireImage", &mx::ImageHandler::acquireImage)
+ .def("acquireImage", &mx::ImageHandler::acquireImage,
+ py::arg("filePath"), py::arg("defaultColor") = mx::Color4(0.0f))
.def("bindImage", &mx::ImageHandler::bindImage)
.def("unbindImage", &mx::ImageHandler::unbindImage)
.def("unbindImages", &mx::ImageHandler::unbindImages)
@@ -54,6 +55,5 @@ void bindPyImageHandler(py::module& mod)
py::arg("image") = nullptr)
.def("clearImageCache", &mx::ImageHandler::clearImageCache)
.def("getZeroImage", &mx::ImageHandler::getZeroImage)
- .def("getInvalidImage", &mx::ImageHandler::getInvalidImage)
.def("getReferencedImages", &mx::ImageHandler::getReferencedImages);
}
diff --git a/source/PyMaterialX/PyMaterialXRender/PyShaderRenderer.cpp b/source/PyMaterialX/PyMaterialXRender/PyShaderRenderer.cpp
index c67238dea5..94c0d49cee 100644
--- a/source/PyMaterialX/PyMaterialXRender/PyShaderRenderer.cpp
+++ b/source/PyMaterialX/PyMaterialXRender/PyShaderRenderer.cpp
@@ -25,6 +25,7 @@ void bindPyShaderRenderer(py::module& mod)
.def("createProgram", static_cast(&mx::ShaderRenderer::createProgram))
.def("createProgram", static_cast(&mx::ShaderRenderer::createProgram))
.def("validateInputs", &mx::ShaderRenderer::validateInputs)
+ .def("updateUniform", &mx::ShaderRenderer::updateUniform)
.def("setSize", &mx::ShaderRenderer::setSize)
.def("render", &mx::ShaderRenderer::render);
diff --git a/source/PyMaterialX/PyMaterialXRenderGlsl/CMakeLists.txt b/source/PyMaterialX/PyMaterialXRenderGlsl/CMakeLists.txt
index a29cdc5c1e..a0b04ddbda 100644
--- a/source/PyMaterialX/PyMaterialXRenderGlsl/CMakeLists.txt
+++ b/source/PyMaterialX/PyMaterialXRenderGlsl/CMakeLists.txt
@@ -14,8 +14,6 @@ set_target_properties(
COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS}"
LINK_FLAGS "${EXTERNAL_LINK_FLAGS}"
INSTALL_RPATH "${MATERIALX_UP_TWO_RPATH}"
- VERSION "${MATERIALX_LIBRARY_VERSION}"
- SOVERSION "${MATERIALX_MAJOR_VERSION}"
DEBUG_POSTFIX "${MATERIALX_PYTHON_DEBUG_POSTFIX}")
target_link_libraries(
@@ -27,4 +25,4 @@ target_link_libraries(
PRIVATE ${CMAKE_DL_LIBS})
install(TARGETS PyMaterialXRenderGlsl
- DESTINATION "python/MaterialX")
+ DESTINATION "${MATERIALX_PYTHON_FOLDER_NAME}")
diff --git a/source/PyMaterialX/PyMaterialXRenderMsl/CMakeLists.txt b/source/PyMaterialX/PyMaterialXRenderMsl/CMakeLists.txt
index ec562fe8cf..04c6d95e3c 100644
--- a/source/PyMaterialX/PyMaterialXRenderMsl/CMakeLists.txt
+++ b/source/PyMaterialX/PyMaterialXRenderMsl/CMakeLists.txt
@@ -14,8 +14,6 @@ set_target_properties(
COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS}"
LINK_FLAGS "${EXTERNAL_LINK_FLAGS}"
INSTALL_RPATH "${MATERIALX_UP_TWO_RPATH}"
- VERSION "${MATERIALX_LIBRARY_VERSION}"
- SOVERSION "${MATERIALX_MAJOR_VERSION}"
DEBUG_POSTFIX "${MATERIALX_PYTHON_DEBUG_POSTFIX}")
target_link_libraries(
@@ -27,4 +25,4 @@ target_link_libraries(
PRIVATE ${CMAKE_DL_LIBS})
install(TARGETS PyMaterialXRenderMsl
- DESTINATION "python/MaterialX")
+ DESTINATION "${MATERIALX_PYTHON_FOLDER_NAME}")
diff --git a/source/PyMaterialX/PyMaterialXRenderOsl/CMakeLists.txt b/source/PyMaterialX/PyMaterialXRenderOsl/CMakeLists.txt
index 4777b13e7b..c0b83948a9 100644
--- a/source/PyMaterialX/PyMaterialXRenderOsl/CMakeLists.txt
+++ b/source/PyMaterialX/PyMaterialXRenderOsl/CMakeLists.txt
@@ -14,8 +14,6 @@ set_target_properties(
COMPILE_FLAGS "${EXTERNAL_COMPILE_FLAGS}"
LINK_FLAGS "${EXTERNAL_LINK_FLAGS}"
INSTALL_RPATH "${MATERIALX_UP_TWO_RPATH}"
- VERSION "${MATERIALX_LIBRARY_VERSION}"
- SOVERSION "${MATERIALX_MAJOR_VERSION}"
DEBUG_POSTFIX "${MATERIALX_PYTHON_DEBUG_POSTFIX}")
target_link_libraries(
@@ -25,4 +23,4 @@ target_link_libraries(
PRIVATE ${CMAKE_DL_LIBS})
install(TARGETS PyMaterialXRenderOsl
- DESTINATION "python/MaterialX")
+ DESTINATION "${MATERIALX_PYTHON_FOLDER_NAME}")